nacos-sdk-rust-binding-py 0.1.0__tar.gz → 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of nacos-sdk-rust-binding-py might be problematic. Click here for more details.

@@ -524,9 +524,9 @@ dependencies = [
524
524
 
525
525
  [[package]]
526
526
  name = "log"
527
- version = "0.4.18"
527
+ version = "0.4.19"
528
528
  source = "registry+https://github.com/rust-lang/crates.io-index"
529
- checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
529
+ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
530
530
 
531
531
  [[package]]
532
532
  name = "matchit"
@@ -609,7 +609,7 @@ dependencies = [
609
609
 
610
610
  [[package]]
611
611
  name = "nacos-sdk-rust-binding-py"
612
- version = "0.1.0"
612
+ version = "0.1.2"
613
613
  dependencies = [
614
614
  "lazy_static",
615
615
  "nacos-sdk",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "nacos-sdk-rust-binding-py"
3
- version = "0.1.0"
3
+ version = "0.1.2"
4
4
  edition = "2021"
5
5
  license = "Apache-2.0"
6
6
  publish = false
@@ -0,0 +1,249 @@
1
+ Metadata-Version: 2.1
2
+ Name: nacos-sdk-rust-binding-py
3
+ Version: 0.1.2
4
+ Classifier: Programming Language :: Rust
5
+ Classifier: Programming Language :: Python :: Implementation :: CPython
6
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
7
+ Requires-Dist: pdoc ; extra == 'docs'
8
+ Requires-Dist: behave ; extra == 'test'
9
+ Provides-Extra: docs
10
+ Provides-Extra: test
11
+ License-File: LICENSE
12
+ Summary: nacos-sdk-rust binding for Python.
13
+ Keywords: nacos,ffi,pyo3,binding,python
14
+ Author: CheirshCai <785427346@qq.com>
15
+ Author-email: CheirshCai <785427346@qq.com>
16
+ License: Apache-2.0
17
+ Requires-Python: >=3.7
18
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
19
+ Project-URL: Documentation, https://github.com/opc-source/nacos-sdk-rust-binding-py.git
20
+ Project-URL: Homepage, https://github.com/opc-source/nacos-sdk-rust-binding-py.git
21
+ Project-URL: Repository, https://github.com/opc-source/nacos-sdk-rust-binding-py.git
22
+
23
+ # nacos-sdk-rust-binding-py
24
+ nacos-sdk-rust binding for Python with PyO3.
25
+
26
+ Tip: nacos-sdk-python 仓库暂未提供 2.x gRPC 交互模式,为了能升级它,故而通过 ffi 方式调用 nacos-sdk-rust
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ pip install nacos-sdk-rust-binding-py
32
+ ```
33
+
34
+ - project package see https://pypi.org/project/nacos-sdk-rust-binding-py
35
+
36
+ ## Usage
37
+
38
+ **使用样例请看仓库内的 examples 目录**
39
+
40
+ - 客户端日志请在目录 `$HOME/logs/nacos/` 查看
41
+
42
+ ### Definition of ClientOptions
43
+
44
+ ```python
45
+ class ClientOptions:
46
+ # Server Addr, e.g. address:port[,address:port],...]
47
+ #[pyo3(set, get)]
48
+ server_addr: String,
49
+ # Namespace/Tenant
50
+ #[pyo3(set, get)]
51
+ namespace: String,
52
+ # AppName
53
+ #[pyo3(set, get)]
54
+ app_name: Option<String>,
55
+ # Username for Auth
56
+ #[pyo3(set, get)]
57
+ username: Option<String>,
58
+ # Password for Auth
59
+ #[pyo3(set, get)]
60
+ password: Option<String>,
61
+
62
+ # Init
63
+ def __init__(self, server_addr, namespace, app_name, username, password):
64
+ self.server_addr = server_addr
65
+ self.server_addr = namespace
66
+ self.app_name = app_name
67
+ self.username = username
68
+ self.password = password
69
+
70
+ ```
71
+
72
+ ### Definition of Config
73
+
74
+ ```python
75
+ class NacosConfigResponse:
76
+ # Namespace/Tenant
77
+ # [pyo3(get)]
78
+ namespace: String,
79
+ # DataId
80
+ # [pyo3(get)]
81
+ data_id: String,
82
+ # Group
83
+ # [pyo3(get)]
84
+ group: String,
85
+ # Content
86
+ # [pyo3(get)]
87
+ content: String,
88
+ # Content's Type; e.g. json,properties,xml,html,text,yaml
89
+ # [pyo3(get)]
90
+ content_type: String,
91
+ # Content's md5
92
+ # [pyo3(get)]
93
+ md5: String,
94
+
95
+
96
+ class NacosConfigClient:
97
+ # Init. If it fails, pay attention to err
98
+ def __init__(self, client_options: ClientOptions):
99
+ # inner logic xxx
100
+ pass
101
+
102
+ # Get config's content. If it fails, pay attention to err
103
+ def get_config(self, data_id: String, group: String) -> String:
104
+ pass
105
+
106
+ # Get NacosConfigResponse. If it fails, pay attention to err
107
+ def get_config_resp(self, data_id: String, group: String) -> NacosConfigResponse:
108
+ pass
109
+
110
+ # Publish config. If it fails, pay attention to err
111
+ def publish_config(self, data_id: String, group: String, content: String) -> bool:
112
+ pass
113
+
114
+ # Remove config. If it fails, pay attention to err
115
+ def remove_config(self, data_id: String, group: String) -> bool:
116
+ pass
117
+
118
+ # Add NacosConfigChangeListener callback func, which listen the config change. If it fails, pay attention to err
119
+ def add_listener(self, data_id: String, group: String, listener: py_function):
120
+ pass
121
+
122
+
123
+ ```
124
+
125
+ ### Definition of Naming
126
+
127
+ ```python
128
+ class NacosServiceInstance:
129
+ # Instance Id
130
+ #[pyo3(set, get)]
131
+ instance_id: Option<String>,
132
+ # Ip
133
+ #[pyo3(set, get)]
134
+ ip: String,
135
+ # Port
136
+ #[pyo3(set, get)]
137
+ port: i32,
138
+ # Weight, default 1.0
139
+ #[pyo3(set, get)]
140
+ weight: Option<f64>,
141
+ # Healthy or not, default true
142
+ #[pyo3(set, get)]
143
+ healthy: Option<bool>,
144
+ # Enabled ot not, default true
145
+ #[pyo3(set, get)]
146
+ enabled: Option<bool>,
147
+ # Ephemeral or not, default true
148
+ #[pyo3(set, get)]
149
+ ephemeral: Option<bool>,
150
+ # Cluster Name, default 'DEFAULT'
151
+ #[pyo3(set, get)]
152
+ cluster_name: Option<String>,
153
+ # Service Name
154
+ #[pyo3(set, get)]
155
+ service_name: Option<String>,
156
+ # Metadata, default '{}'
157
+ #[pyo3(set, get)]
158
+ metadata: Option<std::collections::HashMap<String, String>>,
159
+
160
+ # Init
161
+ def __init__(self, ip, port, weight, healthy, enabled, ephemeral, cluster_name, service_name, metadata):
162
+ # inner logic xxx
163
+ pass
164
+
165
+
166
+ class NacosNamingClient:
167
+ # Init. If it fails, pay attention to err
168
+ def __init__(self, client_options: ClientOptions):
169
+ # inner logic xxx
170
+ pass
171
+
172
+ # Register instance. If it fails, pay attention to err
173
+ def register_instance(self, service_name: String, group: String, service_instance: NacosServiceInstance):
174
+ pass
175
+
176
+ # Deregister instance. If it fails, pay attention to err
177
+ def deregister_instance(self, service_name: String, group: String, service_instance: NacosServiceInstance):
178
+ pass
179
+
180
+ # Batch register instance, improve interaction efficiency. If it fails, pay attention to err
181
+ def batch_register_instance(self, service_name: String, group: String, service_instances: [NacosServiceInstance]):
182
+ pass
183
+
184
+ # Get all instances by service and group. default cluster=[], subscribe=true. If it fails, pay attention to err
185
+ def get_all_instances(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>) -> [NacosServiceInstance]:
186
+ pass
187
+
188
+ # Select instances whether healthy or not. default cluster=[], subscribe=true, healthy=true. If it fails, pay attention to err
189
+ def select_instances(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>, healthy: Option<bool>) -> [NacosServiceInstance]:
190
+ pass
191
+
192
+ # Select one healthy instance. default cluster=[], subscribe=true. If it fails, pay attention to err
193
+ def select_one_healthy_instance(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>) -> NacosServiceInstance:
194
+ pass
195
+
196
+ # Add NacosNamingEventListener callback func, which listen the instance change. If it fails, pay attention to err
197
+ def subscribe(self, service_name: String, group: String, clusters: Option<[String]>, listener: py_function) -> NacosServiceInstance:
198
+ pass
199
+
200
+
201
+ ```
202
+
203
+ ## Development
204
+
205
+ Setup virtualenv:
206
+
207
+ ```shell
208
+ python -m venv venv
209
+ ```
210
+
211
+ Activate venv:
212
+
213
+ ```shell
214
+ source venv/bin/activate
215
+ ````
216
+
217
+ Install `maturin`:
218
+
219
+ ```shell
220
+ pip install maturin[patchelf]
221
+ ```
222
+
223
+ Build bindings:
224
+
225
+ ```shell
226
+ maturin develop
227
+ ```
228
+
229
+ Run some tests:
230
+
231
+ ```shell
232
+ maturin develop -E test
233
+ behave tests
234
+ ```
235
+
236
+ Build API docs:
237
+
238
+ ```shell
239
+ maturin develop -E docs
240
+ pdoc nacos-sdk-rust-binding-py
241
+ ```
242
+
243
+ # License
244
+ [Apache License Version 2.0](LICENSE)
245
+
246
+ # Acknowledgement
247
+ - binding for Python with [PyO3](https://github.com/PyO3/pyo3.git)
248
+ - binding the [nacos-sdk-rust](https://github.com/nacos-group/nacos-sdk-rust.git)
249
+
@@ -0,0 +1,226 @@
1
+ # nacos-sdk-rust-binding-py
2
+ nacos-sdk-rust binding for Python with PyO3.
3
+
4
+ Tip: nacos-sdk-python 仓库暂未提供 2.x gRPC 交互模式,为了能升级它,故而通过 ffi 方式调用 nacos-sdk-rust
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install nacos-sdk-rust-binding-py
10
+ ```
11
+
12
+ - project package see https://pypi.org/project/nacos-sdk-rust-binding-py
13
+
14
+ ## Usage
15
+
16
+ **使用样例请看仓库内的 examples 目录**
17
+
18
+ - 客户端日志请在目录 `$HOME/logs/nacos/` 查看
19
+
20
+ ### Definition of ClientOptions
21
+
22
+ ```python
23
+ class ClientOptions:
24
+ # Server Addr, e.g. address:port[,address:port],...]
25
+ #[pyo3(set, get)]
26
+ server_addr: String,
27
+ # Namespace/Tenant
28
+ #[pyo3(set, get)]
29
+ namespace: String,
30
+ # AppName
31
+ #[pyo3(set, get)]
32
+ app_name: Option<String>,
33
+ # Username for Auth
34
+ #[pyo3(set, get)]
35
+ username: Option<String>,
36
+ # Password for Auth
37
+ #[pyo3(set, get)]
38
+ password: Option<String>,
39
+
40
+ # Init
41
+ def __init__(self, server_addr, namespace, app_name, username, password):
42
+ self.server_addr = server_addr
43
+ self.server_addr = namespace
44
+ self.app_name = app_name
45
+ self.username = username
46
+ self.password = password
47
+
48
+ ```
49
+
50
+ ### Definition of Config
51
+
52
+ ```python
53
+ class NacosConfigResponse:
54
+ # Namespace/Tenant
55
+ # [pyo3(get)]
56
+ namespace: String,
57
+ # DataId
58
+ # [pyo3(get)]
59
+ data_id: String,
60
+ # Group
61
+ # [pyo3(get)]
62
+ group: String,
63
+ # Content
64
+ # [pyo3(get)]
65
+ content: String,
66
+ # Content's Type; e.g. json,properties,xml,html,text,yaml
67
+ # [pyo3(get)]
68
+ content_type: String,
69
+ # Content's md5
70
+ # [pyo3(get)]
71
+ md5: String,
72
+
73
+
74
+ class NacosConfigClient:
75
+ # Init. If it fails, pay attention to err
76
+ def __init__(self, client_options: ClientOptions):
77
+ # inner logic xxx
78
+ pass
79
+
80
+ # Get config's content. If it fails, pay attention to err
81
+ def get_config(self, data_id: String, group: String) -> String:
82
+ pass
83
+
84
+ # Get NacosConfigResponse. If it fails, pay attention to err
85
+ def get_config_resp(self, data_id: String, group: String) -> NacosConfigResponse:
86
+ pass
87
+
88
+ # Publish config. If it fails, pay attention to err
89
+ def publish_config(self, data_id: String, group: String, content: String) -> bool:
90
+ pass
91
+
92
+ # Remove config. If it fails, pay attention to err
93
+ def remove_config(self, data_id: String, group: String) -> bool:
94
+ pass
95
+
96
+ # Add NacosConfigChangeListener callback func, which listen the config change. If it fails, pay attention to err
97
+ def add_listener(self, data_id: String, group: String, listener: py_function):
98
+ pass
99
+
100
+
101
+ ```
102
+
103
+ ### Definition of Naming
104
+
105
+ ```python
106
+ class NacosServiceInstance:
107
+ # Instance Id
108
+ #[pyo3(set, get)]
109
+ instance_id: Option<String>,
110
+ # Ip
111
+ #[pyo3(set, get)]
112
+ ip: String,
113
+ # Port
114
+ #[pyo3(set, get)]
115
+ port: i32,
116
+ # Weight, default 1.0
117
+ #[pyo3(set, get)]
118
+ weight: Option<f64>,
119
+ # Healthy or not, default true
120
+ #[pyo3(set, get)]
121
+ healthy: Option<bool>,
122
+ # Enabled ot not, default true
123
+ #[pyo3(set, get)]
124
+ enabled: Option<bool>,
125
+ # Ephemeral or not, default true
126
+ #[pyo3(set, get)]
127
+ ephemeral: Option<bool>,
128
+ # Cluster Name, default 'DEFAULT'
129
+ #[pyo3(set, get)]
130
+ cluster_name: Option<String>,
131
+ # Service Name
132
+ #[pyo3(set, get)]
133
+ service_name: Option<String>,
134
+ # Metadata, default '{}'
135
+ #[pyo3(set, get)]
136
+ metadata: Option<std::collections::HashMap<String, String>>,
137
+
138
+ # Init
139
+ def __init__(self, ip, port, weight, healthy, enabled, ephemeral, cluster_name, service_name, metadata):
140
+ # inner logic xxx
141
+ pass
142
+
143
+
144
+ class NacosNamingClient:
145
+ # Init. If it fails, pay attention to err
146
+ def __init__(self, client_options: ClientOptions):
147
+ # inner logic xxx
148
+ pass
149
+
150
+ # Register instance. If it fails, pay attention to err
151
+ def register_instance(self, service_name: String, group: String, service_instance: NacosServiceInstance):
152
+ pass
153
+
154
+ # Deregister instance. If it fails, pay attention to err
155
+ def deregister_instance(self, service_name: String, group: String, service_instance: NacosServiceInstance):
156
+ pass
157
+
158
+ # Batch register instance, improve interaction efficiency. If it fails, pay attention to err
159
+ def batch_register_instance(self, service_name: String, group: String, service_instances: [NacosServiceInstance]):
160
+ pass
161
+
162
+ # Get all instances by service and group. default cluster=[], subscribe=true. If it fails, pay attention to err
163
+ def get_all_instances(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>) -> [NacosServiceInstance]:
164
+ pass
165
+
166
+ # Select instances whether healthy or not. default cluster=[], subscribe=true, healthy=true. If it fails, pay attention to err
167
+ def select_instances(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>, healthy: Option<bool>) -> [NacosServiceInstance]:
168
+ pass
169
+
170
+ # Select one healthy instance. default cluster=[], subscribe=true. If it fails, pay attention to err
171
+ def select_one_healthy_instance(self, service_name: String, group: String, clusters: Option<[String]>, subscribe: Option<bool>) -> NacosServiceInstance:
172
+ pass
173
+
174
+ # Add NacosNamingEventListener callback func, which listen the instance change. If it fails, pay attention to err
175
+ def subscribe(self, service_name: String, group: String, clusters: Option<[String]>, listener: py_function) -> NacosServiceInstance:
176
+ pass
177
+
178
+
179
+ ```
180
+
181
+ ## Development
182
+
183
+ Setup virtualenv:
184
+
185
+ ```shell
186
+ python -m venv venv
187
+ ```
188
+
189
+ Activate venv:
190
+
191
+ ```shell
192
+ source venv/bin/activate
193
+ ````
194
+
195
+ Install `maturin`:
196
+
197
+ ```shell
198
+ pip install maturin[patchelf]
199
+ ```
200
+
201
+ Build bindings:
202
+
203
+ ```shell
204
+ maturin develop
205
+ ```
206
+
207
+ Run some tests:
208
+
209
+ ```shell
210
+ maturin develop -E test
211
+ behave tests
212
+ ```
213
+
214
+ Build API docs:
215
+
216
+ ```shell
217
+ maturin develop -E docs
218
+ pdoc nacos-sdk-rust-binding-py
219
+ ```
220
+
221
+ # License
222
+ [Apache License Version 2.0](LICENSE)
223
+
224
+ # Acknowledgement
225
+ - binding for Python with [PyO3](https://github.com/PyO3/pyo3.git)
226
+ - binding the [nacos-sdk-rust](https://github.com/nacos-group/nacos-sdk-rust.git)
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/python3
2
+
3
+ import time
4
+ import nacos_sdk_rust_binding_py as nacos
5
+
6
+ client_options = nacos.ClientOptions("0.0.0.0:8848", "love", "simple_app_py", "nacos", "nacos")
7
+
8
+ config_client = nacos.NacosConfigClient(client_options)
9
+
10
+ time.sleep(1)
11
+
12
+ data_id = "todo-dataid"
13
+ group = "LOVE"
14
+ publish_content = "test-content"
15
+
16
+
17
+ # 自定义配置监听的函数,接受的参数为 `nacos.NacosConfigResponse`
18
+ def listen_config(config_resp: nacos.NacosConfigResponse):
19
+ print(f"listen_config,config_resp={str(config_resp)}")
20
+ print(f"listen_config,config_resp.content={config_resp.content}")
21
+
22
+
23
+ # example: 添加配置监听(对目标 data_id, group 配置变化的监听)
24
+ config_client.add_listener(data_id, group, listen_config)
25
+
26
+ # example: 推送配置
27
+ config_client.publish_config(data_id, group, publish_content)
28
+
29
+ time.sleep(1)
30
+
31
+ # example: 获取配置,返回值为 `nacos.NacosConfigResponse`
32
+ config_content_resp = config_client.get_config_resp(data_id, group)
33
+
34
+ # example: 获取配置,返回值为 content: String
35
+ get_config_content = config_client.get_config(data_id, group)
36
+
37
+ assert get_config_content == publish_content
38
+ assert config_content_resp.content == publish_content
39
+
40
+ print(f"get_config_content={get_config_content}")
41
+ print(f"config_content_resp={str(config_content_resp)},resp_content={config_content_resp.content}")
42
+
43
+ time.sleep(1)
44
+
45
+ # example: 推送配置,使配置监听函数被调用
46
+ config_client.publish_config(data_id, group, "publish_content for listen_config")
47
+
48
+ # sleep for user look at nacos-server, the config be listening
49
+ time.sleep(300)
50
+
51
+ # example: 删除配置
52
+ config_client.remove_config(data_id, group)
53
+
54
+ # example: 获取的配置不存在,会抛出异常
55
+ try:
56
+ get_config_content_removed = config_client.get_config(data_id, group)
57
+ except RuntimeError:
58
+ print("config already be removed.")
59
+
60
+ time.sleep(10)
@@ -0,0 +1,48 @@
1
+ #!/usr/bin/python3
2
+
3
+ import time
4
+ import nacos_sdk_rust_binding_py as nacos
5
+
6
+ client_options = nacos.ClientOptions("0.0.0.0:8848", "love", "simple_app_py", "nacos", "nacos")
7
+
8
+ naming_client = nacos.NacosNamingClient(client_options)
9
+
10
+ time.sleep(1)
11
+
12
+ service_name = "todo-service-name"
13
+ group = "dev"
14
+ service_instance = nacos.NacosServiceInstance("127.0.0.1", 8080)
15
+
16
+
17
+ # 自定义服务订阅函数,接受的参数为 `nacos.NacosConfigResponse`
18
+ def subscribe_instances(instances: [nacos.NacosServiceInstance]):
19
+ print(f"subscribe_instances,instances={str(instances)}")
20
+ for ins in instances:
21
+ print(f"subscribe_instances,instances[x].ip={ins.ip}")
22
+
23
+
24
+ # example: 添加配置监听(对目标 data_id, group 配置变化的监听)
25
+ naming_client.subscribe(service_name, group, None, subscribe_instances)
26
+
27
+ time.sleep(1)
28
+
29
+ # example: 注册服务实例
30
+ naming_client.register_instance(service_name, group, service_instance)
31
+
32
+ time.sleep(1)
33
+
34
+ # example: 获取服务实例列表
35
+ get_instances = naming_client.get_all_instances(service_name, group)
36
+
37
+ assert len(get_instances) > 0
38
+ assert get_instances[0].ip == service_instance.ip
39
+
40
+ print(f"get_instances={str(get_instances)}")
41
+ for i in get_instances:
42
+ print(f"get_instances[x].ip={i.ip}")
43
+
44
+ # example: 批量服务实例,可使前面的配置监听函数被调用
45
+ service_instance2 = nacos.NacosServiceInstance("127.0.0.2", 8080)
46
+ naming_client.batch_register_instance(service_name, group, [service_instance, service_instance2])
47
+
48
+ time.sleep(300)
@@ -20,9 +20,9 @@ docs = ["pdoc"]
20
20
  test = ["behave"]
21
21
 
22
22
  [project.urls]
23
- Documentation = "https://github.com/opc-source/nacos-sdk-rust-binding-node.git"
24
- Homepage = "https://github.com/opc-source/nacos-sdk-rust-binding-node.git"
25
- Repository = "https://github.com/opc-source/nacos-sdk-rust-binding-node.git"
23
+ Documentation = "https://github.com/opc-source/nacos-sdk-rust-binding-py.git"
24
+ Homepage = "https://github.com/opc-source/nacos-sdk-rust-binding-py.git"
25
+ Repository = "https://github.com/opc-source/nacos-sdk-rust-binding-py.git"
26
26
 
27
27
  [tool.maturin]
28
28
  features = ["pyo3/extension-module"]
@@ -1,7 +1,7 @@
1
1
  #![deny(clippy::all)]
2
2
 
3
- use pyo3::exceptions::PyRuntimeError;
4
- use pyo3::{pyclass, pymethods, PyResult, Python};
3
+ use pyo3::exceptions::{PyRuntimeError, PyValueError};
4
+ use pyo3::{pyclass, pymethods, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject};
5
5
 
6
6
  use std::sync::Arc;
7
7
 
@@ -95,25 +95,27 @@ impl NacosConfigClient {
95
95
  /// Add NacosConfigChangeListener callback func, which listen the config change.
96
96
  /// If it fails, pay attention to err
97
97
  #[pyo3(signature = (data_id, group, listener))]
98
- #[allow(unused_variables)]
99
98
  pub fn add_listener(
100
99
  &self,
101
100
  py: Python,
102
101
  data_id: String,
103
102
  group: String,
104
- listener: &pyo3::PyAny, // todo PyFunction arg: <NacosConfigResponse>
103
+ listener: &PyAny, // PyFunction arg: <NacosConfigResponse>
105
104
  ) -> PyResult<()> {
106
- /*
105
+ if !listener.is_callable() {
106
+ return Err(PyErr::new::<PyValueError, _>(
107
+ "Arg `listener` must be a callable",
108
+ ));
109
+ }
107
110
  self.inner
108
111
  .add_listener(
109
112
  data_id,
110
113
  group,
111
114
  Arc::new(NacosConfigChangeListener {
112
- func: Arc::new(listener),
115
+ func: Arc::new(listener.to_object(py)),
113
116
  }),
114
117
  )
115
118
  .map_err(|nacos_err| PyRuntimeError::new_err(format!("{:?}", &nacos_err)))?;
116
- */
117
119
  Ok(())
118
120
  }
119
121
 
@@ -127,7 +129,7 @@ impl NacosConfigClient {
127
129
  py: Python,
128
130
  data_id: String,
129
131
  group: String,
130
- listener: &pyo3::PyAny, // todo PyFunction arg: <NacosConfigResponse>
132
+ listener: &PyAny, // PyFunction arg: <NacosConfigResponse>
131
133
  ) -> PyResult<()> {
132
134
  Ok(())
133
135
  }
@@ -136,33 +138,40 @@ impl NacosConfigClient {
136
138
  #[pyclass]
137
139
  pub struct NacosConfigResponse {
138
140
  /// Namespace/Tenant
141
+ #[pyo3(get)]
139
142
  pub namespace: String,
140
143
  /// DataId
144
+ #[pyo3(get)]
141
145
  pub data_id: String,
142
146
  /// Group
147
+ #[pyo3(get)]
143
148
  pub group: String,
144
149
  /// Content
150
+ #[pyo3(get)]
145
151
  pub content: String,
146
152
  /// Content's Type; e.g. json,properties,xml,html,text,yaml
153
+ #[pyo3(get)]
147
154
  pub content_type: String,
148
155
  /// Content's md5
156
+ #[pyo3(get)]
149
157
  pub md5: String,
150
158
  }
151
159
 
152
- /*
153
160
  pub struct NacosConfigChangeListener {
154
- func: Arc<PyFunction>,
161
+ func: Arc<PyObject>,
155
162
  }
156
163
 
157
164
  impl nacos_sdk::api::config::ConfigChangeListener for NacosConfigChangeListener {
158
165
  fn notify(&self, config_resp: nacos_sdk::api::config::ConfigResponse) {
159
166
  let ffi_conf_resp = transfer_conf_resp(config_resp);
160
167
 
161
- // todo call PyFunction with args
162
- let _ = self.func.call(ffi_conf_resp, None);
168
+ // call PyFunction with args
169
+ let _ = Python::with_gil(|py| -> PyResult<()> {
170
+ let _ = self.func.call(py, (ffi_conf_resp,), None);
171
+ Ok(())
172
+ });
163
173
  }
164
174
  }
165
- */
166
175
 
167
176
  fn transfer_conf_resp(config_resp: nacos_sdk::api::config::ConfigResponse) -> NacosConfigResponse {
168
177
  NacosConfigResponse {
@@ -56,17 +56,42 @@ fn init_logger() -> &'static tracing_appender::non_blocking::WorkerGuard {
56
56
  #[derive(Clone)]
57
57
  pub struct ClientOptions {
58
58
  /// Server Addr, e.g. address:port[,address:port],...]
59
+ #[pyo3(set, get)]
59
60
  pub server_addr: String,
60
61
  /// Namespace/Tenant
62
+ #[pyo3(set, get)]
61
63
  pub namespace: String,
62
64
  /// AppName
65
+ #[pyo3(set, get)]
63
66
  pub app_name: Option<String>,
64
67
  /// Username for Auth
68
+ #[pyo3(set, get)]
65
69
  pub username: Option<String>,
66
70
  /// Password for Auth
71
+ #[pyo3(set, get)]
67
72
  pub password: Option<String>,
68
73
  }
69
74
 
75
+ #[pymethods]
76
+ impl ClientOptions {
77
+ #[new]
78
+ pub fn new(
79
+ server_addr: String,
80
+ namespace: String,
81
+ app_name: Option<String>,
82
+ username: Option<String>,
83
+ password: Option<String>,
84
+ ) -> PyResult<ClientOptions> {
85
+ Ok(Self {
86
+ server_addr,
87
+ namespace,
88
+ app_name,
89
+ username,
90
+ password,
91
+ })
92
+ }
93
+ }
94
+
70
95
  mod config;
71
96
  pub use config::*;
72
97
 
@@ -1,7 +1,7 @@
1
1
  #![deny(clippy::all)]
2
2
 
3
- use pyo3::exceptions::PyRuntimeError;
4
- use pyo3::{pyclass, pymethods, PyResult, Python};
3
+ use pyo3::exceptions::{PyRuntimeError, PyValueError};
4
+ use pyo3::{pyclass, pymethods, PyAny, PyErr, PyObject, PyResult, Python, ToPyObject};
5
5
 
6
6
  use std::sync::Arc;
7
7
 
@@ -183,27 +183,29 @@ impl NacosNamingClient {
183
183
  /// Add NacosNamingEventListener callback func, which listen the instance change.
184
184
  /// If it fails, pay attention to err
185
185
  #[pyo3(signature = (service_name, group, clusters, listener))]
186
- #[allow(unused_variables)]
187
186
  pub fn subscribe(
188
187
  &self,
189
188
  py: Python,
190
189
  service_name: String,
191
190
  group: String,
192
191
  clusters: Option<Vec<String>>,
193
- listener: &pyo3::PyAny, // todo PyFunction arg: Vec<NacosServiceInstance>
192
+ listener: &PyAny, // PyFunction arg: Vec<NacosServiceInstance>
194
193
  ) -> PyResult<()> {
195
- /*
194
+ if !listener.is_callable() {
195
+ return Err(PyErr::new::<PyValueError, _>(
196
+ "Arg `listener` must be a callable",
197
+ ));
198
+ }
196
199
  self.inner
197
200
  .subscribe(
198
201
  service_name,
199
202
  Some(group),
200
203
  clusters.unwrap_or_default(),
201
204
  Arc::new(NacosNamingEventListener {
202
- func: Arc::new(listener),
205
+ func: Arc::new(listener.to_object(py)),
203
206
  }),
204
207
  )
205
208
  .map_err(|nacos_err| PyRuntimeError::new_err(format!("{:?}", &nacos_err)))?;
206
- */
207
209
  Ok(())
208
210
  }
209
211
 
@@ -218,15 +220,14 @@ impl NacosNamingClient {
218
220
  service_name: String,
219
221
  group: String,
220
222
  clusters: Option<Vec<String>>,
221
- listener: &pyo3::PyAny, // todo PyFunction arg: Vec<NacosServiceInstance>
223
+ listener: &PyAny, // PyFunction arg: Vec<NacosServiceInstance>
222
224
  ) -> PyResult<()> {
223
225
  Ok(())
224
226
  }
225
227
  }
226
228
 
227
- /*
228
229
  pub struct NacosNamingEventListener {
229
- func: Arc<PyFunction>,
230
+ func: Arc<PyObject>,
230
231
  }
231
232
 
232
233
  impl nacos_sdk::api::naming::NamingEventListener for NacosNamingEventListener {
@@ -237,42 +238,84 @@ impl nacos_sdk::api::naming::NamingEventListener for NacosNamingEventListener {
237
238
 
238
239
  let rust_instances = event.instances.clone().unwrap();
239
240
 
240
- let ffi_instances = rust_instances
241
+ let ffi_instances: Vec<NacosServiceInstance> = rust_instances
241
242
  .iter()
242
243
  .map(transfer_rust_instance_to_ffi)
243
244
  .collect();
244
245
 
245
- // todo call PyFunction with args
246
- let _ = self.func.call(ffi_instances, None);
246
+ // call PyFunction with args
247
+ let _ = Python::with_gil(|py| -> PyResult<()> {
248
+ let _ = self.func.call(py, (ffi_instances,), None);
249
+ Ok(())
250
+ });
247
251
  }
248
252
  }
249
- */
250
253
 
251
254
  #[pyclass]
252
255
  #[derive(Clone)]
253
256
  pub struct NacosServiceInstance {
254
257
  /// Instance Id
258
+ #[pyo3(set, get)]
255
259
  pub instance_id: Option<String>,
256
260
  /// Ip
261
+ #[pyo3(set, get)]
257
262
  pub ip: String,
258
263
  /// Port
264
+ #[pyo3(set, get)]
259
265
  pub port: i32,
260
266
  /// Weight, default 1.0
267
+ #[pyo3(set, get)]
261
268
  pub weight: Option<f64>,
262
269
  /// Healthy or not, default true
270
+ #[pyo3(set, get)]
263
271
  pub healthy: Option<bool>,
264
272
  /// Enabled ot not, default true
273
+ #[pyo3(set, get)]
265
274
  pub enabled: Option<bool>,
266
275
  /// Ephemeral or not, default true
276
+ #[pyo3(set, get)]
267
277
  pub ephemeral: Option<bool>,
268
278
  /// Cluster Name, default 'DEFAULT'
279
+ #[pyo3(set, get)]
269
280
  pub cluster_name: Option<String>,
270
281
  /// Service Name
282
+ #[pyo3(set, get)]
271
283
  pub service_name: Option<String>,
272
284
  /// Metadata, default '{}'
285
+ #[pyo3(set, get)]
273
286
  pub metadata: Option<std::collections::HashMap<String, String>>,
274
287
  }
275
288
 
289
+ #[pymethods]
290
+ impl NacosServiceInstance {
291
+ #[new]
292
+ #[allow(clippy::too_many_arguments)]
293
+ pub fn new(
294
+ ip: String,
295
+ port: i32,
296
+ weight: Option<f64>,
297
+ healthy: Option<bool>,
298
+ enabled: Option<bool>,
299
+ ephemeral: Option<bool>,
300
+ cluster_name: Option<String>,
301
+ service_name: Option<String>,
302
+ metadata: Option<std::collections::HashMap<String, String>>,
303
+ ) -> PyResult<NacosServiceInstance> {
304
+ Ok(Self {
305
+ instance_id: None,
306
+ ip,
307
+ port,
308
+ weight,
309
+ healthy,
310
+ enabled,
311
+ ephemeral,
312
+ cluster_name,
313
+ service_name,
314
+ metadata,
315
+ })
316
+ }
317
+ }
318
+
276
319
  fn transfer_ffi_instance_to_rust(
277
320
  ffi_instance: &NacosServiceInstance,
278
321
  ) -> nacos_sdk::api::naming::ServiceInstance {
@@ -1,83 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: nacos-sdk-rust-binding-py
3
- Version: 0.1.0
4
- Classifier: Programming Language :: Rust
5
- Classifier: Programming Language :: Python :: Implementation :: CPython
6
- Classifier: Programming Language :: Python :: Implementation :: PyPy
7
- Requires-Dist: pdoc ; extra == 'docs'
8
- Requires-Dist: behave ; extra == 'test'
9
- Provides-Extra: docs
10
- Provides-Extra: test
11
- License-File: LICENSE
12
- Summary: nacos-sdk-rust binding for Python.
13
- Keywords: nacos,ffi,pyo3,binding,python
14
- Author: CheirshCai <785427346@qq.com>
15
- Author-email: CheirshCai <785427346@qq.com>
16
- License: Apache-2.0
17
- Requires-Python: >=3.7
18
- Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
19
- Project-URL: Documentation, https://github.com/opc-source/nacos-sdk-rust-binding-node.git
20
- Project-URL: Homepage, https://github.com/opc-source/nacos-sdk-rust-binding-node.git
21
- Project-URL: Repository, https://github.com/opc-source/nacos-sdk-rust-binding-node.git
22
-
23
- # nacos-sdk-rust-binding-py
24
- nacos-sdk-rust binding for Python with PyO3.
25
-
26
- Tip: nacos-sdk-python 仓库暂未提供 2.x gRPC 交互模式,为了能升级它,故而通过 ffi 方式调用 nacos-sdk-rust
27
-
28
- ## Installation
29
-
30
- ```bash
31
- pip install nacos_sdk_rust_binding_py
32
- ```
33
-
34
- # Usage
35
- - TODO
36
-
37
- ## Development
38
-
39
- Setup virtualenv:
40
-
41
- ```shell
42
- python -m venv venv
43
- ```
44
-
45
- Activate venv:
46
-
47
- ```shell
48
- source venv/bin/activate
49
- ````
50
-
51
- Install `maturin`:
52
-
53
- ```shell
54
- pip install maturin[patchelf]
55
- ```
56
-
57
- Build bindings:
58
-
59
- ```shell
60
- maturin develop
61
- ```
62
-
63
- Run some tests:
64
-
65
- ```shell
66
- maturin develop -E test
67
- behave tests
68
- ```
69
-
70
- Build API docs:
71
-
72
- ```shell
73
- maturin develop -E docs
74
- pdoc nacos_sdk_rust_binding_py
75
- ```
76
-
77
- # License
78
- [Apache License Version 2.0](LICENSE)
79
-
80
- # Acknowledgement
81
- - binding for Python with [PyO3](https://github.com/PyO3/pyo3.git)
82
- - binding the [nacos-sdk-rust](https://github.com/nacos-group/nacos-sdk-rust.git)
83
-
@@ -1,60 +0,0 @@
1
- # nacos-sdk-rust-binding-py
2
- nacos-sdk-rust binding for Python with PyO3.
3
-
4
- Tip: nacos-sdk-python 仓库暂未提供 2.x gRPC 交互模式,为了能升级它,故而通过 ffi 方式调用 nacos-sdk-rust
5
-
6
- ## Installation
7
-
8
- ```bash
9
- pip install nacos_sdk_rust_binding_py
10
- ```
11
-
12
- # Usage
13
- - TODO
14
-
15
- ## Development
16
-
17
- Setup virtualenv:
18
-
19
- ```shell
20
- python -m venv venv
21
- ```
22
-
23
- Activate venv:
24
-
25
- ```shell
26
- source venv/bin/activate
27
- ````
28
-
29
- Install `maturin`:
30
-
31
- ```shell
32
- pip install maturin[patchelf]
33
- ```
34
-
35
- Build bindings:
36
-
37
- ```shell
38
- maturin develop
39
- ```
40
-
41
- Run some tests:
42
-
43
- ```shell
44
- maturin develop -E test
45
- behave tests
46
- ```
47
-
48
- Build API docs:
49
-
50
- ```shell
51
- maturin develop -E docs
52
- pdoc nacos_sdk_rust_binding_py
53
- ```
54
-
55
- # License
56
- [Apache License Version 2.0](LICENSE)
57
-
58
- # Acknowledgement
59
- - binding for Python with [PyO3](https://github.com/PyO3/pyo3.git)
60
- - binding the [nacos-sdk-rust](https://github.com/nacos-group/nacos-sdk-rust.git)