apitable 1.4.0__tar.gz → 2.0.0b4__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.
Files changed (60) hide show
  1. {apitable-1.4.0 → apitable-2.0.0b4}/PKG-INFO +18 -11
  2. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/datasheet.py +12 -1
  3. {apitable-1.4.0 → apitable-2.0.0b4}/pyproject.toml +1 -1
  4. apitable-1.4.0/apitable.egg-info/PKG-INFO +0 -310
  5. apitable-1.4.0/apitable.egg-info/SOURCES.txt +0 -58
  6. apitable-1.4.0/apitable.egg-info/dependency_links.txt +0 -1
  7. apitable-1.4.0/apitable.egg-info/requires.txt +0 -3
  8. apitable-1.4.0/apitable.egg-info/top_level.txt +0 -1
  9. apitable-1.4.0/setup.cfg +0 -4
  10. apitable-1.4.0/setup.py +0 -28
  11. apitable-1.4.0/test/test_apitable.py +0 -18
  12. apitable-1.4.0/test/test_create_datasheet.py +0 -30
  13. apitable-1.4.0/test/test_create_embed_link.py +0 -58
  14. apitable-1.4.0/test/test_create_field.py +0 -43
  15. apitable-1.4.0/test/test_create_records.py +0 -38
  16. apitable-1.4.0/test/test_delete_field.py +0 -37
  17. apitable-1.4.0/test/test_delete_records.py +0 -37
  18. apitable-1.4.0/test/test_get_fields.py +0 -31
  19. apitable-1.4.0/test/test_get_nodes.py +0 -32
  20. apitable-1.4.0/test/test_get_records.py +0 -45
  21. apitable-1.4.0/test/test_get_spaces.py +0 -25
  22. apitable-1.4.0/test/test_get_views.py +0 -24
  23. apitable-1.4.0/test/test_unit.py +0 -91
  24. apitable-1.4.0/test/test_update_records.py +0 -73
  25. apitable-1.4.0/test/test_upload_file.py +0 -32
  26. apitable-1.4.0/test/test_utils.py +0 -26
  27. {apitable-1.4.0 → apitable-2.0.0b4}/LICENSE +0 -0
  28. {apitable-1.4.0 → apitable-2.0.0b4}/README.md +0 -0
  29. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/__init__.py +0 -0
  30. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/apitable.py +0 -0
  31. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/const.py +0 -0
  32. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/__init__.py +0 -0
  33. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/datasheet_manager.py +0 -0
  34. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/field_manager.py +0 -0
  35. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/query_set.py +0 -0
  36. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/record.py +0 -0
  37. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/record_manager.py +0 -0
  38. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/datasheet/view_manager.py +0 -0
  39. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/exceptions.py +0 -0
  40. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/node/__init__.py +0 -0
  41. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/node/node_manager.py +0 -0
  42. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/request.py +0 -0
  43. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/space/__init__.py +0 -0
  44. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/space/space.py +0 -0
  45. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/space/space_manager.py +0 -0
  46. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/__init__.py +0 -0
  47. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/embedlink.py +0 -0
  48. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/field.py +0 -0
  49. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/node.py +0 -0
  50. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/record.py +0 -0
  51. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/response.py +0 -0
  52. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/space.py +0 -0
  53. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/unit_model.py +0 -0
  54. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/types/view.py +0 -0
  55. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/unit/__init__.py +0 -0
  56. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/unit/member.py +0 -0
  57. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/unit/role.py +0 -0
  58. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/unit/team.py +0 -0
  59. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/unit/unit.py +0 -0
  60. {apitable-1.4.0 → apitable-2.0.0b4}/apitable/utils.py +0 -0
@@ -1,19 +1,25 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: apitable
3
- Version: 1.4.0
4
- Summary: Apitable Python SDK
5
- Home-page: https://github.com/apitable/apitable-sdks
6
- Author: apitable
3
+ Version: 2.0.0b4
4
+ Summary: APITable OpenAPI Python SDK
5
+ Author: APITable Ltd.
7
6
  Author-email: dev@apitable.com
7
+ Requires-Python: >=3.8,<4.0
8
8
  Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.6
9
+ Classifier: Programming Language :: Python :: 3.8
10
+ Classifier: Programming Language :: Python :: 3.9
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Requires-Dist: certifi (>=2023.7.22,<2024.0.0)
14
+ Requires-Dist: charset-normalizer (>=3.2.0,<4.0.0)
15
+ Requires-Dist: environs (>=9.5.0,<10.0.0)
16
+ Requires-Dist: idna (>=3.4,<4.0)
17
+ Requires-Dist: marshmallow (>=3.20.1,<4.0.0)
18
+ Requires-Dist: pydantic (==2.4.2)
19
+ Requires-Dist: python-dotenv (>=1.0.0,<2.0.0)
20
+ Requires-Dist: requests (>=2.31.0,<3.0.0)
21
+ Requires-Dist: urllib3 (>=2.0.4,<3.0.0)
12
22
  Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: requests<=2.31.0
15
- Requires-Dist: pydantic==1.7
16
- Requires-Dist: environs<=9.5.0
17
23
 
18
24
  # APITable.py
19
25
 
@@ -308,3 +314,4 @@ pipenv install --pre
308
314
  pipenv shell
309
315
  python -m unittest test
310
316
  ```
317
+
@@ -57,6 +57,11 @@ class Datasheet:
57
57
  return urljoin(self.apitable.api_base,
58
58
  f"/fusion/v1/datasheets/{self.id}/records")
59
59
 
60
+ @property
61
+ def _record_api_endpoint_v3(self):
62
+ return urljoin(self.apitable.api_base,
63
+ f"/fusion/v3/datasheets/{self.id}/records")
64
+
60
65
  @property
61
66
  @timed_lru_cache(seconds=300)
62
67
  def fields(self):
@@ -137,6 +142,12 @@ class Datasheet:
137
142
  """
138
143
  Paginate to get data
139
144
  """
145
+
146
+ is_v3 = bool(kwargs.get("isV3", False))
147
+ endpoint = self._record_api_endpoint
148
+ if is_v3:
149
+ endpoint = self._record_api_endpoint_v3
150
+
140
151
  params = {}
141
152
  for key in kwargs:
142
153
  if key in API_GET_DATASHEET_QS_SET:
@@ -147,7 +158,7 @@ class Datasheet:
147
158
  else:
148
159
  raise ErrorSortParams('The format of the sort parameter is incorrect')
149
160
  params.update({key: params_value})
150
- resp = self.apitable.request.get(self._record_api_endpoint, params=params)
161
+ resp = self.apitable.request.get(endpoint, params=params)
151
162
  return handle_response(resp, GETRecordResponse)
152
163
 
153
164
  def get_records_all(self, **kwargs) -> List[RawRecord]:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "apitable"
3
- version = "1.4.0"
3
+ version = "2.0.0-beta.4"
4
4
  description = "APITable OpenAPI Python SDK"
5
5
  authors = ["APITable Ltd. <dev@apitable.com>"]
6
6
  readme = "README.md"
@@ -1,310 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: apitable
3
- Version: 1.4.0
4
- Summary: Apitable Python SDK
5
- Home-page: https://github.com/apitable/apitable-sdks
6
- Author: apitable
7
- Author-email: dev@apitable.com
8
- Classifier: Programming Language :: Python :: 3
9
- Classifier: License :: OSI Approved :: MIT License
10
- Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.6
12
- Description-Content-Type: text/markdown
13
- License-File: LICENSE
14
- Requires-Dist: requests<=2.31.0
15
- Requires-Dist: pydantic==1.7
16
- Requires-Dist: environs<=9.5.0
17
-
18
- # APITable.py
19
-
20
- [![Latest Version](https://shields.mitmproxy.org/pypi/v/apitable.svg)](https://pypi.python.org/pypi/apitable)
21
-
22
- It is the official package for the Fusion API of APITable, and provides an API similar to the Django ORM style.
23
-
24
- # Requirements
25
-
26
- python3.6 +
27
-
28
- If you want to call apitable rest api, you need get the API Token first: visit the workbench of APITable, click the avatar in the lower left corner, and go to User Center > Developer Configuration. Click to generate Token (you need to bind your email for the first time).
29
-
30
- # Installation
31
-
32
- ```shell
33
- pip install --upgrade apitable
34
- ```
35
-
36
- # Getting started
37
-
38
- ## Example
39
-
40
- ```python
41
- from apitable import Apitable
42
-
43
- apitable = Apitable("your api_token")
44
-
45
- dst = apitable.datasheet("your datasheet id")
46
- # When the URL is used as a parameter, the datasheet id is automatically resolved, ignoring the view id.
47
- # dst = apitable.datasheet("https://apitable.com/workbench/dstxxxxxxxx/viwxxxxxxxx")
48
-
49
- # Create a record
50
- record = dst.records.create({"title": "new record from Python SDK"})
51
- print(record.title)
52
-
53
- # Create records in bulk
54
- records = dst.records.bulk_create([
55
- {"title": "new record from Python SDK"},
56
- {"title": "new record from Python SDK2"}
57
- ])
58
-
59
- # Update a single field
60
- record.title = "new title"
61
- print(record.title)
62
- # "new title"
63
-
64
- # Update multiple fields
65
- record.update({
66
- "title": "new title",
67
- "other_field": "new value",
68
- })
69
-
70
- # Batch update multiple records
71
- records = dst.records.bulk_update([
72
- {"recordId": "recxxxxx1", "fields":{"title": "new record.title from Python SDK"}},
73
- {"recordId": "recxxxxx2", "fields":{"title": "new record.title from Python SDK2"}},
74
- ])
75
-
76
- # Attachment field update
77
- my_file = dst.upload_file( <local or network file path>)
78
- record.files = [my_file]
79
-
80
- # Filter record
81
- songs = dst_songs.records.filter(artist="faye wong")
82
- for song in songs:
83
- print(song.title)
84
-
85
- # Batch update a batch of records
86
- dst_tasks.records.filter(title=None).update(status="Pending")
87
-
88
- # Get a single record
89
- book = dst_book.records.get(ISBN="9787506341271")
90
- print(book.title)
91
-
92
- # Convert the record object to json
93
- record.json()
94
-
95
- # Delete a batch of records that match the filter criteria
96
- dst.records.filter(title=None).delete()
97
-
98
- # Get fields
99
- for field in apitable.datasheet("dstId").fields.all():
100
- print(field.name)
101
-
102
- # Get the fields of the specified view, hidden fields will not be returned
103
- for field in apitable.datasheet("dstId").fields.all(viewId="viewId"):
104
- print(field.name)
105
-
106
- # Get views
107
- for view in apitable.datasheet("dstId").views.all():
108
- print(view.name)
109
-
110
- ```
111
-
112
- ## Field mapping
113
-
114
- Using the field name of the datasheet directly as a variable may not conform to the variable specification. So you have to fall back to using fieldId as the key, making the code less readable.
115
-
116
- In order to solve this problem, the Python SDK provides the function of field mapping.
117
-
118
- | Bug title\! | Bug status |
119
- | --------------------------------- | ---------- |
120
- | The page crashes after logging in | Waiting |
121
-
122
- ```python
123
- dst = apitable.datasheet("dstt3KGCKtp11fgK0t",field_key_map={
124
- "title": "Bug title!",
125
- "state": "Bug status",
126
- })
127
-
128
- record = dst.records.get()
129
- print(record.title)
130
- # "The page crashes after logging in"
131
- print(record.state)
132
- # "Waiting"
133
- record.state="Done"
134
- ```
135
-
136
- Keep the use of field id as the key
137
-
138
- ```python
139
- bug = apitable.datasheet("dstn2lEFltyGHe2j86", field_key="id")
140
- row = bug.records.get(flddpSLHEzDPQ="The page crashes after logging in")
141
- row.flddpSLHEzDPQ = "The page crashes after logging in"
142
- row.update({
143
- "flddpSLHEzDPQ": "The page crashes after logging in",
144
- "fldwvNDf9teD2": "Done"
145
- })
146
- ```
147
-
148
- When specifying `field_key="id"`, specify the corresponding key value of `field_key_map` should be `fieldId`
149
-
150
- ```python
151
- bug = apitable.datasheet("dstn2lEFltyGHe2j86", field_key="id", field_key_map={
152
- "title": "flddpSLHEzDPQ",
153
- "state": "fldwvNDf9teD2",
154
- })
155
- ```
156
-
157
- # Documentation
158
-
159
- ## records
160
-
161
- `dst.records` manage records in datasheets.
162
-
163
- | Method | Parameter | Type | Description | Example |
164
- | ---------------- | --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------- |
165
- | create | dict | Record | Create a single record | `dst.records.create({"title":"new title"})` |
166
- | bulk_create | dict[] | Record[] | Create multiple records in batches | `dst.records.bulk_create([{"title":"new record1"},{"title":"new record2"}])` |
167
- | bulk_update | dict[] | Record[] | Batch update multiple records | `dst.records.bulk_update([{"recordId": "recxxxxx1", "fields":{"title": "new record.title from Python SDK"}}])` |
168
- | all | \*\*kwargs | QuerySet | Return the record collection, you can pass parameters to customize the return content | `dst.records.all()` |
169
- | get | \*\*kwargs | Record | single record | `dst.records.get(title="new title")` |
170
- | get_or_create | (defaults,\*\*kwargs) | Record,bool | Query the corresponding record through kwargs. If it does not exist, create a new record in combination with defaults. The returned bool indicates whether it is a new record. | `dst.records.get_or_create(title="new title",defaults={"status":"pending"})` |
171
- | update_or_create | (defaults,\*\*kwargs) | Record,bool | Query the corresponding record through kwargs, and update the record with defaults. Create if it does not exist (same as get_or_create) | `dst.records.update_or_create(title="new title",defaults={"status":"done"})` |
172
- | filter | \*\*kwargs | QuerySet | Filter a batch of records | `dst.records.filter(title="new title")` |
173
-
174
- ## QuerySet
175
-
176
- Chained calls are possible. For example, `qs = dst.records.all()` returns a batch of queried datasets.
177
-
178
- | Method | Parameter | Type | Description | Example |
179
- | ------ | --------- | -------- | ---------------------------------------- | -------------------------------------------------------- |
180
- | filter | \*\*dict | QuerySet | Filter out a batch of records | `qs.filter(title="new title")` |
181
- | all | / | QuerySet | Returns a copy of the current record set | `qs.filter(title="new title").all()` |
182
- | get | \*\*dict | Record | Single record | `qs.get(title="new title")` |
183
- | count | / | int | Total number of records | `qs.filter(title="new title").count()` |
184
- | last | / | Record | Last record | `qs.filter(title="new title").last()` |
185
- | first | / | Record | First record | `qs.filter(title="new title").first()` |
186
- | update | \*\*dict | Record | Number of records successfully updated | `qs.filter(title="new title").update(title="new title")` |
187
- | delete | / | bool | Whether the deletion is successful | `qs.filter(title="new title").delete()` |
188
-
189
- ## Record
190
-
191
- The QuerySet queried out is a collection of Records. A single Record can obtain the value of the specified field through `record.fieldname`.
192
-
193
- **Please try to avoid the same name of the field name and the method property reserved by Record, the field with the same name in the table will be obscured. If it does exist, use the field mapping configuration**
194
-
195
- | Method/Attribute | Parameter | Type | Description | Example |
196
- | ---------------- | --------- | ---- | ------------------------------------------------------------------------ | --------------- |
197
- | json | / | dict | Returns all field values of the current record | `record.json()` |
198
- | \_id | / | str | \_id is a reserved attribute, returns the recordId of the current record | `record._id` |
199
-
200
- ## Field
201
-
202
- The mapping relationship between Field and Python data structure. The data with empty cells in the datasheet is always null, and the records returned by the API will not contain fields with null values.
203
-
204
- | Field Type | Data type |
205
- | ---------------- | ------------------- |
206
- | SingleText | str |
207
- | Text | str |
208
- | SingleSelect | str |
209
- | MultiSelect | str[] |
210
- | URL | str |
211
- | Phone | str |
212
- | Email | str |
213
- | Number | number |
214
- | Currency | number |
215
- | Percent | number |
216
- | AutoNumber | number |
217
- | DateTime | number |
218
- | CreatedTime | number |
219
- | LastModifiedTime | number |
220
- | Attachment | attachment object[] |
221
- | Member | unit object[] |
222
- | Checkbox | bool |
223
- | Rating | int |
224
- | CreatedBy | unit object |
225
- | LastModifiedBy | unit object |
226
- | MagicLink | str[] |
227
- | MagicLookUp | any[] |
228
- | Formula | str / bool |
229
-
230
- ## all
231
-
232
- all method will automatically handle paging loading all resources
233
-
234
- _When the paging-related parameters (pageNum, pageSize) are passed in, the SDK will no longer automatically load all records, and only return the specified page data_。
235
-
236
- > Try to avoid using the dst.records.all method without parameters to get all the data.
237
- > The API can obtain a maximum of 1000 pieces of data per request. If your data volume is too large, it is close to the limit of 50000. In the case of no parameters, calling all will serially request the API 50 times. Not only is it very slow, but it consumes API request credit.
238
-
239
- _Return the records of the specified pagination_
240
-
241
- ```python
242
- dst.records.all(pageNum=3)
243
- ```
244
-
245
- _Use with views_
246
-
247
- Specifying the view id returns the same data as in the view.
248
-
249
- ```python
250
- dst.records.all(viewId="viwxxxxxx")
251
- ```
252
-
253
- _Filter data using formulas_
254
-
255
- ```python
256
- dst.records.all(filterByFormula='{title}="hello"')
257
- ```
258
-
259
- | Parameter | Type | Description | Example |
260
- | --------------- | ------------------ | ----------------------------------------------------------------------------------------------------------- | ------------------------------------- |
261
- | viewId | str | View ID. The request will return the filtered/sorted results in the view | |
262
- | pageNum | int | Default 1 | |
263
- | pageSize | int | Default 100, maximum 1000 | |
264
- | sort | dict[] | Specify the sorting field, which overrides the view sorting conditions | `[{ field: 'field1', order: 'asc' }]` |
265
- | recordIds | str[] | Returns the recordset with the specified recordId | `['recordId1', 'recordId2']` |
266
- | fields | str[] | Only the specified fields will be returned | |
267
- | filterByFormula | str | Returns matching records using formulas as filter criteria | |
268
- | maxRecords | int | Limit the number of records returned, the default is 5000 | |
269
- | cellFormat | 'json' or 'string' | Defaults to 'json', when specified as 'string' all values will be automatically converted to string format. | |
270
- | fieldKey | 'name' or 'id' | Specifies the field query and returned key. The column name 'name' is used by default. | |
271
-
272
- See: [Tutorial getting started with formulas](https://help.apitable.com/docs/guide/tutorial-getting-started-with-formulas)
273
-
274
- ## FAQ
275
-
276
- ### Can I get the field type (meta) information of the datasheet?
277
-
278
- Can be get through the fields/views API.
279
-
280
- ### Can option be created automatically?
281
-
282
- If you write to a non-existent option, the option will be created automatically
283
-
284
- ### How many records can a single datasheet?
285
-
286
- 5w records.
287
-
288
- ### Can more records be processed per request?
289
-
290
- 10 records. In the future, we will adjust the size of this limit according to the actual situation.
291
-
292
- ### Can more records be fetched per request?
293
-
294
- The current maximum is 1000 records. In the future, we will adjust the size of this limit according to the actual situation.
295
-
296
- # Development and test
297
-
298
- Create a new `.env`, the content can refer to `.env.example`.
299
-
300
- ```shell
301
- cp .env .env.example
302
- ```
303
-
304
- Then modify the test code in the `test/` folder for testing.
305
-
306
- ```shell
307
- pipenv install --pre
308
- pipenv shell
309
- python -m unittest test
310
- ```
@@ -1,58 +0,0 @@
1
- LICENSE
2
- README.md
3
- pyproject.toml
4
- setup.py
5
- apitable/__init__.py
6
- apitable/apitable.py
7
- apitable/const.py
8
- apitable/exceptions.py
9
- apitable/request.py
10
- apitable/utils.py
11
- apitable.egg-info/PKG-INFO
12
- apitable.egg-info/SOURCES.txt
13
- apitable.egg-info/dependency_links.txt
14
- apitable.egg-info/requires.txt
15
- apitable.egg-info/top_level.txt
16
- apitable/datasheet/__init__.py
17
- apitable/datasheet/datasheet.py
18
- apitable/datasheet/datasheet_manager.py
19
- apitable/datasheet/field_manager.py
20
- apitable/datasheet/query_set.py
21
- apitable/datasheet/record.py
22
- apitable/datasheet/record_manager.py
23
- apitable/datasheet/view_manager.py
24
- apitable/node/__init__.py
25
- apitable/node/node_manager.py
26
- apitable/space/__init__.py
27
- apitable/space/space.py
28
- apitable/space/space_manager.py
29
- apitable/types/__init__.py
30
- apitable/types/embedlink.py
31
- apitable/types/field.py
32
- apitable/types/node.py
33
- apitable/types/record.py
34
- apitable/types/response.py
35
- apitable/types/space.py
36
- apitable/types/unit_model.py
37
- apitable/types/view.py
38
- apitable/unit/__init__.py
39
- apitable/unit/member.py
40
- apitable/unit/role.py
41
- apitable/unit/team.py
42
- apitable/unit/unit.py
43
- test/test_apitable.py
44
- test/test_create_datasheet.py
45
- test/test_create_embed_link.py
46
- test/test_create_field.py
47
- test/test_create_records.py
48
- test/test_delete_field.py
49
- test/test_delete_records.py
50
- test/test_get_fields.py
51
- test/test_get_nodes.py
52
- test/test_get_records.py
53
- test/test_get_spaces.py
54
- test/test_get_views.py
55
- test/test_unit.py
56
- test/test_update_records.py
57
- test/test_upload_file.py
58
- test/test_utils.py
@@ -1,3 +0,0 @@
1
- requests<=2.31.0
2
- pydantic==1.7
3
- environs<=9.5.0
@@ -1 +0,0 @@
1
- apitable
apitable-1.4.0/setup.cfg DELETED
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
apitable-1.4.0/setup.py DELETED
@@ -1,28 +0,0 @@
1
- import setuptools
2
-
3
- with open("README.md", "r") as fh:
4
- long_description = fh.read()
5
-
6
- with open(".version", "r") as fh:
7
- version_number = fh.read()
8
-
9
- setuptools.setup(
10
- name="apitable",
11
- version=version_number,
12
- author="apitable",
13
- author_email="dev@apitable.com",
14
- description="Apitable Python SDK",
15
- long_description=long_description,
16
- long_description_content_type="text/markdown",
17
- url="https://github.com/apitable/apitable-sdks",
18
- packages=[
19
- "apitable", "apitable.datasheet", "apitable.types", "apitable.node", "apitable.space", "apitable.unit"
20
- ],
21
- classifiers=[
22
- "Programming Language :: Python :: 3",
23
- "License :: OSI Approved :: MIT License",
24
- "Operating System :: OS Independent",
25
- ],
26
- python_requires=">=3.6",
27
- install_requires=["requests<=2.31.0", "pydantic==1.7", "environs<=9.5.0"],
28
- )
@@ -1,18 +0,0 @@
1
- import unittest
2
- from unittest.mock import patch
3
-
4
- from apitable.space import Space
5
-
6
-
7
- class TestApitable(unittest.TestCase):
8
- """
9
- base test class.
10
- """
11
-
12
- def setUp(self):
13
- """
14
- set up.
15
- """
16
- with patch('apitable.apitable') as mock_apitable:
17
- self._apitable = mock_apitable
18
- self._space = Space(self._apitable, 'test_space_id')
@@ -1,30 +0,0 @@
1
- import unittest
2
- import warnings
3
- from apitable import Apitable
4
- from . import DOMAIN, TOKEN, SPACE_ID, FOLDER_ID
5
-
6
-
7
- class TestCreateDatasheet(unittest.TestCase):
8
- """Apitable Python SDK create datasheet test class
9
- - Datasheet Creation SDK Test
10
- """
11
-
12
- def setUp(self):
13
- """Create a datasheet test class object initial hook:"""
14
- warnings.simplefilter("ignore", ResourceWarning)
15
- apitable = Apitable(TOKEN)
16
- apitable.set_api_base(DOMAIN)
17
- self.spc = apitable.space(SPACE_ID)
18
-
19
- def test_datasheet_create(self):
20
- """Datasheet Creation SDK Test"""
21
- req_data = {"name": "python_test_datasheet_create", "folderId": FOLDER_ID}
22
- self.datasheet = self.spc.datasheets.create(req_data)
23
- self.assertIsNotNone(self.datasheet.id)
24
-
25
- def tearDown(self):
26
- """Create a Datasheet test class object destroy hook:"""
27
-
28
-
29
- if __name__ == "__main__":
30
- unittest.main()
@@ -1,58 +0,0 @@
1
- import time
2
- import unittest
3
- import warnings
4
- from apitable import Apitable
5
- from apitable.types import EmbedLinkThemeEnum,EmbedLinkPermissionType
6
- from . import DOMAIN, TOKEN, SPACE_ID, DATASHEET_ID
7
-
8
-
9
- class TestEmbedLinkCRD(unittest.TestCase):
10
- def setUp(self):
11
- warnings.simplefilter("ignore", ResourceWarning)
12
- apitable = Apitable(TOKEN)
13
- apitable.set_api_base(DOMAIN)
14
- self.spc = apitable.space(SPACE_ID)
15
-
16
- def test_embed_link_crd(self):
17
- datasheet = self.spc.datasheet(DATASHEET_ID)
18
- newEmbedLink = datasheet.create_embed_link(
19
- {
20
- "paylod": {
21
- "primarySideBar": {"collapsed": False},
22
- "viewControl": {
23
- "viewId": "viwBBc0PMN3WB",
24
- "tabBar": False,
25
- "toolBar": {
26
- "basicTools": False,
27
- "shareBtn": False,
28
- "widgetBtn": False,
29
- "apiBtn": False,
30
- "formBtn": False,
31
- "historyBtn": False,
32
- "robotBtn": False,
33
- },
34
- "collapsed": False,
35
- },
36
- "bannerLogo": True,
37
- "permissionType": EmbedLinkPermissionType.READ_ONLY,
38
- },
39
- "theme": EmbedLinkThemeEnum.Light,
40
- }
41
- )
42
- self.assertIsNotNone(newEmbedLink.linkId)
43
- time.sleep(0.5)
44
- embedLinks = datasheet.get_embed_links()
45
- self.assertEqual(len(embedLinks), 1)
46
- time.sleep(0.5)
47
- isDeleted = datasheet.delete_embed_link(newEmbedLink.linkId)
48
- self.assertTrue(isDeleted)
49
- time.sleep(0.5)
50
- embedLinks = datasheet.get_embed_links()
51
- self.assertEqual(len(embedLinks), 0)
52
-
53
- def tearDown(self):
54
- """Create an embed link test class object destroy hook:"""
55
-
56
-
57
- if __name__ == "__main__":
58
- unittest.main()
@@ -1,43 +0,0 @@
1
- import unittest
2
- import warnings
3
- from apitable import Apitable
4
- from . import TOKEN, DOMAIN, SPACE_ID, DATASHEET_ID
5
-
6
-
7
- class TestCreateFields(unittest.TestCase):
8
- """Apitable Python SDK create field test class
9
- - Field Creation SDK Test
10
- """
11
-
12
- def setUp(self):
13
- """Create a field test class object initial hook:
14
- - Warnings related to resource usage are ignored
15
- - Initialize the Apitable object
16
- - Get action sheet
17
- """
18
- warnings.simplefilter("ignore", ResourceWarning)
19
- apitable = Apitable(TOKEN)
20
- apitable.set_api_base(DOMAIN)
21
- self.dst = apitable.space(SPACE_ID).datasheet(DATASHEET_ID)
22
- self.field = None
23
-
24
- def test_field_create(self):
25
- """Field Creation SDK Test"""
26
- req_data = {
27
- "type": "SingleText",
28
- "name": "test_field_create",
29
- "property": {"defaultValue": "hello apitable"},
30
- }
31
- self.field = self.dst.fields.create(req_data)
32
- self.assertIsNotNone(self.field.id)
33
- self.assertEqual(self.field.name, "test_field_create")
34
-
35
- def tearDown(self):
36
- """Create a field test class object to destroy the hook:
37
- - Delete test created fields
38
- """
39
- self.dst.fields.delete(self.field.id)
40
-
41
-
42
- if __name__ == "__main__":
43
- unittest.main()