REST2JSON 0.1.3__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.
- rest2json-0.1.3/MANIFEST.in +1 -0
- rest2json-0.1.3/PKG-INFO +348 -0
- rest2json-0.1.3/README.md +301 -0
- rest2json-0.1.3/pyproject.toml +3 -0
- rest2json-0.1.3/setup.cfg +4 -0
- rest2json-0.1.3/setup.py +79 -0
- rest2json-0.1.3/src/REST2JSON/Rest2JSON.py +330 -0
- rest2json-0.1.3/src/REST2JSON/URESTClient.py +130 -0
- rest2json-0.1.3/src/REST2JSON/__init__.py +5 -0
- rest2json-0.1.3/src/REST2JSON/utils/OASParser.py +774 -0
- rest2json-0.1.3/src/REST2JSON/utils/__init__.py +8 -0
- rest2json-0.1.3/src/REST2JSON/utils/loggerdec.py +67 -0
- rest2json-0.1.3/src/REST2JSON/utils/utils.py +305 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/PKG-INFO +348 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/SOURCES.txt +17 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/dependency_links.txt +1 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/not-zip-safe +1 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/requires.txt +15 -0
- rest2json-0.1.3/src/REST2JSON.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include src/REST2JSON *.py
|
rest2json-0.1.3/PKG-INFO
ADDED
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: REST2JSON
|
|
3
|
+
Version: 0.1.3
|
|
4
|
+
Summary: metadriven-адаптер для RESTAPI запросов
|
|
5
|
+
Home-page: https://github.com/Siinthd/REST2JSON
|
|
6
|
+
Author: Denis Kodolich
|
|
7
|
+
Author-email: d.kodolich@concept-software.ru
|
|
8
|
+
Project-URL: Bug Reports, https://github.com/yourusername/REST2JSON/issues
|
|
9
|
+
Project-URL: Source, https://github.com/yourusername/REST2JSON
|
|
10
|
+
Project-URL: Documentation, https://REST2JSON.readthedocs.io
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Operating System :: OS Independent
|
|
21
|
+
Requires-Python: >=3.8
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
Requires-Dist: httpx>=0.24.0
|
|
24
|
+
Requires-Dist: omegaconf>=2.3.0
|
|
25
|
+
Requires-Dist: pyyaml>=6.0
|
|
26
|
+
Requires-Dist: requests>=2.28.0
|
|
27
|
+
Provides-Extra: dev
|
|
28
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
30
|
+
Requires-Dist: black>=23.0.0; extra == "dev"
|
|
31
|
+
Requires-Dist: isort>=5.0.0; extra == "dev"
|
|
32
|
+
Requires-Dist: mypy>=1.0.0; extra == "dev"
|
|
33
|
+
Provides-Extra: docs
|
|
34
|
+
Requires-Dist: sphinx>=6.0.0; extra == "docs"
|
|
35
|
+
Requires-Dist: sphinx-rtd-theme>=1.0.0; extra == "docs"
|
|
36
|
+
Dynamic: author
|
|
37
|
+
Dynamic: author-email
|
|
38
|
+
Dynamic: classifier
|
|
39
|
+
Dynamic: description
|
|
40
|
+
Dynamic: description-content-type
|
|
41
|
+
Dynamic: home-page
|
|
42
|
+
Dynamic: project-url
|
|
43
|
+
Dynamic: provides-extra
|
|
44
|
+
Dynamic: requires-dist
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
# REST2JSON
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
Конфигурируемый адаптер, способный выполнять чтение данных с использованием внешнего REST-сервиса без написания клиента под каждый конкретный API на основании описания метаданных этого сервиса.
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
## Особенности
|
|
56
|
+
|
|
57
|
+
- Гибкая конфигурация через OmegaConf
|
|
58
|
+
- Загрузка OpenAPI спецификаций из файлов (YAML/JSON) или по URL
|
|
59
|
+
- Пакетная обработка запросов с подготовкой payload(Возможно,придется отказаться в пользу явного построения запроса)
|
|
60
|
+
- Поддержка контекстного менеджера для безопасного управления ресурсами
|
|
61
|
+
- Генерация JSON Schema из OpenAPI спецификации
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
## Установка
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
pip install git+https://github.com/Siinthd/Rest2JSON.git
|
|
68
|
+
pip install REST2JSON --index-url {mirror}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
## Быстрый старт
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
### Простой запрос
|
|
76
|
+
```Python
|
|
77
|
+
from rest2json import REST2JSON
|
|
78
|
+
|
|
79
|
+
config_file = 'C:/Users/kdenis/Documents/Work/configs/config_WorldBank.yaml'
|
|
80
|
+
|
|
81
|
+
import yaml
|
|
82
|
+
|
|
83
|
+
with open(config_file) as stream:
|
|
84
|
+
try:
|
|
85
|
+
config = yaml.safe_load(stream)
|
|
86
|
+
except yaml.YAMLError as exc:
|
|
87
|
+
print(exc)
|
|
88
|
+
|
|
89
|
+
#Иницализация адаптера, в этот момент происходит чтение/конфигурации,скачивание спецификации и ее парсинг
|
|
90
|
+
adapter = REST2JSON(config)
|
|
91
|
+
# get_schema() возвращает схему данных в <class 'dict'> - формате
|
|
92
|
+
# по умолчанию (raw = False) вернет Spark dataframe ddl
|
|
93
|
+
# (raw = True) возвращает структуру ответа без обработки (не подходит,чтобы создать dataframe)
|
|
94
|
+
schema = adapter.get_schema(raw = False)
|
|
95
|
+
# get_data() возвращает данные ответов с сервера в формате [<class 'dict'>]
|
|
96
|
+
# по умолчанию (пустые скобки), payload берется из конфигурации
|
|
97
|
+
data = adapter.get_data()
|
|
98
|
+
# При наличии payload (get_data(payload)) у сервера запрашиваются конкретные в payload данные.
|
|
99
|
+
payload = [{"query": 123}, {"query": 456}, {"query": 789}]
|
|
100
|
+
results = adapter.get_response(payload)
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
### Использование с контекстным менеджером
|
|
106
|
+
```Python
|
|
107
|
+
# возможность докачки данных вне конфигурации
|
|
108
|
+
with REST2JSON(config) as adapter:
|
|
109
|
+
# Работа с адаптером
|
|
110
|
+
response = adapter.get_data({})
|
|
111
|
+
print(response)
|
|
112
|
+
# Автоматическое закрытие соединений
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Пакетная обработка
|
|
116
|
+
```Python
|
|
117
|
+
payload = [{"query": 123}, {"query": 456}, {"query": 789}] # API-сервис ожидает параметр c именем query
|
|
118
|
+
|
|
119
|
+
with REST2JSON(config) as adapter:
|
|
120
|
+
results = adapter.get_response(payload)
|
|
121
|
+
for result in results:
|
|
122
|
+
print(result)
|
|
123
|
+
|
|
124
|
+
#или
|
|
125
|
+
adapter = REST2JSON(config)
|
|
126
|
+
response = adapter.get_response(payload)
|
|
127
|
+
for result in response:
|
|
128
|
+
print(result)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
## Конфигурация
|
|
134
|
+
|
|
135
|
+
### Структура конфигурации
|
|
136
|
+
```yaml
|
|
137
|
+
# обязательный: параметры процесса
|
|
138
|
+
# (основные настройки)
|
|
139
|
+
proc:
|
|
140
|
+
# обязательный: конфиг источника
|
|
141
|
+
|
|
142
|
+
src:
|
|
143
|
+
# обязательный: наименование источника
|
|
144
|
+
name: "getEverything" #
|
|
145
|
+
# обязательный: тип подключения
|
|
146
|
+
# определяет, как мы читаем источник
|
|
147
|
+
conn_type: 'rest2json'
|
|
148
|
+
# обязательный: список параметров подключения
|
|
149
|
+
conn_params:
|
|
150
|
+
# опциональный: количество ретраев и таймаут
|
|
151
|
+
# если не указать -- 1 ретрай и какой-нибудь таймаут
|
|
152
|
+
retries: 3
|
|
153
|
+
timeout: 30
|
|
154
|
+
|
|
155
|
+
# обязательный: спецификация сервиса
|
|
156
|
+
# (хотя бы один из двух должен быть указан и заполнен)
|
|
157
|
+
# отсюда берём схемы реплаев,
|
|
158
|
+
# + url для запроса, если возможно
|
|
159
|
+
|
|
160
|
+
spec_url: 'https://dadata.ru/files/openapi/suggestions.yml'
|
|
161
|
+
spec_data:
|
|
162
|
+
# опциональный: адрес для запроса
|
|
163
|
+
|
|
164
|
+
base_url: "https://suggestions.dadata.ru/suggestions"
|
|
165
|
+
# опциональный: ep+method для случаев, когда сервис не использует operation_id
|
|
166
|
+
endpoint_url: "/api/4_1/rs/suggest/bank"
|
|
167
|
+
method: 'post'
|
|
168
|
+
# опциональный: перебор страниц на сервере
|
|
169
|
+
# игнорим, если параметра нет,
|
|
170
|
+
pagination:
|
|
171
|
+
# обязательный: включение
|
|
172
|
+
enabled: false
|
|
173
|
+
# обязательный: название параметра с номером страницы
|
|
174
|
+
page_param: 'page'
|
|
175
|
+
# обязательный: название параметра с размером страницы
|
|
176
|
+
pagesize_param: 'per_page'
|
|
177
|
+
# обязательный: запрашиваемый размер страницы
|
|
178
|
+
pagesize_val: 100
|
|
179
|
+
# обязательный: название параметра с общим числом записей
|
|
180
|
+
pagecnt_param: "total_results"
|
|
181
|
+
|
|
182
|
+
# обязательный: конфиг данных (схема, фильтры, etc)
|
|
183
|
+
data:
|
|
184
|
+
# TODO: использовать динамическую генерацию запросов по спеке,
|
|
185
|
+
# и как-то угадывать, куда какие параметры писать -- нецелесообразно
|
|
186
|
+
payload:
|
|
187
|
+
['SABRRUMM', 'VTBRRUMM',]
|
|
188
|
+
# опциональный: свой маппинг типов
|
|
189
|
+
json_mapping_override:
|
|
190
|
+
"null": "null"
|
|
191
|
+
|
|
192
|
+
# обязательный: данные для авторизации
|
|
193
|
+
# содержат только логины, токены, пароли
|
|
194
|
+
auth:
|
|
195
|
+
# источник (extract)
|
|
196
|
+
src:
|
|
197
|
+
header: # авторизация через хедер (как в dadata)
|
|
198
|
+
"Authorization": "Token "
|
|
199
|
+
"X-Secret": ""
|
|
200
|
+
#X-Secret: "64545645"
|
|
201
|
+
body: # авторизация через параметр в теле (как в random.org)
|
|
202
|
+
#- "API_KEY: 12434547985675"
|
|
203
|
+
env:
|
|
204
|
+
# опциональный: маппинг типов данных (при конвертация в StrucType-json)
|
|
205
|
+
json:
|
|
206
|
+
type_mapping:
|
|
207
|
+
int32: integer
|
|
208
|
+
int64: long
|
|
209
|
+
float: float
|
|
210
|
+
double: double
|
|
211
|
+
date: string
|
|
212
|
+
date-time: string
|
|
213
|
+
binary: binary
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
## Class Reference
|
|
218
|
+
|
|
219
|
+
### Класс `REST2JSON`
|
|
220
|
+
|
|
221
|
+
Основной класс для работы с API.
|
|
222
|
+
|
|
223
|
+
#### Методы
|
|
224
|
+
|
|
225
|
+
##### `get_data(data=None)`
|
|
226
|
+
|
|
227
|
+
Основной метод для выполнения запросов. Автоматически управляет контекстом.
|
|
228
|
+
|
|
229
|
+
**Параметры:**
|
|
230
|
+
|
|
231
|
+
- `data` - Данные для запроса. Может быть:
|
|
232
|
+
|
|
233
|
+
- `None` - запрос без параметров,в таком случае данные для запроса берутся из конфигурации (раздел proc.src.data.payload)
|
|
234
|
+
- `dict` - одиночный запрос (может быть пустым - {})
|
|
235
|
+
- `list[dict]` - пакет запросов (может быть пустым - [])
|
|
236
|
+
- `str/int` - одиночное значение (будет преобразовано в параметр required)(может быть пустым - '')
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
**Возвращает:** JSON ответ от API или список ответов при пакетной обработке.
|
|
240
|
+
|
|
241
|
+
##### `get_schema(raw = False)`
|
|
242
|
+
|
|
243
|
+
**Возвращает:** схема структуры данных из OpenAPI спецификации при raw = False возвращает схему в Spark-формате.
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
## Обработка payload
|
|
247
|
+
|
|
248
|
+
Для получения ответа от API сервиса необходимо передать в запрос параметры, которые он ожидает — обычно это идентификаторы, фильтры или данные для создания/обновления объектов.
|
|
249
|
+
Они могут быть переданы как часть URL (например, /users/123), в строке запроса (?page=2) или в теле запроса (JSON с полями).
|
|
250
|
+
|
|
251
|
+
Такие параметры указаны в разделе "requestBody". Часто, это один required-параметр и можно передать в REST2JSON список значения без указания имени параметра - Сервис сам подставить имя параметра.
|
|
252
|
+
|
|
253
|
+
В противном случае, требуется указать все параметры явно:
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
data = {"query": 123,"status":["ACTIVE"],"type":["BANK","BANK_BRANCH","OTHER"]}
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### Пример requestBody в спецификации
|
|
260
|
+
|
|
261
|
+
```yaml
|
|
262
|
+
requestBody:
|
|
263
|
+
content:
|
|
264
|
+
application/json:
|
|
265
|
+
schema:
|
|
266
|
+
required:
|
|
267
|
+
- query
|
|
268
|
+
type: object
|
|
269
|
+
properties:
|
|
270
|
+
count:
|
|
271
|
+
type: integer
|
|
272
|
+
format: int32
|
|
273
|
+
nullable: true
|
|
274
|
+
default: 10
|
|
275
|
+
locations:
|
|
276
|
+
type: array
|
|
277
|
+
nullable: true
|
|
278
|
+
items:
|
|
279
|
+
$ref: "#/components/schemas/LocationCode"
|
|
280
|
+
locations_boost:
|
|
281
|
+
type: array
|
|
282
|
+
nullable: true
|
|
283
|
+
items:
|
|
284
|
+
$ref: "#/components/schemas/LocationCode"
|
|
285
|
+
query:
|
|
286
|
+
type: string
|
|
287
|
+
status:
|
|
288
|
+
type: array
|
|
289
|
+
nullable: true
|
|
290
|
+
items:
|
|
291
|
+
type: string
|
|
292
|
+
enum:
|
|
293
|
+
- ACTIVE
|
|
294
|
+
- LIQUIDATING
|
|
295
|
+
- LIQUIDATED
|
|
296
|
+
- REORGANIZING
|
|
297
|
+
- BANKRUPT
|
|
298
|
+
type:
|
|
299
|
+
type: array
|
|
300
|
+
nullable: true
|
|
301
|
+
items:
|
|
302
|
+
type: string
|
|
303
|
+
enum:
|
|
304
|
+
- BANK
|
|
305
|
+
- NKO
|
|
306
|
+
- BANK_BRANCH
|
|
307
|
+
- NKO_BRANCH
|
|
308
|
+
- RKC
|
|
309
|
+
- CBR
|
|
310
|
+
- TREASURY
|
|
311
|
+
- OTHER
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
| Тип входных данных | Результат |
|
|
316
|
+
| -------------------- | -------------------------------------------------- |
|
|
317
|
+
| `{}`,`[]`,`''` | `[dict]` - одиночный запрос(сервер не ждет данных) |
|
|
318
|
+
| `dict` | `[dict]` - одиночный запрос |
|
|
319
|
+
| `list[dict]` | `list[dict]` - пакет запросов |
|
|
320
|
+
| `list` (не словарей) | Если required имеет n параметров: `[{query: value_1}...{query: value_n}]` |
|
|
321
|
+
| Одиночное значение | Если required имеет 1 параметр: `[{query: value}]` |
|
|
322
|
+
|
|
323
|
+
### Примеры преобразования данных
|
|
324
|
+
|
|
325
|
+
```python
|
|
326
|
+
# Одиночный словарь
|
|
327
|
+
data = {"query": 123}
|
|
328
|
+
# → [{"query": 123}]
|
|
329
|
+
# Список словарей
|
|
330
|
+
data = [{"query": 123}, {"query": 456}]
|
|
331
|
+
# → [{"query": 123}, {"query": 456}]
|
|
332
|
+
# Список значений (если required = ["id"])
|
|
333
|
+
data = [123, 456, 789]
|
|
334
|
+
# [{"query": 123}, {"query": 456}, {"query": 789}]
|
|
335
|
+
# Одиночное значение (если required = ["query"])
|
|
336
|
+
data = 123
|
|
337
|
+
# [{"query": 123}]
|
|
338
|
+
data = {"query": 123,"status":["ACTIVE"],"type":["BANK","BANK_BRANCH","OTHER"]}
|
|
339
|
+
#Явное указание дополнительных фильтров
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
### TODO
|
|
343
|
+
|
|
344
|
+
- [ ] Проверка наличия ключей словаря в спецификации
|
|
345
|
+
- [ ] Формирование очереди загрузок
|
|
346
|
+
- [ ] Реализация пагинации
|
|
347
|
+
- [ ] Улучшенная валидация ответов
|
|
348
|
+
- [ ] Потокобезопасность
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
# REST2JSON
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
Конфигурируемый адаптер, способный выполнять чтение данных с использованием внешнего REST-сервиса без написания клиента под каждый конкретный API на основании описания метаданных этого сервиса.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Особенности
|
|
9
|
+
|
|
10
|
+
- Гибкая конфигурация через OmegaConf
|
|
11
|
+
- Загрузка OpenAPI спецификаций из файлов (YAML/JSON) или по URL
|
|
12
|
+
- Пакетная обработка запросов с подготовкой payload(Возможно,придется отказаться в пользу явного построения запроса)
|
|
13
|
+
- Поддержка контекстного менеджера для безопасного управления ресурсами
|
|
14
|
+
- Генерация JSON Schema из OpenAPI спецификации
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## Установка
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pip install git+https://github.com/Siinthd/Rest2JSON.git
|
|
21
|
+
pip install REST2JSON --index-url {mirror}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
## Быстрый старт
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Простой запрос
|
|
29
|
+
```Python
|
|
30
|
+
from rest2json import REST2JSON
|
|
31
|
+
|
|
32
|
+
config_file = 'C:/Users/kdenis/Documents/Work/configs/config_WorldBank.yaml'
|
|
33
|
+
|
|
34
|
+
import yaml
|
|
35
|
+
|
|
36
|
+
with open(config_file) as stream:
|
|
37
|
+
try:
|
|
38
|
+
config = yaml.safe_load(stream)
|
|
39
|
+
except yaml.YAMLError as exc:
|
|
40
|
+
print(exc)
|
|
41
|
+
|
|
42
|
+
#Иницализация адаптера, в этот момент происходит чтение/конфигурации,скачивание спецификации и ее парсинг
|
|
43
|
+
adapter = REST2JSON(config)
|
|
44
|
+
# get_schema() возвращает схему данных в <class 'dict'> - формате
|
|
45
|
+
# по умолчанию (raw = False) вернет Spark dataframe ddl
|
|
46
|
+
# (raw = True) возвращает структуру ответа без обработки (не подходит,чтобы создать dataframe)
|
|
47
|
+
schema = adapter.get_schema(raw = False)
|
|
48
|
+
# get_data() возвращает данные ответов с сервера в формате [<class 'dict'>]
|
|
49
|
+
# по умолчанию (пустые скобки), payload берется из конфигурации
|
|
50
|
+
data = adapter.get_data()
|
|
51
|
+
# При наличии payload (get_data(payload)) у сервера запрашиваются конкретные в payload данные.
|
|
52
|
+
payload = [{"query": 123}, {"query": 456}, {"query": 789}]
|
|
53
|
+
results = adapter.get_response(payload)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
### Использование с контекстным менеджером
|
|
59
|
+
```Python
|
|
60
|
+
# возможность докачки данных вне конфигурации
|
|
61
|
+
with REST2JSON(config) as adapter:
|
|
62
|
+
# Работа с адаптером
|
|
63
|
+
response = adapter.get_data({})
|
|
64
|
+
print(response)
|
|
65
|
+
# Автоматическое закрытие соединений
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Пакетная обработка
|
|
69
|
+
```Python
|
|
70
|
+
payload = [{"query": 123}, {"query": 456}, {"query": 789}] # API-сервис ожидает параметр c именем query
|
|
71
|
+
|
|
72
|
+
with REST2JSON(config) as adapter:
|
|
73
|
+
results = adapter.get_response(payload)
|
|
74
|
+
for result in results:
|
|
75
|
+
print(result)
|
|
76
|
+
|
|
77
|
+
#или
|
|
78
|
+
adapter = REST2JSON(config)
|
|
79
|
+
response = adapter.get_response(payload)
|
|
80
|
+
for result in response:
|
|
81
|
+
print(result)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
## Конфигурация
|
|
87
|
+
|
|
88
|
+
### Структура конфигурации
|
|
89
|
+
```yaml
|
|
90
|
+
# обязательный: параметры процесса
|
|
91
|
+
# (основные настройки)
|
|
92
|
+
proc:
|
|
93
|
+
# обязательный: конфиг источника
|
|
94
|
+
|
|
95
|
+
src:
|
|
96
|
+
# обязательный: наименование источника
|
|
97
|
+
name: "getEverything" #
|
|
98
|
+
# обязательный: тип подключения
|
|
99
|
+
# определяет, как мы читаем источник
|
|
100
|
+
conn_type: 'rest2json'
|
|
101
|
+
# обязательный: список параметров подключения
|
|
102
|
+
conn_params:
|
|
103
|
+
# опциональный: количество ретраев и таймаут
|
|
104
|
+
# если не указать -- 1 ретрай и какой-нибудь таймаут
|
|
105
|
+
retries: 3
|
|
106
|
+
timeout: 30
|
|
107
|
+
|
|
108
|
+
# обязательный: спецификация сервиса
|
|
109
|
+
# (хотя бы один из двух должен быть указан и заполнен)
|
|
110
|
+
# отсюда берём схемы реплаев,
|
|
111
|
+
# + url для запроса, если возможно
|
|
112
|
+
|
|
113
|
+
spec_url: 'https://dadata.ru/files/openapi/suggestions.yml'
|
|
114
|
+
spec_data:
|
|
115
|
+
# опциональный: адрес для запроса
|
|
116
|
+
|
|
117
|
+
base_url: "https://suggestions.dadata.ru/suggestions"
|
|
118
|
+
# опциональный: ep+method для случаев, когда сервис не использует operation_id
|
|
119
|
+
endpoint_url: "/api/4_1/rs/suggest/bank"
|
|
120
|
+
method: 'post'
|
|
121
|
+
# опциональный: перебор страниц на сервере
|
|
122
|
+
# игнорим, если параметра нет,
|
|
123
|
+
pagination:
|
|
124
|
+
# обязательный: включение
|
|
125
|
+
enabled: false
|
|
126
|
+
# обязательный: название параметра с номером страницы
|
|
127
|
+
page_param: 'page'
|
|
128
|
+
# обязательный: название параметра с размером страницы
|
|
129
|
+
pagesize_param: 'per_page'
|
|
130
|
+
# обязательный: запрашиваемый размер страницы
|
|
131
|
+
pagesize_val: 100
|
|
132
|
+
# обязательный: название параметра с общим числом записей
|
|
133
|
+
pagecnt_param: "total_results"
|
|
134
|
+
|
|
135
|
+
# обязательный: конфиг данных (схема, фильтры, etc)
|
|
136
|
+
data:
|
|
137
|
+
# TODO: использовать динамическую генерацию запросов по спеке,
|
|
138
|
+
# и как-то угадывать, куда какие параметры писать -- нецелесообразно
|
|
139
|
+
payload:
|
|
140
|
+
['SABRRUMM', 'VTBRRUMM',]
|
|
141
|
+
# опциональный: свой маппинг типов
|
|
142
|
+
json_mapping_override:
|
|
143
|
+
"null": "null"
|
|
144
|
+
|
|
145
|
+
# обязательный: данные для авторизации
|
|
146
|
+
# содержат только логины, токены, пароли
|
|
147
|
+
auth:
|
|
148
|
+
# источник (extract)
|
|
149
|
+
src:
|
|
150
|
+
header: # авторизация через хедер (как в dadata)
|
|
151
|
+
"Authorization": "Token "
|
|
152
|
+
"X-Secret": ""
|
|
153
|
+
#X-Secret: "64545645"
|
|
154
|
+
body: # авторизация через параметр в теле (как в random.org)
|
|
155
|
+
#- "API_KEY: 12434547985675"
|
|
156
|
+
env:
|
|
157
|
+
# опциональный: маппинг типов данных (при конвертация в StrucType-json)
|
|
158
|
+
json:
|
|
159
|
+
type_mapping:
|
|
160
|
+
int32: integer
|
|
161
|
+
int64: long
|
|
162
|
+
float: float
|
|
163
|
+
double: double
|
|
164
|
+
date: string
|
|
165
|
+
date-time: string
|
|
166
|
+
binary: binary
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
## Class Reference
|
|
171
|
+
|
|
172
|
+
### Класс `REST2JSON`
|
|
173
|
+
|
|
174
|
+
Основной класс для работы с API.
|
|
175
|
+
|
|
176
|
+
#### Методы
|
|
177
|
+
|
|
178
|
+
##### `get_data(data=None)`
|
|
179
|
+
|
|
180
|
+
Основной метод для выполнения запросов. Автоматически управляет контекстом.
|
|
181
|
+
|
|
182
|
+
**Параметры:**
|
|
183
|
+
|
|
184
|
+
- `data` - Данные для запроса. Может быть:
|
|
185
|
+
|
|
186
|
+
- `None` - запрос без параметров,в таком случае данные для запроса берутся из конфигурации (раздел proc.src.data.payload)
|
|
187
|
+
- `dict` - одиночный запрос (может быть пустым - {})
|
|
188
|
+
- `list[dict]` - пакет запросов (может быть пустым - [])
|
|
189
|
+
- `str/int` - одиночное значение (будет преобразовано в параметр required)(может быть пустым - '')
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
**Возвращает:** JSON ответ от API или список ответов при пакетной обработке.
|
|
193
|
+
|
|
194
|
+
##### `get_schema(raw = False)`
|
|
195
|
+
|
|
196
|
+
**Возвращает:** схема структуры данных из OpenAPI спецификации при raw = False возвращает схему в Spark-формате.
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
## Обработка payload
|
|
200
|
+
|
|
201
|
+
Для получения ответа от API сервиса необходимо передать в запрос параметры, которые он ожидает — обычно это идентификаторы, фильтры или данные для создания/обновления объектов.
|
|
202
|
+
Они могут быть переданы как часть URL (например, /users/123), в строке запроса (?page=2) или в теле запроса (JSON с полями).
|
|
203
|
+
|
|
204
|
+
Такие параметры указаны в разделе "requestBody". Часто, это один required-параметр и можно передать в REST2JSON список значения без указания имени параметра - Сервис сам подставить имя параметра.
|
|
205
|
+
|
|
206
|
+
В противном случае, требуется указать все параметры явно:
|
|
207
|
+
|
|
208
|
+
```python
|
|
209
|
+
data = {"query": 123,"status":["ACTIVE"],"type":["BANK","BANK_BRANCH","OTHER"]}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
#### Пример requestBody в спецификации
|
|
213
|
+
|
|
214
|
+
```yaml
|
|
215
|
+
requestBody:
|
|
216
|
+
content:
|
|
217
|
+
application/json:
|
|
218
|
+
schema:
|
|
219
|
+
required:
|
|
220
|
+
- query
|
|
221
|
+
type: object
|
|
222
|
+
properties:
|
|
223
|
+
count:
|
|
224
|
+
type: integer
|
|
225
|
+
format: int32
|
|
226
|
+
nullable: true
|
|
227
|
+
default: 10
|
|
228
|
+
locations:
|
|
229
|
+
type: array
|
|
230
|
+
nullable: true
|
|
231
|
+
items:
|
|
232
|
+
$ref: "#/components/schemas/LocationCode"
|
|
233
|
+
locations_boost:
|
|
234
|
+
type: array
|
|
235
|
+
nullable: true
|
|
236
|
+
items:
|
|
237
|
+
$ref: "#/components/schemas/LocationCode"
|
|
238
|
+
query:
|
|
239
|
+
type: string
|
|
240
|
+
status:
|
|
241
|
+
type: array
|
|
242
|
+
nullable: true
|
|
243
|
+
items:
|
|
244
|
+
type: string
|
|
245
|
+
enum:
|
|
246
|
+
- ACTIVE
|
|
247
|
+
- LIQUIDATING
|
|
248
|
+
- LIQUIDATED
|
|
249
|
+
- REORGANIZING
|
|
250
|
+
- BANKRUPT
|
|
251
|
+
type:
|
|
252
|
+
type: array
|
|
253
|
+
nullable: true
|
|
254
|
+
items:
|
|
255
|
+
type: string
|
|
256
|
+
enum:
|
|
257
|
+
- BANK
|
|
258
|
+
- NKO
|
|
259
|
+
- BANK_BRANCH
|
|
260
|
+
- NKO_BRANCH
|
|
261
|
+
- RKC
|
|
262
|
+
- CBR
|
|
263
|
+
- TREASURY
|
|
264
|
+
- OTHER
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
|
|
268
|
+
| Тип входных данных | Результат |
|
|
269
|
+
| -------------------- | -------------------------------------------------- |
|
|
270
|
+
| `{}`,`[]`,`''` | `[dict]` - одиночный запрос(сервер не ждет данных) |
|
|
271
|
+
| `dict` | `[dict]` - одиночный запрос |
|
|
272
|
+
| `list[dict]` | `list[dict]` - пакет запросов |
|
|
273
|
+
| `list` (не словарей) | Если required имеет n параметров: `[{query: value_1}...{query: value_n}]` |
|
|
274
|
+
| Одиночное значение | Если required имеет 1 параметр: `[{query: value}]` |
|
|
275
|
+
|
|
276
|
+
### Примеры преобразования данных
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
# Одиночный словарь
|
|
280
|
+
data = {"query": 123}
|
|
281
|
+
# → [{"query": 123}]
|
|
282
|
+
# Список словарей
|
|
283
|
+
data = [{"query": 123}, {"query": 456}]
|
|
284
|
+
# → [{"query": 123}, {"query": 456}]
|
|
285
|
+
# Список значений (если required = ["id"])
|
|
286
|
+
data = [123, 456, 789]
|
|
287
|
+
# [{"query": 123}, {"query": 456}, {"query": 789}]
|
|
288
|
+
# Одиночное значение (если required = ["query"])
|
|
289
|
+
data = 123
|
|
290
|
+
# [{"query": 123}]
|
|
291
|
+
data = {"query": 123,"status":["ACTIVE"],"type":["BANK","BANK_BRANCH","OTHER"]}
|
|
292
|
+
#Явное указание дополнительных фильтров
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### TODO
|
|
296
|
+
|
|
297
|
+
- [ ] Проверка наличия ключей словаря в спецификации
|
|
298
|
+
- [ ] Формирование очереди загрузок
|
|
299
|
+
- [ ] Реализация пагинации
|
|
300
|
+
- [ ] Улучшенная валидация ответов
|
|
301
|
+
- [ ] Потокобезопасность
|