cycle.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. # Copyright 2023 Avaiga Private Limited
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
  4. # the License. You may obtain a copy of the License at
  5. #
  6. # http://www.apache.org/licenses/LICENSE-2.0
  7. #
  8. # Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
  9. # an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
  10. # specific language governing permissions and limitations under the License.
  11. from datetime import datetime
  12. from flask import request
  13. from flask_restful import Resource
  14. from taipy.config.common.frequency import Frequency
  15. from taipy.core import Cycle
  16. from taipy.core.cycle._cycle_manager_factory import _CycleManagerFactory
  17. from taipy.core.exceptions.exceptions import NonExistingCycle
  18. from ...commons.to_from_model import _to_model
  19. from ..middlewares._middleware import _middleware
  20. from ..schemas import CycleResponseSchema, CycleSchema
  21. REPOSITORY = "cycle"
  22. def _get_or_raise(cycle_id: str) -> Cycle:
  23. manager = _CycleManagerFactory._build_manager()
  24. cycle = manager._get(cycle_id)
  25. if not cycle:
  26. raise NonExistingCycle(cycle_id)
  27. return cycle
  28. class CycleResource(Resource):
  29. """Single object resource
  30. ---
  31. get:
  32. tags:
  33. - api
  34. description: |
  35. Returns a `CycleSchema^` representing the unique `Cycle^` identified by the *cycle_id*
  36. given as parameter. If no cycle corresponds to *cycle_id*, a `404` error is returned.
  37. !!! Example
  38. === "Curl"
  39. ```shell
  40. curl -X GET http://localhost:5000/api/v1/cycles/CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a
  41. ```
  42. In this example the REST API is served on port 5000 on localhost. We are using curl command line
  43. client.
  44. `CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a` is the value of the *cycle_id* parameter. It
  45. represents the identifier of the Cycle we want to retrieve.
  46. In case of success here is an example of the response:
  47. ``` JSON
  48. {"cycle": {
  49. "frequency": "Frequency.DAILY",
  50. "creation_date": "2022-08-04T17:13:32.797384",
  51. "id": "CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a",
  52. "start_date": "2022-08-04T00:00:00",
  53. "end_date": "2022-08-04T23:59:59.999999",
  54. "name": "Frequency.DAILY_2022-08-04T17:13:32.797384"
  55. ```
  56. In case of failure here is an example of the response:
  57. ``` JSON
  58. {"message": "Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a not found."}
  59. ```
  60. === "Python"
  61. This Python example requires the 'requests' package to be installed (`pip install requests`).
  62. ```python
  63. import requests
  64. response = requests.get("http://localhost:5000/api/v1/cycles/CYCLE_223894_e019-b50b-4b9f-ac09-527a")
  65. print(response)
  66. print(response.json())
  67. ```
  68. `CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a` is the value of the *cycle_id* parameter. It
  69. represents the identifier of the Cycle we want to retrieve.
  70. In case of success here is an output example:
  71. ```
  72. <Response [200]>
  73. {'cycle': {
  74. 'frequency': 'Frequency.DAILY',
  75. 'creation_date': '2022-08-04T17:13:32.797384',
  76. 'id': 'CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a',
  77. 'start_date': '2022-08-04T00:00:00',
  78. 'end_date': '2022-08-04T23:59:59.999999',
  79. 'name': 'Frequency.DAILY_2022-08-04T17:13:32.797384'
  80. ```
  81. In case of failure here is an output example:
  82. ```
  83. <Response [404]>
  84. {'message': 'Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a not found.'}
  85. ```
  86. !!! Note
  87. When the authorization feature is activated (available in Taipy Enterprise edition only), this endpoint
  88. requires the `TAIPY_READER` role.
  89. parameters:
  90. - in: path
  91. name: cycle_id
  92. schema:
  93. type: string
  94. description: The identifier of the cycle to retrieve.
  95. responses:
  96. 200:
  97. content:
  98. application/json:
  99. schema:
  100. type: object
  101. properties:
  102. cycle: CycleSchema
  103. 404:
  104. description: No cycle has the *cycle_id* identifier.
  105. delete:
  106. tags:
  107. - api
  108. description: |
  109. Deletes the `Cycle^` identified by the *cycle_id* given as parameter. If the cycle does not exist,
  110. a 404 error is returned.
  111. !!! Example
  112. === "Curl"
  113. ```shell
  114. curl -X DELETE http://localhost:5000/api/v1/cycles/CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a
  115. ```
  116. In this example the REST API is served on port 5000 on localhost. We are using curl command line
  117. client.
  118. `CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a` is the value of the *cycle_id* parameter. It
  119. represents the identifier of the Cycle we want to delete.
  120. In case of success here is an example of the response:
  121. ``` JSON
  122. {"message": "Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a was deleted."}
  123. ```
  124. In case of failure here is an example of the response:
  125. ``` JSON
  126. {"message": "Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a not found."}
  127. ```
  128. === "Python"
  129. This Python example requires the 'requests' package to be installed (`pip install requests`).
  130. ```python
  131. import requests
  132. response = requests.delete("http://localhost:5000/api/v1/cycles/CYCLE_794_ef21-af91-4f41-b6e8-7648eda")
  133. print(response)
  134. print(response.json())
  135. ```
  136. `CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a` is the value of the *cycle_id* parameter. It
  137. represents the identifier of the Cycle we want to delete.
  138. In case of success here is an output example:
  139. ```
  140. <Response [200]>
  141. {"message": "Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a was deleted."}
  142. ```
  143. In case of failure here is an output example:
  144. ```
  145. <Response [404]>
  146. {'message': 'Cycle CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a not found.'}
  147. ```
  148. !!! Note
  149. When the authorization feature is activated (available in Taipy Enterprise edition only), this endpoint
  150. requires the `TAIPY_EDITOR` role.
  151. parameters:
  152. - in: path
  153. name: cycle_id
  154. schema:
  155. type: string
  156. description: The id of the cycle to delete.
  157. responses:
  158. 200:
  159. content:
  160. application/json:
  161. schema:
  162. type: object
  163. properties:
  164. message:
  165. type: string
  166. description: Status message.
  167. 404:
  168. description: No cycle has the *cycle_id* identifier.
  169. """
  170. def __init__(self, **kwargs):
  171. self.logger = kwargs.get("logger")
  172. @_middleware
  173. def get(self, cycle_id):
  174. schema = CycleResponseSchema()
  175. cycle = _get_or_raise(cycle_id)
  176. return {"cycle": schema.dump(_to_model(REPOSITORY, cycle))}
  177. @_middleware
  178. def delete(self, cycle_id):
  179. manager = _CycleManagerFactory._build_manager()
  180. _get_or_raise(cycle_id)
  181. manager._delete(cycle_id)
  182. return {"message": f"Cycle {cycle_id} was deleted."}
  183. class CycleList(Resource):
  184. """Creation and get_all
  185. ---
  186. get:
  187. tags:
  188. - api
  189. description: |
  190. Returns a `CycleSchema^` list representing all existing Cycles.
  191. !!! Example
  192. === "Curl"
  193. ```shell
  194. curl -X GET http://localhost:5000/api/v1/cycles
  195. ```
  196. In this example the REST API is served on port 5000 on localhost. We are using curl command line
  197. client.
  198. Here is an example of the response:
  199. ``` JSON
  200. [
  201. {
  202. "frequency": "Frequency.DAILY",
  203. "end_date": "2022-08-06T23:59:59.999999",
  204. "creation_date": "2022-08-06T15:45:50.223894",
  205. "start_date": "2022-08-06T00:00:00",
  206. "id": "CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a",
  207. "name": "Frequency.DAILY_2022-08-06T15:45:50.223894"
  208. }
  209. ]
  210. ```
  211. If there is no cycle, the response is an empty list as follows:
  212. ``` JSON
  213. []
  214. ```
  215. === "Python"
  216. This Python example requires the 'requests' package to be installed (`pip install requests`).
  217. ```python
  218. import requests
  219. response = requests.get("http://localhost:5000/api/v1/cycles")
  220. print(response)
  221. print(response.json())
  222. ```
  223. In case of success here is an output example:
  224. ```
  225. <Response [200]>
  226. [{
  227. "frequency": "Frequency.DAILY",
  228. "end_date": "2022-08-06T23:59:59.999999",
  229. "creation_date": "2022-08-06T15:45:50.223894",
  230. "start_date": "2022-08-06T00:00:00",
  231. "id": "CYCLE_223894_e0fab919-b50b-4b9f-ac09-52f77474fa7a",
  232. "name": "Frequency.DAILY_2022-08-06T15:45:50.223894"
  233. }
  234. ]
  235. ```
  236. If there is no cycle, the response is an empty list as follows:
  237. ```
  238. <Response [200]>
  239. []
  240. ```
  241. !!! Note
  242. When the authorization feature is activated (available in Taipy Enterprise edition only), this endpoint
  243. requires the `TAIPY_READER` role.
  244. responses:
  245. 200:
  246. content:
  247. application/json:
  248. schema:
  249. allOf:
  250. - type: object
  251. properties:
  252. results:
  253. type: array
  254. items:
  255. $ref: '#/components/schemas/CycleSchema'
  256. post:
  257. tags:
  258. - api
  259. description: |
  260. Creates a new cycle from the `CycleSchema^` given in the request body.
  261. !!! Example
  262. === "Curl"
  263. ```shell
  264. curl -X POST -H "Content-Type: application/json"\
  265. -d '{"frequency": "DAILY", "properties": {}, "creation_date": "2020-01-01T00:00:00",\
  266. "start_date": "2020-01-01T00:00:00", "end_date": "2020-01-01T00:00:00"}'\
  267. http://localhost:5000/api/v1/cycles
  268. ```
  269. In this example the REST API is served on port 5000 on localhost. We are using curl command line
  270. client.
  271. In the curl command line, a `CycleSchema^` is provided as JSON dictionary parameter with the curl
  272. option -d (--data) to specify the various attributes of the `Cycle^` to create:
  273. ``` JSON
  274. {
  275. "frequency": "DAILY",
  276. "properties": {},
  277. "creation_date": "2020-01-01T00:00:00",
  278. "start_date": "2020-01-01T00:00:00",
  279. "end_date": "2020-01-01T00:00:00"
  280. }
  281. ```
  282. === "Python"
  283. This Python example requires the 'requests' package to be installed (`pip install requests`).
  284. ```python
  285. import requests
  286. cycle_schema = {
  287. "frequency": "DAILY",
  288. "properties": {},
  289. "creation_date": "2020-01-01T00:00:00",
  290. "start_date": "2020-01-01T00:00:00",
  291. "end_date": "2020-01-01T00:00:00"
  292. }
  293. response = requests.post("http://localhost:5000/api/v1/cycles", json=cycle_schema)
  294. print(response)
  295. print(response.json())
  296. ```
  297. A `CycleSchema^` is provided as a dictionary to specify the various attributes of the `Cycle^` to
  298. create.
  299. Here is the output example:
  300. ```
  301. <Response [201]>
  302. {
  303. 'message': 'Cycle was created.',
  304. 'cycle': {
  305. 'frequency': 'Frequency.DAILY',
  306. 'end_date': '2020-01-01T00:00:00',
  307. 'creation_date': '2020-01-01T00:00:00',
  308. 'start_date': '2020-01-01T00:00:00',
  309. 'id': 'CYCLE_c9cc527f-a8c8-4238-8f31-42166a9817db',
  310. 'name': 'Frequency.DAILY_2020-01-01T00:00:00',
  311. 'properties': {}}}
  312. ```
  313. !!! Note
  314. When the authorization feature is activated (available in Taipy Enterprise edition only), this endpoint
  315. requires the `TAIPY_EDITOR` role.
  316. requestBody:
  317. required: true
  318. content:
  319. application/json:
  320. schema:
  321. CycleSchema
  322. responses:
  323. 201:
  324. content:
  325. application/json:
  326. schema:
  327. type: object
  328. properties:
  329. message:
  330. type: string
  331. description: Status message.
  332. cycle: CycleSchema
  333. """
  334. def __init__(self, **kwargs):
  335. self.logger = kwargs.get("logger")
  336. @_middleware
  337. def get(self):
  338. schema = CycleResponseSchema(many=True)
  339. manager = _CycleManagerFactory._build_manager()
  340. cycles = [_to_model(REPOSITORY, cycle) for cycle in manager._get_all()]
  341. return schema.dump(cycles)
  342. @_middleware
  343. def post(self):
  344. schema = CycleResponseSchema()
  345. manager = _CycleManagerFactory._build_manager()
  346. cycle = self.__create_cycle_from_schema(schema.load(request.json))
  347. manager._set(cycle)
  348. return {
  349. "message": "Cycle was created.",
  350. "cycle": schema.dump(_to_model(REPOSITORY, cycle)),
  351. }, 201
  352. def __create_cycle_from_schema(self, cycle_schema: CycleSchema):
  353. return Cycle(
  354. id=cycle_schema.get("id"),
  355. frequency=Frequency(getattr(Frequency, cycle_schema.get("frequency", "").upper())),
  356. properties=cycle_schema.get("properties", {}),
  357. creation_date=datetime.fromisoformat(cycle_schema.get("creation_date")),
  358. start_date=datetime.fromisoformat(cycle_schema.get("start_date")),
  359. end_date=datetime.fromisoformat(cycle_schema.get("end_date")),
  360. )