businnect 0.0.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.
- businnect-0.0.2/LICENSE +21 -0
- businnect-0.0.2/PKG-INFO +186 -0
- businnect-0.0.2/README.md +174 -0
- businnect-0.0.2/businnect/__init__.py +3 -0
- businnect-0.0.2/businnect/client.py +37 -0
- businnect-0.0.2/businnect/resources/__init__.py +0 -0
- businnect-0.0.2/businnect/resources/blog.py +34 -0
- businnect-0.0.2/businnect/resources/micropost.py +105 -0
- businnect-0.0.2/businnect/schemas/__init__.py +1 -0
- businnect-0.0.2/businnect/schemas/blog.py +37 -0
- businnect-0.0.2/businnect/schemas/common.py +10 -0
- businnect-0.0.2/businnect/schemas/micropost.py +6 -0
- businnect-0.0.2/businnect/settings.py +1 -0
- businnect-0.0.2/businnect/tests/test_businnect_integration.py +24 -0
- businnect-0.0.2/businnect/tests/test_businnect_unit.py +131 -0
- businnect-0.0.2/businnect.egg-info/PKG-INFO +186 -0
- businnect-0.0.2/businnect.egg-info/SOURCES.txt +20 -0
- businnect-0.0.2/businnect.egg-info/dependency_links.txt +1 -0
- businnect-0.0.2/businnect.egg-info/requires.txt +3 -0
- businnect-0.0.2/businnect.egg-info/top_level.txt +1 -0
- businnect-0.0.2/pyproject.toml +20 -0
- businnect-0.0.2/setup.cfg +4 -0
businnect-0.0.2/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Businnect https://www.businnect.com support@businnect.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
businnect-0.0.2/PKG-INFO
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: businnect
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Python SDK for the Businnect API
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: requests>=2.32.0
|
|
9
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
|
10
|
+
Requires-Dist: pydantic>=2.0.0
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# Businnect Python
|
|
14
|
+
|
|
15
|
+
The official Python SDK for the [Businnect](https://businnect.com) API.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install businnect
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
Find your API token at [https://businnect.com/settings/developer](https://businnect.com/settings/developer) after creating an account at [https://businnect.com/register](https://businnect.com/register).
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from businnect import Businnect
|
|
29
|
+
|
|
30
|
+
client = Businnect(api_token="your_api_token_here")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Micropost
|
|
36
|
+
|
|
37
|
+
### Create a post
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from businnect.schemas.micropost import PostType
|
|
41
|
+
|
|
42
|
+
# Text post
|
|
43
|
+
post = client.micropost.client_create_micropost(
|
|
44
|
+
title="Hello World",
|
|
45
|
+
body="This is my first post.",
|
|
46
|
+
)
|
|
47
|
+
print(post.public_id)
|
|
48
|
+
print(post.link)
|
|
49
|
+
|
|
50
|
+
# Media post
|
|
51
|
+
with open("photo.png", "rb") as f:
|
|
52
|
+
post = client.micropost.client_create_micropost(
|
|
53
|
+
title="My photo",
|
|
54
|
+
body="Check this out",
|
|
55
|
+
post_type=PostType.MEDIA,
|
|
56
|
+
file=("photo.png", f, "image/png"),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Reply to a post
|
|
60
|
+
reply = client.micropost.client_create_micropost(
|
|
61
|
+
body="Great post!",
|
|
62
|
+
parent_micropost_public_id="post_public_id_here",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Nested reply (reply to a comment)
|
|
66
|
+
nested = client.micropost.client_create_micropost(
|
|
67
|
+
body="I agree!",
|
|
68
|
+
parent_micropost_public_id="post_public_id_here",
|
|
69
|
+
parent_micropost_comment_public_id="comment_public_id_here",
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Delete a post
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
client.micropost.client_delete_micropost(public_id="post_public_id_here")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Vote on a post (toggle)
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
result = client.micropost.client_vote_micropost(public_id="post_public_id_here")
|
|
83
|
+
print(result.user_voted) # True or False
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Blog
|
|
89
|
+
|
|
90
|
+
### Get admin article
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
article = client.blog.client_get_admin_blog()
|
|
94
|
+
if article:
|
|
95
|
+
print(article.title)
|
|
96
|
+
print(article.body)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### List admin articles
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
result = client.blog.client_list_admin_blogs()
|
|
103
|
+
print(result.total_list)
|
|
104
|
+
for article in result.list:
|
|
105
|
+
print(article.title, article.slug)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## API Reference
|
|
111
|
+
|
|
112
|
+
### `Businnect(api_token, base_url?)`
|
|
113
|
+
|
|
114
|
+
| Parameter | Type | Description |
|
|
115
|
+
|-----------|------|-------------|
|
|
116
|
+
| `api_token` | `str` | Your API token |
|
|
117
|
+
| `base_url` | `str` | API base URL (default: `https://api.businnect.com`) |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### `client.micropost.client_create_micropost(...)`
|
|
122
|
+
|
|
123
|
+
| Parameter | Type | Default | Description |
|
|
124
|
+
|-----------|------|---------|-------------|
|
|
125
|
+
| `body` | `str` | required | Content of the post |
|
|
126
|
+
| `title` | `str` | `None` | Required for original posts |
|
|
127
|
+
| `post_type` | `PostType` | `PostType.TEXT` | `TEXT` or `MEDIA` |
|
|
128
|
+
| `community_name` | `str` | `None` | Community to post in |
|
|
129
|
+
| `parent_micropost_public_id` | `str` | `None` | For replies |
|
|
130
|
+
| `parent_micropost_comment_public_id` | `str` | `None` | For nested replies |
|
|
131
|
+
| `allow_comments` | `bool` | `True` | Whether comments are allowed |
|
|
132
|
+
| `is_draft` | `bool` | `False` | Save as draft |
|
|
133
|
+
| `file` | `tuple` | `None` | `(filename, file_object, mime_type)` for MEDIA posts |
|
|
134
|
+
|
|
135
|
+
**Returns:** `CreatedWithPublicIdAndLinkResponse` with `public_id` and `link`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### `client.micropost.client_delete_micropost(public_id)`
|
|
140
|
+
|
|
141
|
+
| Parameter | Type | Description |
|
|
142
|
+
|-----------|------|-------------|
|
|
143
|
+
| `public_id` | `str` | Public ID of the post to delete |
|
|
144
|
+
|
|
145
|
+
**Returns:** `None` (204 on success)
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### `client.micropost.client_vote_micropost(public_id)`
|
|
150
|
+
|
|
151
|
+
| Parameter | Type | Description |
|
|
152
|
+
|-----------|------|-------------|
|
|
153
|
+
| `public_id` | `str` | Public ID of the post to vote on |
|
|
154
|
+
|
|
155
|
+
**Returns:** `VoteResponse` with `user_voted` (bool)
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### `client.blog.client_get_admin_blog()`
|
|
160
|
+
|
|
161
|
+
**Returns:** `BlogResponse` or `None`
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### `client.blog.client_list_admin_blogs()`
|
|
166
|
+
|
|
167
|
+
**Returns:** `BlogListResponse` with `list`, `total_list` and `total_pages`
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Install in editable mode
|
|
175
|
+
pip install -e .
|
|
176
|
+
|
|
177
|
+
# Run unit tests
|
|
178
|
+
python -m pytest businnect/tests/test_businnect_unit.py -v
|
|
179
|
+
|
|
180
|
+
# Run integration tests (requires real API token)
|
|
181
|
+
BUSINNECT_API_TOKEN=your_token python -m pytest businnect/tests/test_businnect_integration.py -v -s
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# Businnect Python
|
|
2
|
+
|
|
3
|
+
The official Python SDK for the [Businnect](https://businnect.com) API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install businnect
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
Find your API token at [https://businnect.com/settings/developer](https://businnect.com/settings/developer) after creating an account at [https://businnect.com/register](https://businnect.com/register).
|
|
14
|
+
|
|
15
|
+
```python
|
|
16
|
+
from businnect import Businnect
|
|
17
|
+
|
|
18
|
+
client = Businnect(api_token="your_api_token_here")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Micropost
|
|
24
|
+
|
|
25
|
+
### Create a post
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from businnect.schemas.micropost import PostType
|
|
29
|
+
|
|
30
|
+
# Text post
|
|
31
|
+
post = client.micropost.client_create_micropost(
|
|
32
|
+
title="Hello World",
|
|
33
|
+
body="This is my first post.",
|
|
34
|
+
)
|
|
35
|
+
print(post.public_id)
|
|
36
|
+
print(post.link)
|
|
37
|
+
|
|
38
|
+
# Media post
|
|
39
|
+
with open("photo.png", "rb") as f:
|
|
40
|
+
post = client.micropost.client_create_micropost(
|
|
41
|
+
title="My photo",
|
|
42
|
+
body="Check this out",
|
|
43
|
+
post_type=PostType.MEDIA,
|
|
44
|
+
file=("photo.png", f, "image/png"),
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Reply to a post
|
|
48
|
+
reply = client.micropost.client_create_micropost(
|
|
49
|
+
body="Great post!",
|
|
50
|
+
parent_micropost_public_id="post_public_id_here",
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# Nested reply (reply to a comment)
|
|
54
|
+
nested = client.micropost.client_create_micropost(
|
|
55
|
+
body="I agree!",
|
|
56
|
+
parent_micropost_public_id="post_public_id_here",
|
|
57
|
+
parent_micropost_comment_public_id="comment_public_id_here",
|
|
58
|
+
)
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Delete a post
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
client.micropost.client_delete_micropost(public_id="post_public_id_here")
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Vote on a post (toggle)
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
result = client.micropost.client_vote_micropost(public_id="post_public_id_here")
|
|
71
|
+
print(result.user_voted) # True or False
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Blog
|
|
77
|
+
|
|
78
|
+
### Get admin article
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
article = client.blog.client_get_admin_blog()
|
|
82
|
+
if article:
|
|
83
|
+
print(article.title)
|
|
84
|
+
print(article.body)
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### List admin articles
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
result = client.blog.client_list_admin_blogs()
|
|
91
|
+
print(result.total_list)
|
|
92
|
+
for article in result.list:
|
|
93
|
+
print(article.title, article.slug)
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## API Reference
|
|
99
|
+
|
|
100
|
+
### `Businnect(api_token, base_url?)`
|
|
101
|
+
|
|
102
|
+
| Parameter | Type | Description |
|
|
103
|
+
|-----------|------|-------------|
|
|
104
|
+
| `api_token` | `str` | Your API token |
|
|
105
|
+
| `base_url` | `str` | API base URL (default: `https://api.businnect.com`) |
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### `client.micropost.client_create_micropost(...)`
|
|
110
|
+
|
|
111
|
+
| Parameter | Type | Default | Description |
|
|
112
|
+
|-----------|------|---------|-------------|
|
|
113
|
+
| `body` | `str` | required | Content of the post |
|
|
114
|
+
| `title` | `str` | `None` | Required for original posts |
|
|
115
|
+
| `post_type` | `PostType` | `PostType.TEXT` | `TEXT` or `MEDIA` |
|
|
116
|
+
| `community_name` | `str` | `None` | Community to post in |
|
|
117
|
+
| `parent_micropost_public_id` | `str` | `None` | For replies |
|
|
118
|
+
| `parent_micropost_comment_public_id` | `str` | `None` | For nested replies |
|
|
119
|
+
| `allow_comments` | `bool` | `True` | Whether comments are allowed |
|
|
120
|
+
| `is_draft` | `bool` | `False` | Save as draft |
|
|
121
|
+
| `file` | `tuple` | `None` | `(filename, file_object, mime_type)` for MEDIA posts |
|
|
122
|
+
|
|
123
|
+
**Returns:** `CreatedWithPublicIdAndLinkResponse` with `public_id` and `link`
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### `client.micropost.client_delete_micropost(public_id)`
|
|
128
|
+
|
|
129
|
+
| Parameter | Type | Description |
|
|
130
|
+
|-----------|------|-------------|
|
|
131
|
+
| `public_id` | `str` | Public ID of the post to delete |
|
|
132
|
+
|
|
133
|
+
**Returns:** `None` (204 on success)
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### `client.micropost.client_vote_micropost(public_id)`
|
|
138
|
+
|
|
139
|
+
| Parameter | Type | Description |
|
|
140
|
+
|-----------|------|-------------|
|
|
141
|
+
| `public_id` | `str` | Public ID of the post to vote on |
|
|
142
|
+
|
|
143
|
+
**Returns:** `VoteResponse` with `user_voted` (bool)
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
### `client.blog.client_get_admin_blog()`
|
|
148
|
+
|
|
149
|
+
**Returns:** `BlogResponse` or `None`
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
### `client.blog.client_list_admin_blogs()`
|
|
154
|
+
|
|
155
|
+
**Returns:** `BlogListResponse` with `list`, `total_list` and `total_pages`
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
## Development
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
# Install in editable mode
|
|
163
|
+
pip install -e .
|
|
164
|
+
|
|
165
|
+
# Run unit tests
|
|
166
|
+
python -m pytest businnect/tests/test_businnect_unit.py -v
|
|
167
|
+
|
|
168
|
+
# Run integration tests (requires real API token)
|
|
169
|
+
BUSINNECT_API_TOKEN=your_token python -m pytest businnect/tests/test_businnect_integration.py -v -s
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## License
|
|
173
|
+
|
|
174
|
+
MIT
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from businnect.settings import DEFAULT_API_SERVER
|
|
2
|
+
from businnect.resources.micropost import MicropostResource
|
|
3
|
+
from businnect.resources.blog import BlogResource
|
|
4
|
+
import requests
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class Businnect:
|
|
8
|
+
"""
|
|
9
|
+
Cliente para a API Businnect.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
api_token: Seu token de API. Gere em https://businnect.com/settings/developer
|
|
13
|
+
base_url: URL base da API. Padrão: servidor Businnect.
|
|
14
|
+
|
|
15
|
+
Example:
|
|
16
|
+
client = Businnect(api_token="seu_token_aqui")
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
api_token: str,
|
|
22
|
+
base_url: str = DEFAULT_API_SERVER,
|
|
23
|
+
) -> None:
|
|
24
|
+
self.api_token = api_token
|
|
25
|
+
self.base_url = base_url
|
|
26
|
+
self._headers = {"USER-API-TOKEN": api_token}
|
|
27
|
+
|
|
28
|
+
self.micropost = MicropostResource(self)
|
|
29
|
+
self.blog = BlogResource(self)
|
|
30
|
+
|
|
31
|
+
def _request(self, method: str, path: str, **kwargs) -> requests.Response:
|
|
32
|
+
url = f"{self.base_url}{path}"
|
|
33
|
+
extra_headers = kwargs.pop("headers", {})
|
|
34
|
+
headers = {**self._headers, **extra_headers}
|
|
35
|
+
response = requests.request(method, url, headers=headers, **kwargs)
|
|
36
|
+
response.raise_for_status()
|
|
37
|
+
return response
|
|
File without changes
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
from businnect.schemas.blog import BlogResponse, BlogListResponse
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from ..client import Businnect
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class BlogResource:
|
|
10
|
+
def __init__(self, client: "Businnect"):
|
|
11
|
+
self._client = client
|
|
12
|
+
|
|
13
|
+
def client_get_admin_blog(self) -> Optional[BlogResponse]:
|
|
14
|
+
"""
|
|
15
|
+
Retorna um artigo público do admin.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
BlogResponse ou None se não houver artigo.
|
|
19
|
+
"""
|
|
20
|
+
response = self._client._request("GET", "/api/v1/client/admin/blog")
|
|
21
|
+
data = response.json()
|
|
22
|
+
if data is None:
|
|
23
|
+
return None
|
|
24
|
+
return BlogResponse(**data)
|
|
25
|
+
|
|
26
|
+
def client_list_admin_blogs(self) -> BlogListResponse:
|
|
27
|
+
"""
|
|
28
|
+
Retorna a lista de artigos públicos do admin.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
BlogListResponse com list, total_list e total_pages.
|
|
32
|
+
"""
|
|
33
|
+
response = self._client._request("GET", "/api/v1/client/admin/blog/list")
|
|
34
|
+
return BlogListResponse(**response.json())
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from typing import TYPE_CHECKING, Optional
|
|
3
|
+
from requests_toolbelt.multipart.encoder import MultipartEncoder
|
|
4
|
+
|
|
5
|
+
from businnect.schemas.micropost import PostType
|
|
6
|
+
from businnect.schemas.common import CreatedWithPublicIdAndLinkResponse, VoteResponse
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from ..client import Businnect
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MicropostResource:
|
|
13
|
+
def __init__(self, client: "Businnect"):
|
|
14
|
+
self._client = client
|
|
15
|
+
|
|
16
|
+
def client_create_micropost(
|
|
17
|
+
self,
|
|
18
|
+
body: str,
|
|
19
|
+
title: Optional[str] = None,
|
|
20
|
+
post_type: PostType = PostType.TEXT,
|
|
21
|
+
community_name: Optional[str] = None,
|
|
22
|
+
parent_micropost_public_id: Optional[str] = None,
|
|
23
|
+
parent_micropost_comment_public_id: Optional[str] = None,
|
|
24
|
+
allow_comments: bool = True,
|
|
25
|
+
is_draft: bool = False,
|
|
26
|
+
file: Optional[tuple] = None,
|
|
27
|
+
) -> CreatedWithPublicIdAndLinkResponse:
|
|
28
|
+
"""
|
|
29
|
+
Cria um micropost (texto, mídia ou reply).
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
body: Conteúdo do post.
|
|
33
|
+
title: Obrigatório para posts originais.
|
|
34
|
+
post_type: "TEXT" ou "MEDIA". Padrão: TEXT.
|
|
35
|
+
community_name: Comunidade onde postar (opcional).
|
|
36
|
+
parent_micropost_public_id: Para replies a um post.
|
|
37
|
+
parent_micropost_comment_public_id: Para replies aninhados.
|
|
38
|
+
allow_comments: Se permite comentários. Padrão: True.
|
|
39
|
+
is_draft: Salvar como rascunho. Padrão: False.
|
|
40
|
+
file: Tuple (filename, file_object, mime_type) para posts MEDIA.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
CreatedWithPublicIdAndLinkResponse com public_id e link.
|
|
44
|
+
"""
|
|
45
|
+
fields = {
|
|
46
|
+
"body": body,
|
|
47
|
+
"post_type": post_type,
|
|
48
|
+
"allow_comments": str(allow_comments).lower(),
|
|
49
|
+
"is_draft": str(is_draft).lower(),
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if title:
|
|
53
|
+
fields["title"] = title
|
|
54
|
+
if community_name:
|
|
55
|
+
fields["community_name"] = community_name
|
|
56
|
+
if parent_micropost_public_id:
|
|
57
|
+
fields["parent_micropost_public_id"] = parent_micropost_public_id
|
|
58
|
+
if parent_micropost_comment_public_id:
|
|
59
|
+
fields["parent_micropost_comment_public_id"] = parent_micropost_comment_public_id
|
|
60
|
+
if file:
|
|
61
|
+
fields["file"] = file
|
|
62
|
+
|
|
63
|
+
m = MultipartEncoder(fields=fields)
|
|
64
|
+
|
|
65
|
+
response = self._client._request(
|
|
66
|
+
"POST",
|
|
67
|
+
"/api/v1/client/micropost",
|
|
68
|
+
data=m,
|
|
69
|
+
headers={"Content-Type": m.content_type},
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
return CreatedWithPublicIdAndLinkResponse(**response.json())
|
|
73
|
+
|
|
74
|
+
def client_delete_micropost(self, public_id: str) -> None:
|
|
75
|
+
"""
|
|
76
|
+
Deleta um micropost pelo public_id.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
public_id: ID público do post a ser deletado.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
None (204 No Content em caso de sucesso).
|
|
83
|
+
"""
|
|
84
|
+
self._client._request(
|
|
85
|
+
"DELETE",
|
|
86
|
+
"/api/v1/client/micropost",
|
|
87
|
+
json={"public_id": public_id},
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
def client_vote_micropost(self, public_id: str) -> VoteResponse:
|
|
91
|
+
"""
|
|
92
|
+
Vota ou remove o voto de um micropost (toggle).
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
public_id: ID público do post.
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
VoteResponse com user_voted (bool).
|
|
99
|
+
"""
|
|
100
|
+
response = self._client._request(
|
|
101
|
+
"PATCH",
|
|
102
|
+
"/api/v1/client/micropost/vote",
|
|
103
|
+
json={"public_id": public_id},
|
|
104
|
+
)
|
|
105
|
+
return VoteResponse(**response.json())
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
from enum import Enum, unique
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@unique
|
|
8
|
+
class BlogCategory(str, Enum):
|
|
9
|
+
ANNOUNCEMENT = "ANNOUNCEMENT"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class BlogItem(BaseModel):
|
|
13
|
+
body: str
|
|
14
|
+
category: BlogCategory
|
|
15
|
+
cover: Optional[str] = None
|
|
16
|
+
is_featured: bool
|
|
17
|
+
published_at: str
|
|
18
|
+
slug: str
|
|
19
|
+
summary: Optional[str] = None
|
|
20
|
+
title: str
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class BlogResponse(BaseModel):
|
|
24
|
+
body: str
|
|
25
|
+
category: BlogCategory
|
|
26
|
+
cover: Optional[str] = None
|
|
27
|
+
is_featured: bool
|
|
28
|
+
published_at: str
|
|
29
|
+
slug: str
|
|
30
|
+
summary: Optional[str] = None
|
|
31
|
+
title: str
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class BlogListResponse(BaseModel):
|
|
35
|
+
list: List[BlogItem]
|
|
36
|
+
total_list: int
|
|
37
|
+
total_pages: int
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DEFAULT_API_SERVER = "https://api.businnect.com"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Unit tests
|
|
2
|
+
|
|
3
|
+
import httpx
|
|
4
|
+
import pytest
|
|
5
|
+
from unittest.mock import MagicMock, patch
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import os
|
|
9
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
10
|
+
|
|
11
|
+
from client import Businnect
|
|
12
|
+
|
|
13
|
+
# $pip install -e .
|
|
14
|
+
# $BUSINNECT_API_TOKEN=yours python -m pytest businnect/tests/test_businnect_integration.py -v -s
|
|
15
|
+
# @pytest.mark.skip(reason="already tested")
|
|
16
|
+
def test_client_create_micropost():
|
|
17
|
+
client = Businnect(api_token=os.environ["BUSINNECT_API_TOKEN"])
|
|
18
|
+
try:
|
|
19
|
+
response = client.micropost.client_create_micropost(title="Test", body="Hello")
|
|
20
|
+
assert response.public_id is not None
|
|
21
|
+
except Exception as e:
|
|
22
|
+
if hasattr(e, 'response'):
|
|
23
|
+
print(repr(e.response.text))
|
|
24
|
+
raise
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
# Testes unitários
|
|
2
|
+
# pip install -e .
|
|
3
|
+
# pytest businnect/tests/test_businnect_unit.py -v
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
from unittest.mock import MagicMock, patch
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import os
|
|
10
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))
|
|
11
|
+
|
|
12
|
+
from client import Businnect
|
|
13
|
+
from settings import DEFAULT_API_SERVER
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.fixture
|
|
17
|
+
def client():
|
|
18
|
+
return Businnect(api_token="test_token")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# --- Client ---
|
|
22
|
+
|
|
23
|
+
def test_init(client):
|
|
24
|
+
assert client.api_token == "test_token"
|
|
25
|
+
assert client._headers == {"USER-API-TOKEN": "test_token"}
|
|
26
|
+
assert client.base_url == DEFAULT_API_SERVER
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@patch("businnect.client.requests.request")
|
|
30
|
+
def test_request_success(mock_request, client):
|
|
31
|
+
mock_response = MagicMock()
|
|
32
|
+
mock_response.status_code = 200
|
|
33
|
+
mock_request.return_value = mock_response
|
|
34
|
+
|
|
35
|
+
response = client._request("GET", "/some/path")
|
|
36
|
+
|
|
37
|
+
mock_request.assert_called_once_with(
|
|
38
|
+
"GET",
|
|
39
|
+
f"{DEFAULT_API_SERVER}/some/path",
|
|
40
|
+
headers={"USER-API-TOKEN": "test_token"},
|
|
41
|
+
)
|
|
42
|
+
assert response == mock_response
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@patch("businnect.client.requests.request")
|
|
46
|
+
def test_request_raises_on_error(mock_request, client):
|
|
47
|
+
import requests as req
|
|
48
|
+
mock_response = MagicMock()
|
|
49
|
+
mock_response.raise_for_status.side_effect = req.exceptions.HTTPError("404")
|
|
50
|
+
mock_request.return_value = mock_response
|
|
51
|
+
|
|
52
|
+
with pytest.raises(req.exceptions.HTTPError):
|
|
53
|
+
client._request("GET", "/bad/path")
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
# --- Micropost ---
|
|
57
|
+
|
|
58
|
+
@patch("businnect.resources.micropost.MultipartEncoder")
|
|
59
|
+
def test_create_micropost(mock_encoder, client):
|
|
60
|
+
mock_m = MagicMock()
|
|
61
|
+
mock_m.content_type = "multipart/form-data; boundary=abc"
|
|
62
|
+
mock_encoder.return_value = mock_m
|
|
63
|
+
|
|
64
|
+
mock_response = MagicMock()
|
|
65
|
+
mock_response.json.return_value = {"public_id": "abc123", "link": "https://businnect.com/p/abc123"}
|
|
66
|
+
client._request = MagicMock(return_value=mock_response)
|
|
67
|
+
|
|
68
|
+
result = client.micropost.client_create_micropost(title="Teste", body="Olá mundo")
|
|
69
|
+
|
|
70
|
+
assert result.public_id == "abc123"
|
|
71
|
+
assert result.link == "https://businnect.com/p/abc123"
|
|
72
|
+
client._request.assert_called_once()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def test_delete_micropost(client):
|
|
76
|
+
client._request = MagicMock()
|
|
77
|
+
client.micropost.client_delete_micropost(public_id="abc123")
|
|
78
|
+
client._request.assert_called_once_with(
|
|
79
|
+
"DELETE",
|
|
80
|
+
"/api/v1/client/micropost",
|
|
81
|
+
json={"public_id": "abc123"},
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def test_vote_micropost(client):
|
|
86
|
+
mock_response = MagicMock()
|
|
87
|
+
mock_response.json.return_value = {"user_voted": True}
|
|
88
|
+
client._request = MagicMock(return_value=mock_response)
|
|
89
|
+
|
|
90
|
+
result = client.micropost.client_vote_micropost(public_id="abc123")
|
|
91
|
+
|
|
92
|
+
assert result.user_voted is True
|
|
93
|
+
client._request.assert_called_once_with(
|
|
94
|
+
"PATCH",
|
|
95
|
+
"/api/v1/client/micropost/vote",
|
|
96
|
+
json={"public_id": "abc123"},
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# --- Blog ---
|
|
101
|
+
|
|
102
|
+
def test_get_admin_blog_none(client):
|
|
103
|
+
mock_response = MagicMock()
|
|
104
|
+
mock_response.json.return_value = None
|
|
105
|
+
client._request = MagicMock(return_value=mock_response)
|
|
106
|
+
|
|
107
|
+
result = client.blog.client_get_admin_blog()
|
|
108
|
+
assert result is None
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def test_list_admin_blogs(client):
|
|
112
|
+
mock_response = MagicMock()
|
|
113
|
+
mock_response.json.return_value = {
|
|
114
|
+
"list": [
|
|
115
|
+
{
|
|
116
|
+
"body": "Conteúdo",
|
|
117
|
+
"category": "ANNOUNCEMENT",
|
|
118
|
+
"is_featured": True,
|
|
119
|
+
"published_at": "2026-03-25T16:17:12.799Z",
|
|
120
|
+
"slug": "meu-artigo",
|
|
121
|
+
"title": "Meu Artigo",
|
|
122
|
+
}
|
|
123
|
+
],
|
|
124
|
+
"total_list": 1,
|
|
125
|
+
"total_pages": 1,
|
|
126
|
+
}
|
|
127
|
+
client._request = MagicMock(return_value=mock_response)
|
|
128
|
+
|
|
129
|
+
result = client.blog.client_list_admin_blogs()
|
|
130
|
+
assert result.total_list == 1
|
|
131
|
+
assert result.list[0].slug == "meu-artigo"
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: businnect
|
|
3
|
+
Version: 0.0.2
|
|
4
|
+
Summary: Python SDK for the Businnect API
|
|
5
|
+
Requires-Python: >=3.9
|
|
6
|
+
Description-Content-Type: text/markdown
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Requires-Dist: requests>=2.32.0
|
|
9
|
+
Requires-Dist: requests-toolbelt>=1.0.0
|
|
10
|
+
Requires-Dist: pydantic>=2.0.0
|
|
11
|
+
Dynamic: license-file
|
|
12
|
+
|
|
13
|
+
# Businnect Python
|
|
14
|
+
|
|
15
|
+
The official Python SDK for the [Businnect](https://businnect.com) API.
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install businnect
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
Find your API token at [https://businnect.com/settings/developer](https://businnect.com/settings/developer) after creating an account at [https://businnect.com/register](https://businnect.com/register).
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from businnect import Businnect
|
|
29
|
+
|
|
30
|
+
client = Businnect(api_token="your_api_token_here")
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Micropost
|
|
36
|
+
|
|
37
|
+
### Create a post
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from businnect.schemas.micropost import PostType
|
|
41
|
+
|
|
42
|
+
# Text post
|
|
43
|
+
post = client.micropost.client_create_micropost(
|
|
44
|
+
title="Hello World",
|
|
45
|
+
body="This is my first post.",
|
|
46
|
+
)
|
|
47
|
+
print(post.public_id)
|
|
48
|
+
print(post.link)
|
|
49
|
+
|
|
50
|
+
# Media post
|
|
51
|
+
with open("photo.png", "rb") as f:
|
|
52
|
+
post = client.micropost.client_create_micropost(
|
|
53
|
+
title="My photo",
|
|
54
|
+
body="Check this out",
|
|
55
|
+
post_type=PostType.MEDIA,
|
|
56
|
+
file=("photo.png", f, "image/png"),
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
# Reply to a post
|
|
60
|
+
reply = client.micropost.client_create_micropost(
|
|
61
|
+
body="Great post!",
|
|
62
|
+
parent_micropost_public_id="post_public_id_here",
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Nested reply (reply to a comment)
|
|
66
|
+
nested = client.micropost.client_create_micropost(
|
|
67
|
+
body="I agree!",
|
|
68
|
+
parent_micropost_public_id="post_public_id_here",
|
|
69
|
+
parent_micropost_comment_public_id="comment_public_id_here",
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Delete a post
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
client.micropost.client_delete_micropost(public_id="post_public_id_here")
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Vote on a post (toggle)
|
|
80
|
+
|
|
81
|
+
```python
|
|
82
|
+
result = client.micropost.client_vote_micropost(public_id="post_public_id_here")
|
|
83
|
+
print(result.user_voted) # True or False
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Blog
|
|
89
|
+
|
|
90
|
+
### Get admin article
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
article = client.blog.client_get_admin_blog()
|
|
94
|
+
if article:
|
|
95
|
+
print(article.title)
|
|
96
|
+
print(article.body)
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### List admin articles
|
|
100
|
+
|
|
101
|
+
```python
|
|
102
|
+
result = client.blog.client_list_admin_blogs()
|
|
103
|
+
print(result.total_list)
|
|
104
|
+
for article in result.list:
|
|
105
|
+
print(article.title, article.slug)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## API Reference
|
|
111
|
+
|
|
112
|
+
### `Businnect(api_token, base_url?)`
|
|
113
|
+
|
|
114
|
+
| Parameter | Type | Description |
|
|
115
|
+
|-----------|------|-------------|
|
|
116
|
+
| `api_token` | `str` | Your API token |
|
|
117
|
+
| `base_url` | `str` | API base URL (default: `https://api.businnect.com`) |
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### `client.micropost.client_create_micropost(...)`
|
|
122
|
+
|
|
123
|
+
| Parameter | Type | Default | Description |
|
|
124
|
+
|-----------|------|---------|-------------|
|
|
125
|
+
| `body` | `str` | required | Content of the post |
|
|
126
|
+
| `title` | `str` | `None` | Required for original posts |
|
|
127
|
+
| `post_type` | `PostType` | `PostType.TEXT` | `TEXT` or `MEDIA` |
|
|
128
|
+
| `community_name` | `str` | `None` | Community to post in |
|
|
129
|
+
| `parent_micropost_public_id` | `str` | `None` | For replies |
|
|
130
|
+
| `parent_micropost_comment_public_id` | `str` | `None` | For nested replies |
|
|
131
|
+
| `allow_comments` | `bool` | `True` | Whether comments are allowed |
|
|
132
|
+
| `is_draft` | `bool` | `False` | Save as draft |
|
|
133
|
+
| `file` | `tuple` | `None` | `(filename, file_object, mime_type)` for MEDIA posts |
|
|
134
|
+
|
|
135
|
+
**Returns:** `CreatedWithPublicIdAndLinkResponse` with `public_id` and `link`
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
### `client.micropost.client_delete_micropost(public_id)`
|
|
140
|
+
|
|
141
|
+
| Parameter | Type | Description |
|
|
142
|
+
|-----------|------|-------------|
|
|
143
|
+
| `public_id` | `str` | Public ID of the post to delete |
|
|
144
|
+
|
|
145
|
+
**Returns:** `None` (204 on success)
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
### `client.micropost.client_vote_micropost(public_id)`
|
|
150
|
+
|
|
151
|
+
| Parameter | Type | Description |
|
|
152
|
+
|-----------|------|-------------|
|
|
153
|
+
| `public_id` | `str` | Public ID of the post to vote on |
|
|
154
|
+
|
|
155
|
+
**Returns:** `VoteResponse` with `user_voted` (bool)
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### `client.blog.client_get_admin_blog()`
|
|
160
|
+
|
|
161
|
+
**Returns:** `BlogResponse` or `None`
|
|
162
|
+
|
|
163
|
+
---
|
|
164
|
+
|
|
165
|
+
### `client.blog.client_list_admin_blogs()`
|
|
166
|
+
|
|
167
|
+
**Returns:** `BlogListResponse` with `list`, `total_list` and `total_pages`
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Development
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
# Install in editable mode
|
|
175
|
+
pip install -e .
|
|
176
|
+
|
|
177
|
+
# Run unit tests
|
|
178
|
+
python -m pytest businnect/tests/test_businnect_unit.py -v
|
|
179
|
+
|
|
180
|
+
# Run integration tests (requires real API token)
|
|
181
|
+
BUSINNECT_API_TOKEN=your_token python -m pytest businnect/tests/test_businnect_integration.py -v -s
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## License
|
|
185
|
+
|
|
186
|
+
MIT
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
businnect/__init__.py
|
|
5
|
+
businnect/client.py
|
|
6
|
+
businnect/settings.py
|
|
7
|
+
businnect.egg-info/PKG-INFO
|
|
8
|
+
businnect.egg-info/SOURCES.txt
|
|
9
|
+
businnect.egg-info/dependency_links.txt
|
|
10
|
+
businnect.egg-info/requires.txt
|
|
11
|
+
businnect.egg-info/top_level.txt
|
|
12
|
+
businnect/resources/__init__.py
|
|
13
|
+
businnect/resources/blog.py
|
|
14
|
+
businnect/resources/micropost.py
|
|
15
|
+
businnect/schemas/__init__.py
|
|
16
|
+
businnect/schemas/blog.py
|
|
17
|
+
businnect/schemas/common.py
|
|
18
|
+
businnect/schemas/micropost.py
|
|
19
|
+
businnect/tests/test_businnect_integration.py
|
|
20
|
+
businnect/tests/test_businnect_unit.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
businnect
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "businnect"
|
|
7
|
+
# version = "0.0.3" # Test
|
|
8
|
+
version = "0.0.2" # Prod
|
|
9
|
+
description = "Python SDK for the Businnect API"
|
|
10
|
+
readme = "README.md"
|
|
11
|
+
requires-python = ">=3.9"
|
|
12
|
+
dependencies = [
|
|
13
|
+
# "httpx>=0.27.0"
|
|
14
|
+
"requests>=2.32.0",
|
|
15
|
+
"requests-toolbelt>=1.0.0",
|
|
16
|
+
"pydantic>=2.0.0"
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[tool.setuptools.packages.find]
|
|
20
|
+
include = ["businnect*"]
|