You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iotdb.apache.org by ro...@apache.org on 2022/12/12 08:33:49 UTC

[iotdb] 01/01: python udf api package

This is an automated email from the ASF dual-hosted git repository.

rong pushed a commit to branch python-udf
in repository https://gitbox.apache.org/repos/asf/iotdb.git

commit d86f3f9a037c5e0ef9afb56bd6988ad25092ec44
Author: Steve Yurong Su <ro...@apache.org>
AuthorDate: Mon Dec 12 16:32:43 2022 +0800

    python udf api package
---
 udf-py/.flake8                                     |  32 ++++
 udf-py/.gitignore                                  |   3 +
 udf-py/LICENSE                                     | 201 +++++++++++++++++++++
 udf-py/README.md                                   |  45 +++++
 udf-py/pyproject.toml                              |  45 +++++
 udf-py/release.sh                                  |  37 ++++
 udf-py/requirements.txt                            |  17 ++
 udf-py/requirements_dev.txt                        |  26 +++
 udf-py/setup.py                                    |  51 ++++++
 udf-py/tests/__init__.py                           |  17 ++
 udf-py/udf_api/__init__.py                         |  16 ++
 udf-py/udf_api/access/__init__.py                  |  16 ++
 udf-py/udf_api/access/row.py                       | 138 ++++++++++++++
 udf-py/udf_api/access/row_iterator.py              |  41 +++++
 udf-py/udf_api/access/row_window.py                |  95 ++++++++++
 udf-py/udf_api/collector/__init__.py               |  16 ++
 udf-py/udf_api/collector/point_collector.py        |  98 ++++++++++
 udf-py/udf_api/customizer/__init__.py              |  16 ++
 udf-py/udf_api/customizer/config/__init__.py       |  16 ++
 .../customizer/config/udf_configurations.py        |  32 ++++
 .../customizer/config/udtf_configurations.py       |  64 +++++++
 udf-py/udf_api/customizer/parameter/__init__.py    |  16 ++
 .../parameter/udf_parameter_validator.py           | 136 ++++++++++++++
 .../udf_api/customizer/parameter/udf_parameters.py |  71 ++++++++
 udf-py/udf_api/customizer/strategy/__init__.py     |  16 ++
 .../udf_api/customizer/strategy/access_strategy.py |  45 +++++
 .../customizer/strategy/access_strategy_type.py    |  38 ++++
 .../mappable_row_by_row_access_strategy.py         |  40 ++++
 .../strategy/row_by_row_access_strategy.py         |  40 ++++
 .../session_time_window_access_strategy.py         |  77 ++++++++
 .../sliding_size_window_access_strategy.py         |  98 ++++++++++
 .../sliding_time_window_access_strategy.py         | 127 +++++++++++++
 .../strategy/state_window_access_strategy.py       |  77 ++++++++
 udf-py/udf_api/exception/__init__.py               |  16 ++
 .../udf_attribute_not_provided_exception.py        |  27 +++
 udf-py/udf_api/exception/udf_exception.py          |  36 ++++
 ...f_input_series_data_type_not_valid_exception.py |  32 ++++
 .../udf_input_series_index_not_valid_exception.py  |  29 +++
 .../udf_input_series_number_not_valid_exception.py |  35 ++++
 .../udf_api/exception/udf_management_exception.py  |  23 +++
 ..._output_series_data_type_not_valid_exception.py |  29 +++
 .../exception/udf_parameter_not_valid_exception.py |  23 +++
 udf-py/udf_api/type/__init__.py                    |  16 ++
 udf-py/udf_api/type/binary.py                      |  77 ++++++++
 udf-py/udf_api/type/type.py                        |  27 +++
 udf-py/udf_api/udf.py                              |  37 ++++
 udf-py/udf_api/udtf.py                             | 104 +++++++++++
 47 files changed, 2314 insertions(+)

diff --git a/udf-py/.flake8 b/udf-py/.flake8
new file mode 100644
index 0000000000..8c86f0d1d6
--- /dev/null
+++ b/udf-py/.flake8
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+[flake8]
+ignore =
+    E203,
+    W503
+max-line-length=200
+exclude =
+    .git,
+    test/*,
+extend-exclude =
+    dist,
+    build,
+    venv
+show-source = True
+statistics = True
+format = %(path)s:%(row)d,%(col)d:%(code)s:%(text)s:https://lintlyci.github.io/Flake8Rules/rules/%(code)s.html
diff --git a/udf-py/.gitignore b/udf-py/.gitignore
new file mode 100644
index 0000000000..237854a3c0
--- /dev/null
+++ b/udf-py/.gitignore
@@ -0,0 +1,3 @@
+# generated by Pypi
+/build/
+/dist/
diff --git a/udf-py/LICENSE b/udf-py/LICENSE
new file mode 100644
index 0000000000..261eeb9e9f
--- /dev/null
+++ b/udf-py/LICENSE
@@ -0,0 +1,201 @@
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
diff --git a/udf-py/README.md b/udf-py/README.md
new file mode 100644
index 0000000000..c45bbb3748
--- /dev/null
+++ b/udf-py/README.md
@@ -0,0 +1,45 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+
+        http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+
+-->
+
+# Apache IoTDB Python UDF
+
+## Releasing
+
+To do a release just ensure that you have the right set of dev dependencies.
+Then run linting and auto-formatting.
+Then, ensure that all tests work (via `pytest .`).
+Then you are good to go to do a release!
+
+### Preparing your environment
+
+First, install all necessary dev dependencies via `pip install -r requirements_dev.txt`.
+
+### Doing the Release
+
+There is a convenient script `release.sh` to do all steps for a release.
+Namely, these are
+
+* Remove all transient directories from last release (if exists)
+* Run Autoformatting (`black .`) 
+* Run Linting (`flake8 .`)
+* Run Tests via pytest
+* Build
+* Release to pypi
diff --git a/udf-py/pyproject.toml b/udf-py/pyproject.toml
new file mode 100644
index 0000000000..0a72182bb7
--- /dev/null
+++ b/udf-py/pyproject.toml
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+[tool.black]
+line-length = 88
+target-version = ['py37']
+include = '\.pyi?$'
+exclude = '''
+
+(
+  /(
+      \.eggs         # exclude a few common directories in the
+    | \.git          # root of the project
+    | \.hg
+    | \.mypy_cache
+    | \.tox
+    | \.venv
+    | venv
+    | _build
+    | buck-out
+    | build
+    | dist
+    | migrations
+    | test
+    | iotdb/thrift
+  )/
+  | foo.py           # also separately exclude a file named foo.py in
+                     # the root of the project
+)
+'''
diff --git a/udf-py/release.sh b/udf-py/release.sh
new file mode 100755
index 0000000000..1c64990cfb
--- /dev/null
+++ b/udf-py/release.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+#
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+# the python version must be python3.
+python --version
+
+rm -Rf build
+rm -Rf dist
+
+# Run Autoformatting & Linting
+black .
+flake8 .
+
+# Run unit tests
+pytest .
+
+# See https://packaging.python.org/tutorials/packaging-projects/
+python setup.py sdist bdist_wheel
+twine upload --repository pypi dist/*
diff --git a/udf-py/requirements.txt b/udf-py/requirements.txt
new file mode 100644
index 0000000000..2a1e720805
--- /dev/null
+++ b/udf-py/requirements.txt
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
diff --git a/udf-py/requirements_dev.txt b/udf-py/requirements_dev.txt
new file mode 100644
index 0000000000..276fed3ef4
--- /dev/null
+++ b/udf-py/requirements_dev.txt
@@ -0,0 +1,26 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+-r requirements.txt
+# Pytest to run tests
+pytest==7.2.0
+flake8==3.9.0
+black==20.8b1
+# For releases
+twine==3.4.1
+wheel==0.36.2
diff --git a/udf-py/setup.py b/udf-py/setup.py
new file mode 100644
index 0000000000..79404284c3
--- /dev/null
+++ b/udf-py/setup.py
@@ -0,0 +1,51 @@
+#  Licensed to the Apache Software Foundation (ASF) under one
+#  or more contributor license agreements.  See the NOTICE file
+#  distributed with this work for additional information
+#  regarding copyright ownership.  The ASF licenses this file
+#  to you under the Apache License, Version 2.0 (the
+#  "License"); you may not use this file except in compliance
+#  with the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing,
+#  software distributed under the License is distributed on an
+#  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+#  KIND, either express or implied.  See the License for the
+#  specific language governing permissions and limitations
+#  under the License.
+#
+
+import setuptools
+import io
+
+try:
+    with io.open("README.md", encoding="utf-8") as f:
+        long_description = f.read()
+except FileNotFoundError:
+    long_description = ""
+
+print(long_description)
+
+setuptools.setup(
+    name="apache-iotdb-udf",
+    version="1.0.0",
+    author=" Apache Software Foundation",
+    author_email="dev@iotdb.apache.org",
+    description="Apache IoTDB client API",
+    long_description=long_description,
+    long_description_content_type="text/markdown",
+    url="https://github.com/apache/iotdb",
+    packages=setuptools.find_packages(),
+    install_requires=[],
+    classifiers=[
+        "Programming Language :: Python :: 3",
+        "License :: OSI Approved :: Apache Software License",
+        "Operating System :: OS Independent",
+        "Topic :: Software Development :: Libraries",
+        "Topic :: Software Development :: Libraries :: Python Modules",
+    ],
+    python_requires=">=3.7",
+    license="Apache License, Version 2.0",
+    website="https://iotdb.apache.org",
+)
diff --git a/udf-py/tests/__init__.py b/udf-py/tests/__init__.py
new file mode 100644
index 0000000000..2a1e720805
--- /dev/null
+++ b/udf-py/tests/__init__.py
@@ -0,0 +1,17 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
diff --git a/udf-py/udf_api/__init__.py b/udf-py/udf_api/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/access/__init__.py b/udf-py/udf_api/access/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/access/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/access/row.py b/udf-py/udf_api/access/row.py
new file mode 100644
index 0000000000..ae9e8b87a4
--- /dev/null
+++ b/udf-py/udf_api/access/row.py
@@ -0,0 +1,138 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta, abstractmethod
+
+from udf_api.type.binary import Binary
+from udf_api.type.type import Type
+
+
+class Row(metaclass=ABCMeta):
+    @abstractmethod
+    def get_time(self) -> int:
+        """
+        Returns the timestamp of this row.
+
+        :return: timestamp
+        """
+        pass
+
+    @abstractmethod
+    def get_int(self, column_index: int) -> int:
+        """
+        Returns the int value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.INT32.
+
+        :return: the int value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_long(self, column_index: int) -> int:
+        """
+        Returns the long value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.INT64.
+
+        :return: the long value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_float(self, column_index: int) -> float:
+        """
+        Returns the float value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.FLOAT.
+
+        :return: the float value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_double(self, column_index: int) -> float:
+        """
+        Returns the double value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.DOUBLE.
+
+        :return: the double value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_boolean(self, column_index: int) -> bool:
+        """
+        Returns the bool value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.BOOLEAN.
+
+        :return: the bool value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_binary(self, column_index: int) -> Binary:
+        """
+        Returns the Binary value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.TEXT.
+
+        :return: the Binary value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_string(self, column_index: int) -> str:
+        """
+        Returns the str value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.TEXT.
+
+        :return: the str value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def get_data_type(self, column_index: int) -> Type:
+        """
+        Returns the actual data type of the value at the specified column in this row.
+
+        Users need to ensure that the data type of the specified column is Type.TEXT.
+
+        :return: the actual data type of the value at the specified column in this row
+        """
+        pass
+
+    @abstractmethod
+    def is_null(self, column_index: int) -> bool:
+        """
+        Returns true if the value of the specified column is null.
+
+        :return: true if the value of the specified column is null
+        """
+        pass
+
+    @abstractmethod
+    def __len__(self):
+        """
+        Returns the number of columns
+
+        :return: the number of columns
+        """
+        pass
diff --git a/udf-py/udf_api/access/row_iterator.py b/udf-py/udf_api/access/row_iterator.py
new file mode 100644
index 0000000000..697d44f44a
--- /dev/null
+++ b/udf-py/udf_api/access/row_iterator.py
@@ -0,0 +1,41 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta, abstractmethod
+
+
+class RowIterator(metaclass=ABCMeta):
+    def __iter__(self):
+        return self
+
+    def __next__(self):
+        if self._has_next_row():
+            return self._next_row()
+        else:
+            raise StopIteration()
+
+    @abstractmethod
+    def _has_next_row(self):
+        pass
+
+    @abstractmethod
+    def _next_row(self):
+        pass
+
+    @abstractmethod
+    def reset(self):
+        pass
diff --git a/udf-py/udf_api/access/row_window.py b/udf-py/udf_api/access/row_window.py
new file mode 100644
index 0000000000..783c2bb2bd
--- /dev/null
+++ b/udf-py/udf_api/access/row_window.py
@@ -0,0 +1,95 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+from abc import ABCMeta, abstractmethod
+
+from udf_api.access.row import Row
+from udf_api.access.row_iterator import RowIterator
+from udf_api.type.type import Type
+
+
+class RowWindow(metaclass=ABCMeta):
+    @abstractmethod
+    def window_size(self):
+        """
+        Returns the number of rows in this window.
+
+        :return: the number of rows in this window
+        """
+        pass
+
+    @abstractmethod
+    def get_row(self, row_index: int) -> Row:
+        """
+        Returns the row at the specified position in this window.
+
+        Note that the Row instance returned by this method each time is the same instance. In other words, calling this
+        method will only change the member variables inside the Row instance, but will not generate a new Row instance.
+
+        :return: the row at the specified position in this window.
+        """
+        pass
+
+    @abstractmethod
+    def get_data_type(self, column_index: int) -> Type:
+        """
+        Returns the actual data type of the values at the specified column in this window.
+
+        :return: the actual data type of the values at the specified column in this window
+        """
+        pass
+
+    @abstractmethod
+    def get_row_iterator(self) -> RowIterator:
+        """
+        Returns an iterator used to access this window.
+
+        :return: an iterator used to access this window
+        """
+        pass
+
+    @abstractmethod
+    def window_start_time(self) -> int:
+        """
+        For different types of windows, the definition of the window start time is different.
+        For sliding size window: the window start time is equal to the timestamp of the first row.
+        For sliding time window: The window start time is determined by display_window_begin
+        SlidingTimeWindowAccessStrategy#get_display_window_begin() and
+        slidingStep SlidingTimeWindowAccessStrategy#get_sliding_step().
+        The window start time for the i-th window (i starts at 0) can be calculated as
+        display_window_begin + i * sliding_step.
+
+        :return: the start time of the window
+        """
+        pass
+
+    @abstractmethod
+    def window_start_end(self) -> int:
+        """
+        For different types of windows, the definition of the window end time is different.
+        For sliding size window: the window end time is equal to the timestamp of the last row.
+        For sliding time window: The window end time is determined by display_window_begin
+        SlidingTimeWindowAccessStrategy#get_display_window_begin(), time_interval
+        SlidingTimeWindowAccessStrategy#get_time_interval() and sliding_step
+        SlidingTimeWindowAccessStrategy#get_sliding_step(). The window end time for the i-th window (i starts at 0) can
+        be calculated as display_window_begin + i * sliding_step + time_interval - 1 or
+        window_start_time(i) + time_interval - 1.
+
+        :return: the end time of the window
+        """
+        pass
diff --git a/udf-py/udf_api/collector/__init__.py b/udf-py/udf_api/collector/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/collector/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/collector/point_collector.py b/udf-py/udf_api/collector/point_collector.py
new file mode 100644
index 0000000000..2c35439222
--- /dev/null
+++ b/udf-py/udf_api/collector/point_collector.py
@@ -0,0 +1,98 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta, abstractmethod
+
+from udf_api.type.binary import Binary
+
+
+class PointCollector(metaclass=ABCMeta):
+    """
+    Used to collect time series data points generated by UDTF.transform(Row, PointCollector), UDTF.transform(RowWindow,
+    PointCollector) or UDTF.terminate(PointCollector). Notice that one timestamp can not be put in the PointCollector
+    more than once, or it may stop the calculation.
+    """
+
+    @abstractmethod
+    def put_int(self, timestamp: int, value: int):
+        """
+        Collects an int data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.INT32 by calling
+        UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_long(self, timestamp: int, value: int):
+        """
+        Collects a long data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.INT64 by calling
+        UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_float(self, timestamp: int, value: float):
+        """
+        Collects a float data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.FLOAT by
+        calling UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_double(self, timestamp: int, value: float):
+        """
+        Collects a double data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.DOUBLE by
+        calling UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_boolean(self, timestamp: int, value: bool):
+        """
+        Collects a boolean data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.BOOLEAN by calling
+        UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_binary(self, timestamp: int, value: Binary):
+        """
+        Collects a Binary data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.TEXT by calling
+        UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
+
+    @abstractmethod
+    def put_string(self, timestamp: int, value: str):
+        """
+        Collects a String data point with timestamp.
+
+        Before calling this method, you need to ensure that the UDF output data type is set to Type.TEXT by calling
+        UDTFConfigurations.setOutputDataType(Type) in UDTF.beforeStart(UDFParameters, UDTFConfigurations).
+        """
+        pass
diff --git a/udf-py/udf_api/customizer/__init__.py b/udf-py/udf_api/customizer/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/customizer/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/customizer/config/__init__.py b/udf-py/udf_api/customizer/config/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/customizer/config/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/customizer/config/udf_configurations.py b/udf-py/udf_api/customizer/config/udf_configurations.py
new file mode 100644
index 0000000000..14f9a45d2a
--- /dev/null
+++ b/udf-py/udf_api/customizer/config/udf_configurations.py
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta
+
+from udf_api.exception.udf_exception import UDFException
+from udf_api.type.type import Type
+
+
+class UDFConfigurations(metaclass=ABCMeta):
+    _output_data_type: Type
+
+    def get_output_data_type(self):
+        return self._output_data_type
+
+    def check(self):
+        if self._output_data_type is None:
+            raise UDFException("UDF output_data_type is not set.")
diff --git a/udf-py/udf_api/customizer/config/udtf_configurations.py b/udf-py/udf_api/customizer/config/udtf_configurations.py
new file mode 100644
index 0000000000..99881bc26b
--- /dev/null
+++ b/udf-py/udf_api/customizer/config/udtf_configurations.py
@@ -0,0 +1,64 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.config.udf_configurations import UDFConfigurations
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.exception.udf_exception import UDFException
+from udf_api.type.type import Type
+
+
+class UDTFConfigurations(UDFConfigurations):
+    """
+    Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+    Supports calling methods in a chain.
+    """
+
+    __access_strategy: AccessStrategy
+
+    def set_access_strategy(self, access_strategy: AccessStrategy):
+        """
+        Used to specify the strategy for accessing raw query data in UDTF.
+
+        :param access_strategy: the specified access strategy. it should be an instance of AccessStrategy.
+        :return: self
+        """
+        self.__access_strategy = access_strategy
+        return self
+
+    def get_access_strategy(self) -> AccessStrategy:
+        return self.__access_strategy
+
+    def set_output_data_type(self, output_data_type: Type):
+        """
+        Used to specify the output data type of the UDTF.
+
+        In other words, the data type you set here determines the type of data that the PointCollector in
+        UDTF#transform(Row, PointCollector), UDTF#transform(RowWindow, PointCollector) or UDTF#terminate(PointCollector)
+        can receive.
+
+        :param output_data_type: the output data type of the UDTF
+        :return: self
+        """
+        self._output_data_type = output_data_type
+        return self
+
+    def check(self):
+        super().check()
+
+        if self.__access_strategy is None:
+            raise UDFException("Access strategy is not set.")
+        self.__access_strategy.check()
diff --git a/udf-py/udf_api/customizer/parameter/__init__.py b/udf-py/udf_api/customizer/parameter/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/customizer/parameter/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/customizer/parameter/udf_parameter_validator.py b/udf-py/udf_api/customizer/parameter/udf_parameter_validator.py
new file mode 100644
index 0000000000..0194b60765
--- /dev/null
+++ b/udf-py/udf_api/customizer/parameter/udf_parameter_validator.py
@@ -0,0 +1,136 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from typing import List
+
+from udf_api.customizer.parameter.udf_parameters import UDFParameters
+from udf_api.exception.udf_attribute_not_provided_exception import (
+    UDFAttributeNotProvidedException,
+)
+from udf_api.exception.udf_input_series_data_type_not_valid_exception import (
+    UDFInputSeriesDataTypeNotValidException,
+)
+from udf_api.exception.udf_input_series_index_not_valid_exception import (
+    UDFInputSeriesIndexNotValidException,
+)
+from udf_api.exception.udf_input_series_number_not_valid_exception import (
+    UDFInputSeriesNumberNotValidException,
+)
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+from udf_api.type.type import Type
+
+
+class UDFParameterValidator:
+    __parameters: UDFParameters
+
+    def __init__(self, parameters: UDFParameters):
+        self.__parameters = parameters
+
+    def get_parameters(self) -> UDFParameters:
+        return self.__parameters
+
+    def validate_required_attribute(self, attribute_key: str):
+        """
+        Validates whether the attributes entered by the user contain an attribute whose key is
+        attributeKey.
+
+        :param attribute_key: key of the attribute
+        :raise UDFAttributeNotProvidedException: if the attribute is not provided
+        """
+        if not self.__parameters.has_attribute(attribute_key):
+            raise UDFAttributeNotProvidedException(attribute_key)
+
+        return self
+
+    def validate_input_series_data_type(
+        self, index: int, expected_data_types: List[Type]
+    ):
+        """
+        Validates whether the data type of the input series at the specified column is as expected.
+
+        :param index: index of the specified column
+        :param expected_data_types: the expected data types
+        :raise UDFInputSeriesIndexNotValidException: if the index of the specified column is out of bound
+        :raise UDFInputSeriesDataTypeNotValidException: if the data type of the input series at the specified column is
+        not as expected
+        """
+        self.validate_input_series_index(index)
+
+        actual_data_type = self.__parameters.get_child_expression_data_types()[index]
+
+        for expected_data_type in expected_data_types:
+            if expected_data_type == actual_data_type:
+                return self
+
+        raise UDFInputSeriesDataTypeNotValidException(
+            index, actual_data_type, expected_data_types
+        )
+
+    def validate_input_series_number(
+        self,
+        expected_series_number_lower_bound: int,
+        expected_series_number_upper_bound,
+    ):
+        """
+        Validates whether the number of the input series is as expected.
+
+        :param expected_series_number_lower_bound: the number of the input series must be greater than or equal to the
+        expected_series_number_lower_bound
+        :param expected_series_number_upper_bound: the number of the input series must be less than or equal to the
+        expected_series_number_upper_bound
+        :raise UDFInputSeriesNumberNotValidException: if the number of the input series is not as expected
+        """
+        actual_series_number = self.__parameters.get_child_expressions_count()
+        if (
+            actual_series_number < expected_series_number_lower_bound
+            or expected_series_number_upper_bound < actual_series_number
+        ):
+            raise UDFInputSeriesNumberNotValidException(
+                actual_series_number,
+                expected_series_number_lower_bound,
+                expected_series_number_upper_bound,
+            )
+
+        return self
+
+    def validate(self, message_to_raise: str, validation_rule, **kwargs):
+        """
+        Validates the input parameters according to the validation rule given by the user.
+
+        :param message_to_raise: the message to throw when the given arguments are not valid
+        :param validation_rule: the validation rule, which can be a lambda expression
+        :param kwargs: the given arguments
+        :raise UDFParameterNotValidException: if the given arguments are not valid
+        """
+        if not validation_rule(kwargs):
+            raise UDFParameterNotValidException(message_to_raise)
+
+        return self
+
+    def validate_input_series_index(self, index: int):
+        """
+        Validates whether the index of the specified column is out of bound. bound: [0,
+        self.__parameters.get_child_expressions_count())
+
+        :param index: the index of the specified column
+        :raise UDFInputSeriesIndexNotValidException: if the index of the specified column is out of bound
+        """
+        actual_series_number = self.__parameters.get_child_expressions_count()
+        if index < 0 or actual_series_number <= index:
+            raise UDFInputSeriesIndexNotValidException(index, actual_series_number)
diff --git a/udf-py/udf_api/customizer/parameter/udf_parameters.py b/udf-py/udf_api/customizer/parameter/udf_parameters.py
new file mode 100644
index 0000000000..90fc64c05b
--- /dev/null
+++ b/udf-py/udf_api/customizer/parameter/udf_parameters.py
@@ -0,0 +1,71 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from typing import Dict, List
+
+from udf_api.type.type import Type
+
+
+# Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+# This class is used to parse the parameters in the UDF entered by the user.
+# The input parameters of UDF have two parts. The first part is the paths (measurements) of the time series that the UDF
+# needs to process, and the second part is the key-value pair attributes for customization. Only the second part can be
+# empty.
+# Note that the user must enter the paths (measurements) part before entering the attributes part.
+class UDFParameters:
+    __child_expressions: List[str]
+    __child_expression_data_types: List[Type]
+    __child_expressions_count: int
+    __attributes: Dict[str, str]
+
+    def __init__(
+        self,
+        child_expressions: List[str],
+        child_expression_data_types: List[Type],
+        attributes: Dict[str, str],
+    ):
+        self.__child_expressions = child_expressions
+        self.__child_expression_data_types = child_expression_data_types
+        self.__child_expressions_count = len(child_expressions)
+        self.__attributes = attributes
+
+    def get_child_expressions(self) -> List[str]:
+        return self.__child_expressions
+
+    def get_child_expression_data_types(self) -> List[Type]:
+        return self.__child_expression_data_types
+
+    def get_attributes(self) -> Dict[str, str]:
+        return self.__attributes
+
+    def get_child_expressions_count(self) -> int:
+        return self.__child_expressions_count
+
+    def has_attribute(self, key: str) -> bool:
+        return key in self.__attributes
+
+    def get_string(self, key: str, default: str = None) -> str:
+        string_value = self.__attributes[key]
+        return default if string_value is None else string_value
+
+    def get_int(self, key: str, default: int = None) -> int:
+        string_value = self.get_string(key)
+        return default if string_value is None else int(string_value)
+
+    def get_float(self, key: str, default: float = None) -> float:
+        string_value = self.get_string(key)
+        return default if string_value is None else float(string_value)
diff --git a/udf-py/udf_api/customizer/strategy/__init__.py b/udf-py/udf_api/customizer/strategy/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/customizer/strategy/access_strategy.py b/udf-py/udf_api/customizer/strategy/access_strategy.py
new file mode 100644
index 0000000000..007aba9ce8
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/access_strategy.py
@@ -0,0 +1,45 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta, abstractmethod
+
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+
+
+class AccessStrategy(metaclass=ABCMeta):
+    """
+    Used to customize the strategy for accessing raw data in UDTF#beforeStart(UDFParameters,
+    UDTFConfigurations)}.
+    """
+
+    @abstractmethod
+    def check(self):
+        """
+        Used by the system to check the access strategy.
+
+        :raise UDFException: if invalid strategy is set
+        """
+        pass
+
+    @abstractmethod
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        """
+        Returns the actual access strategy type.
+
+        :return AccessStrategyType: the actual access strategy type
+        """
+        pass
diff --git a/udf-py/udf_api/customizer/strategy/access_strategy_type.py b/udf-py/udf_api/customizer/strategy/access_strategy_type.py
new file mode 100644
index 0000000000..23dbfdad7c
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/access_strategy_type.py
@@ -0,0 +1,38 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from enum import Enum
+
+
+class AccessStrategyType(Enum):
+    # MappableRowByRowAccessStrategy
+    MAPPABLE_ROW_BY_ROW = 0
+
+    # RowByRowAccessStrategy
+    ROW_BY_ROW = 1
+
+    # SlidingTimeWindowAccessStrategy
+    SLIDING_TIME_WINDOW = 2
+
+    # SlidingSizeWindowAccessStrategy
+    SLIDING_SIZE_WINDOW = 3
+
+    # SessionTimeWindowAccessStrategy
+    SESSION_TIME_WINDOW = 4
+
+    # StateWindowAccessStrategy
+    STATE_WINDOW = 5
diff --git a/udf-py/udf_api/customizer/strategy/mappable_row_by_row_access_strategy.py b/udf-py/udf_api/customizer/strategy/mappable_row_by_row_access_strategy.py
new file mode 100644
index 0000000000..eb2e92fc90
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/mappable_row_by_row_access_strategy.py
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+
+
+class MappableRowByRowAccessStrategy(AccessStrategy):
+    """
+    Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+
+    When the access strategy of a UDTF is set to an instance of this class, the method UDTF#transform(Row) of the UDTF
+    will be called to transform the original data. You need to override the method in your own UDTF class.
+
+    Each call of the method UDTF#transform(Row) processes only one row (aligned by time) of the original data and can
+    generate any number of data points.
+    """
+
+    def check(self):
+        """
+        nothing needs to check
+        """
+        pass
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.MAPPABLE_ROW_BY_ROW
diff --git a/udf-py/udf_api/customizer/strategy/row_by_row_access_strategy.py b/udf-py/udf_api/customizer/strategy/row_by_row_access_strategy.py
new file mode 100644
index 0000000000..39a272a276
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/row_by_row_access_strategy.py
@@ -0,0 +1,40 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+
+
+class RowByRowAccessStrategy(AccessStrategy):
+    """
+    Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+
+    When the access strategy of a UDTF is set to an instance of this class, the method UDTF#transform(Row) of the UDTF
+    will be called to transform the original data. You need to override the method in your own UDTF class.
+
+    Each call of the method UDTF#transform(Row) processes only one row (aligned by time) of the original data and can
+    generate any number of data points.
+    """
+
+    def check(self):
+        """
+        nothing needs to check
+        """
+        pass
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.ROW_BY_ROW
diff --git a/udf-py/udf_api/customizer/strategy/session_time_window_access_strategy.py b/udf-py/udf_api/customizer/strategy/session_time_window_access_strategy.py
new file mode 100644
index 0000000000..b9d2bb72b1
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/session_time_window_access_strategy.py
@@ -0,0 +1,77 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+from udf_api.exception.udf_exception import UDFException
+
+
+class SessionTimeWindowAccessStrategy(AccessStrategy):
+    __session_time_gap: int
+    __display_window_begin: int
+    __display_window_end: int
+
+    def __init__(
+        self,
+        session_time_gap: int,
+        display_window_begin: int = -9223372036854775808,
+        display_window_end: int = 9223372036854775807,
+    ):
+        self.__session_time_gap = session_time_gap
+        self.__display_window_begin = display_window_begin
+        self.__display_window_end = display_window_end
+
+    def check(self):
+        if self.__session_time_gap < 0:
+            raise UDFException(
+                "Parameter session_time_gap({}) should be equal to or greater than zero.".format(
+                    self.__session_time_gap
+                )
+            )
+
+        if self.__display_window_begin < -9223372036854775808:
+            raise UDFException(
+                "Parameter display_window_begin({}) should be equal to or greater than -9223372036854775808.".format(
+                    self.__display_window_begin
+                )
+            )
+
+        if 9223372036854775807 < self.__display_window_end:
+            raise UDFException(
+                "Parameter display_window_end({}) should be equal to or less than 9223372036854775807.".format(
+                    self.__display_window_end
+                )
+            )
+
+        if self.__display_window_end < self.__display_window_begin:
+            raise UDFException(
+                "display_window_end({}) < display_window_begin({})".format(
+                    self.__display_window_end, self.__display_window_begin
+                )
+            )
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.SESSION_TIME_WINDOW
+
+    def get_session_time_gap(self) -> int:
+        return self.__session_time_gap
+
+    def get_display_window_begin(self) -> int:
+        return self.__display_window_begin
+
+    def get_display_window_end(self) -> int:
+        return self.__display_window_end
diff --git a/udf-py/udf_api/customizer/strategy/sliding_size_window_access_strategy.py b/udf-py/udf_api/customizer/strategy/sliding_size_window_access_strategy.py
new file mode 100644
index 0000000000..4f992847e9
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/sliding_size_window_access_strategy.py
@@ -0,0 +1,98 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+from udf_api.exception.udf_exception import UDFException
+
+
+class SlidingSizeWindowAccessStrategy(AccessStrategy):
+    """
+    Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+
+    When the access strategy of a UDTF is set to an instance of this class, the method UDTF#transform(RowWindow,
+    PointCollector) of the UDTF will be called to transform the original data. You need to override the method in your
+    own UDTF class.
+
+    Sliding size window is a kind of size-based window. Except for the last call, each call of the method
+    UDTF#transform(RowWindow, PointCollector) processes a window with windowSize rows (aligned by time) of the original
+    data and can generate any number of data points.
+    """
+
+    __window_size: int
+    __sliding_step: int
+
+    def __init__(self, window_size: int, sliding_step: int):
+        """
+        Constructor. You need to specify the number of rows in each sliding size window (except for the last window) and
+        the sliding step to the next window.
+
+        Example
+        Original data points (time, s1, s2):
+        (1, 100, null )
+        (2, 100, null )
+        (3, 100, null )
+        (4, 100, 'error')
+        (5, 100, null )
+        (6, 101, 'error')
+        (7, 102, 'error')
+
+        Set windowSize to 2 and set slidingStep to 3, windows will be generated as below: Window 0: [(1, 100, null ),
+        (2, 100, null)] Window 1: [(4, 100, 'error'), (5, 100, null)] Window 2: [(7, 102, 'error')]
+
+        :param window_size: the number of rows in each sliding size window (0 < window_size)
+        :param sliding_step: the number of rows between the first point of the next window and the first point of the
+        current window (0 < sliding_step)
+        """
+        self.__window_size = window_size
+        self.__sliding_step = sliding_step
+
+    def check(self):
+        if self.__window_size <= 0:
+            raise UDFException(
+                "Parameter window_size({}) should be positive.".format(
+                    self.__window_size
+                )
+            )
+        if 2147483647 < self.__window_size:
+            raise UDFException(
+                "Parameter window_size({}) should be less than or equals to 2147483647.".format(
+                    self.__window_size
+                )
+            )
+
+        if self.__sliding_step <= 0:
+            raise UDFException(
+                "Parameter sliding_step({}) should be positive.".format(
+                    self.__sliding_step
+                )
+            )
+        if 2147483647 < self.__sliding_step:
+            raise UDFException(
+                "Parameter sliding_step({}) should be less than or equals to 2147483647.".format(
+                    self.__sliding_step
+                )
+            )
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.SLIDING_SIZE_WINDOW
+
+    def get_window_size(self) -> int:
+        return self.__window_size
+
+    def get_sliding_step(self) -> int:
+        return self.__sliding_step
diff --git a/udf-py/udf_api/customizer/strategy/sliding_time_window_access_strategy.py b/udf-py/udf_api/customizer/strategy/sliding_time_window_access_strategy.py
new file mode 100644
index 0000000000..3aaaecc4b6
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/sliding_time_window_access_strategy.py
@@ -0,0 +1,127 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+from udf_api.exception.udf_exception import UDFException
+
+
+class SlidingTimeWindowAccessStrategy(AccessStrategy):
+    """
+    Used in UDTF#beforeStart(UDFParameters, UDTFConfigurations).
+
+    When the access strategy of a UDTF is set to an instance of this class, the method UDTF#transform(RowWindow,
+    PointCollector) of the UDTF will be called to transform the original data. You need to override the method in your
+    own UDTF class.
+
+    Sliding time window is a kind of time-based window. To partition the raw query data set into sliding time windows,
+    you need to give the following 4 parameters:
+
+    * display window begin: determines the start time of the first window
+    * display window end: if the start time of current window + sliding step > display window end, then current window
+      is the last window that your UDTF can process
+    * time interval: determines the time range of a window
+    * sliding step: the start time of the next window = the start time of current window + sliding step
+
+    Each call of the method UDTF.transform(RowWindow, PointCollector) processes one time window and can generate any
+    number of data points. Note that the transform method will still be called when there is no data point in a window.
+    Note that the time range of the last few windows may be less than the specified time interval.
+    """
+
+    __time_interval: int
+    __sliding_step: int
+    __display_window_begin: int
+    __display_window_end: int
+
+    def __init__(
+        self,
+        time_interval: int,
+        sliding_step: int,
+        display_window_begin: int,
+        display_window_end: int,
+    ):
+        """
+        :param time_interval: 0 < time_interval
+        :param sliding_step: 0 < sliding_step
+        :param display_window_begin: display_window_begin < display_window_end
+        :param display_window_end: display_window_begin < display_window_end
+        """
+        self.__time_interval = time_interval
+        self.__sliding_step = sliding_step
+        self.__display_window_begin = display_window_begin
+        self.__display_window_end = display_window_end
+
+    def check(self):
+        if self.__time_interval <= 0:
+            raise UDFException(
+                "Parameter time_interval({}) should be positive.".format(
+                    self.__time_interval
+                )
+            )
+        if 9223372036854775807 < self.__time_interval:
+            raise UDFException(
+                "Parameter window_size({}) should be less than or equals to 9223372036854775807.".format(
+                    self.__time_interval
+                )
+            )
+
+        if self.__sliding_step <= 0:
+            raise UDFException(
+                "Parameter sliding_step({}) should be positive.".format(
+                    self.__sliding_step
+                )
+            )
+        if 9223372036854775807 < self.__sliding_step:
+            raise UDFException(
+                "Parameter sliding_step({}) should be less than or equals to 9223372036854775807.".format(
+                    self.__sliding_step
+                )
+            )
+
+        if self.__display_window_begin < -9223372036854775808:
+            raise UDFException(
+                "Parameter display_window_begin({}) should be equal to or greater than -9223372036854775808.".format(
+                    self.__display_window_begin
+                )
+            )
+        if 9223372036854775807 < self.__display_window_end:
+            raise UDFException(
+                "Parameter display_window_end({}) should be less than or equals to 9223372036854775807.".format(
+                    self.__display_window_end
+                )
+            )
+        if self.__display_window_end < self.__display_window_begin:
+            raise UDFException(
+                "Parameter display_window_end({}) < display_window_begin({})".format(
+                    self.__display_window_end, self.__display_window_begin
+                )
+            )
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.SLIDING_TIME_WINDOW
+
+    def get_time_interval(self) -> int:
+        return self.__time_interval
+
+    def get_sliding_step(self) -> int:
+        return self.__sliding_step
+
+    def get_display_window_begin(self) -> int:
+        return self.__display_window_begin
+
+    def get_display_window_end(self) -> int:
+        return self.__display_window_end
diff --git a/udf-py/udf_api/customizer/strategy/state_window_access_strategy.py b/udf-py/udf_api/customizer/strategy/state_window_access_strategy.py
new file mode 100644
index 0000000000..fb6d35b142
--- /dev/null
+++ b/udf-py/udf_api/customizer/strategy/state_window_access_strategy.py
@@ -0,0 +1,77 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.customizer.strategy.access_strategy import AccessStrategy
+from udf_api.customizer.strategy.access_strategy_type import AccessStrategyType
+from udf_api.exception.udf_exception import UDFException
+
+
+class StateWindowAccessStrategy(AccessStrategy):
+    __delta: float = 0
+    __display_window_begin: int = -9223372036854775808
+    __display_window_end: int = 9223372036854775807
+
+    def __init__(
+        self,
+        delta: float = 0,
+        display_window_begin: int = -9223372036854775808,
+        display_window_end: int = 9223372036854775807,
+    ):
+        self.__delta = delta
+        self.__display_window_begin = display_window_begin
+        self.__display_window_end = display_window_end
+
+    def check(self):
+        if self.__delta < 0:
+            raise UDFException(
+                "Parameter delta({}) should be equal to or greater than zero.".format(
+                    self.__delta
+                )
+            )
+
+        if self.__display_window_begin < -9223372036854775808:
+            raise UDFException(
+                "Parameter display_window_begin({}) should be equal to or greater than -9223372036854775808.".format(
+                    self.__display_window_begin
+                )
+            )
+
+        if 9223372036854775807 < self.__display_window_end:
+            raise UDFException(
+                "Parameter display_window_end({}) should be equal to or less than 9223372036854775807.".format(
+                    self.__display_window_end
+                )
+            )
+
+        if self.__display_window_end < self.__display_window_begin:
+            raise UDFException(
+                "display_window_end({}) < display_window_begin({})".format(
+                    self.__display_window_end, self.__display_window_begin
+                )
+            )
+
+    def get_access_strategy_type(self) -> AccessStrategyType:
+        return AccessStrategyType.STATE_WINDOW
+
+    def get_delta(self) -> float:
+        return self.__delta
+
+    def get_display_window_begin(self) -> int:
+        return self.__display_window_begin
+
+    def get_display_window_end(self) -> int:
+        return self.__display_window_end
diff --git a/udf-py/udf_api/exception/__init__.py b/udf-py/udf_api/exception/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/exception/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/exception/udf_attribute_not_provided_exception.py b/udf-py/udf_api/exception/udf_attribute_not_provided_exception.py
new file mode 100644
index 0000000000..7ffc44c181
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_attribute_not_provided_exception.py
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+
+
+class UDFAttributeNotProvidedException(UDFParameterNotValidException):
+    def __init__(self, required_attribute: str):
+        super().__init__(
+            "attribute {} is required but was not provided.".format(required_attribute)
+        )
diff --git a/udf-py/udf_api/exception/udf_exception.py b/udf-py/udf_api/exception/udf_exception.py
new file mode 100644
index 0000000000..50b95bae24
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_exception.py
@@ -0,0 +1,36 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class UDFException(Exception):
+    __message: str
+    __cause: Exception = None
+
+    def __init__(self, message: str, cause: Exception = None):
+        self.__message = message
+        self.__cause = cause
+
+    def get_message(self):
+        return self.__message
+
+    def get_cause(self):
+        return self.__cause
+
+    def __str__(self):
+        return "UDF exception occurred: {}, caused by: {}".format(
+            self.__message, str(self.__cause.__class__)
+        )
diff --git a/udf-py/udf_api/exception/udf_input_series_data_type_not_valid_exception.py b/udf-py/udf_api/exception/udf_input_series_data_type_not_valid_exception.py
new file mode 100644
index 0000000000..d7c4bbea1a
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_input_series_data_type_not_valid_exception.py
@@ -0,0 +1,32 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from typing import List
+
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+from udf_api.type.type import Type
+
+
+class UDFInputSeriesDataTypeNotValidException(UDFParameterNotValidException):
+    def __init__(self, index: int, actual: Type, expected: List[Type]):
+        super(
+            "the data type of the input series (index: {}) is not valid. expected: {}. actual: {}.".format(
+                index, expected, actual
+            )
+        )
diff --git a/udf-py/udf_api/exception/udf_input_series_index_not_valid_exception.py b/udf-py/udf_api/exception/udf_input_series_index_not_valid_exception.py
new file mode 100644
index 0000000000..8fe059ca82
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_input_series_index_not_valid_exception.py
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+
+
+class UDFInputSeriesIndexNotValidException(UDFParameterNotValidException):
+    def __init__(self, provided_index: int, valid_index_upper_bound: int):
+        super().__init__(
+            "the index ({}) of the input series is not valid. valid index range: [0, {}).".format(
+                provided_index, valid_index_upper_bound
+            )
+        )
diff --git a/udf-py/udf_api/exception/udf_input_series_number_not_valid_exception.py b/udf-py/udf_api/exception/udf_input_series_number_not_valid_exception.py
new file mode 100644
index 0000000000..25287fde64
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_input_series_number_not_valid_exception.py
@@ -0,0 +1,35 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+
+
+class UDFInputSeriesNumberNotValidException(UDFParameterNotValidException):
+    def __init__(
+        self, actual: int, expected_lower_bound: int, expected_upper_bound: int
+    ):
+        super().__init__(
+            "the number of the input series is not valid. expected: [{}, {}]. actual: {}.".format(
+                expected_lower_bound, expected_upper_bound, actual
+            )
+            if expected_lower_bound != expected_upper_bound
+            else "the number of the input series is not valid. expected: {}. actual: {}.".format(
+                expected_lower_bound, actual
+            )
+        )
diff --git a/udf-py/udf_api/exception/udf_management_exception.py b/udf-py/udf_api/exception/udf_management_exception.py
new file mode 100644
index 0000000000..cc3165a617
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_management_exception.py
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_exception import UDFException
+
+
+class UDFManagementException(UDFException):
+    def __init__(self, message: str, cause: Exception = None):
+        super().__init__(message, cause)
diff --git a/udf-py/udf_api/exception/udf_output_series_data_type_not_valid_exception.py b/udf-py/udf_api/exception/udf_output_series_data_type_not_valid_exception.py
new file mode 100644
index 0000000000..c2ef7146a9
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_output_series_data_type_not_valid_exception.py
@@ -0,0 +1,29 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_parameter_not_valid_exception import (
+    UDFParameterNotValidException,
+)
+
+
+class UDFOutputSeriesDataTypeNotValidException(UDFParameterNotValidException):
+    def __init__(self, index: int, types: str):
+        super().__init__(
+            "the data type of the output series (index: {}) is not valid. expected: {}.".format(
+                index, types
+            )
+        )
diff --git a/udf-py/udf_api/exception/udf_parameter_not_valid_exception.py b/udf-py/udf_api/exception/udf_parameter_not_valid_exception.py
new file mode 100644
index 0000000000..69279acf90
--- /dev/null
+++ b/udf-py/udf_api/exception/udf_parameter_not_valid_exception.py
@@ -0,0 +1,23 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from udf_api.exception.udf_exception import UDFException
+
+
+class UDFParameterNotValidException(UDFException):
+    def __init__(self, message: str):
+        super().__init__(message)
diff --git a/udf-py/udf_api/type/__init__.py b/udf-py/udf_api/type/__init__.py
new file mode 100644
index 0000000000..b74423fa90
--- /dev/null
+++ b/udf-py/udf_api/type/__init__.py
@@ -0,0 +1,16 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
diff --git a/udf-py/udf_api/type/binary.py b/udf-py/udf_api/type/binary.py
new file mode 100644
index 0000000000..75a02d3c7b
--- /dev/null
+++ b/udf-py/udf_api/type/binary.py
@@ -0,0 +1,77 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+class Binary:
+    __values: bytes = None
+    __string_cache: str = None
+
+    @staticmethod
+    def value_of(s: str, encoding="utf-8"):
+        instance = Binary(bytes(s, encoding))
+        instance.__string_cache = s
+        return instance
+
+    def __init__(self, values: bytes = None):
+        self.__values = values
+
+    def is_null(self) -> bool:
+        return self.__values is None
+
+    def get_values(self) -> bytes:
+        return self.__values
+
+    def get_string_value(self, encoding: str = "utf-8"):
+        if self.__values is None:
+            return None
+
+        if self.__string_cache is None:
+            self.__string_cache = str(self.__values, encoding)
+        return self.__string_cache
+
+    # Get length of values. Returns -1 if values is null.
+    def __len__(self):
+        return -1 if self.__values is None else len(self.__values)
+
+    def __hash__(self):
+        return 0 if self.__values is None else self.__values.__hash__()
+
+    def __eq__(self, other):
+        return self.__values == other.__value
+
+    def __cmp__(self, other):
+        if other is None:
+            if self.__values is None:
+                return 0
+            else:
+                return 1
+
+        index = 1
+        self_length = len(self)
+        other_length = len(other)
+
+        while index < self_length and index < other_length:
+            if self.__values[index] == other.__values[index]:
+                index += 1
+                continue
+            else:
+                return self.__values[index] - other.__values[index]
+
+        return self_length - other_length
+
+    def __str__(self):
+        return self.get_string_value()
diff --git a/udf-py/udf_api/type/type.py b/udf-py/udf_api/type/type.py
new file mode 100644
index 0000000000..39fe202ea1
--- /dev/null
+++ b/udf-py/udf_api/type/type.py
@@ -0,0 +1,27 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from enum import Enum
+
+
+class Type(Enum):
+    BOOLEAN = 0
+    INT32 = 1
+    INT64 = 2
+    FLOAT = 3
+    DOUBLE = 4
+    TEXT = 5
diff --git a/udf-py/udf_api/udf.py b/udf-py/udf_api/udf.py
new file mode 100644
index 0000000000..22bbaa1e25
--- /dev/null
+++ b/udf-py/udf_api/udf.py
@@ -0,0 +1,37 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+from abc import ABCMeta
+
+from udf_api.customizer.parameter.udf_parameter_validator import UDFParameterValidator
+
+
+class UDF(metaclass=ABCMeta):
+    def validate(self, validator: UDFParameterValidator):
+        """
+        This method is mainly used to validate UDFParameters and it is executed before UDTF.beforeStart(UDFParameters,
+        UDTFConfigurations) is called.
+
+        :param validator: the validator used to validate UDFParameters
+        """
+        pass
+
+    def before_destroy(self):
+        """
+        This method is mainly used to release the resources used in the UDF.
+        """
+        pass
diff --git a/udf-py/udf_api/udtf.py b/udf-py/udf_api/udtf.py
new file mode 100644
index 0000000000..c4684660b8
--- /dev/null
+++ b/udf-py/udf_api/udtf.py
@@ -0,0 +1,104 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+from abc import abstractmethod
+
+from udf_api.access.row import Row
+from udf_api.access.row_window import RowWindow
+from udf_api.collector.point_collector import PointCollector
+from udf_api.customizer.config.udtf_configurations import UDTFConfigurations
+from udf_api.customizer.parameter.udf_parameters import UDFParameters
+from udf_api.udf import UDF
+
+
+class UDTF(UDF):
+    """
+    User-defined Time-series Generating Function (UDTF)
+
+    New UDTF classes need to inherit from this UDTF class.
+
+    Generates a variable number of output data points for a single input row or a single input window (time-based or
+    size-based).
+
+    A complete UDTF needs to override at least the following methods:
+    * beforeStart(UDFParameters, UDTFConfigurations)
+    * transform(RowWindow, PointCollector) or transform(Row, PointCollector)
+
+    In the life cycle of a UDTF instance, the calling sequence of each method is as follows:
+    1. validate(UDFParameterValidator)
+    2. beforeStart(UDFParameters, UDTFConfigurations)
+    3. transform(RowWindow, PointCollector) or transform(Row, PointCollector)
+    4. terminate(PointCollector) 5. beforeDestroy()
+
+    The query engine will instantiate an independent UDTF instance for each udf query column, and different UDTF
+    instances will not affect each other.
+    """
+
+    @abstractmethod
+    def before_start(
+        self, parameters: UDFParameters, configurations: UDTFConfigurations
+    ):
+        """
+        This method is mainly used to customize UDTF. In this method, the user can do the following things:
+        * Use UDFParameters to get the time series paths and parse key-value pair attributes entered by the user.
+        * Set the strategy to access the original data and set the output data type in UDTFConfigurations.
+        * Create resources, such as establishing external connections, opening files, etc.
+
+        This method is called after the UDTF is instantiated and before the beginning of the transformation process.
+
+        :param parameters: used to parse the input parameters entered by the user
+        :param configurations: used to set the required properties in the UDTF
+        """
+        pass
+
+    def transform_row(self, row: Row, collector: PointCollector):
+        """
+        When the user specifies RowByRowAccessStrategy to access the original data in UDTFConfigurations, this method
+        will be called to process the transformation. In a single UDF query, this method may be called multiple times.
+
+        :param row: original input data row (aligned by time)
+        :param collector: used to collect output data points
+        """
+        pass
+
+    def transform_window(self, row_window: RowWindow, collector: PointCollector):
+        """
+        When the user specifies SlidingSizeWindowAccessStrategy or SlidingTimeWindowAccessStrategy to access the
+        original data in UDTFConfigurations, this method will be called to process the transformation. In a single UDF
+        query, this method may be called multiple times.
+
+        :param row_window: original input data window (rows inside the window are aligned by time)
+        :param collector: used to collect output data points
+        """
+
+    def map_row(self, row: Row) -> object:
+        """
+        When the user specifies MappableRowByRowAccessStrategy to access the original data in UDTFConfigurations, this
+        method will be called to process the transformation. In a single UDF query, this method may be called multiple
+        times.
+
+        :param row: original input data row (aligned by time)
+        """
+        pass
+
+    def terminate(self, collector: PointCollector):
+        """
+        This method will be called once after all calls or { UDTF#transform(RowWindow, PointCollector) calls have been
+        executed. In a single UDF query, this method will and will only be called once.
+
+        :param collector: used to collect output data points
+        """
+        pass