Skip to content

Commit f3e45fa

Browse files
authored
[Feature][Dubbo-python] Implement the basic functions of an RPC framework. (#34)
* feat: do something about service reference * fix: fix ci * feat: define UnaryUnaryMultiCallable * feat: update applicationConfig * feat: do some work related to service reference * feat: add ci * fix: fix ci * fix: fix ci * feat: add logger feat * fix: fix ci * perf: Extension Manager becomes a singleton * fix: fix ci * refactor: Make the code more standardized and robust * feat: add logger extension * feat: add url * fix: fix ci * feat: finish logger part * perf: update something about logger * style: Becoming more regulated * fix: fix ci * fix: fix ci * feat: update something about client * fix: fix ci * fix: Delete some invalid files * feat: Complete the network transmission part * perf: Optimization of the network transmission part * feat: Complete the client's call link * feat: Complete the basic functions of the client * feat: Refactored and refined rpc calling capabilities * docs: Comment completely using reStructuredText style * fix: update something * fix: fix ci
1 parent 4fd4b33 commit f3e45fa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+9675
-1
lines changed

.flake8

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,14 @@ ignore =
1616
max-line-length = 120
1717

1818
exclude =
19+
.idea,
1920
.git,
2021
__pycache__,
2122
docs
2223

2324
per-file-ignores =
24-
__init__.py:F401
25+
__init__.py:F401
26+
# module level import not at top of file
27+
dubbo/_imports.py:F401
28+
# module level import not at top of file
29+
dubbo/common/extension/logger_extension.py:E402

.github/workflows/unittest.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: Run Unittests
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
unittest:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: actions/checkout@v4
10+
11+
- name: Set up Python 3.10
12+
uses: actions/setup-python@v5
13+
with:
14+
python-version: '3.10'
15+
16+
- name: Install dependencies
17+
run: |
18+
pip install -r requirements.txt
19+
20+
- name: Run unittests
21+
run: |
22+
python -m unittest discover -s tests -p 'test_*.py'

.licenserc.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ header: # `header` section is configurations for source codes license header.
6161
- '.gitignore'
6262
- '.github'
6363
- '.flake8'
64+
- 'requirements.txt'
6465
comment: on-failure # on what condition license-eye will comment on the pull request, `on-failure`, `always`, `never`.
6566

6667
# license-location-threshold specifies the index threshold where the license header can be located,

dubbo/__init__.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.

dubbo/client.py

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from typing import Optional
18+
19+
from dubbo.common import constants as common_constants
20+
from dubbo.common.types import DeserializingFunction, SerializingFunction
21+
from dubbo.config import ReferenceConfig
22+
from dubbo.proxy import RpcCallable
23+
from dubbo.proxy.callables import MultipleRpcCallable
24+
25+
26+
class Client:
27+
28+
__slots__ = ["_reference"]
29+
30+
def __init__(self, reference: ReferenceConfig):
31+
self._reference = reference
32+
33+
def unary(
34+
self,
35+
method_name: str,
36+
request_serializer: Optional[SerializingFunction] = None,
37+
response_deserializer: Optional[DeserializingFunction] = None,
38+
) -> RpcCallable:
39+
return self._callable(
40+
common_constants.UNARY_CALL_VALUE,
41+
method_name,
42+
request_serializer,
43+
response_deserializer,
44+
)
45+
46+
def client_stream(
47+
self,
48+
method_name: str,
49+
request_serializer: Optional[SerializingFunction] = None,
50+
response_deserializer: Optional[DeserializingFunction] = None,
51+
) -> RpcCallable:
52+
return self._callable(
53+
common_constants.CLIENT_STREAM_CALL_VALUE,
54+
method_name,
55+
request_serializer,
56+
response_deserializer,
57+
)
58+
59+
def server_stream(
60+
self,
61+
method_name: str,
62+
request_serializer: Optional[SerializingFunction] = None,
63+
response_deserializer: Optional[DeserializingFunction] = None,
64+
) -> RpcCallable:
65+
return self._callable(
66+
common_constants.SERVER_STREAM_CALL_VALUE,
67+
method_name,
68+
request_serializer,
69+
response_deserializer,
70+
)
71+
72+
def bidi_stream(
73+
self,
74+
method_name: str,
75+
request_serializer: Optional[SerializingFunction] = None,
76+
response_deserializer: Optional[DeserializingFunction] = None,
77+
) -> RpcCallable:
78+
return self._callable(
79+
common_constants.BI_STREAM_CALL_VALUE,
80+
method_name,
81+
request_serializer,
82+
response_deserializer,
83+
)
84+
85+
def _callable(
86+
self,
87+
call_type: str,
88+
method_name: str,
89+
request_serializer: Optional[SerializingFunction] = None,
90+
response_deserializer: Optional[DeserializingFunction] = None,
91+
) -> RpcCallable:
92+
"""
93+
Generate a proxy for the given method
94+
:param call_type: The call type.
95+
:type call_type: str
96+
:param method_name: The method name.
97+
:type method_name: str
98+
:param request_serializer: The request serializer.
99+
:type request_serializer: Optional[SerializingFunction]
100+
:param response_deserializer: The response deserializer.
101+
:type response_deserializer: Optional[DeserializingFunction]
102+
:return: The proxy.
103+
:rtype: RpcCallable
104+
"""
105+
# get invoker
106+
invoker = self._reference.get_invoker()
107+
url = invoker.get_url()
108+
109+
# clone url
110+
url = url.copy()
111+
url.parameters[common_constants.METHOD_KEY] = method_name
112+
url.parameters[common_constants.CALL_KEY] = call_type
113+
114+
# set serializer and deserializer
115+
url.attributes[common_constants.SERIALIZER_KEY] = request_serializer
116+
url.attributes[common_constants.DESERIALIZER_KEY] = response_deserializer
117+
118+
# create proxy
119+
return MultipleRpcCallable(invoker, url)

dubbo/common/__init__.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
from .classes import SingletonBase
18+
from .deliverers import MultiMessageDeliverer, SingleMessageDeliverer
19+
from .node import Node
20+
from .types import DeserializingFunction, SerializingFunction
21+
from .url import URL, create_url
22+
23+
__all__ = [
24+
"SingleMessageDeliverer",
25+
"MultiMessageDeliverer",
26+
"URL",
27+
"create_url",
28+
"Node",
29+
"SingletonBase",
30+
"DeserializingFunction",
31+
"SerializingFunction",
32+
]

dubbo/common/classes.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
import threading
18+
19+
__all__ = ["SingletonBase"]
20+
21+
22+
class SingletonBase:
23+
"""
24+
Singleton base class. This class ensures that only one instance of a derived class exists.
25+
26+
This implementation is thread-safe.
27+
"""
28+
29+
_instance = None
30+
_instance_lock = threading.Lock()
31+
32+
def __new__(cls, *args, **kwargs):
33+
"""
34+
Create a new instance of the class if it does not exist.
35+
"""
36+
if cls._instance is None:
37+
with cls._instance_lock:
38+
# double check
39+
if cls._instance is None:
40+
cls._instance = super(SingletonBase, cls).__new__(cls)
41+
return cls._instance

dubbo/common/constants.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
PROTOCOL_KEY = "protocol"
18+
TRIPLE = "triple"
19+
TRIPLE_SHORT = "tri"
20+
21+
SIDE_KEY = "side"
22+
SERVER_VALUE = "server"
23+
CLIENT_VALUE = "client"
24+
25+
METHOD_KEY = "method"
26+
SERVICE_KEY = "service"
27+
28+
SERVICE_HANDLER_KEY = "service-handler"
29+
30+
GROUP_KEY = "group"
31+
32+
LOCAL_HOST_KEY = "localhost"
33+
LOCAL_HOST_VALUE = "127.0.0.1"
34+
DEFAULT_PORT = 50051
35+
36+
SSL_ENABLED_KEY = "ssl-enabled"
37+
38+
SERIALIZATION_KEY = "serialization"
39+
SERIALIZER_KEY = "serializer"
40+
DESERIALIZER_KEY = "deserializer"
41+
42+
43+
COMPRESSION_KEY = "compression"
44+
COMPRESSOR_KEY = "compressor"
45+
DECOMPRESSOR_KEY = "decompressor"
46+
47+
48+
TRANSPORTER_KEY = "transporter"
49+
TRANSPORTER_DEFAULT_VALUE = "aio"
50+
51+
TRUE_VALUE = "true"
52+
FALSE_VALUE = "false"
53+
54+
CALL_KEY = "call"
55+
UNARY_CALL_VALUE = "unary"
56+
CLIENT_STREAM_CALL_VALUE = "client-stream"
57+
SERVER_STREAM_CALL_VALUE = "server-stream"
58+
BI_STREAM_CALL_VALUE = "bi-stream"
59+
60+
PATH_SEPARATOR = "/"
61+
PROTOCOL_SEPARATOR = "://"
62+
DYNAMIC_KEY = "dynamic"

0 commit comments

Comments
 (0)