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

albumenj pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/dubbo-python.git


The following commit(s) were added to refs/heads/main by this push:
     new 6325c2e  [Feature] [Dubbo-python] Project standardization (#41)
6325c2e is described below

commit 6325c2ed1afa3e9d59f16fe5fa7f3f5ea035b755
Author: Zaki <[email protected]>
AuthorDate: Mon Jan 20 15:08:25 2025 +0800

    [Feature] [Dubbo-python] Project standardization (#41)
    
    * Code Formatting
    
    * Add CONTRIBUTING
    
    * Complete pyproject.toml and use hatch as the packaging tool
    
    * update ci
    
    * Update script permissions
    
    * fix ci
    
    * fix ci
    
    * fix ci
    
    * fix ci
---
 .github/workflows/license-check.yaml               |   2 +-
 .github/workflows/python-lint.yaml                 |  18 --
 .github/workflows/test-suite.yaml                  |  30 +++
 .license-ignore                                    |   1 +
 CONTRIBUTING.md                                    | 104 +++++++++++
 pyproject.toml                                     | 207 ++++++++++++++-------
 requirements-dev.txt                               |  19 ++
 requirements.txt                                   |   4 -
 samples/helloworld/client.py                       |   4 +-
 samples/helloworld/server.py                       |   8 +-
 samples/registry/zookeeper/client.py               |   4 +-
 samples/serialization/json/client.py               |   4 +-
 samples/serialization/json/server.py               |   7 +-
 samples/serialization/protobuf/client.py           |   4 +-
 samples/serialization/protobuf/server.py           |   4 +-
 samples/stream/bidi_stream/client.py               |   4 +-
 samples/stream/bidi_stream/server.py               |   4 +-
 samples/stream/client_stream/client.py             |   4 +-
 samples/stream/client_stream/server.py             |   4 +-
 samples/stream/server_stream/client.py             |   8 +-
 dubbo/__version__.py => scripts/build.sh           |   9 +-
 .../remoting/aio/constants.py => scripts/check.sh  |  16 +-
 .../aio/constants.py => scripts/install-dev.sh     |  15 +-
 scripts/{check_license.sh => rat.sh}               |  19 +-
 dubbo/remoting/aio/constants.py => scripts/test.sh |  15 +-
 setup.py                                           |  64 -------
 dubbo/__version__.py => src/dubbo/__about__.py     |   0
 {dubbo => src/dubbo}/__init__.py                   |   0
 {dubbo => src/dubbo}/bootstrap.py                  |   0
 {dubbo => src/dubbo}/classes.py                    |  16 +-
 {dubbo => src/dubbo}/client.py                     |  16 +-
 {dubbo => src/dubbo}/cluster/__init__.py           |   0
 {dubbo => src/dubbo}/cluster/_interfaces.py        |   8 +-
 {dubbo => src/dubbo}/cluster/directories.py        |   7 +-
 {dubbo => src/dubbo}/cluster/failfast_cluster.py   |   2 +-
 {dubbo => src/dubbo}/cluster/loadbalances.py       |  18 +-
 {dubbo => src/dubbo}/cluster/monitor/__init__.py   |   0
 {dubbo => src/dubbo}/cluster/monitor/cpu.py        |  31 +--
 {dubbo => src/dubbo}/compression/__init__.py       |   0
 {dubbo => src/dubbo}/compression/_interfaces.py    |   0
 {dubbo => src/dubbo}/compression/bzip2s.py         |   0
 {dubbo => src/dubbo}/compression/gzips.py          |   0
 {dubbo => src/dubbo}/compression/identities.py     |   0
 {dubbo => src/dubbo}/configs.py                    |  11 +-
 {dubbo => src/dubbo}/constants/__init__.py         |   0
 {dubbo => src/dubbo}/constants/common_constants.py |   0
 {dubbo => src/dubbo}/constants/config_constants.py |   0
 {dubbo => src/dubbo}/constants/logger_constants.py |   0
 .../dubbo}/constants/registry_constants.py         |   0
 {dubbo => src/dubbo}/deliverers.py                 |   8 +-
 {dubbo => src/dubbo}/extension/__init__.py         |   3 +-
 {dubbo => src/dubbo}/extension/extension_loader.py |   7 +-
 {dubbo => src/dubbo}/extension/registries.py       |   4 +-
 {dubbo => src/dubbo}/loadbalance/__init__.py       |   0
 {dubbo => src/dubbo}/loadbalance/_interfaces.py    |  14 +-
 {dubbo => src/dubbo}/loggers.py                    |  27 +--
 {dubbo => src/dubbo}/node.py                       |   0
 {dubbo => src/dubbo}/protocol/__init__.py          |   0
 {dubbo => src/dubbo}/protocol/_interfaces.py       |   0
 {dubbo => src/dubbo}/protocol/invocation.py        |   6 +-
 {dubbo => src/dubbo}/protocol/triple/__init__.py   |   0
 .../dubbo}/protocol/triple/call/__init__.py        |   0
 .../dubbo}/protocol/triple/call/_interfaces.py     |   6 +-
 .../dubbo}/protocol/triple/call/client_call.py     |  23 +--
 .../dubbo}/protocol/triple/call/server_call.py     |  33 +---
 {dubbo => src/dubbo}/protocol/triple/coders.py     |   4 +-
 {dubbo => src/dubbo}/protocol/triple/constants.py  |   3 +-
 {dubbo => src/dubbo}/protocol/triple/exceptions.py |   0
 {dubbo => src/dubbo}/protocol/triple/invoker.py    |  41 ++--
 {dubbo => src/dubbo}/protocol/triple/metadata.py   |  16 +-
 {dubbo => src/dubbo}/protocol/triple/protocol.py   |  12 +-
 {dubbo => src/dubbo}/protocol/triple/results.py    |   0
 {dubbo => src/dubbo}/protocol/triple/status.py     |   0
 .../dubbo}/protocol/triple/stream/__init__.py      |   0
 .../dubbo}/protocol/triple/stream/_interfaces.py   |  10 +-
 .../dubbo}/protocol/triple/stream/client_stream.py |  30 +--
 .../dubbo}/protocol/triple/stream/server_stream.py |  40 ++--
 {dubbo => src/dubbo}/protocol/triple/streams.py    |   6 +-
 {dubbo => src/dubbo}/proxy/__init__.py             |   0
 {dubbo => src/dubbo}/proxy/_interfaces.py          |   0
 {dubbo => src/dubbo}/proxy/callables.py            |   4 +-
 {dubbo => src/dubbo}/proxy/handlers.py             |  10 +-
 {dubbo => src/dubbo}/registry/__init__.py          |   0
 {dubbo => src/dubbo}/registry/_interfaces.py       |   3 +-
 {dubbo => src/dubbo}/registry/protocol.py          |   4 +-
 .../dubbo}/registry/zookeeper/__init__.py          |   0
 .../dubbo}/registry/zookeeper/_interfaces.py       |   4 +-
 .../dubbo}/registry/zookeeper/kazoo_transport.py   |  16 +-
 .../dubbo}/registry/zookeeper/zk_registry.py       |  32 +---
 {dubbo => src/dubbo}/remoting/__init__.py          |   0
 {dubbo => src/dubbo}/remoting/_interfaces.py       |   0
 {dubbo => src/dubbo}/remoting/aio/__init__.py      |   0
 {dubbo => src/dubbo}/remoting/aio/_interfaces.py   |   0
 .../dubbo}/remoting/aio/aio_transporter.py         |  27 +--
 {dubbo => src/dubbo}/remoting/aio/constants.py     |   0
 {dubbo => src/dubbo}/remoting/aio/event_loop.py    |  17 +-
 {dubbo => src/dubbo}/remoting/aio/exceptions.py    |   0
 .../dubbo}/remoting/aio/http2/__init__.py          |   0
 .../dubbo}/remoting/aio/http2/controllers.py       |  32 +---
 {dubbo => src/dubbo}/remoting/aio/http2/frames.py  |   8 +-
 {dubbo => src/dubbo}/remoting/aio/http2/headers.py |  10 +-
 .../dubbo}/remoting/aio/http2/protocol.py          |  33 +---
 .../dubbo}/remoting/aio/http2/registries.py        |   9 +-
 {dubbo => src/dubbo}/remoting/aio/http2/stream.py  |  13 +-
 .../dubbo}/remoting/aio/http2/stream_handler.py    |  20 +-
 {dubbo => src/dubbo}/remoting/aio/http2/utils.py   |   8 +-
 {dubbo => src/dubbo}/serialization/__init__.py     |   0
 {dubbo => src/dubbo}/serialization/_interfaces.py  |   0
 .../dubbo}/serialization/custom_serializers.py     |   0
 .../dubbo}/serialization/direct_serializers.py     |   0
 {dubbo => src/dubbo}/server.py                     |   8 +-
 {dubbo => src/dubbo}/types.py                      |   0
 {dubbo => src/dubbo}/url.py                        |  10 +-
 {dubbo => src/dubbo}/utils.py                      |  20 +-
 tests/test_utils.py                                |  96 ----------
 115 files changed, 572 insertions(+), 796 deletions(-)

diff --git a/.github/workflows/license-check.yaml 
b/.github/workflows/license-check.yaml
index 4ed7226..abf3754 100644
--- a/.github/workflows/license-check.yaml
+++ b/.github/workflows/license-check.yaml
@@ -16,4 +16,4 @@ jobs:
           distribution: 'temurin'
           java-version: '11'
       - name: Check License Header
-        run:  bash ./scripts/check_license.sh
+        run:  "scripts/rat.sh"
diff --git a/.github/workflows/python-lint.yaml 
b/.github/workflows/python-lint.yaml
deleted file mode 100644
index 2854111..0000000
--- a/.github/workflows/python-lint.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Lint Python Code
-on: [push, pull_request]
-jobs:
-  build:
-    runs-on: ubuntu-latest
-    steps:
-      - uses: actions/checkout@v4
-      - name: Install Python
-        uses: actions/setup-python@v5
-        with:
-          python-version: "3.11"
-      - name: Install dependencies
-        run: |
-          python -m pip install --upgrade pip
-          pip install -r requirements.txt
-          pip install ruff
-      - name: Run Ruff
-        run: ruff check --output-format=github . --config=pyproject.toml
\ No newline at end of file
diff --git a/.github/workflows/test-suite.yaml 
b/.github/workflows/test-suite.yaml
new file mode 100644
index 0000000..cc2bb7c
--- /dev/null
+++ b/.github/workflows/test-suite.yaml
@@ -0,0 +1,30 @@
+name: Check and test
+on: [push, pull_request]
+
+
+jobs:
+  tests:
+    name: "Python ${{ matrix.python-version }}"
+    runs-on: "ubuntu-latest"
+
+    strategy:
+      matrix:
+        python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
+
+    steps:
+      - uses: "actions/checkout@v4"
+      - uses: "actions/setup-python@v5"
+        with:
+          python-version: "${{ matrix.python-version }}"
+
+      - name: "Install dependencies"
+        run: "scripts/install-dev.sh"
+
+      - name: "Check Code Style"
+        run: "scripts/check.sh"
+
+      - name: "Build package"
+        run: "scripts/build.sh"
+
+      - name: "Run tests and report coverage"
+        run: "scripts/test.sh"
diff --git a/.license-ignore b/.license-ignore
index 874df2c..c045e65 100644
--- a/.license-ignore
+++ b/.license-ignore
@@ -11,6 +11,7 @@ LICENSE
 NOTICE
 README.md
 requirements.txt
+requirements-dev.txt
 rat-report.txt
 
 # directories
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100755
index 0000000..457f604
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,104 @@
+# CONTRIBUTING
+
+## Contributing to Dubbo Python
+
+Dubbo Python is released under the non-restrictive Apache 2.0 licenses and 
follows a very standard Github development process, using Github tracker for 
issues and merging pull requests into main. Contributions of all form to this 
repository is acceptable, as long as it follows the prescribed community 
guidelines enumerated below.
+
+### Sign the Contributor License Agreement
+
+Before we accept a non-trivial patch or pull request (PRs), we will need you 
to sign the Contributor License Agreement. Signing the contributors' agreement 
does not grant anyone commits rights to the main repository, but it does mean 
that we can accept your contributions, and you will get an author credit if we 
do. Active contributors may get invited to join the core team that will grant 
them privileges to merge existing PRs.
+
+### Contact
+
+### Mailing list
+
+The mailing list is the recommended way of pursuing a discussion on almost 
anything related to Dubbo. Please refer to this 
[guide](https://github.com/apache/dubbo/wiki/Mailing-list-subscription-guide) 
for detailed documentation on how to subscribe.
+
+- [[email protected]](mailto:[email protected]): the 
developer mailing list where you can ask questions about an issue you may have 
encountered while working with Dubbo.
+- [[email protected]](mailto:[email protected]): the 
commit updates will get broadcasted on this mailing list. You can subscribe to 
it, should you be interested in following Dubbo's development.
+- 
[[email protected]](mailto:[email protected]):
 all the Github [issue](https://github.com/apache/dubbo/issues) updates and 
[pull request](https://github.com/apache/dubbo/pulls) updates will be sent to 
this mailing list.
+
+### Reporting issue
+
+Please follow the 
[template](https://github.com/apache/dubbo/issues/new?template=dubbo-issue-report-template.md)
 for reporting any issues.
+
+NOTE: Issues related to Dubbo Python should be submitted in the 
[Dubbo](https://github.com/apache/dubbo/issues) repository, and the **Apache 
Dubbo Component** option should be set to `Python SDK`.
+
+### Code Conventions
+
+Our code style almost fully adheres to the [**PEP 8 style 
guide**](https://peps.python.org/pep-0008/), with the following adjustments and 
new constraints:
+
+1. We have relaxed the **Maximum Line Length** limit from 79 to **120**.
+2. For **Documentation Strings**, or **comment style**, we follow the 
`reStructuredText` format.
+3. ...
+
+### Contribution flow
+
+A rough outline of an ideal contributors' workflow is as follows:
+
+- Fork the current repository
+- Create a topic branch from where to base the contribution. Mostly, it's the 
main branch.
+- Make commits of logical units.
+- Make sure the commit messages are in the proper format (see below).
+- Push changes in a topic branch to your forked repository.
+- Follow the checklist in the [pull request 
template](https://github.com/apache/dubbo-python/blob/main/.github/PULL_REQUEST_TEMPLATE.md)
+- Before sending out the pull request, please sync your forked repository with 
the remote repository to ensure that your PR is elegant, concise. Reference the 
guide below:
+
+```
+git remote add upstream [email protected]:apache/dubbo-python.git
+git fetch upstream
+git rebase upstream/master
+git checkout -b your_awesome_patch
+... add some work
+git push origin your_awesome_patch
+
+```
+
+- Submit a pull request to apache/dubbo-python and wait for the reply.
+
+Thanks for contributing!
+
+### Code style
+
+We use **ruff** as the linter and code formatter for Dubbo-Python, and 
**Mypy** as the static type checker.
+
+Therefore, when developing, you should install both tools:
+
+- ruff: [https://github.com/astral-sh/ruff](https://github.com/astral-sh/ruff)
+- Mypy: [https://github.com/python/mypy](https://github.com/python/mypy)
+
+We have already set up the configurations for ruff and Mypy in the 
`pyproject.toml` file. You only need to specify the configuration path 
(`pyproject.toml`) when using them.
+
+1. Code Formatting
+   
+    By default, ruff will look for the `pyproject.toml` file in the current 
directory and its parent directories and load its configuration.
+    
+    ```bash
+    # Default
+    ruff format
+    
+    # Specify configuration file
+    ruff format --config pyproject.toml
+    ```
+    
+2. Code Linting
+   
+    ```bash
+    # Just check
+    ruff check
+    
+    # Check and fix
+    ruff check --fix
+    ```
+    
+3. Static Type Checking
+   
+    Mypy will also automatically look for the `pyproject.toml` file and load 
its configuration.
+    
+    ```bash
+    # Default
+    mypy
+    
+    # Specify configuration file
+    mypy --config-file pyproject.toml
+    ```
\ No newline at end of file
diff --git a/pyproject.toml b/pyproject.toml
index f929a4e..f493e4c 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -14,89 +14,158 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+[build-system]
+requires = ["hatchling", "hatch-fancy-pypi-readme"]
+build-backend = "hatchling.build"
 
-## ruff settings ##
-[tool.ruff]
-# Exclude a variety of commonly ignored directories.
-exclude = [
-    ".bzr",
-    ".direnv",
-    ".eggs",
-    ".git",
-    ".git-rewrite",
-    ".hg",
-    ".ipynb_checkpoints",
-    ".mypy_cache",
-    ".nox",
-    ".pants.d",
-    ".pyenv",
-    ".pytest_cache",
-    ".pytype",
-    ".ruff_cache",
-    ".svn",
-    ".tox",
-    ".venv",
-    ".vscode",
-    "__pypackages__",
-    "_build",
-    "buck-out",
-    "build",
-    "dist",
-    "node_modules",
-    "site-packages",
-    "venv",
-    "samples/proto",
+[project]
+name="dubbo-python"
+requires-python = ">=3.9"
+authors = [
+    {name = "Apache Dubbo Community", email = "[email protected]"}
+]
+maintainers = [
+    {name = "Apache Dubbo Community", email = "[email protected]"}
+]
+description = "Python Implementation For Apache Dubbo."
+license = "Apache-2.0"
+license-files = ["LICEN[CS]E.*"]
+keywords=["dubbo", "rpc","grpc", "dubbo-python", "http2", "network"]
+classifiers=[
+    "Development Status :: 4 - Beta",
+    "Intended Audience :: Developers",
+    "License :: OSI Approved :: Apache Software License",
+    "Operating System :: OS Independent",
+    "Programming Language :: Python :: 3",
+    "Programming Language :: Python :: 3 :: Only",
+    "Programming Language :: Python :: 3.9",
+    "Programming Language :: Python :: 3.10",
+    "Programming Language :: Python :: 3.11",
+    "Framework :: AsyncIO",
+    "Topic :: Internet",
+    "Topic :: Internet :: WWW/HTTP",
+    "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
+    "Topic :: Software Development :: Libraries",
+    "Topic :: Software Development :: Libraries :: Python Modules",
+    "Topic :: System :: Networking",
 ]
 
-# Same as Black.
-line-length = 88
-indent-width = 4
+dependencies = [
+    "h2>=4.1.0",
+    "uvloop>=0.19.0; platform_system!='Windows'",
+    "psutil>=6.0.0",
+]
+dynamic = ["version", "readme"]
 
-target-version = "py38"
 
-[tool.ruff.lint]
-# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`)  codes by 
default.
-# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
-# McCabe complexity (`C901`) by default.
-select = ["E4", "E7", "E9", "F"]
-ignore = []
+[project.urls]
+Homepage = "https://cn.dubbo.apache.org";
+Documentation = "https://cn.dubbo.apache.org/en/overview/mannual/python-sdk/";
+Repository = "https://github.com/apache/dubbo-python";
+Issues = "https://github.com/apache/dubbo/issues";
 
-# Allow fix for all enabled rules (when `--fix`) is provided.
-fixable = ["ALL"]
-unfixable = []
+[project.optional-dependencies]
+zookeeper = [
+    "kazoo>=2.10.0",
+]
 
-# Allow unused variables when underscore-prefixed.
-dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
+### Hatch settings ###
+[tool.hatch.version]
+path = "src/dubbo/__about__.py"
 
-[tool.ruff.format]
-# Like Black, use double quotes for strings.
-quote-style = "double"
+[tool.hatch.build.targets.sdist]
+include = [
+    "/src",
+    "/tests",
+    "/README.md",
+]
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/dubbo"]
+
+
+[tool.hatch.metadata.hooks.fancy-pypi-readme]
+content-type = "text/markdown"
 
-# Like Black, indent with spaces, rather than tabs.
-indent-style = "space"
+[[tool.hatch.metadata.hooks.fancy-pypi-readme.fragments]]
+path = "README.md"
 
-# Like Black, respect magic trailing commas.
-skip-magic-trailing-comma = false
 
-# Like Black, automatically detect the appropriate line ending.
-line-ending = "auto"
 
-# Enable auto-formatting of code examples in docstrings. Markdown,
-# reStructuredText code/literal blocks and doctests are all supported.
+### Ruff settings ###
+
+# Top-level
+[tool.ruff]
+target-version = "py39"
+line-length = 120
+extend-exclude = ["samples/proto"]
+
+# Format
+[tool.ruff.format]
 docstring-code-format = true
 
-# Set the line length limit used when formatting code snippets in
-# docstrings.
-#
-# This only has an effect when the `docstring-code-format` setting is
-# enabled.
-docstring-code-line-length = "dynamic"
+# Lint
+[tool.ruff.lint]
+select = [
+    "E", # pycodestyle errors
+    "W", # pycodestyle warnings
+    "F", # pyflakes
+    "I", # Check for missing imports (auto-fixable)
+    "UP", # pyupgrade
+    "ASYNC", # flake8-async
+    "ISC", # Checks for implicit literal string concatenation (auto-fixable)
+    "LOG", # Checking the use of logging objects
+    "G",  # Check for logging format issues (auto-fixable)
+]
+ignore = [
+    "ISC001" # may casue conflict with ruff
+]
+
 
+[tool.ruff.lint.isort]
+combine-as-imports = true
 
-## pytest settings ##
-[tool.pytest.ini_options]
-addopts = [
-    "-ra",
-    "-p", "no:warnings"
+section-order = [
+  "future",
+  "standard-library",
+  "third-party",
+  "first-party",
+  "local-folder"
 ]
-testpaths = ["tests"]
\ No newline at end of file
+
+### Coverage settings ###
+[tool.coverage.run]
+branch = true
+relative_files = true
+include = ["src/dubbo/*"]
+
+[tool.coverage.report]
+# Skip coverage report for 100% covered files
+skip_covered = true
+exclude_also = [
+    "def __repr__",
+    "raise AssertionError",
+    "raise NotImplementedError",
+    "if __name__ == .__main__.:",
+    "@(abc\\.)?abstractmethod",
+    "@(typing(_extensions)?\\.)?overload",
+    "if (typing(_extensions)?\\.)?TYPE_CHECKING:"
+]
+
+
+### Mypy settings ###
+[tool.mypy]
+ignore_missing_imports = true
+
+[[tool.mypy.overrides]]
+module = "tests.*"
+disallow_untyped_defs = false
+check_untyped_defs = true
+
+### Pytest settings ###
+[tool.pytest]
+addopts = "-rxXs"
+testpaths = ["tests"]
+python_files = [
+    "test_*.py"
+]
\ No newline at end of file
diff --git a/requirements-dev.txt b/requirements-dev.txt
new file mode 100644
index 0000000..d43d7e5
--- /dev/null
+++ b/requirements-dev.txt
@@ -0,0 +1,19 @@
+# Here, we do not specify the dependencies required by the project in the 
requirements.txt file,
+# as they have all been moved to the pyproject.toml file.
+# In this file, we only specify the dependencies needed for the development 
environment,
+# such as testing, packaging, linting, etc.
+
+-e .[zoopkeeper]
+
+
+# Packaging
+hatch>=1.14.0
+
+
+# Formatting & Linting
+ruff>=0.9.1
+mypy>=1.14.1
+
+# Testing
+pytest>=8.3.4
+coverage[toml]>=7.6.10
\ No newline at end of file
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index 89dbdc6..0000000
--- a/requirements.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-h2>=4.1.0
-uvloop>=0.19.0
-kazoo>=2.10.0
-psutil>=6.0.0
\ No newline at end of file
diff --git a/samples/helloworld/client.py b/samples/helloworld/client.py
index be0a5f7..8881547 100644
--- a/samples/helloworld/client.py
+++ b/samples/helloworld/client.py
@@ -27,9 +27,7 @@ class UnaryServiceStub:
 
 if __name__ == "__main__":
     # Create a client
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.HelloWorld"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.HelloWorld")
     dubbo_client = dubbo.Client(reference_config)
     unary_service_stub = UnaryServiceStub(dubbo_client)
 
diff --git a/samples/helloworld/server.py b/samples/helloworld/server.py
index 3d54eeb..6ace94c 100644
--- a/samples/helloworld/server.py
+++ b/samples/helloworld/server.py
@@ -26,9 +26,7 @@ class UnaryServiceServicer:
 
 def build_service_handler():
     # build a method handler
-    method_handler = RpcMethodHandler.unary(
-        method=UnaryServiceServicer().say_hello, method_name="unary"
-    )
+    method_handler = 
RpcMethodHandler.unary(method=UnaryServiceServicer().say_hello, 
method_name="unary")
     # build a service handler
     service_handler = RpcServiceHandler(
         service_name="org.apache.dubbo.samples.HelloWorld",
@@ -40,9 +38,7 @@ def build_service_handler():
 if __name__ == "__main__":
     # build service config
     service_handler = build_service_handler()
-    service_config = ServiceConfig(
-        service_handler=service_handler, host="127.0.0.1", port=50051
-    )
+    service_config = ServiceConfig(service_handler=service_handler, 
host="127.0.0.1", port=50051)
     # start the server
     server = dubbo.Server(service_config).start()
 
diff --git a/samples/registry/zookeeper/client.py 
b/samples/registry/zookeeper/client.py
index 220f8e5..b9035d6 100644
--- a/samples/registry/zookeeper/client.py
+++ b/samples/registry/zookeeper/client.py
@@ -35,9 +35,7 @@ if __name__ == "__main__":
     registry_config = RegistryConfig.from_url("zookeeper://127.0.0.1:2181")
     bootstrap = dubbo.Dubbo(registry_config=registry_config)
 
-    reference_config = ReferenceConfig(
-        protocol="tri", service="org.apache.dubbo.samples.data.Greeter"
-    )
+    reference_config = ReferenceConfig(protocol="tri", 
service="org.apache.dubbo.samples.data.Greeter")
     dubbo_client = bootstrap.create_client(reference_config)
 
     stub = GreeterServiceStub(dubbo_client)
diff --git a/samples/serialization/json/client.py 
b/samples/serialization/json/client.py
index c7760b1..9cd13c8 100644
--- a/samples/serialization/json/client.py
+++ b/samples/serialization/json/client.py
@@ -42,9 +42,7 @@ class GreeterServiceStub:
 
 
 if __name__ == "__main__":
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.serialization.json"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.serialization.json")
     dubbo_client = dubbo.Client(reference_config)
 
     stub = GreeterServiceStub(dubbo_client)
diff --git a/samples/serialization/json/server.py 
b/samples/serialization/json/server.py
index eb1ba22..f2b7160 100644
--- a/samples/serialization/json/server.py
+++ b/samples/serialization/json/server.py
@@ -13,7 +13,6 @@
 # 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 Tuple
 
 import orjson
 
@@ -22,7 +21,7 @@ from dubbo.configs import ServiceConfig
 from dubbo.proxy.handlers import RpcMethodHandler, RpcServiceHandler
 
 
-def request_deserializer(data: bytes) -> Tuple[str, int]:
+def request_deserializer(data: bytes) -> tuple[str, int]:
     json_dict = orjson.loads(data)
     return json_dict["name"], json_dict["age"]
 
@@ -57,9 +56,7 @@ def build_service_handler():
 if __name__ == "__main__":
     # build server config
     service_handler = build_service_handler()
-    service_config = ServiceConfig(
-        service_handler=service_handler, host="127.0.0.1", port=50051
-    )
+    service_config = ServiceConfig(service_handler=service_handler, 
host="127.0.0.1", port=50051)
 
     # start the server
     server = dubbo.Server(service_config).start()
diff --git a/samples/serialization/protobuf/client.py 
b/samples/serialization/protobuf/client.py
index a936928..0f33137 100644
--- a/samples/serialization/protobuf/client.py
+++ b/samples/serialization/protobuf/client.py
@@ -31,9 +31,7 @@ class GreeterServiceStub:
 
 
 if __name__ == "__main__":
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter")
     dubbo_client = dubbo.Client(reference_config)
 
     stub = GreeterServiceStub(dubbo_client)
diff --git a/samples/serialization/protobuf/server.py 
b/samples/serialization/protobuf/server.py
index fa39a6e..7381179 100644
--- a/samples/serialization/protobuf/server.py
+++ b/samples/serialization/protobuf/server.py
@@ -44,9 +44,7 @@ def build_service_handler():
 if __name__ == "__main__":
     # build a service handler
     service_handler = build_service_handler()
-    service_config = ServiceConfig(
-        service_handler=service_handler, host="127.0.0.1", port=50051
-    )
+    service_config = ServiceConfig(service_handler=service_handler, 
host="127.0.0.1", port=50051)
 
     # start the server
     server = dubbo.Server(service_config).start()
diff --git a/samples/stream/bidi_stream/client.py 
b/samples/stream/bidi_stream/client.py
index 1d4f566..4c387dc 100644
--- a/samples/stream/bidi_stream/client.py
+++ b/samples/stream/bidi_stream/client.py
@@ -34,9 +34,7 @@ class GreeterServiceStub:
 
 if __name__ == "__main__":
     # Create a reference config
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter")
     dubbo_client = dubbo.Client(reference_config)
     stub = GreeterServiceStub(dubbo_client)
 
diff --git a/samples/stream/bidi_stream/server.py 
b/samples/stream/bidi_stream/server.py
index b65c1c0..a01246a 100644
--- a/samples/stream/bidi_stream/server.py
+++ b/samples/stream/bidi_stream/server.py
@@ -13,13 +13,13 @@
 # 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 time
+
 import dubbo
 from dubbo.configs import ServiceConfig
 from dubbo.proxy.handlers import RpcMethodHandler, RpcServiceHandler
 from samples.proto import greeter_pb2
 
-import time
-
 
 class GreeterServiceServicer:
     def bi_stream(self, stream):
diff --git a/samples/stream/client_stream/client.py 
b/samples/stream/client_stream/client.py
index 3206d76..b9c1bbe 100644
--- a/samples/stream/client_stream/client.py
+++ b/samples/stream/client_stream/client.py
@@ -31,9 +31,7 @@ class GreeterServiceStub:
 
 
 if __name__ == "__main__":
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter")
     dubbo_client = dubbo.Client(reference_config)
     stub = GreeterServiceStub(dubbo_client)
 
diff --git a/samples/stream/client_stream/server.py 
b/samples/stream/client_stream/server.py
index c473b2c..2ab0a28 100644
--- a/samples/stream/client_stream/server.py
+++ b/samples/stream/client_stream/server.py
@@ -47,9 +47,7 @@ def build_service_handler():
 if __name__ == "__main__":
     # build server config
     service_handler = build_service_handler()
-    service_config = ServiceConfig(
-        service_handler=service_handler, host="127.0.0.1", port=50051
-    )
+    service_config = ServiceConfig(service_handler=service_handler, 
host="127.0.0.1", port=50051)
     # start the server
     server = dubbo.Server(service_config).start()
 
diff --git a/samples/stream/server_stream/client.py 
b/samples/stream/server_stream/client.py
index 03fed16..383b226 100644
--- a/samples/stream/server_stream/client.py
+++ b/samples/stream/server_stream/client.py
@@ -31,15 +31,11 @@ class GreeterServiceStub:
 
 
 if __name__ == "__main__":
-    reference_config = ReferenceConfig.from_url(
-        "tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter"
-    )
+    reference_config = 
ReferenceConfig.from_url("tri://127.0.0.1:50051/org.apache.dubbo.samples.data.Greeter")
     dubbo_client = dubbo.Client(reference_config)
     stub = GreeterServiceStub(dubbo_client)
 
-    stream = stub.server_stream(
-        greeter_pb2.GreeterRequest(name="hello world from dubbo-python")
-    )
+    stream = stub.server_stream(greeter_pb2.GreeterRequest(name="hello world 
from dubbo-python"))
 
     for i in stream:
         print(f"Received response: {i.message}")
diff --git a/dubbo/__version__.py b/scripts/build.sh
old mode 100644
new mode 100755
similarity index 89%
copy from dubbo/__version__.py
copy to scripts/build.sh
index 7302839..51d538d
--- a/dubbo/__version__.py
+++ b/scripts/build.sh
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -14,4 +16,9 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__version__ = "3.0.0b1"
+
+echo "Building the project..."
+
+hatch build
+
+echo "Finished building the project."
\ No newline at end of file
diff --git a/dubbo/remoting/aio/constants.py b/scripts/check.sh
old mode 100644
new mode 100755
similarity index 70%
copy from dubbo/remoting/aio/constants.py
copy to scripts/check.sh
index 17712a8..015db37
--- a/dubbo/remoting/aio/constants.py
+++ b/scripts/check.sh
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -14,13 +16,15 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__all__ = ["STREAM_HANDLER_KEY"]
+export SOURCE_FILES="src/dubbo tests"
 
-STREAM_HANDLER_KEY = "stream-handler"
+# check code style
+echo "Checking code style..."
+ruff format $SOURCE_FILES --diff
+ruff check --output-format=github $SOURCE_FILES --config=pyproject.toml
 
-CLOSE_FUTURE_KEY = "close-future"
+# TODO:Temporarily disable mypy check, because it's too strict for now
+# mypy $SOURCE_FILES
 
-HEARTBEAT_KEY = "heartbeat"
-DEFAULT_HEARTBEAT = 6
 
-RECONNECT_TIMES = 3
+echo "Finished code style check."
diff --git a/dubbo/remoting/aio/constants.py b/scripts/install-dev.sh
old mode 100644
new mode 100755
similarity index 81%
copy from dubbo/remoting/aio/constants.py
copy to scripts/install-dev.sh
index 17712a8..9bc2377
--- a/dubbo/remoting/aio/constants.py
+++ b/scripts/install-dev.sh
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -14,13 +16,12 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__all__ = ["STREAM_HANDLER_KEY"]
-
-STREAM_HANDLER_KEY = "stream-handler"
+# Install dependencies for development
+REQUIREMENTS_DEV="requirements-dev.txt"
 
-CLOSE_FUTURE_KEY = "close-future"
+# Upgrade pip
+pip install -U pip
 
-HEARTBEAT_KEY = "heartbeat"
-DEFAULT_HEARTBEAT = 6
+# Install dependencies
+pip install -r $REQUIREMENTS_DEV
 
-RECONNECT_TIMES = 3
diff --git a/scripts/check_license.sh b/scripts/rat.sh
old mode 100644
new mode 100755
similarity index 81%
rename from scripts/check_license.sh
rename to scripts/rat.sh
index e1be00a..ee77741
--- a/scripts/check_license.sh
+++ b/scripts/rat.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
 
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
@@ -16,7 +16,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-set -e # Exit on error
+### Apache RAT license check script ###
+# This script downloads Apache RAT and runs it to check the license headers of 
the source files.
+
+set -e # Exit immediately if a command exits with a non-zero status.
 
 # Some variables
 ROOT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
@@ -54,12 +57,14 @@ if [ ! -f "${RAT_JAR}" ]; then
 
     mv "${JAR_PART}" "${RAT_JAR}"
 
+
+    # TODO: Strange phenomenon:its integrity cannot be verified, but it still 
works normally. (Ignore the check for now)
     # Check if the JAR file is valid
-    if ! unzip -tq "${RAT_JAR}" &> /dev/null; then
-        rm "${RAT_JAR}"
-        echo "Download ${RAT_JAR} failed or the file is not a valid JAR."
-        exit 1
-    fi
+#    if ! unzip -tq "${RAT_JAR}" &> /dev/null; then
+#        rm "${RAT_JAR}"
+#        echo "Download ${RAT_JAR} failed or the file is not a valid JAR."
+#        exit 1
+#    fi
 
     echo "Downloaded Apache RAT ${RAT_VERSION} successfully."
 fi
diff --git a/dubbo/remoting/aio/constants.py b/scripts/test.sh
old mode 100644
new mode 100755
similarity index 77%
copy from dubbo/remoting/aio/constants.py
copy to scripts/test.sh
index 17712a8..bded3cf
--- a/dubbo/remoting/aio/constants.py
+++ b/scripts/test.sh
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 #
 # Licensed to the Apache Software Foundation (ASF) under one or more
 # contributor license agreements.  See the NOTICE file distributed with
@@ -14,13 +16,10 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__all__ = ["STREAM_HANDLER_KEY"]
-
-STREAM_HANDLER_KEY = "stream-handler"
-
-CLOSE_FUTURE_KEY = "close-future"
 
-HEARTBEAT_KEY = "heartbeat"
-DEFAULT_HEARTBEAT = 6
+# Run tests
+coverage run -m pytest
 
-RECONNECT_TIMES = 3
+# Generate coverage report
+# TODO: shut down the coverage report for now, because the current code 
coverage is too low
+# coverage report --show-missing --skip-covered --fail-under=100
\ No newline at end of file
diff --git a/setup.py b/setup.py
deleted file mode 100644
index 7db984d..0000000
--- a/setup.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#
-# 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 setuptools import find_packages, setup
-
-# Read version from dubbo/__version__.py
-with open("dubbo/__version__.py", "r", encoding="utf-8") as f:
-    global_vars = {}
-    exec(f.read(), global_vars)
-    version = global_vars["__version__"]
-
-# Read long description from README.md
-with open("README.md", "r", encoding="utf-8") as f:
-    long_description = f.read()
-
-setup(
-    name="dubbo-python",
-    version=version,
-    license="Apache License Version 2.0",
-    description="Python Implementation For Apache Dubbo.",
-    long_description=long_description,
-    long_description_content_type="text/markdown",
-    author="Apache Dubbo Community",
-    author_email="[email protected]",
-    url="https://github.com/apache/dubbo-python";,
-    classifiers=[
-        "Development Status :: 4- Beta",
-        "Intended Audience :: Developers",
-        "License :: OSI Approved :: Apache Software License",
-        "Operating System :: OS Independent",
-        "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3 :: Only",
-        "Programming Language :: Python :: 3.11",
-        "Framework :: AsyncIO",
-        "Topic :: Internet",
-        "Topic :: Internet :: WWW/HTTP",
-        "Topic :: Internet :: WWW/HTTP :: HTTP Servers",
-        "Topic :: Software Development :: Libraries",
-        "Topic :: Software Development :: Libraries :: Python Modules",
-        "Topic :: System :: Networking",
-    ],
-    keywords=["dubbo", "rpc", "dubbo-python", "http2", "network"],
-    packages=find_packages(include=("dubbo", "dubbo.*")),
-    test_suite="tests",
-    python_requires=">=3.11",
-    install_requires=[
-        "h2>=4.1.0",
-        "uvloop>=0.19.0; platform_system!='Windows'",
-        "psutil>=6.0.0",
-    ],
-    extras_require={"zookeeper": ["kazoo>=2.10.0"]},
-)
diff --git a/dubbo/__version__.py b/src/dubbo/__about__.py
similarity index 100%
rename from dubbo/__version__.py
rename to src/dubbo/__about__.py
diff --git a/dubbo/__init__.py b/src/dubbo/__init__.py
similarity index 100%
rename from dubbo/__init__.py
rename to src/dubbo/__init__.py
diff --git a/dubbo/bootstrap.py b/src/dubbo/bootstrap.py
similarity index 100%
rename from dubbo/bootstrap.py
rename to src/dubbo/bootstrap.py
diff --git a/dubbo/classes.py b/src/dubbo/classes.py
similarity index 93%
rename from dubbo/classes.py
rename to src/dubbo/classes.py
index 0a396c8..8d87299 100644
--- a/dubbo/classes.py
+++ b/src/dubbo/classes.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 import abc
 import threading
-from typing import Callable, Optional, Tuple, Any, Union
+from typing import Any, Callable, Optional, Union
 
 from dubbo.types import DeserializingFunction, RpcType, RpcTypes, 
SerializingFunction
 
@@ -71,7 +71,7 @@ class SingletonBase:
             with cls._instance_lock:
                 # double check
                 if cls._instance is None:
-                    cls._instance = super(SingletonBase, cls).__new__(cls)
+                    cls._instance = super().__new__(cls)
         return cls._instance
 
 
@@ -92,12 +92,8 @@ class MethodDescriptor:
     def __init__(
         self,
         method_name: str,
-        arg_serialization: Tuple[
-            Optional[SerializingFunction], Optional[DeserializingFunction]
-        ],
-        return_serialization: Tuple[
-            Optional[SerializingFunction], Optional[DeserializingFunction]
-        ],
+        arg_serialization: tuple[Optional[SerializingFunction], 
Optional[DeserializingFunction]],
+        return_serialization: tuple[Optional[SerializingFunction], 
Optional[DeserializingFunction]],
         rpc_type: Union[RpcType, RpcTypes, str] = RpcTypes.UNARY.value,
         callable_method: Optional[Callable] = None,
     ):
@@ -134,9 +130,7 @@ class MethodDescriptor:
         elif isinstance(rpc_type, RpcTypes):
             rpc_type = rpc_type.value
         elif not isinstance(rpc_type, RpcType):
-            raise TypeError(
-                f"rpc_type must be of type RpcType, RpcTypes, or str, not 
{type(rpc_type)}"
-            )
+            raise TypeError(f"rpc_type must be of type RpcType, RpcTypes, or 
str, not {type(rpc_type)}")
         self._rpc_type = rpc_type
 
     def get_method(self) -> Callable:
diff --git a/dubbo/client.py b/src/dubbo/client.py
similarity index 92%
rename from dubbo/client.py
rename to src/dubbo/client.py
index d02e9ea..33e6264 100644
--- a/dubbo/client.py
+++ b/src/dubbo/client.py
@@ -27,8 +27,8 @@ from dubbo.proxy.callables import DefaultRpcCallableFactory
 from dubbo.registry.protocol import RegistryProtocol
 from dubbo.types import (
     DeserializingFunction,
-    SerializingFunction,
     RpcTypes,
+    SerializingFunction,
 )
 from dubbo.url import URL
 
@@ -61,17 +61,11 @@ class Client:
                 return
 
             # get the protocol
-            protocol = extensionLoader.get_extension(
-                Protocol, self._reference.protocol
-            )()
+            protocol = extensionLoader.get_extension(Protocol, 
self._reference.protocol)()
 
             registry_config = self._dubbo.registry_config
 
-            self._protocol = (
-                RegistryProtocol(registry_config, protocol)
-                if self._dubbo.registry_config
-                else protocol
-            )
+            self._protocol = RegistryProtocol(registry_config, protocol) if 
self._dubbo.registry_config else protocol
 
             # build url
             reference_url = self._reference.to_url()
@@ -161,9 +155,7 @@ class Client:
 
         # clone url
         url = url.copy()
-        url.parameters[common_constants.METHOD_KEY] = (
-            method_descriptor.get_method_name()
-        )
+        url.parameters[common_constants.METHOD_KEY] = 
method_descriptor.get_method_name()
         # set method descriptor
         url.attributes[common_constants.METHOD_DESCRIPTOR_KEY] = 
method_descriptor
 
diff --git a/dubbo/cluster/__init__.py b/src/dubbo/cluster/__init__.py
similarity index 100%
rename from dubbo/cluster/__init__.py
rename to src/dubbo/cluster/__init__.py
diff --git a/dubbo/cluster/_interfaces.py b/src/dubbo/cluster/_interfaces.py
similarity index 91%
rename from dubbo/cluster/_interfaces.py
rename to src/dubbo/cluster/_interfaces.py
index b8a7f64..f6c999b 100644
--- a/dubbo/cluster/_interfaces.py
+++ b/src/dubbo/cluster/_interfaces.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 import abc
-from typing import List, Optional
+from typing import Optional
 
 from dubbo.node import Node
 from dubbo.protocol import Invocation, Invoker
@@ -28,7 +28,7 @@ class Directory(Node, abc.ABC):
     """
 
     @abc.abstractmethod
-    def list(self, invocation: Invocation) -> List[Invoker]:
+    def get_list(self, invocation: Invocation) -> list[Invoker]:
         """
         List the directory.
         :param invocation: The invocation.
@@ -45,9 +45,7 @@ class LoadBalance(abc.ABC):
     """
 
     @abc.abstractmethod
-    def select(
-        self, invokers: List[Invoker], invocation: Invocation
-    ) -> Optional[Invoker]:
+    def select(self, invokers: list[Invoker], invocation: Invocation) -> 
Optional[Invoker]:
         """
         Select an invoker from the list.
         :param invokers: The invokers.
diff --git a/dubbo/cluster/directories.py b/src/dubbo/cluster/directories.py
similarity index 91%
rename from dubbo/cluster/directories.py
rename to src/dubbo/cluster/directories.py
index 6749c2e..866ce8b 100644
--- a/dubbo/cluster/directories.py
+++ b/src/dubbo/cluster/directories.py
@@ -13,7 +13,6 @@
 # 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 dubbo.cluster import Directory
 from dubbo.protocol import Invoker, Protocol
@@ -32,15 +31,15 @@ class RegistryDirectory(Directory, NotifyListener):
 
         self._url = url
 
-        self._invokers: Dict[str, Invoker] = {}
+        self._invokers: dict[str, Invoker] = {}
 
         # subscribe
         self._registry.subscribe(url, self)
 
-    def list(self, invocation) -> List[Invoker]:
+    def get_list(self, invocation) -> list[Invoker]:
         return list(self._invokers.values())
 
-    def notify(self, urls: List[URL]) -> None:
+    def notify(self, urls: list[URL]) -> None:
         old_invokers = self._invokers
         self._invokers = {}
 
diff --git a/dubbo/cluster/failfast_cluster.py 
b/src/dubbo/cluster/failfast_cluster.py
similarity index 97%
rename from dubbo/cluster/failfast_cluster.py
rename to src/dubbo/cluster/failfast_cluster.py
index d50f3df..85ed01e 100644
--- a/dubbo/cluster/failfast_cluster.py
+++ b/src/dubbo/cluster/failfast_cluster.py
@@ -40,7 +40,7 @@ class FailfastInvoker(Invoker):
 
     def invoke(self, invocation) -> Result:
         # get the invokers
-        invokers = self._directory.list(invocation)
+        invokers = self._directory.get_list(invocation)
         if not invokers:
             raise RpcError("No provider available for the service")
 
diff --git a/dubbo/cluster/loadbalances.py b/src/dubbo/cluster/loadbalances.py
similarity index 86%
rename from dubbo/cluster/loadbalances.py
rename to src/dubbo/cluster/loadbalances.py
index 94e2e54..850d227 100644
--- a/dubbo/cluster/loadbalances.py
+++ b/src/dubbo/cluster/loadbalances.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 import abc
 import random
-from typing import List, Optional
+from typing import Optional
 
 from dubbo.cluster import LoadBalance
 from dubbo.cluster.monitor.cpu import CpuMonitor
@@ -27,9 +27,7 @@ class AbstractLoadBalance(LoadBalance, abc.ABC):
     The abstract load balance.
     """
 
-    def select(
-        self, invokers: List[Invoker], invocation: Invocation
-    ) -> Optional[Invoker]:
+    def select(self, invokers: list[Invoker], invocation: Invocation) -> 
Optional[Invoker]:
         if not invokers:
             return None
 
@@ -39,9 +37,7 @@ class AbstractLoadBalance(LoadBalance, abc.ABC):
         return self.do_select(invokers, invocation)
 
     @abc.abstractmethod
-    def do_select(
-        self, invokers: List[Invoker], invocation: Invocation
-    ) -> Optional[Invoker]:
+    def do_select(self, invokers: list[Invoker], invocation: Invocation) -> 
Optional[Invoker]:
         """
         Do select an invoker from the list.
         :param invokers: The invokers.
@@ -59,9 +55,7 @@ class RandomLoadBalance(AbstractLoadBalance):
     Random load balance.
     """
 
-    def do_select(
-        self, invokers: List[Invoker], invocation: Invocation
-    ) -> Optional[Invoker]:
+    def do_select(self, invokers: list[Invoker], invocation: Invocation) -> 
Optional[Invoker]:
         randint = random.randint(0, len(invokers) - 1)
         return invokers[randint]
 
@@ -82,9 +76,7 @@ class CpuLoadBalance(AbstractLoadBalance):
         """
         self._monitor = monitor
 
-    def do_select(
-        self, invokers: List[Invoker], invocation: Invocation
-    ) -> Optional[Invoker]:
+    def do_select(self, invokers: list[Invoker], invocation: Invocation) -> 
Optional[Invoker]:
         # get the CPU usage
         cpu_usages = self._monitor.get_cpu_usage(invokers)
         # Select the caller with the lowest CPU usage, 0 means CPU usage is 
unknown.
diff --git a/dubbo/cluster/monitor/__init__.py 
b/src/dubbo/cluster/monitor/__init__.py
similarity index 100%
rename from dubbo/cluster/monitor/__init__.py
rename to src/dubbo/cluster/monitor/__init__.py
diff --git a/dubbo/cluster/monitor/cpu.py b/src/dubbo/cluster/monitor/cpu.py
similarity index 83%
rename from dubbo/cluster/monitor/cpu.py
rename to src/dubbo/cluster/monitor/cpu.py
index 33f9e5e..4df5d51 100644
--- a/dubbo/cluster/monitor/cpu.py
+++ b/src/dubbo/cluster/monitor/cpu.py
@@ -14,7 +14,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 import threading
-from typing import Dict, List
 
 from dubbo.cluster.directories import RegistryDirectory
 from dubbo.loggers import loggerFactory
@@ -47,16 +46,14 @@ class CpuMonitor(RegistryDirectory):
 
         # about CPU usage
         self._usages_lock = threading.Lock()
-        self._cpu_usages: Dict[Invoker, float] = {}
+        self._cpu_usages: dict[Invoker, float] = {}
 
         # running invokers
-        self._running_invokers: Dict[str, Invoker] = {}
+        self._running_invokers: dict[str, Invoker] = {}
 
         # thread
         self._started = False
-        self._thread: threading.Thread = threading.Thread(
-            target=self._monitor_cpu, daemon=True
-        )
+        self._thread: threading.Thread = 
threading.Thread(target=self._monitor_cpu, daemon=True)
         self._stop_event: threading.Event = threading.Event()
 
         # start the monitor
@@ -90,11 +87,7 @@ class CpuMonitor(RegistryDirectory):
         """
         while True:
             # get available invokers
-            available_invokers = {
-                url: invoker
-                for url, invoker in self._invokers.items()
-                if invoker.is_available()
-            }
+            available_invokers = {url: invoker for url, invoker in 
self._invokers.items() if invoker.is_available()}
 
             # update the running invokers
             self._running_invokers = available_invokers
@@ -114,10 +107,8 @@ class CpuMonitor(RegistryDirectory):
                         result = invoker.invoke(_cpu_invocation)
                         cpu_usage = float(result.value().decode("utf-8"))
                         self._cpu_usages[invoker] = cpu_usage
-                    except Exception as e:
-                        _LOGGER.error(
-                            f"Failed to get the CPU usage for invoker {url}: 
{str(e)}"
-                        )
+                    except Exception:
+                        _LOGGER.error("Failed to get the CPU usage for invoker 
%s: %s", url, str)
                         # remove the cpu usage
                         self._remove_cpu_usage(invoker)
 
@@ -126,7 +117,7 @@ class CpuMonitor(RegistryDirectory):
                 _LOGGER.info("The CPU monitor has been stopped.")
                 break
 
-    def get_cpu_usage(self, invokers: List[Invoker]) -> Dict[Invoker, float]:
+    def get_cpu_usage(self, invokers: list[Invoker]) -> dict[Invoker, float]:
         """
         Get the CPU usage for the invoker.
         :param invokers: The invokers.
@@ -157,9 +148,7 @@ class CpuInnerRpcHandler:
         return RpcServiceHandler(
             "org.apache.dubbo.MetricsService",
             [
-                RpcMethodHandler.unary(
-                    CpuInnerRpcHandler.get_cpu_usage, method_name="cpu"
-                ),
+                RpcMethodHandler.unary(CpuInnerRpcHandler.get_cpu_usage, 
method_name="cpu"),
             ],
         )
 
@@ -172,7 +161,5 @@ class CpuInnerRpcHandler:
         :return: The CPU usage.
         :rtype: bytes
         """
-        float_value = CpuUtils.get_total_cpu_usage(
-            interval=int(interval.decode("utf-8"))
-        )
+        float_value = 
CpuUtils.get_total_cpu_usage(interval=int(interval.decode("utf-8")))
         return str(float_value).encode("utf-8")
diff --git a/dubbo/compression/__init__.py b/src/dubbo/compression/__init__.py
similarity index 100%
rename from dubbo/compression/__init__.py
rename to src/dubbo/compression/__init__.py
diff --git a/dubbo/compression/_interfaces.py 
b/src/dubbo/compression/_interfaces.py
similarity index 100%
rename from dubbo/compression/_interfaces.py
rename to src/dubbo/compression/_interfaces.py
diff --git a/dubbo/compression/bzip2s.py b/src/dubbo/compression/bzip2s.py
similarity index 100%
rename from dubbo/compression/bzip2s.py
rename to src/dubbo/compression/bzip2s.py
diff --git a/dubbo/compression/gzips.py b/src/dubbo/compression/gzips.py
similarity index 100%
rename from dubbo/compression/gzips.py
rename to src/dubbo/compression/gzips.py
diff --git a/dubbo/compression/identities.py 
b/src/dubbo/compression/identities.py
similarity index 100%
rename from dubbo/compression/identities.py
rename to src/dubbo/compression/identities.py
diff --git a/dubbo/configs.py b/src/dubbo/configs.py
similarity index 98%
rename from dubbo/configs.py
rename to src/dubbo/configs.py
index 3c081a8..f7a85d7 100644
--- a/dubbo/configs.py
+++ b/src/dubbo/configs.py
@@ -23,7 +23,6 @@ from dubbo.constants import (
     logger_constants,
     registry_constants,
 )
-
 from dubbo.proxy.handlers import RpcServiceHandler
 from dubbo.url import URL, create_url
 from dubbo.utils import NetworkUtils
@@ -387,11 +386,7 @@ class ServiceConfig(AbstractConfig):
         super().__init__()
 
         self._service_handler = service_handler
-        self._host = (
-            host
-            or NetworkUtils.get_local_address()
-            or common_constants.LOCAL_HOST_VALUE
-        )
+        self._host = host or NetworkUtils.get_local_address() or 
common_constants.LOCAL_HOST_VALUE
         self._port = port or common_constants.DEFAULT_PORT
         self._protocol = protocol or common_constants.TRIPLE_SHORT
 
@@ -477,9 +472,7 @@ class ServiceConfig(AbstractConfig):
             scheme=self.protocol,
             host=self.host,
             port=self.port,
-            parameters={
-                common_constants.SERVICE_KEY: self.service_handler.service_name
-            },
+            parameters={common_constants.SERVICE_KEY: 
self.service_handler.service_name},
             attributes={common_constants.SERVICE_HANDLER_KEY: 
self.service_handler},
         )
 
diff --git a/dubbo/constants/__init__.py b/src/dubbo/constants/__init__.py
similarity index 100%
rename from dubbo/constants/__init__.py
rename to src/dubbo/constants/__init__.py
diff --git a/dubbo/constants/common_constants.py 
b/src/dubbo/constants/common_constants.py
similarity index 100%
rename from dubbo/constants/common_constants.py
rename to src/dubbo/constants/common_constants.py
diff --git a/dubbo/constants/config_constants.py 
b/src/dubbo/constants/config_constants.py
similarity index 100%
rename from dubbo/constants/config_constants.py
rename to src/dubbo/constants/config_constants.py
diff --git a/dubbo/constants/logger_constants.py 
b/src/dubbo/constants/logger_constants.py
similarity index 100%
rename from dubbo/constants/logger_constants.py
rename to src/dubbo/constants/logger_constants.py
diff --git a/dubbo/constants/registry_constants.py 
b/src/dubbo/constants/registry_constants.py
similarity index 100%
rename from dubbo/constants/registry_constants.py
rename to src/dubbo/constants/registry_constants.py
diff --git a/dubbo/deliverers.py b/src/dubbo/deliverers.py
similarity index 97%
rename from dubbo/deliverers.py
rename to src/dubbo/deliverers.py
index 67790ec..fa962f0 100644
--- a/dubbo/deliverers.py
+++ b/src/dubbo/deliverers.py
@@ -40,9 +40,7 @@ class DelivererStatus(enum.Enum):
     FINISHED = 3
 
     @classmethod
-    def change_allowed(
-        cls, current_status: "DelivererStatus", target_status: 
"DelivererStatus"
-    ) -> bool:
+    def change_allowed(cls, current_status: "DelivererStatus", target_status: 
"DelivererStatus") -> bool:
         """
         Check if a transition from `current_status` to `target_status` is 
allowed.
 
@@ -257,9 +255,7 @@ class MultiMessageDeliverer(MessageDeliverer):
         with self._lock:
             if DelivererStatus.change_allowed(self._status, 
DelivererStatus.CANCELLED):
                 # Set the priority to -1 -> make sure it is the first message
-                self._messages.put_nowait(
-                    (-1, exc or RuntimeError("delivery cancelled."))
-                )
+                self._messages.put_nowait((-1, exc or RuntimeError("delivery 
cancelled.")))
                 self._status = DelivererStatus.CANCELLED
 
     def get(self) -> Any:
diff --git a/dubbo/extension/__init__.py b/src/dubbo/extension/__init__.py
similarity index 86%
rename from dubbo/extension/__init__.py
rename to src/dubbo/extension/__init__.py
index 7f339ca..6af90b2 100644
--- a/dubbo/extension/__init__.py
+++ b/src/dubbo/extension/__init__.py
@@ -14,8 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from dubbo.extension.extension_loader import ExtensionError
-from dubbo.extension.extension_loader import ExtensionLoader as 
_ExtensionLoader
+from dubbo.extension.extension_loader import ExtensionError, ExtensionLoader 
as _ExtensionLoader
 
 __all__ = ["ExtensionError", "extensionLoader"]
 
diff --git a/dubbo/extension/extension_loader.py 
b/src/dubbo/extension/extension_loader.py
similarity index 93%
rename from dubbo/extension/extension_loader.py
rename to src/dubbo/extension/extension_loader.py
index 8018df3..1f9e814 100644
--- a/dubbo/extension/extension_loader.py
+++ b/src/dubbo/extension/extension_loader.py
@@ -73,9 +73,7 @@ class ExtensionLoader(SingletonBase):
         # Get the full name of the implementation
         full_name = impls.get(impl_name)
         if not full_name:
-            raise ExtensionError(
-                f"Implementation '{impl_name}' for interface 
'{interface.__name__}' is not exist."
-            )
+            raise ExtensionError(f"Implementation '{impl_name}' for interface 
'{interface.__name__}' is not exist.")
 
         try:
             # Split the full name into module and class
@@ -89,6 +87,5 @@ class ExtensionLoader(SingletonBase):
             return subclass
         except Exception as e:
             raise ExtensionError(
-                f"Failed to load extension '{impl_name}' for interface 
'{interface.__name__}'. \n"
-                f"Detail: {e}"
+                f"Failed to load extension '{impl_name}' for interface 
'{interface.__name__}'. \nDetail: {e}"
             )
diff --git a/dubbo/extension/registries.py b/src/dubbo/extension/registries.py
similarity index 98%
rename from dubbo/extension/registries.py
rename to src/dubbo/extension/registries.py
index f98974f..cf23ae7 100644
--- a/dubbo/extension/registries.py
+++ b/src/dubbo/extension/registries.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 from dataclasses import dataclass
-from typing import Any, Dict
+from typing import Any
 
 from dubbo.cluster import LoadBalance
 from dubbo.compression import Compressor, Decompressor
@@ -36,7 +36,7 @@ class ExtendedRegistry:
     """
 
     interface: Any
-    impls: Dict[str, Any]
+    impls: dict[str, Any]
 
 
 # All Extension Registries
diff --git a/dubbo/loadbalance/__init__.py b/src/dubbo/loadbalance/__init__.py
similarity index 100%
rename from dubbo/loadbalance/__init__.py
rename to src/dubbo/loadbalance/__init__.py
diff --git a/dubbo/loadbalance/_interfaces.py 
b/src/dubbo/loadbalance/_interfaces.py
similarity index 84%
rename from dubbo/loadbalance/_interfaces.py
rename to src/dubbo/loadbalance/_interfaces.py
index dfbf85d..b2d7e43 100644
--- a/dubbo/loadbalance/_interfaces.py
+++ b/src/dubbo/loadbalance/_interfaces.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import abc
-from typing import List, Optional
+from typing import Optional
 
 from dubbo.common import URL
 from dubbo.protocol import Invocation, Invoker
@@ -27,9 +27,7 @@ class LoadBalance(abc.ABC):
     """
 
     @abc.abstractmethod
-    def select(
-        self, invokers: List[Invoker], url: URL, invocation: Invocation
-    ) -> Optional[Invoker]:
+    def select(self, invokers: list[Invoker], url: URL, invocation: 
Invocation) -> Optional[Invoker]:
         """
         Select an invoker from the list.
         :param invokers: The invokers.
@@ -49,9 +47,7 @@ class AbstractLoadBalance(LoadBalance, abc.ABC):
     The abstract load balance.
     """
 
-    def select(
-        self, invokers: List[Invoker], url: URL, invocation: Invocation
-    ) -> Optional[Invoker]:
+    def select(self, invokers: list[Invoker], url: URL, invocation: 
Invocation) -> Optional[Invoker]:
         if not invokers:
             return None
 
@@ -61,9 +57,7 @@ class AbstractLoadBalance(LoadBalance, abc.ABC):
         return self.do_select(invokers, url, invocation)
 
     @abc.abstractmethod
-    def do_select(
-        self, invokers: List[Invoker], url: URL, invocation: Invocation
-    ) -> Optional[Invoker]:
+    def do_select(self, invokers: list[Invoker], url: URL, invocation: 
Invocation) -> Optional[Invoker]:
         """
         Do select an invoker from the list.
         :param invokers: The invokers.
diff --git a/dubbo/loggers.py b/src/dubbo/loggers.py
similarity index 89%
rename from dubbo/loggers.py
rename to src/dubbo/loggers.py
index 1cc4a13..6b9d91c 100644
--- a/dubbo/loggers.py
+++ b/src/dubbo/loggers.py
@@ -70,11 +70,7 @@ class ColorFormatter(logging.Formatter):
 
     def __init__(self, suffix: str = ""):
         super().__init__(self.LOG_FORMAT, self.DATE_FORMAT)
-        self.suffix = (
-            f"{self.Colors.PURPLE.value}[{suffix}]{self.Colors.END.value} "
-            if suffix
-            else ""
-        )
+        self.suffix = 
f"{self.Colors.PURPLE.value}[{suffix}]{self.Colors.END.value} " if suffix else 
""
 
     def format(self, record) -> str:
         levelname = record.levelname
@@ -129,9 +125,7 @@ class _LoggerFactory:
         with cls._logger_lock:
             # create logger if not exists
             if not cls._loggers:
-                cls._loggers[cls.DEFAULT_LOGGER_NAME] = logging.getLogger(
-                    cls.DEFAULT_LOGGER_NAME
-                )
+                cls._loggers[cls.DEFAULT_LOGGER_NAME] = 
logging.getLogger(cls.DEFAULT_LOGGER_NAME)
 
             # update all loggers
             for name, logger in cls._loggers.items():
@@ -179,14 +173,10 @@ class _LoggerFactory:
         console_handler = logging.StreamHandler()
         if not cls._config.console_config.formatter or 
cls._config.global_formatter:
             # set default color formatter
-            console_handler.setFormatter(
-                ColorFormatter(name if name != cls.DEFAULT_LOGGER_NAME else "")
-            )
+            console_handler.setFormatter(ColorFormatter(name if name != 
cls.DEFAULT_LOGGER_NAME else ""))
         else:
             console_handler.setFormatter(
-                logging.Formatter(
-                    cls._config.console_config.formatter or 
cls._config.global_formatter
-                )
+                logging.Formatter(cls._config.console_config.formatter or 
cls._config.global_formatter)
             )
 
         return console_handler
@@ -208,15 +198,10 @@ class _LoggerFactory:
         )
         if not cls._config.file_config.file_formatter or 
cls._config.global_formatter:
             # set default no color formatter
-            file_handler.setFormatter(
-                NoColorFormatter(name if name != cls.DEFAULT_LOGGER_NAME else 
"")
-            )
+            file_handler.setFormatter(NoColorFormatter(name if name != 
cls.DEFAULT_LOGGER_NAME else ""))
         else:
             file_handler.setFormatter(
-                logging.Formatter(
-                    cls._config.file_config.file_formatter
-                    or cls._config.global_formatter
-                )
+                logging.Formatter(cls._config.file_config.file_formatter or 
cls._config.global_formatter)
             )
 
         return file_handler
diff --git a/dubbo/node.py b/src/dubbo/node.py
similarity index 100%
rename from dubbo/node.py
rename to src/dubbo/node.py
diff --git a/dubbo/protocol/__init__.py b/src/dubbo/protocol/__init__.py
similarity index 100%
rename from dubbo/protocol/__init__.py
rename to src/dubbo/protocol/__init__.py
diff --git a/dubbo/protocol/_interfaces.py b/src/dubbo/protocol/_interfaces.py
similarity index 100%
rename from dubbo/protocol/_interfaces.py
rename to src/dubbo/protocol/_interfaces.py
diff --git a/dubbo/protocol/invocation.py b/src/dubbo/protocol/invocation.py
similarity index 94%
rename from dubbo/protocol/invocation.py
rename to src/dubbo/protocol/invocation.py
index 8e29800..400361d 100644
--- a/dubbo/protocol/invocation.py
+++ b/src/dubbo/protocol/invocation.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Any, Dict, Optional
+from typing import Any, Optional
 
 from ._interfaces import Invocation
 
@@ -37,8 +37,8 @@ class RpcInvocation(Invocation):
         service_name: str,
         method_name: str,
         argument: Any,
-        attachments: Optional[Dict[str, str]] = None,
-        attributes: Optional[Dict[str, Any]] = None,
+        attachments: Optional[dict[str, str]] = None,
+        attributes: Optional[dict[str, Any]] = None,
     ):
         """
         Initialize a new RpcInvocation instance.
diff --git a/dubbo/protocol/triple/__init__.py 
b/src/dubbo/protocol/triple/__init__.py
similarity index 100%
rename from dubbo/protocol/triple/__init__.py
rename to src/dubbo/protocol/triple/__init__.py
diff --git a/dubbo/protocol/triple/call/__init__.py 
b/src/dubbo/protocol/triple/call/__init__.py
similarity index 100%
rename from dubbo/protocol/triple/call/__init__.py
rename to src/dubbo/protocol/triple/call/__init__.py
diff --git a/dubbo/protocol/triple/call/_interfaces.py 
b/src/dubbo/protocol/triple/call/_interfaces.py
similarity index 96%
rename from dubbo/protocol/triple/call/_interfaces.py
rename to src/dubbo/protocol/triple/call/_interfaces.py
index 08764c8..65c84bf 100644
--- a/dubbo/protocol/triple/call/_interfaces.py
+++ b/src/dubbo/protocol/triple/call/_interfaces.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import abc
-from typing import Any, Dict
+from typing import Any
 
 from dubbo.protocol.triple.metadata import RequestMetadata
 from dubbo.protocol.triple.status import TriRpcStatus
@@ -76,7 +76,7 @@ class ClientCall(abc.ABC):
             raise NotImplementedError()
 
         @abc.abstractmethod
-        def on_close(self, status: TriRpcStatus, trailers: Dict[str, Any]) -> 
None:
+        def on_close(self, status: TriRpcStatus, trailers: dict[str, Any]) -> 
None:
             """
             Called when the call is closed.
 
@@ -104,7 +104,7 @@ class ServerCall(abc.ABC):
         raise NotImplementedError()
 
     @abc.abstractmethod
-    def complete(self, status: TriRpcStatus, attachments: Dict[str, Any]) -> 
None:
+    def complete(self, status: TriRpcStatus, attachments: dict[str, Any]) -> 
None:
         """
         Complete this call.
 
diff --git a/dubbo/protocol/triple/call/client_call.py 
b/src/dubbo/protocol/triple/call/client_call.py
similarity index 90%
rename from dubbo/protocol/triple/call/client_call.py
rename to src/dubbo/protocol/triple/call/client_call.py
index 1854efa..676826f 100644
--- a/dubbo/protocol/triple/call/client_call.py
+++ b/src/dubbo/protocol/triple/call/client_call.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Any, Dict, Optional
+from typing import Any, Optional
 
 from dubbo.compression import Compressor, Identity
 from dubbo.loggers import loggerFactory
@@ -86,17 +86,8 @@ class TripleClientCall(ClientCall, ClientStream.Listener):
 
         # send message
         try:
-            data = (
-                FunctionHelper.call_func(self._serializer.serialize, message)
-                if message
-                else b""
-            )
-            compress_flag = (
-                0
-                if self._compressor.get_message_encoding()
-                == Identity.get_message_encoding()
-                else 1
-            )
+            data = FunctionHelper.call_func(self._serializer.serialize, 
message) if message else b""
+            compress_flag = 0 if self._compressor.get_message_encoding() == 
Identity.get_message_encoding() else 1
             self._client_stream.send_message(data, compress_flag, last)
         except SerializationError as e:
             _LOGGER.error("Failed to serialize message: %s", e)
@@ -130,7 +121,7 @@ class TripleClientCall(ClientCall, ClientStream.Listener):
         :type data: bytes
         """
         if self._done:
-            _LOGGER.warning(f"Received message after call is done, data: 
{data}")
+            _LOGGER.warning("Call is done, cannot receive message")
             return
 
         try:
@@ -148,7 +139,7 @@ class TripleClientCall(ClientCall, ClientStream.Listener):
             )
             self._listener.on_close(status, {})
 
-    def on_complete(self, status: TriRpcStatus, attachments: Dict[str, Any]) 
-> None:
+    def on_complete(self, status: TriRpcStatus, attachments: dict[str, Any]) 
-> None:
         """
         Called when the call is completed.
         :param status: The status
@@ -181,7 +172,7 @@ class 
FutureToClientCallListenerAdapter(ClientCall.Listener):
     def on_message(self, message: Any) -> None:
         self._message = message
 
-    def on_close(self, status: TriRpcStatus, attachments: Dict[str, Any]) -> 
None:
+    def on_close(self, status: TriRpcStatus, attachments: dict[str, Any]) -> 
None:
         if status.code != GRpcCode.OK:
             self._future.set_exception(status.as_exception())
         else:
@@ -199,7 +190,7 @@ class 
ReadStreamToClientCallListenerAdapter(ClientCall.Listener):
     def on_message(self, message: Any) -> None:
         self._read_stream.put(message)
 
-    def on_close(self, status: TriRpcStatus, trailers: Dict[str, Any]) -> None:
+    def on_close(self, status: TriRpcStatus, trailers: dict[str, Any]) -> None:
         if status.code != GRpcCode.OK:
             self._read_stream.put_exception(status.as_exception())
         else:
diff --git a/dubbo/protocol/triple/call/server_call.py 
b/src/dubbo/protocol/triple/call/server_call.py
similarity index 89%
rename from dubbo/protocol/triple/call/server_call.py
rename to src/dubbo/protocol/triple/call/server_call.py
index 71fb52b..d46947d 100644
--- a/dubbo/protocol/triple/call/server_call.py
+++ b/src/dubbo/protocol/triple/call/server_call.py
@@ -16,7 +16,7 @@
 
 import abc
 from concurrent.futures import ThreadPoolExecutor
-from typing import Any, Callable, Dict
+from typing import Any, Callable
 
 from dubbo.classes import ReadWriteStream
 from dubbo.loggers import loggerFactory
@@ -30,8 +30,8 @@ from dubbo.protocol.triple.status import TriRpcStatus
 from dubbo.protocol.triple.stream import ServerStream
 from dubbo.protocol.triple.streams import (
     TriReadStream,
-    TriServerWriteStream,
     TriReadWriteStream,
+    TriServerWriteStream,
 )
 from dubbo.proxy.handlers import RpcMethodHandler
 from dubbo.remoting.aio.http2.headers import Http2Headers
@@ -45,7 +45,6 @@ from dubbo.serialization import (
 from dubbo.types import RpcType, RpcTypes
 from dubbo.utils import FunctionHelper
 
-
 _LOGGER = loggerFactory.get_logger()
 
 
@@ -66,28 +65,18 @@ class TripleServerCall(ServerCall, ServerStream.Listener):
         write_stream = TriServerWriteStream(self)
         read_write_stream = TriReadWriteStream(write_stream, self._read_stream)
 
-        self._method_runner: MethodRunner = MethodRunnerFactory.create(
-            method_handler, read_write_stream
-        )
+        self._method_runner: MethodRunner = 
MethodRunnerFactory.create(method_handler, read_write_stream)
 
         # get method descriptor
         method_descriptor = method_handler.method_descriptor
 
         # get arguments deserializer
         arg_deserializer = method_descriptor.get_arg_deserializer()
-        self._deserializer = (
-            CustomDeserializer(arg_deserializer)
-            if arg_deserializer
-            else DirectDeserializer()
-        )
+        self._deserializer = CustomDeserializer(arg_deserializer) if 
arg_deserializer else DirectDeserializer()
 
         # get return serializer
         return_serializer = method_descriptor.get_return_serializer()
-        self._serializer = (
-            CustomSerializer(return_serializer)
-            if return_serializer
-            else DirectSerializer()
-        )
+        self._serializer = CustomSerializer(return_serializer) if 
return_serializer else DirectSerializer()
 
         self._headers_sent = False
 
@@ -105,14 +94,12 @@ class TripleServerCall(ServerCall, ServerStream.Listener):
         # TODO support compression
         self._server_stream.send_message(serialized_data, False)
 
-    def complete(self, status: TriRpcStatus, attachments: Dict[str, Any]) -> 
None:
+    def complete(self, status: TriRpcStatus, attachments: dict[str, Any]) -> 
None:
         if not attachments.get(TripleHeaderName.CONTENT_TYPE.value):
-            attachments[TripleHeaderName.CONTENT_TYPE.value] = (
-                TripleHeaderValue.APPLICATION_GRPC_PROTO.value
-            )
+            attachments[TripleHeaderName.CONTENT_TYPE.value] = 
TripleHeaderValue.APPLICATION_GRPC_PROTO.value
         self._server_stream.complete(status, attachments)
 
-    def on_headers(self, headers: Dict[str, Any]) -> None:
+    def on_headers(self, headers: dict[str, Any]) -> None:
         # start a new thread to run the method
         self._executor.submit(self._method_runner.run)
 
@@ -224,9 +211,7 @@ class MethodRunnerFactory:
     """
 
     @staticmethod
-    def create(
-        method_handler: RpcMethodHandler, read_write_stream: ReadWriteStream
-    ) -> MethodRunner:
+    def create(method_handler: RpcMethodHandler, read_write_stream: 
ReadWriteStream) -> MethodRunner:
         """
         Create a method runner.
 
diff --git a/dubbo/protocol/triple/coders.py 
b/src/dubbo/protocol/triple/coders.py
similarity index 98%
rename from dubbo/protocol/triple/coders.py
rename to src/dubbo/protocol/triple/coders.py
index 9e73e9c..8eb67b8 100644
--- a/dubbo/protocol/triple/coders.py
+++ b/src/dubbo/protocol/triple/coders.py
@@ -94,9 +94,7 @@ class TriEncoder:
 
         # check message size
         if len(message) > DEFAULT_MAX_MESSAGE_SIZE:
-            raise RpcError(
-                f"Message too large. Allowed maximum size is 4194304 bytes, 
but got {len(message)} bytes."
-            )
+            raise RpcError(f"Message too large. Allowed maximum size is 
4194304 bytes, but got {len(message)} bytes.")
 
         # check compress_flag and compress the payload
         if compress_flag == 1:
diff --git a/dubbo/protocol/triple/constants.py 
b/src/dubbo/protocol/triple/constants.py
similarity index 98%
rename from dubbo/protocol/triple/constants.py
rename to src/dubbo/protocol/triple/constants.py
index 24db2a0..d0684a6 100644
--- a/dubbo/protocol/triple/constants.py
+++ b/src/dubbo/protocol/triple/constants.py
@@ -53,7 +53,8 @@ class GRpcCode(enum.Enum):
     # The operation was rejected because the system is not in a state required 
for the operation's execution.
     FAILED_PRECONDITION = 9
 
-    # The operation was aborted, typically due to a concurrency issue such as 
a sequencer check failure or transaction abort.
+    # The operation was aborted, typically due to a concurrency issue
+    # such as a sequencer check failure or transaction abort.
     ABORTED = 10
 
     # The operation was attempted past the valid range.
diff --git a/dubbo/protocol/triple/exceptions.py 
b/src/dubbo/protocol/triple/exceptions.py
similarity index 100%
rename from dubbo/protocol/triple/exceptions.py
rename to src/dubbo/protocol/triple/exceptions.py
diff --git a/dubbo/protocol/triple/invoker.py 
b/src/dubbo/protocol/triple/invoker.py
similarity index 86%
rename from dubbo/protocol/triple/invoker.py
rename to src/dubbo/protocol/triple/invoker.py
index 61b4a64..31a7c2d 100644
--- a/dubbo/protocol/triple/invoker.py
+++ b/src/dubbo/protocol/triple/invoker.py
@@ -25,16 +25,16 @@ from dubbo.protocol import Invoker, Result
 from dubbo.protocol.invocation import Invocation, RpcInvocation
 from dubbo.protocol.triple.call import TripleClientCall
 from dubbo.protocol.triple.call.client_call import (
-    ReadStreamToClientCallListenerAdapter,
     FutureToClientCallListenerAdapter,
+    ReadStreamToClientCallListenerAdapter,
 )
 from dubbo.protocol.triple.constants import TripleHeaderName, TripleHeaderValue
 from dubbo.protocol.triple.metadata import RequestMetadata
 from dubbo.protocol.triple.results import TriResult
 from dubbo.protocol.triple.streams import (
-    TriReadWriteStream,
     TriClientWriteStream,
     TriReadStream,
+    TriReadWriteStream,
 )
 from dubbo.remoting import Client
 from dubbo.remoting.aio.exceptions import RemotingError
@@ -48,7 +48,6 @@ from dubbo.serialization import (
 from dubbo.url import URL
 from dubbo.utils import FunctionHelper
 
-
 __all__ = ["TripleInvoker"]
 
 
@@ -62,9 +61,7 @@ class TripleInvoker(Invoker):
 
     __slots__ = ["_url", "_client", "_stream_multiplexer", "_compression"]
 
-    def __init__(
-        self, url: URL, client: Client, stream_multiplexer: 
StreamClientMultiplexHandler
-    ):
+    def __init__(self, url: URL, client: Client, stream_multiplexer: 
StreamClientMultiplexHandler):
         self._url = url
         self._client = client
         self._stream_multiplexer = stream_multiplexer
@@ -80,30 +77,20 @@ class TripleInvoker(Invoker):
         future = concurrent.futures.Future()
         result = TriResult(future)
         if not self._client.is_connected():
-            result.set_exception(
-                RemotingError("The client is not connected to the server.")
-            )
+            result.set_exception(RemotingError("The client is not connected to 
the server."))
             return result
 
         # get method descriptor
-        method_descriptor: MethodDescriptor = invocation.get_attribute(
-            common_constants.METHOD_DESCRIPTOR_KEY
-        )
+        method_descriptor: MethodDescriptor = 
invocation.get_attribute(common_constants.METHOD_DESCRIPTOR_KEY)
 
         # get arg_serializer
         arg_serializing_function = method_descriptor.get_arg_serializer()
-        arg_serializer = (
-            CustomSerializer(arg_serializing_function)
-            if arg_serializing_function
-            else DirectSerializer()
-        )
+        arg_serializer = CustomSerializer(arg_serializing_function) if 
arg_serializing_function else DirectSerializer()
 
         # get return_deserializer
         return_deserializing_function = 
method_descriptor.get_return_deserializer()
         return_deserializer = (
-            CustomDeserializer(return_deserializing_function)
-            if return_deserializing_function
-            else DirectDeserializer()
+            CustomDeserializer(return_deserializing_function) if 
return_deserializing_function else DirectDeserializer()
         )
 
         write_stream = TriClientWriteStream()
@@ -185,25 +172,19 @@ class TripleInvoker(Invoker):
         )
 
         # get compressor
-        compression = self._url.parameters.get(
-            common_constants.COMPRESSION_KEY, Identity.get_message_encoding()
-        )
+        compression = 
self._url.parameters.get(common_constants.COMPRESSION_KEY, 
Identity.get_message_encoding())
         if metadata.compressor.get_message_encoding() != compression:
             try:
-                metadata.compressor = extensionLoader.get_extension(
-                    Compressor, compression
-                )()
+                metadata.compressor = 
extensionLoader.get_extension(Compressor, compression)()
             except ExtensionError as e:
-                _LOGGER.error(f"Unsupported compression: {compression}")
+                _LOGGER.error("Unsupported compressor: %s", compression)
                 raise e
 
         # get address
         metadata.address = self._url.location
 
         # TODO add more metadata
-        metadata.attachments[TripleHeaderName.TE.value] = (
-            TripleHeaderValue.TRAILERS.value
-        )
+        metadata.attachments[TripleHeaderName.TE.value] = 
TripleHeaderValue.TRAILERS.value
 
         return metadata
 
diff --git a/dubbo/protocol/triple/metadata.py 
b/src/dubbo/protocol/triple/metadata.py
similarity index 87%
rename from dubbo/protocol/triple/metadata.py
rename to src/dubbo/protocol/triple/metadata.py
index 974277b..40692c9 100644
--- a/dubbo/protocol/triple/metadata.py
+++ b/src/dubbo/protocol/triple/metadata.py
@@ -14,7 +14,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Any, Dict, Optional
+from typing import Any, Optional
 
 from dubbo.compression import Compressor, Identity
 from dubbo.protocol.triple.constants import TripleHeaderName, TripleHeaderValue
@@ -37,7 +37,7 @@ class RequestMetadata:
         self.timeout: Optional[str] = None
         self.compressor: Compressor = Identity()
         self.method: Optional[str] = None
-        self.attachments: Dict[str, Any] = {}
+        self.attachments: dict[str, Any] = {}
 
     def to_headers(self) -> Http2Headers:
         """
@@ -56,18 +56,12 @@ class RequestMetadata:
         )
 
         if self.version != "1.0.0":
-            set_if_not_none(
-                headers, TripleHeaderName.SERVICE_VERSION.value, self.version
-            )
+            set_if_not_none(headers, TripleHeaderName.SERVICE_VERSION.value, 
self.version)
 
         set_if_not_none(headers, TripleHeaderName.GRPC_TIMEOUT.value, 
self.timeout)
         set_if_not_none(headers, TripleHeaderName.SERVICE_GROUP.value, 
self.group)
-        set_if_not_none(
-            headers, TripleHeaderName.CONSUMER_APP_NAME.value, self.application
-        )
-        set_if_not_none(
-            headers, TripleHeaderName.GRPC_ENCODING.value, self.acceptEncoding
-        )
+        set_if_not_none(headers, TripleHeaderName.CONSUMER_APP_NAME.value, 
self.application)
+        set_if_not_none(headers, TripleHeaderName.GRPC_ENCODING.value, 
self.acceptEncoding)
 
         if self.compressor.get_message_encoding() != 
Identity.get_message_encoding():
             set_if_not_none(
diff --git a/dubbo/protocol/triple/protocol.py 
b/src/dubbo/protocol/triple/protocol.py
similarity index 90%
rename from dubbo/protocol/triple/protocol.py
rename to src/dubbo/protocol/triple/protocol.py
index 01ae3af..1326507 100644
--- a/dubbo/protocol/triple/protocol.py
+++ b/src/dubbo/protocol/triple/protocol.py
@@ -18,7 +18,7 @@ import functools
 import uuid
 from collections.abc import Iterable
 from concurrent.futures import ThreadPoolExecutor
-from typing import Dict, Optional
+from typing import Optional
 
 from dubbo.constants import common_constants
 from dubbo.extension import extensionLoader
@@ -53,7 +53,7 @@ class TripleProtocol(Protocol):
         self._invokers = []
         self._server: Optional[Server] = None
 
-        self._path_resolver: Dict[str, RpcServiceHandler] = {}
+        self._path_resolver: dict[str, RpcServiceHandler] = {}
 
     def export(self, url: URL):
         """
@@ -70,13 +70,9 @@ class TripleProtocol(Protocol):
         else:
             self._path_resolver[service_handler.service_name] = service_handler
 
-        method_executor = ThreadPoolExecutor(
-            thread_name_prefix=f"dubbo_tri_method_{str(uuid.uuid4())}", 
max_workers=10
-        )
+        method_executor = 
ThreadPoolExecutor(thread_name_prefix=f"dubbo_tri_method_{str(uuid.uuid4())}", 
max_workers=10)
 
-        listener_factory = functools.partial(
-            ServerTransportListener, self._path_resolver, method_executor
-        )
+        listener_factory = functools.partial(ServerTransportListener, 
self._path_resolver, method_executor)
 
         # Create a stream handler
         stream_multiplexer = StreamServerMultiplexHandler(listener_factory)
diff --git a/dubbo/protocol/triple/results.py 
b/src/dubbo/protocol/triple/results.py
similarity index 100%
rename from dubbo/protocol/triple/results.py
rename to src/dubbo/protocol/triple/results.py
diff --git a/dubbo/protocol/triple/status.py 
b/src/dubbo/protocol/triple/status.py
similarity index 100%
rename from dubbo/protocol/triple/status.py
rename to src/dubbo/protocol/triple/status.py
diff --git a/dubbo/protocol/triple/stream/__init__.py 
b/src/dubbo/protocol/triple/stream/__init__.py
similarity index 100%
rename from dubbo/protocol/triple/stream/__init__.py
rename to src/dubbo/protocol/triple/stream/__init__.py
diff --git a/dubbo/protocol/triple/stream/_interfaces.py 
b/src/dubbo/protocol/triple/stream/_interfaces.py
similarity index 94%
rename from dubbo/protocol/triple/stream/_interfaces.py
rename to src/dubbo/protocol/triple/stream/_interfaces.py
index 369fd07..92c04e6 100644
--- a/dubbo/protocol/triple/stream/_interfaces.py
+++ b/src/dubbo/protocol/triple/stream/_interfaces.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import abc
-from typing import Any, Dict
+from typing import Any
 
 from dubbo.protocol.triple.status import TriRpcStatus
 from dubbo.remoting.aio.http2.headers import Http2Headers
@@ -96,9 +96,7 @@ class ClientStream(Stream, abc.ABC):
         """
 
         @abc.abstractmethod
-        def on_complete(
-            self, status: TriRpcStatus, attachments: Dict[str, Any]
-        ) -> None:
+        def on_complete(self, status: TriRpcStatus, attachments: dict[str, 
Any]) -> None:
             """
             Called when the stream is completed.
             :param status: The status
@@ -135,7 +133,7 @@ class ServerStream(Stream, abc.ABC):
         raise NotImplementedError()
 
     @abc.abstractmethod
-    def complete(self, status: TriRpcStatus, attachments: Dict[str, Any]) -> 
None:
+    def complete(self, status: TriRpcStatus, attachments: dict[str, Any]) -> 
None:
         """
         Complete the stream
         :param status: The status
@@ -151,7 +149,7 @@ class ServerStream(Stream, abc.ABC):
         """
 
         @abc.abstractmethod
-        def on_headers(self, headers: Dict[str, Any]) -> None:
+        def on_headers(self, headers: dict[str, Any]) -> None:
             """
             Called when headers are received.
             :param headers: The headers
diff --git a/dubbo/protocol/triple/stream/client_stream.py 
b/src/dubbo/protocol/triple/stream/client_stream.py
similarity index 91%
rename from dubbo/protocol/triple/stream/client_stream.py
rename to src/dubbo/protocol/triple/stream/client_stream.py
index 3aef898..0007acb 100644
--- a/dubbo/protocol/triple/stream/client_stream.py
+++ b/src/dubbo/protocol/triple/stream/client_stream.py
@@ -195,15 +195,11 @@ class ClientTransportListener(Http2Stream.Listener, 
TriDecoder.Listener):
 
         # get messageEncoding
         decompressor: Optional[Decompressor] = None
-        message_encoding = headers.get(
-            TripleHeaderName.GRPC_ENCODING.value, 
Identity.get_message_encoding()
-        )
+        message_encoding = headers.get(TripleHeaderName.GRPC_ENCODING.value, 
Identity.get_message_encoding())
         if message_encoding != Identity.get_message_encoding():
             try:
                 # get decompressor by messageEncoding
-                decompressor = extensionLoader.get_extension(
-                    Decompressor, message_encoding
-                )()
+                decompressor = extensionLoader.get_extension(Decompressor, 
message_encoding)()
             except ExtensionError:
                 # unsupported
                 self._rpc_status = TriRpcStatus(
@@ -224,14 +220,12 @@ class ClientTransportListener(Http2Stream.Listener, 
TriDecoder.Listener):
         if status_code:
             content_type = headers.get(TripleHeaderName.CONTENT_TYPE.value, "")
             if not 
content_type.startswith(TripleHeaderValue.APPLICATION_GRPC.value):
-                self._rpc_status = TriRpcStatus.from_http_code(
-                    status_code
-                ).with_description(f"Invalid content type: {content_type}")
+                self._rpc_status = 
TriRpcStatus.from_http_code(status_code).with_description(
+                    f"Invalid content type: {content_type}"
+                )
 
         else:
-            self._rpc_status = TriRpcStatus(
-                GRpcCode.INTERNAL, description="Missing HTTP status code"
-            )
+            self._rpc_status = TriRpcStatus(GRpcCode.INTERNAL, 
description="Missing HTTP status code")
 
     def _on_trailers_received(self, trailers: Http2Headers) -> None:
         """
@@ -270,22 +264,16 @@ class ClientTransportListener(Http2Stream.Listener, 
TriDecoder.Listener):
 
         # If the status code is not found , something is broken. Try to 
provide a rational error.
         if self._headers_received:
-            return TriRpcStatus(
-                GRpcCode.UNKNOWN, description="Missing GRPC status in response"
-            )
+            return TriRpcStatus(GRpcCode.UNKNOWN, description="Missing GRPC 
status in response")
 
         # Try to get status from headers
         status_code = int(trailers.status) if trailers.status else None
         if status_code is not None:
             status = TriRpcStatus.from_http_code(status_code)
         else:
-            status = TriRpcStatus(
-                GRpcCode.INTERNAL, description="Missing HTTP status code"
-            )
+            status = TriRpcStatus(GRpcCode.INTERNAL, description="Missing HTTP 
status code")
 
-        status.append_description(
-            "Missing GRPC status, please infer the error from the HTTP status 
code"
-        )
+        status.append_description("Missing GRPC status, please infer the error 
from the HTTP status code")
         return status
 
     def _handle_transport_error(self, transport_error: TriRpcStatus) -> None:
diff --git a/dubbo/protocol/triple/stream/server_stream.py 
b/src/dubbo/protocol/triple/stream/server_stream.py
similarity index 89%
rename from dubbo/protocol/triple/stream/server_stream.py
rename to src/dubbo/protocol/triple/stream/server_stream.py
index 8189a64..78545c9 100644
--- a/dubbo/protocol/triple/stream/server_stream.py
+++ b/src/dubbo/protocol/triple/stream/server_stream.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 import logging
 from concurrent.futures import ThreadPoolExecutor
-from typing import Any, Dict, Optional
+from typing import Any, Optional
 
 from dubbo.compression import Decompressor
 from dubbo.compression.identities import Identity
@@ -73,10 +73,8 @@ class TripleServerStream(ServerStream):
             decompressor = extensionLoader.get_extension(Decompressor, 
compression)()
             self._tri_encoder.compressor = decompressor
         except ExtensionError:
-            _LOGGER.warning(f"Unsupported compression: {compression}")
-            self.cancel_by_local(
-                TriRpcStatus(GRpcCode.INTERNAL, description="Unsupported 
compression")
-            )
+            _LOGGER.warning("Unsupported compression: %s", compression)
+            self.cancel_by_local(TriRpcStatus(GRpcCode.INTERNAL, 
description="Unsupported compression"))
 
     def send_headers(self, headers: Http2Headers) -> None:
         if not self.headers_sent:
@@ -88,7 +86,7 @@ class TripleServerStream(ServerStream):
         encoded_data = self._tri_encoder.encode(data, compress_flag)
         self._stream.send_data(encoded_data, end_stream=False)
 
-    def complete(self, status: TriRpcStatus, attachments: Dict[str, Any]) -> 
None:
+    def complete(self, status: TriRpcStatus, attachments: dict[str, Any]) -> 
None:
         trailers = Http2Headers()
         if not self.headers_sent:
             trailers.status = HttpStatus.OK.value
@@ -115,7 +113,7 @@ class TripleServerStream(ServerStream):
 
     def cancel_by_local(self, status: TriRpcStatus) -> None:
         if _LOGGER.isEnabledFor(logging.DEBUG):
-            _LOGGER.debug(f"Cancel stream:{self._stream} by local: {status}")
+            _LOGGER.debug("Cancel stream: %s, status: %s", self._stream.id, 
status)
 
         if not self._rst:
             self._rst = True
@@ -129,7 +127,7 @@ class ServerTransportListener(Http2Stream.Listener):
 
     def __init__(
         self,
-        service_handles: Dict[str, RpcServiceHandler],
+        service_handles: dict[str, RpcServiceHandler],
         method_executor: ThreadPoolExecutor,
     ):
         super().__init__()
@@ -190,11 +188,7 @@ class ServerTransportListener(Http2Stream.Listener):
         # split the path
         parts = path.split("/")
         if len(parts) != 3:
-            self._response_error(
-                TriRpcStatus(
-                    GRpcCode.UNIMPLEMENTED, description=f"Bad path format: 
{path}"
-                )
-            )
+            self._response_error(TriRpcStatus(GRpcCode.UNIMPLEMENTED, 
description=f"Bad path format: {path}"))
             return
 
         service_name, method_name = parts[1], parts[2]
@@ -219,9 +213,7 @@ class ServerTransportListener(Http2Stream.Listener):
         if message_encoding and message_encoding != 
decompressor.get_message_encoding():
             # update decompressor
             try:
-                decompressor = extensionLoader.get_extension(
-                    Decompressor, message_encoding
-                )()
+                decompressor = extensionLoader.get_extension(Decompressor, 
message_encoding)()
             except ExtensionError:
                 self._response_error(
                     TriRpcStatus(
@@ -232,21 +224,15 @@ class ServerTransportListener(Http2Stream.Listener):
                 return
 
         # create a server call
-        self._listener = TripleServerCall(
-            TripleServerStream(self._stream), handler, self._executor
-        )
+        self._listener = TripleServerCall(TripleServerStream(self._stream), 
handler, self._executor)
 
         # create a decoder
-        self._decoder = TriDecoder(
-            ServerTransportListener.ServerDecoderListener(self._listener), 
decompressor
-        )
+        self._decoder = 
TriDecoder(ServerTransportListener.ServerDecoderListener(self._listener), 
decompressor)
 
         # deliver the headers to the listener
         self._listener.on_headers(headers.to_dict())
 
-    def _get_handler(
-        self, service_name: str, method_name: str
-    ) -> Optional[RpcMethodHandler]:
+    def _get_handler(self, service_name: str, method_name: str) -> 
Optional[RpcMethodHandler]:
         """
         Get the method handler.
         :param service_name: The service name
@@ -290,9 +276,7 @@ class ServerTransportListener(Http2Stream.Listener):
         headers.status = code
         headers.add(TripleHeaderName.GRPC_STATUS.value, status.code.value)
         headers.add(TripleHeaderName.GRPC_MESSAGE.value, status.description)
-        headers.add(
-            TripleHeaderName.CONTENT_TYPE.value, 
TripleHeaderValue.TEXT_PLAIN_UTF8.value
-        )
+        headers.add(TripleHeaderName.CONTENT_TYPE.value, 
TripleHeaderValue.TEXT_PLAIN_UTF8.value)
 
         # send headers
         self._stream.send_headers(headers, end_stream=True)
diff --git a/dubbo/protocol/triple/streams.py 
b/src/dubbo/protocol/triple/streams.py
similarity index 97%
rename from dubbo/protocol/triple/streams.py
rename to src/dubbo/protocol/triple/streams.py
index 3ef0b2c..5376ec8 100644
--- a/dubbo/protocol/triple/streams.py
+++ b/src/dubbo/protocol/triple/streams.py
@@ -17,7 +17,7 @@ import queue
 import threading
 from typing import Any, Optional, Union
 
-from dubbo.classes import ReadStream, EOF, WriteStream, ReadWriteStream
+from dubbo.classes import EOF, ReadStream, ReadWriteStream, WriteStream
 from dubbo.protocol.triple.call import ClientCall, ServerCall
 from dubbo.protocol.triple.constants import GRpcCode
 from dubbo.protocol.triple.exceptions import RpcError
@@ -83,9 +83,7 @@ class TriReadStream(ReadStream):
             return EOF
 
         try:
-            data = self._storage.get(
-                timeout=max(0, timeout) if timeout is not None else None
-            )
+            data = self._storage.get(timeout=max(0, timeout) if timeout is not 
None else None)
             return data
         except queue.Empty:
             return None
diff --git a/dubbo/proxy/__init__.py b/src/dubbo/proxy/__init__.py
similarity index 100%
rename from dubbo/proxy/__init__.py
rename to src/dubbo/proxy/__init__.py
diff --git a/dubbo/proxy/_interfaces.py b/src/dubbo/proxy/_interfaces.py
similarity index 100%
rename from dubbo/proxy/_interfaces.py
rename to src/dubbo/proxy/_interfaces.py
diff --git a/dubbo/proxy/callables.py b/src/dubbo/proxy/callables.py
similarity index 94%
rename from dubbo/proxy/callables.py
rename to src/dubbo/proxy/callables.py
index 3d6fdb0..3aa2b4a 100644
--- a/dubbo/proxy/callables.py
+++ b/src/dubbo/proxy/callables.py
@@ -37,9 +37,7 @@ class MultipleRpcCallable(RpcCallable):
         self._invoker = invoker
         self._url = url
 
-        self._method_model: MethodDescriptor = url.attributes[
-            common_constants.METHOD_DESCRIPTOR_KEY
-        ]
+        self._method_model: MethodDescriptor = 
url.attributes[common_constants.METHOD_DESCRIPTOR_KEY]
 
         self._service_name = url.path
         self._method_name = self._method_model.get_method_name()
diff --git a/dubbo/proxy/handlers.py b/src/dubbo/proxy/handlers.py
similarity index 96%
rename from dubbo/proxy/handlers.py
rename to src/dubbo/proxy/handlers.py
index 78aa39b..8c89663 100644
--- a/dubbo/proxy/handlers.py
+++ b/src/dubbo/proxy/handlers.py
@@ -14,13 +14,13 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-from typing import Callable, Optional, List, Dict
+from typing import Callable, Optional
 
 from dubbo.classes import MethodDescriptor
 from dubbo.types import (
     DeserializingFunction,
-    SerializingFunction,
     RpcTypes,
+    SerializingFunction,
 )
 
 __all__ = ["RpcMethodHandler", "RpcServiceHandler"]
@@ -182,7 +182,7 @@ class RpcServiceHandler:
 
     __slots__ = ["_service_name", "_method_handlers"]
 
-    def __init__(self, service_name: str, method_handlers: 
List[RpcMethodHandler]):
+    def __init__(self, service_name: str, method_handlers: 
list[RpcMethodHandler]):
         """
         Initialize the RpcServiceHandler
         :param service_name: the name of the service.
@@ -191,7 +191,7 @@ class RpcServiceHandler:
         :type method_handlers: List[RpcMethodHandler]
         """
         self._service_name = service_name
-        self._method_handlers: Dict[str, RpcMethodHandler] = {}
+        self._method_handlers: dict[str, RpcMethodHandler] = {}
 
         for method_handler in method_handlers:
             method_name = method_handler.method_descriptor.get_method_name()
@@ -207,7 +207,7 @@ class RpcServiceHandler:
         return self._service_name
 
     @property
-    def method_handlers(self) -> Dict[str, RpcMethodHandler]:
+    def method_handlers(self) -> dict[str, RpcMethodHandler]:
         """
         Get the method handlers
         :return: the method handlers
diff --git a/dubbo/registry/__init__.py b/src/dubbo/registry/__init__.py
similarity index 100%
rename from dubbo/registry/__init__.py
rename to src/dubbo/registry/__init__.py
diff --git a/dubbo/registry/_interfaces.py b/src/dubbo/registry/_interfaces.py
similarity index 97%
rename from dubbo/registry/_interfaces.py
rename to src/dubbo/registry/_interfaces.py
index 078589c..d41c496 100644
--- a/dubbo/registry/_interfaces.py
+++ b/src/dubbo/registry/_interfaces.py
@@ -15,7 +15,6 @@
 # limitations under the License.
 
 import abc
-from typing import List
 
 from dubbo.node import Node
 from dubbo.url import URL
@@ -29,7 +28,7 @@ class NotifyListener(abc.ABC):
     """
 
     @abc.abstractmethod
-    def notify(self, urls: List[URL]) -> None:
+    def notify(self, urls: list[URL]) -> None:
         """
         Notify the listener.
 
diff --git a/dubbo/registry/protocol.py b/src/dubbo/registry/protocol.py
similarity index 97%
rename from dubbo/registry/protocol.py
rename to src/dubbo/registry/protocol.py
index 52afad5..273f4af 100644
--- a/dubbo/registry/protocol.py
+++ b/src/dubbo/registry/protocol.py
@@ -36,9 +36,7 @@ class RegistryProtocol(Protocol):
         self._config = config
         self._protocol = protocol
 
-        self._factory: RegistryFactory = extensionLoader.get_extension(
-            RegistryFactory, self._config.protocol
-        )()
+        self._factory: RegistryFactory = 
extensionLoader.get_extension(RegistryFactory, self._config.protocol)()
 
     def export(self, url: URL):
         # get the server registry
diff --git a/dubbo/registry/zookeeper/__init__.py 
b/src/dubbo/registry/zookeeper/__init__.py
similarity index 100%
rename from dubbo/registry/zookeeper/__init__.py
rename to src/dubbo/registry/zookeeper/__init__.py
diff --git a/dubbo/registry/zookeeper/_interfaces.py 
b/src/dubbo/registry/zookeeper/_interfaces.py
similarity index 98%
rename from dubbo/registry/zookeeper/_interfaces.py
rename to src/dubbo/registry/zookeeper/_interfaces.py
index f7e715b..c104bd2 100644
--- a/dubbo/registry/zookeeper/_interfaces.py
+++ b/src/dubbo/registry/zookeeper/_interfaces.py
@@ -62,9 +62,7 @@ class DataListener(abc.ABC):
         NONE = "NONE"
 
     @abc.abstractmethod
-    def data_changed(
-        self, path: str, data: bytes, event_type: "DataListener.EventType"
-    ) -> None:
+    def data_changed(self, path: str, data: bytes, event_type: 
"DataListener.EventType") -> None:
         """
         Notify when data changed.
 
diff --git a/dubbo/registry/zookeeper/kazoo_transport.py 
b/src/dubbo/registry/zookeeper/kazoo_transport.py
similarity index 96%
rename from dubbo/registry/zookeeper/kazoo_transport.py
rename to src/dubbo/registry/zookeeper/kazoo_transport.py
index f62b4ac..be34fc3 100644
--- a/dubbo/registry/zookeeper/kazoo_transport.py
+++ b/src/dubbo/registry/zookeeper/kazoo_transport.py
@@ -16,7 +16,7 @@
 
 import abc
 import threading
-from typing import Dict, List, Union
+from typing import Union
 
 from kazoo.client import KazooClient
 from kazoo.protocol.states import EventType, KazooState, WatchedEvent, 
ZnodeStat
@@ -108,8 +108,8 @@ class AbstractListenerAdapterFactory(abc.ABC):
         """
         self._client = client
         self._lock = threading.Lock()
-        self._adapters: Dict[str, AbstractListenerAdapter] = {}
-        self._listener_to_path: Dict[LISTENER_TYPE, str] = {}
+        self._adapters: dict[str, AbstractListenerAdapter] = {}
+        self._listener_to_path: dict[LISTENER_TYPE, str] = {}
 
     def create(self, path: str, listener) -> None:
         """
@@ -286,7 +286,7 @@ class ChildrenListenerAdapter(AbstractListenerAdapter):
         super().__init__(listener)
         self._path = path
 
-    def __call__(self, children: List[str]):
+    def __call__(self, children: list[str]):
         """
         Handle children changes and notify the listener.
 
@@ -310,9 +310,7 @@ class 
DataListenerAdapterFactory(AbstractListenerAdapterFactory):
 
 
 class ChildrenListenerAdapterFactory(AbstractListenerAdapterFactory):
-    def do_create(
-        self, path: str, listener: ChildrenListener
-    ) -> AbstractListenerAdapter:
+    def do_create(self, path: str, listener: ChildrenListener) -> 
AbstractListenerAdapter:
         children_adapter = ChildrenListenerAdapter(path, listener)
         self._client.ChildrenWatch(path, children_adapter)
         return children_adapter
@@ -330,7 +328,7 @@ class KazooZookeeperClient(ZookeeperClient):
 
         # state listener dict
         self._state_lock = threading.Lock()
-        self._state_listeners: Dict[StateListener, StateListenerAdapter] = {}
+        self._state_listeners: dict[StateListener, StateListenerAdapter] = {}
 
         self._data_adapter_factory = DataListenerAdapterFactory(self._client)
 
@@ -401,7 +399,7 @@ class KazooZookeeperTransport(ZookeeperTransport):
     def __init__(self):
         self._lock = threading.Lock()
         # key: location, value: KazooZookeeperClient
-        self._zk_client_dict: Dict[str, KazooZookeeperClient] = {}
+        self._zk_client_dict: dict[str, KazooZookeeperClient] = {}
 
     def connect(self, url: URL) -> ZookeeperClient:
         with self._lock:
diff --git a/dubbo/registry/zookeeper/zk_registry.py 
b/src/dubbo/registry/zookeeper/zk_registry.py
similarity index 86%
rename from dubbo/registry/zookeeper/zk_registry.py
rename to src/dubbo/registry/zookeeper/zk_registry.py
index 9908e7b..ba46e31 100644
--- a/dubbo/registry/zookeeper/zk_registry.py
+++ b/src/dubbo/registry/zookeeper/zk_registry.py
@@ -13,7 +13,6 @@
 # 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 dubbo.constants import common_constants, registry_constants
 from dubbo.loggers import loggerFactory
@@ -41,7 +40,7 @@ class _DefaultChildrenListener(ChildrenListener):
     def __init__(self, listener: NotifyListener):
         self._listener = listener
 
-    def children_changed(self, path: str, children: List[str]) -> None:
+    def children_changed(self, path: str, children: list[str]) -> None:
         urls = []
         for child in children:
             url = create_url(child, encoded=True)
@@ -140,12 +139,10 @@ class ZookeeperRegistry(Registry):
         :return: The category path.
         :rtype: str
         """
-        category = url.parameters.get(
-            registry_constants.CATEGORY_KEY, 
registry_constants.PROVIDERS_CATEGORY
-        )
+        category = url.parameters.get(registry_constants.CATEGORY_KEY, 
registry_constants.PROVIDERS_CATEGORY)
         return self.get_service_path(url) + common_constants.PATH_SEPARATOR + 
category
 
-    def get_categories_path(self, url: URL) -> List[str]:
+    def get_categories_path(self, url: URL) -> list[str]:
         """
         Get the categories' path.
         :param url: The URL.
@@ -154,26 +151,17 @@ class ZookeeperRegistry(Registry):
         :rtype: List[str]
         """
         # get the categories
-        if common_constants.ANY_VALUE == url.parameters.get(
-            registry_constants.CATEGORY_KEY
-        ):
+        if common_constants.ANY_VALUE == 
url.parameters.get(registry_constants.CATEGORY_KEY):
             categories = [
                 registry_constants.PROVIDERS_CATEGORY,
                 registry_constants.CONSUMERS_CATEGORY,
             ]
         else:
-            parameter = url.parameters.get(
-                registry_constants.CATEGORY_KEY, 
registry_constants.PROVIDERS_CATEGORY
-            )
-            categories = [
-                s.strip() for s in 
parameter.split(common_constants.COMMA_SEPARATOR)
-            ]
+            parameter = url.parameters.get(registry_constants.CATEGORY_KEY, 
registry_constants.PROVIDERS_CATEGORY)
+            categories = [s.strip() for s in 
parameter.split(common_constants.COMMA_SEPARATOR)]
 
         # get paths
-        return [
-            self.get_service_path(url) + common_constants.PATH_SEPARATOR + 
category
-            for category in categories
-        ]
+        return [self.get_service_path(url) + common_constants.PATH_SEPARATOR + 
category for category in categories]
 
     def to_url_path(self, url: URL) -> str:
         """
@@ -184,11 +172,7 @@ class ZookeeperRegistry(Registry):
         :rtype: str
         """
         # return the path
-        return (
-            self.get_category_path(url)
-            + common_constants.PATH_SEPARATOR
-            + url.to_str(encode=True)
-        )
+        return self.get_category_path(url) + common_constants.PATH_SEPARATOR + 
url.to_str(encode=True)
 
     def get_url(self) -> URL:
         return self._url
diff --git a/dubbo/remoting/__init__.py b/src/dubbo/remoting/__init__.py
similarity index 100%
rename from dubbo/remoting/__init__.py
rename to src/dubbo/remoting/__init__.py
diff --git a/dubbo/remoting/_interfaces.py b/src/dubbo/remoting/_interfaces.py
similarity index 100%
rename from dubbo/remoting/_interfaces.py
rename to src/dubbo/remoting/_interfaces.py
diff --git a/dubbo/remoting/aio/__init__.py b/src/dubbo/remoting/aio/__init__.py
similarity index 100%
rename from dubbo/remoting/aio/__init__.py
rename to src/dubbo/remoting/aio/__init__.py
diff --git a/dubbo/remoting/aio/_interfaces.py 
b/src/dubbo/remoting/aio/_interfaces.py
similarity index 100%
rename from dubbo/remoting/aio/_interfaces.py
rename to src/dubbo/remoting/aio/_interfaces.py
diff --git a/dubbo/remoting/aio/aio_transporter.py 
b/src/dubbo/remoting/aio/aio_transporter.py
similarity index 91%
rename from dubbo/remoting/aio/aio_transporter.py
rename to src/dubbo/remoting/aio/aio_transporter.py
index d650f6c..a47087b 100644
--- a/dubbo/remoting/aio/aio_transporter.py
+++ b/src/dubbo/remoting/aio/aio_transporter.py
@@ -22,8 +22,7 @@ from typing import Union
 from dubbo.constants import common_constants
 from dubbo.loggers import loggerFactory
 from dubbo.remoting._interfaces import Client, Server, Transporter
-from dubbo.remoting.aio import ConnectionStateListener
-from dubbo.remoting.aio import constants as aio_constants
+from dubbo.remoting.aio import ConnectionStateListener, constants as 
aio_constants
 from dubbo.remoting.aio.event_loop import EventLoop
 from dubbo.remoting.aio.exceptions import RemotingError
 from dubbo.url import URL
@@ -99,9 +98,7 @@ class AioClient(Client, ConnectionStateListener):
                 self._event_loop.start()
 
             future = concurrent.futures.Future()
-            asyncio.run_coroutine_threadsafe(
-                self._do_connect(future), self._event_loop.loop
-            )
+            asyncio.run_coroutine_threadsafe(self._do_connect(future), 
self._event_loop.loop)
 
             try:
                 self._protocol = future.result(timeout=3)
@@ -111,22 +108,16 @@ class AioClient(Client, ConnectionStateListener):
                     self._url.port,
                 )
             except Exception:
-                raise RemotingError(
-                    f"Failed to connect to the server. host: {self._url.host}, 
port: {self._url.port}"
-                )
+                raise RemotingError(f"Failed to connect to the server. host: 
{self._url.host}, port: {self._url.port}")
 
-    async def _do_connect(
-        self, future: Union[concurrent.futures.Future, asyncio.Future]
-    ):
+    async def _do_connect(self, future: Union[concurrent.futures.Future, 
asyncio.Future]):
         """
         Connect to the server.
         """
         running_loop = asyncio.get_running_loop()
         # Create the connection.
         _, protocol = await running_loop.create_connection(
-            lambda: self._url.attributes[common_constants.PROTOCOL_KEY](
-                self._url, self
-            ),
+            lambda: 
self._url.attributes[common_constants.PROTOCOL_KEY](self._url, self),
             self._url.host,
             self._url.port,
         )
@@ -232,9 +223,7 @@ class AioServer(Server):
             try:
                 running_loop = asyncio.get_running_loop()
                 server = await running_loop.create_server(
-                    lambda: 
self._url.attributes[common_constants.PROTOCOL_KEY](
-                        self._url
-                    ),
+                    lambda: 
self._url.attributes[common_constants.PROTOCOL_KEY](self._url),
                     self._url.host,
                     self._url.port,
                 )
@@ -248,9 +237,7 @@ class AioServer(Server):
 
         # Run the server logic in the event loop.
         future = concurrent.futures.Future()
-        asyncio.run_coroutine_threadsafe(
-            _inner_operation(future), self._event_loop.loop
-        )
+        asyncio.run_coroutine_threadsafe(_inner_operation(future), 
self._event_loop.loop)
 
         try:
             exc = future.exception()
diff --git a/dubbo/remoting/aio/constants.py 
b/src/dubbo/remoting/aio/constants.py
similarity index 100%
rename from dubbo/remoting/aio/constants.py
rename to src/dubbo/remoting/aio/constants.py
diff --git a/dubbo/remoting/aio/event_loop.py 
b/src/dubbo/remoting/aio/event_loop.py
similarity index 91%
rename from dubbo/remoting/aio/event_loop.py
rename to src/dubbo/remoting/aio/event_loop.py
index f2d38b7..f0140a9 100644
--- a/dubbo/remoting/aio/event_loop.py
+++ b/src/dubbo/remoting/aio/event_loop.py
@@ -34,9 +34,7 @@ def _try_use_uvloop() -> None:
     # Check if the operating system.
     if os.name == "nt":
         # Windows is not supported.
-        _LOGGER.warning(
-            "Unable to use uvloop, because it is not supported on your 
operating system."
-        )
+        _LOGGER.warning("Unable to use uvloop, because it is not supported on 
your operating system.")
         return
 
     # Try import uvloop.
@@ -45,8 +43,7 @@ def _try_use_uvloop() -> None:
     except ImportError:
         # uvloop is not available.
         _LOGGER.warning(
-            "Unable to use uvloop, because it is not installed. "
-            "You can install it by running `pip install uvloop`."
+            "Unable to use uvloop, because it is not installed. You can 
install it by running `pip install uvloop`."
         )
         return
 
@@ -65,9 +62,7 @@ class EventLoop:
         # The event loop to run the asynchronous function.
         self._loop = asyncio.new_event_loop()
         # The thread to run the event loop.
-        self._thread: Optional[threading.Thread] = (
-            None if in_other_tread else threading.current_thread()
-        )
+        self._thread: Optional[threading.Thread] = None if in_other_tread else 
threading.current_thread()
 
         self._started = False
         self._stopped = False
@@ -171,11 +166,7 @@ class EventLoop:
         Real stop the asyncio event loop.
         """
         # Cancel all tasks
-        tasks = [
-            task
-            for task in asyncio.all_tasks(self._loop)
-            if task is not asyncio.current_task()
-        ]
+        tasks = [task for task in asyncio.all_tasks(self._loop) if task is not 
asyncio.current_task()]
         for task in tasks:
             task.cancel()
         await asyncio.gather(*tasks, return_exceptions=True)
diff --git a/dubbo/remoting/aio/exceptions.py 
b/src/dubbo/remoting/aio/exceptions.py
similarity index 100%
rename from dubbo/remoting/aio/exceptions.py
rename to src/dubbo/remoting/aio/exceptions.py
diff --git a/dubbo/remoting/aio/http2/__init__.py 
b/src/dubbo/remoting/aio/http2/__init__.py
similarity index 100%
rename from dubbo/remoting/aio/http2/__init__.py
rename to src/dubbo/remoting/aio/http2/__init__.py
diff --git a/dubbo/remoting/aio/http2/controllers.py 
b/src/dubbo/remoting/aio/http2/controllers.py
similarity index 93%
rename from dubbo/remoting/aio/http2/controllers.py
rename to src/dubbo/remoting/aio/http2/controllers.py
index acd2440..04ab366 100644
--- a/dubbo/remoting/aio/http2/controllers.py
+++ b/src/dubbo/remoting/aio/http2/controllers.py
@@ -19,7 +19,7 @@ import asyncio
 import threading
 from concurrent.futures import ThreadPoolExecutor
 from dataclasses import dataclass
-from typing import Dict, Optional, Set
+from typing import Optional
 
 from h2.connection import H2Connection
 
@@ -84,20 +84,18 @@ class RemoteFlowController(Controller):
         self._h2_connection = h2_connection
         self._transport = transport
 
-        self._stream_dict: Dict[int, RemoteFlowController.Item] = {}
+        self._stream_dict: dict[int, RemoteFlowController.Item] = {}
 
         self._outbound_queue: asyncio.Queue[int] = asyncio.Queue()
-        self._flow_controls: Set[int] = set()
+        self._flow_controls: set[int] = set()
 
         # Start the controller
         self.start()
 
-    def write_data(
-        self, stream: Http2Stream, frame: DataFrame, event: 
Optional[asyncio.Event]
-    ) -> None:
+    def write_data(self, stream: Http2Stream, frame: DataFrame, event: 
Optional[asyncio.Event]) -> None:
         if stream.local_closed:
             EventHelper.set(event)
-            _LOGGER.warning(f"Stream {stream.id} is closed.")
+            _LOGGER.warning("Stream %s is closed locally, ignoring the data 
frame.", stream.id)
             return
 
         item = self._stream_dict.get(stream.id)
@@ -110,9 +108,7 @@ class RemoteFlowController(Controller):
             item.event = event
         else:
             # Create a new stream item
-            item = RemoteFlowController.Item(
-                stream, bytearray(frame.data), frame.end_stream, event
-            )
+            item = RemoteFlowController.Item(stream, bytearray(frame.data), 
frame.end_stream, event)
             self._stream_dict[stream.id] = item
             self._outbound_queue.put_nowait(stream.id)
 
@@ -154,14 +150,8 @@ class RemoteFlowController(Controller):
                 # Split the data into chunks and send them out
                 for x in range(0, len(data_to_send), max_size):
                     chunk = data_to_send[x : x + max_size]
-                    end_stream_flag = (
-                        item.end_stream
-                        and not data_to_buffer
-                        and (x + max_size >= len(data_to_send))
-                    )
-                    self._h2_connection.send_data(
-                        stream.id, chunk, end_stream=end_stream_flag
-                    )
+                    end_stream_flag = item.end_stream and not data_to_buffer 
and (x + max_size >= len(data_to_send))
+                    self._h2_connection.send_data(stream.id, chunk, 
end_stream=end_stream_flag)
 
                 outbound_data = self._h2_connection.data_to_send()
                 if not outbound_data:
@@ -277,7 +267,7 @@ class FrameInboundController(Controller):
         elif frame_type == Http2FrameType.RST_STREAM:
             listener.cancel_by_remote(frame.error_code)
         else:
-            _LOGGER.warning(f"unprocessed frame type: {frame.frame_type}")
+            _LOGGER.warning("unprocessed frame type: %s", frame_type)
 
         # acknowledge the frame
         self.ack_frame(frame)
@@ -291,9 +281,7 @@ class FrameOutboundController(Controller):
 
     LAST_DATA_FRAME = DataFrame(-1, b"", 0)
 
-    def __init__(
-        self, stream: DefaultHttp2Stream, loop: asyncio.AbstractEventLoop, 
protocol
-    ):
+    def __init__(self, stream: DefaultHttp2Stream, loop: 
asyncio.AbstractEventLoop, protocol):
         from dubbo.remoting.aio.http2.protocol import AbstractHttp2Protocol
 
         super().__init__(loop)
diff --git a/dubbo/remoting/aio/http2/frames.py 
b/src/dubbo/remoting/aio/http2/frames.py
similarity index 96%
rename from dubbo/remoting/aio/http2/frames.py
rename to src/dubbo/remoting/aio/http2/frames.py
index b216b4d..7576472 100644
--- a/dubbo/remoting/aio/http2/frames.py
+++ b/src/dubbo/remoting/aio/http2/frames.py
@@ -86,7 +86,9 @@ class HeadersFrame(Http2Frame):
         self.headers = headers
 
     def __repr__(self) -> str:
-        return f"<HeadersFrame stream_id={self.stream_id} 
headers={self.headers.to_list()} end_stream={self.end_stream}>"
+        return (
+            f"<HeadersFrame stream_id={self.stream_id} 
headers={self.headers.to_list()} end_stream={self.end_stream}>"
+        )
 
 
 class DataFrame(Http2Frame):
@@ -170,9 +172,7 @@ class RstStreamFrame(Http2Frame):
         self.error_code = error_code
 
     def __repr__(self) -> str:
-        return (
-            f"<RstStreamFrame stream_id={self.stream_id} 
error_code={self.error_code}>"
-        )
+        return f"<RstStreamFrame stream_id={self.stream_id} 
error_code={self.error_code}>"
 
 
 class PingFrame(Http2Frame):
diff --git a/dubbo/remoting/aio/http2/headers.py 
b/src/dubbo/remoting/aio/http2/headers.py
similarity index 95%
rename from dubbo/remoting/aio/http2/headers.py
rename to src/dubbo/remoting/aio/http2/headers.py
index 47311be..1f715cc 100644
--- a/dubbo/remoting/aio/http2/headers.py
+++ b/src/dubbo/remoting/aio/http2/headers.py
@@ -16,7 +16,7 @@
 
 import enum
 from collections import OrderedDict
-from typing import List, Optional, Tuple, Union
+from typing import Optional, Union
 
 
 class PseudoHeaderName(enum.Enum):
@@ -34,7 +34,7 @@ class PseudoHeaderName(enum.Enum):
     STATUS = ":status"
 
     @classmethod
-    def to_list(cls) -> List[str]:
+    def to_list(cls) -> list[str]:
         """
         Get all pseudo-header names.
         Returns:
@@ -124,7 +124,7 @@ class Http2Headers:
     def status(self, value: str) -> None:
         self.add(PseudoHeaderName.STATUS.value, value)
 
-    def to_list(self) -> List[Tuple[str, str]]:
+    def to_list(self) -> list[tuple[str, str]]:
         """
         Convert the headers to a list. The list contains all non-None headers.
         :return: The headers list.
@@ -154,7 +154,7 @@ class Http2Headers:
         return f"<Http2Headers {self.to_list()}>"
 
     @classmethod
-    def from_list(cls, headers: List[Tuple[str, str]]) -> "Http2Headers":
+    def from_list(cls, headers: list[tuple[str, str]]) -> "Http2Headers":
         """
         Create an Http2Headers object from a list.
         :param headers: The headers list.
@@ -163,5 +163,5 @@ class Http2Headers:
         :rtype: Http2Headers
         """
         http2_headers = cls()
-        http2_headers._headers = dict(headers)
+        http2_headers._headers = dict(headers)  # type: ignore
         return http2_headers
diff --git a/dubbo/remoting/aio/http2/protocol.py 
b/src/dubbo/remoting/aio/http2/protocol.py
similarity index 92%
rename from dubbo/remoting/aio/http2/protocol.py
rename to src/dubbo/remoting/aio/http2/protocol.py
index 89ff26f..a11f671 100644
--- a/dubbo/remoting/aio/http2/protocol.py
+++ b/src/dubbo/remoting/aio/http2/protocol.py
@@ -23,8 +23,7 @@ from h2.config import H2Configuration
 from h2.connection import H2Connection
 
 from dubbo.loggers import loggerFactory
-from dubbo.remoting.aio import ConnectionStateListener, 
EmptyConnectionStateListener
-from dubbo.remoting.aio import constants as h2_constants
+from dubbo.remoting.aio import ConnectionStateListener, 
EmptyConnectionStateListener, constants as h2_constants
 from dubbo.remoting.aio.exceptions import ProtocolError
 from dubbo.remoting.aio.http2.controllers import RemoteFlowController
 from dubbo.remoting.aio.http2.frames import (
@@ -123,9 +122,7 @@ class AbstractHttp2Protocol(asyncio.Protocol, abc.ABC):
         self._flush()
 
         # Create and start the follow controller
-        self._flow_controller = RemoteFlowController(
-            self._h2_connection, self._transport, self._loop
-        )
+        self._flow_controller = RemoteFlowController(self._h2_connection, 
self._transport, self._loop)
 
         # Initialize the stream handler
         self._stream_handler.do_init(self._loop, self)
@@ -165,7 +162,7 @@ class AbstractHttp2Protocol(asyncio.Protocol, abc.ABC):
         elif frame_type == Http2FrameType.RST_STREAM:
             self._send_reset_frame(frame.stream_id, frame.error_code.value, 
event)
         else:
-            _LOGGER.warning(f"Unhandled frame: {frame}")
+            _LOGGER.warning("Unhandled frame: %s", frame)
 
     def _send_headers_frame(
         self,
@@ -185,15 +182,11 @@ class AbstractHttp2Protocol(asyncio.Protocol, abc.ABC):
             stream.id = self._h2_connection.get_next_available_stream_id()
             self._stream_handler.put_stream(stream.id, stream)
 
-        self._h2_connection.send_headers(
-            stream.id, frame.headers.to_list(), end_stream=frame.end_stream
-        )
+        self._h2_connection.send_headers(stream.id, frame.headers.to_list(), 
end_stream=frame.end_stream)
         self._flush()
         EventHelper.set(event)
 
-    def _send_reset_frame(
-        self, stream_id: int, error_code: int, event: Optional[asyncio.Event] 
= None
-    ) -> None:
+    def _send_reset_frame(self, stream_id: int, error_code: int, event: 
Optional[asyncio.Event] = None) -> None:
         """
         Send the HTTP/2 reset frame.(thread-unsafe)
         :param stream_id: The stream identifier.
@@ -307,17 +300,11 @@ class Http2ClientProtocol(AbstractHttp2Protocol):
         url: URL,
         connection_listener: ConnectionStateListener = None,
     ):
-        super().__init__(
-            url, H2Configuration(client_side=True, header_encoding="utf-8")
-        )
-        self._connection_listener = (
-            connection_listener or EmptyConnectionStateListener()
-        )
+        super().__init__(url, H2Configuration(client_side=True, 
header_encoding="utf-8"))
+        self._connection_listener = connection_listener or 
EmptyConnectionStateListener()
 
         # get heartbeat interval -> default 60s
-        self._heartbeat_interval = url.parameters.get(
-            h2_constants.HEARTBEAT_KEY, h2_constants.DEFAULT_HEARTBEAT
-        )
+        self._heartbeat_interval = 
url.parameters.get(h2_constants.HEARTBEAT_KEY, h2_constants.DEFAULT_HEARTBEAT)
         self._ping_ack_future: Optional[asyncio.Future] = None
         self._heartbeat_task: Optional[asyncio.Task] = None
 
@@ -372,6 +359,4 @@ class Http2ServerProtocol(AbstractHttp2Protocol):
     """
 
     def __init__(self, url: URL):
-        super().__init__(
-            url, H2Configuration(client_side=False, header_encoding="utf-8")
-        )
+        super().__init__(url, H2Configuration(client_side=False, 
header_encoding="utf-8"))
diff --git a/dubbo/remoting/aio/http2/registries.py 
b/src/dubbo/remoting/aio/http2/registries.py
similarity index 97%
rename from dubbo/remoting/aio/http2/registries.py
rename to src/dubbo/remoting/aio/http2/registries.py
index 10e636d..e232807 100644
--- a/dubbo/remoting/aio/http2/registries.py
+++ b/src/dubbo/remoting/aio/http2/registries.py
@@ -59,7 +59,8 @@ class Http2FrameType(enum.Enum):
 
 class Http2ErrorCode(enum.Enum):
     """
-    Error codes are 32-bit fields that are used in RST_STREAM and GOAWAY 
frames to convey the reasons for the stream or connection error.
+    Error codes are 32-bit fields that are used in RST_STREAM and GOAWAY frames
+    to convey the reasons for the stream or connection error.
 
     see: https://datatracker.ietf.org/doc/html/rfc7540#section-11.4
     """
@@ -137,7 +138,8 @@ class Http2Settings:
             # If the initial value is "none", it means no limitation.
             self.initial_value = initial_value
 
-    # Allows the sender to inform the remote endpoint of the maximum size of 
the header compression table used to decode header blocks, in octets.
+    # Allows the sender to inform the remote endpoint of the maximum size
+    # of the header compression table used to decode header blocks, in octets.
     HEADER_TABLE_SIZE = Http2Setting(0x1, 4096)
 
     # This setting can be used to disable server push (Section 8.2).
@@ -153,7 +155,8 @@ class Http2Settings:
     # Indicates the size of the largest frame payload that the sender is 
willing to receive, in octets.
     MAX_FRAME_SIZE = Http2Setting(0x5, 16384)
 
-    # This advisory setting informs a peer of the maximum size of header list 
that the sender is prepared to accept, in octets.
+    # This advisory setting informs a peer of the maximum size of header list
+    # that the sender is prepared to accept, in octets.
     MAX_HEADER_LIST_SIZE = Http2Setting(0x6, None)
 
 
diff --git a/dubbo/remoting/aio/http2/stream.py 
b/src/dubbo/remoting/aio/http2/stream.py
similarity index 96%
rename from dubbo/remoting/aio/http2/stream.py
rename to src/dubbo/remoting/aio/http2/stream.py
index c072a95..26d6d89 100644
--- a/dubbo/remoting/aio/http2/stream.py
+++ b/src/dubbo/remoting/aio/http2/stream.py
@@ -34,7 +34,8 @@ __all__ = ["Http2Stream", "DefaultHttp2Stream"]
 
 class Http2Stream(abc.ABC):
     """
-    A "stream" is an independent, bidirectional sequence of frames exchanged 
between the client and server within an HTTP/2 connection.
+    A "stream" is an independent, bidirectional sequence of frames exchanged
+    between the client and server within an HTTP/2 connection.
     see: https://datatracker.ietf.org/doc/html/rfc7540#section-5
     """
 
@@ -145,7 +146,7 @@ class Http2Stream(abc.ABC):
         __slots__ = ["_stream"]
 
         def __init__(self):
-            self._stream: Optional["Http2Stream"] = None
+            self._stream: Optional[Http2Stream] = None
 
         def bind(self, stream: "Http2Stream") -> None:
             """
@@ -229,9 +230,7 @@ class DefaultHttp2Stream(Http2Stream):
             self, self._loop, self._protocol, executor
         )
         # steam outbound controller
-        self._outbound_controller: FrameOutboundController = 
FrameOutboundController(
-            self, self._loop, self._protocol
-        )
+        self._outbound_controller: FrameOutboundController = 
FrameOutboundController(self, self._loop, self._protocol)
 
         # The flag to indicate whether the headers have been sent.
         self._headers_sent = False
@@ -248,9 +247,7 @@ class DefaultHttp2Stream(Http2Stream):
         if self.local_closed:
             raise StreamError("The stream has been closed locally.")
         elif self._headers_sent and not end_stream:
-            raise StreamError(
-                "Trailers must be the last frame of the stream(end_stream must 
be True)."
-            )
+            raise StreamError("Trailers must be the last frame of the 
stream(end_stream must be True).")
 
         self._headers_sent = True
         headers_frame = HeadersFrame(self.id, headers, end_stream=end_stream)
diff --git a/dubbo/remoting/aio/http2/stream_handler.py 
b/src/dubbo/remoting/aio/http2/stream_handler.py
similarity index 90%
rename from dubbo/remoting/aio/http2/stream_handler.py
rename to src/dubbo/remoting/aio/http2/stream_handler.py
index 73d2d4f..4e1064e 100644
--- a/dubbo/remoting/aio/http2/stream_handler.py
+++ b/src/dubbo/remoting/aio/http2/stream_handler.py
@@ -17,7 +17,7 @@
 import asyncio
 import uuid
 from concurrent.futures import ThreadPoolExecutor
-from typing import Callable, Dict, Optional
+from typing import Callable, Optional
 
 from dubbo.loggers import loggerFactory
 from dubbo.remoting.aio.http2.frames import UserActionFrames
@@ -48,12 +48,10 @@ class StreamMultiplexHandler:
         self._protocol: Optional[AbstractHttp2Protocol] = None
 
         # The map of stream_id to stream.
-        self._streams: Optional[Dict[int, DefaultHttp2Stream]] = None
+        self._streams: Optional[dict[int, DefaultHttp2Stream]] = None
 
         # The executor for handling received frames.
-        self._executor = ThreadPoolExecutor(
-            thread_name_prefix=f"dubbo_tri_stream_{str(uuid.uuid4())}"
-        )
+        self._executor = 
ThreadPoolExecutor(thread_name_prefix=f"dubbo_tri_stream_{str(uuid.uuid4())}")
 
     def do_init(self, loop: asyncio.AbstractEventLoop, protocol) -> None:
         """
@@ -109,9 +107,7 @@ class StreamMultiplexHandler:
             if frame.end_stream and stream.local_closed:
                 self.remove_stream(frame.stream_id)
         else:
-            _LOGGER.warning(
-                f"Stream {frame.stream_id} not found. Ignoring frame {frame}"
-            )
+            _LOGGER.warning("Stream %s not found. Ignoring frame %s", 
frame.stream_id, frame)
 
     def destroy(self) -> None:
         """
@@ -135,9 +131,7 @@ class StreamClientMultiplexHandler(StreamMultiplexHandler):
         :return: The stream.
         :rtype: DefaultHttp2Stream
         """
-        return DefaultHttp2Stream(
-            -1, listener, self._loop, self._protocol, self._executor
-        )
+        return DefaultHttp2Stream(-1, listener, self._loop, self._protocol, 
self._executor)
 
 
 class StreamServerMultiplexHandler(StreamMultiplexHandler):
@@ -163,9 +157,7 @@ class StreamServerMultiplexHandler(StreamMultiplexHandler):
         :rtype: DefaultHttp2Stream
         """
         stream_listener = self._listener_factory()
-        new_stream = DefaultHttp2Stream(
-            stream_id, stream_listener, self._loop, self._protocol, 
self._executor
-        )
+        new_stream = DefaultHttp2Stream(stream_id, stream_listener, 
self._loop, self._protocol, self._executor)
         self.put_stream(stream_id, new_stream)
         return new_stream
 
diff --git a/dubbo/remoting/aio/http2/utils.py 
b/src/dubbo/remoting/aio/http2/utils.py
similarity index 92%
rename from dubbo/remoting/aio/http2/utils.py
rename to src/dubbo/remoting/aio/http2/utils.py
index 32d52f0..965a56a 100644
--- a/dubbo/remoting/aio/http2/utils.py
+++ b/src/dubbo/remoting/aio/http2/utils.py
@@ -39,9 +39,7 @@ class Http2EventUtils:
     @staticmethod
     def convert_to_frame(
         event: h2_event.Event,
-    ) -> Union[
-        HeadersFrame, DataFrame, RstStreamFrame, WindowUpdateFrame, PingFrame, 
None
-    ]:
+    ) -> Union[HeadersFrame, DataFrame, RstStreamFrame, WindowUpdateFrame, 
PingFrame, None]:
         """
         Convert a h2.events.Event to HTTP/2 Frame.
         :param event: The H2 event.
@@ -79,8 +77,6 @@ class Http2EventUtils:
             return WindowUpdateFrame(event.stream_id, event.delta)
         elif isinstance(event, (h2_event.PingAckReceived, 
h2_event.PingReceived)):
             # PING frame.
-            return PingFrame(
-                event.ping_data, ack=isinstance(event, 
h2_event.PingAckReceived)
-            )
+            return PingFrame(event.ping_data, ack=isinstance(event, 
h2_event.PingAckReceived))
 
         return None
diff --git a/dubbo/serialization/__init__.py 
b/src/dubbo/serialization/__init__.py
similarity index 100%
rename from dubbo/serialization/__init__.py
rename to src/dubbo/serialization/__init__.py
diff --git a/dubbo/serialization/_interfaces.py 
b/src/dubbo/serialization/_interfaces.py
similarity index 100%
rename from dubbo/serialization/_interfaces.py
rename to src/dubbo/serialization/_interfaces.py
diff --git a/dubbo/serialization/custom_serializers.py 
b/src/dubbo/serialization/custom_serializers.py
similarity index 100%
rename from dubbo/serialization/custom_serializers.py
rename to src/dubbo/serialization/custom_serializers.py
diff --git a/dubbo/serialization/direct_serializers.py 
b/src/dubbo/serialization/direct_serializers.py
similarity index 100%
rename from dubbo/serialization/direct_serializers.py
rename to src/dubbo/serialization/direct_serializers.py
diff --git a/dubbo/server.py b/src/dubbo/server.py
similarity index 92%
rename from dubbo/server.py
rename to src/dubbo/server.py
index 99e55d3..b7c4dee 100644
--- a/dubbo/server.py
+++ b/src/dubbo/server.py
@@ -53,16 +53,12 @@ class Server:
                 return
 
             # get the protocol
-            service_protocol = extensionLoader.get_extension(
-                Protocol, self._service.protocol
-            )()
+            service_protocol = extensionLoader.get_extension(Protocol, 
self._service.protocol)()
 
             registry_config = self._dubbo.registry_config
 
             self._protocol = (
-                RegistryProtocol(registry_config, service_protocol)
-                if self._dubbo.registry_config
-                else service_protocol
+                RegistryProtocol(registry_config, service_protocol) if 
self._dubbo.registry_config else service_protocol
             )
 
             # build url
diff --git a/dubbo/types.py b/src/dubbo/types.py
similarity index 100%
rename from dubbo/types.py
rename to src/dubbo/types.py
diff --git a/dubbo/url.py b/src/dubbo/url.py
similarity index 97%
rename from dubbo/url.py
rename to src/dubbo/url.py
index 043688a..8dae9fa 100644
--- a/dubbo/url.py
+++ b/src/dubbo/url.py
@@ -15,7 +15,7 @@
 # limitations under the License.
 
 import copy
-from typing import Any, Dict, Optional
+from typing import Any, Optional
 from urllib import parse
 from urllib.parse import urlencode, urlunparse
 
@@ -87,8 +87,8 @@ class URL:
         username: str = "",
         password: str = "",
         path: str = "",
-        parameters: Optional[Dict[str, str]] = None,
-        attributes: Optional[Dict[str, Any]] = None,
+        parameters: Optional[dict[str, str]] = None,
+        attributes: Optional[dict[str, Any]] = None,
     ):
         """
         Initialize the URL object.
@@ -228,7 +228,7 @@ class URL:
         self._path = value.lstrip("/")
 
     @property
-    def parameters(self) -> Dict[str, str]:
+    def parameters(self) -> dict[str, str]:
         """
         Get the query parameters of the URL.
 
@@ -238,7 +238,7 @@ class URL:
         return self._parameters
 
     @property
-    def attributes(self) -> Dict[str, Any]:
+    def attributes(self) -> dict[str, Any]:
         """
         Get the additional attributes of the URL.
 
diff --git a/dubbo/utils.py b/src/dubbo/utils.py
similarity index 95%
rename from dubbo/utils.py
rename to src/dubbo/utils.py
index a0a40d8..d5e039e 100644
--- a/dubbo/utils.py
+++ b/src/dubbo/utils.py
@@ -13,13 +13,13 @@
 # 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 inspect
 import os
 import socket
 from collections.abc import Callable
-from typing import Any, List, Tuple, Optional
+from typing import Any, Optional
 
 import psutil
-import inspect
 
 __all__ = ["EventHelper", "FutureHelper", "NetworkUtils", "CpuUtils", 
"FunctionHelper"]
 
@@ -187,9 +187,9 @@ class NetworkUtils:
                     # only consider IPv4 address
                     if addr.family == socket.AF_INET:
                         # ignore the loopback address and check if the IP 
address is reachable
-                        if not NetworkUtils.is_loopback_address(
+                        if not NetworkUtils.is_loopback_address(addr.address) 
and NetworkUtils.is_address_reachable(
                             addr.address
-                        ) and NetworkUtils.is_address_reachable(addr.address):
+                        ):
                             return addr.address
         except Exception:
             pass
@@ -232,7 +232,7 @@ class CpuUtils:
         return psutil.cpu_percent(interval=interval)
 
     @staticmethod
-    def get_per_cpu_usage(interval=1) -> List[float]:
+    def get_per_cpu_usage(interval=1) -> list[float]:
         """
         Get the per CPU usage of the system.
 
@@ -244,7 +244,7 @@ class CpuUtils:
         return psutil.cpu_percent(interval=interval, percpu=True)
 
     @staticmethod
-    def get_load_avg() -> Tuple[float, float, float]:
+    def get_load_avg() -> tuple[float, float, float]:
         """
         Get the load average over the last 1, 5, and 15 minutes
 
@@ -299,9 +299,7 @@ class FunctionHelper:
         :return: True if the function has arguments, False otherwise.
         :rtype: bool
         """
-        return inspect.Parameter.VAR_POSITIONAL in [
-            p.kind for p in inspect.signature(func).parameters.values()
-        ]
+        return inspect.Parameter.VAR_POSITIONAL in [p.kind for p in 
inspect.signature(func).parameters.values()]
 
     @staticmethod
     def has_kwargs(func: Callable) -> bool:
@@ -313,9 +311,7 @@ class FunctionHelper:
         :return: True if the function has keyword arguments, False otherwise.
         :rtype: bool
         """
-        return inspect.Parameter.VAR_KEYWORD in [
-            p.kind for p in inspect.signature(func).parameters.values()
-        ]
+        return inspect.Parameter.VAR_KEYWORD in [p.kind for p in 
inspect.signature(func).parameters.values()]
 
     @staticmethod
     def call_func(func: Callable, args_and_kwargs: Any = None) -> Any:
diff --git a/tests/test_utils.py b/tests/test_utils.py
deleted file mode 100644
index 67a10c6..0000000
--- a/tests/test_utils.py
+++ /dev/null
@@ -1,96 +0,0 @@
-#
-# 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 Tuple, List, Dict, Any
-
-
-def test_func_helper():
-    """
-    Test the function helper.
-    """
-    from dubbo.utils import FunctionHelper
-
-    # zero arguments
-    def func_0():
-        return 0
-
-    # one argument
-    def func_1(a):
-        return a + 1
-
-    # two arguments
-    def func_2(a, b):
-        return a + b
-
-    # two arguments, one default
-    def func_3(a, b=2):
-        return a + b
-
-    # two arguments, positional only
-    def func_4(a, b, /):
-        return a + b
-
-    # two arguments, keyword only
-    def func_5(a, b, *, c):
-        return a + b + c
-
-    # variable arguments
-    def func_6(*args):
-        return sum(args)
-
-    # variable keyword arguments
-    def func_7(**kwargs):
-        return kwargs
-
-    # variable arguments and keyword arguments
-    def func_8(*args, **kwargs):
-        return sum(args), kwargs
-
-    # mixed arguments - 1
-    def func_9(a: Tuple[int, int], b: List[int], c: Dict[str, Any]):
-        return f"a={a}, b={b}, c={c}"
-
-    # class
-    class User:
-        def __init__(self, name, age):
-            self.name = name
-            self.age = age
-
-    def func_10(user: User, name, age):
-        return user.name, user.age, name, age
-
-    # test function helper
-    assert FunctionHelper.call_func(func_0) == 0
-    assert FunctionHelper.call_func(func_1, ((1,), {})) == 2
-    assert FunctionHelper.call_func(func_2, ((1, 2), {})) == 3
-    assert FunctionHelper.call_func(func_3, ((1,), {})) == 3
-    assert FunctionHelper.call_func(func_4, ((1, 2), {})) == 3
-    assert FunctionHelper.call_func(func_5, ((1, 2), {"c": 3})) == 6
-    assert FunctionHelper.call_func(func_6, ((1, 2, 3), {})) == 6
-    assert FunctionHelper.call_func(func_7, ((), {"a": 1, "b": 2})) == {"a": 
1, "b": 2}
-    assert FunctionHelper.call_func(func_8, ((1, 2, 3), {"a": 1, "b": 2})) == (
-        6,
-        {"a": 1, "b": 2},
-    )
-    assert (
-        FunctionHelper.call_func(
-            func_9,
-            (((1, 2), [1, 2], {"a": 1, "b": 2}), {}),
-        )
-        == "a=(1, 2), b=[1, 2], c={'a': 1, 'b': 2}"
-    )
-    assert FunctionHelper.call_func(
-        func_10, ((User("Alice", 20),), {"name": "Bob", "age": 30})
-    ) == ("Alice", 20, "Bob", 30)


Reply via email to