singlestoredb 1.16.1__py3-none-any.whl

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 (183) hide show
  1. singlestoredb/__init__.py +75 -0
  2. singlestoredb/ai/__init__.py +2 -0
  3. singlestoredb/ai/chat.py +139 -0
  4. singlestoredb/ai/embeddings.py +128 -0
  5. singlestoredb/alchemy/__init__.py +90 -0
  6. singlestoredb/apps/__init__.py +3 -0
  7. singlestoredb/apps/_cloud_functions.py +90 -0
  8. singlestoredb/apps/_config.py +72 -0
  9. singlestoredb/apps/_connection_info.py +18 -0
  10. singlestoredb/apps/_dashboards.py +47 -0
  11. singlestoredb/apps/_process.py +32 -0
  12. singlestoredb/apps/_python_udfs.py +100 -0
  13. singlestoredb/apps/_stdout_supress.py +30 -0
  14. singlestoredb/apps/_uvicorn_util.py +36 -0
  15. singlestoredb/auth.py +245 -0
  16. singlestoredb/config.py +484 -0
  17. singlestoredb/connection.py +1487 -0
  18. singlestoredb/converters.py +950 -0
  19. singlestoredb/docstring/__init__.py +33 -0
  20. singlestoredb/docstring/attrdoc.py +126 -0
  21. singlestoredb/docstring/common.py +230 -0
  22. singlestoredb/docstring/epydoc.py +267 -0
  23. singlestoredb/docstring/google.py +412 -0
  24. singlestoredb/docstring/numpydoc.py +562 -0
  25. singlestoredb/docstring/parser.py +100 -0
  26. singlestoredb/docstring/py.typed +1 -0
  27. singlestoredb/docstring/rest.py +256 -0
  28. singlestoredb/docstring/tests/__init__.py +1 -0
  29. singlestoredb/docstring/tests/_pydoctor.py +21 -0
  30. singlestoredb/docstring/tests/test_epydoc.py +729 -0
  31. singlestoredb/docstring/tests/test_google.py +1007 -0
  32. singlestoredb/docstring/tests/test_numpydoc.py +1100 -0
  33. singlestoredb/docstring/tests/test_parse_from_object.py +109 -0
  34. singlestoredb/docstring/tests/test_parser.py +248 -0
  35. singlestoredb/docstring/tests/test_rest.py +547 -0
  36. singlestoredb/docstring/tests/test_util.py +70 -0
  37. singlestoredb/docstring/util.py +141 -0
  38. singlestoredb/exceptions.py +120 -0
  39. singlestoredb/functions/__init__.py +16 -0
  40. singlestoredb/functions/decorator.py +201 -0
  41. singlestoredb/functions/dtypes.py +1793 -0
  42. singlestoredb/functions/ext/__init__.py +1 -0
  43. singlestoredb/functions/ext/arrow.py +375 -0
  44. singlestoredb/functions/ext/asgi.py +2133 -0
  45. singlestoredb/functions/ext/json.py +420 -0
  46. singlestoredb/functions/ext/mmap.py +413 -0
  47. singlestoredb/functions/ext/rowdat_1.py +724 -0
  48. singlestoredb/functions/ext/timer.py +89 -0
  49. singlestoredb/functions/ext/utils.py +218 -0
  50. singlestoredb/functions/signature.py +1578 -0
  51. singlestoredb/functions/typing/__init__.py +41 -0
  52. singlestoredb/functions/typing/numpy.py +20 -0
  53. singlestoredb/functions/typing/pandas.py +2 -0
  54. singlestoredb/functions/typing/polars.py +2 -0
  55. singlestoredb/functions/typing/pyarrow.py +2 -0
  56. singlestoredb/functions/utils.py +421 -0
  57. singlestoredb/fusion/__init__.py +11 -0
  58. singlestoredb/fusion/graphql.py +213 -0
  59. singlestoredb/fusion/handler.py +916 -0
  60. singlestoredb/fusion/handlers/__init__.py +0 -0
  61. singlestoredb/fusion/handlers/export.py +525 -0
  62. singlestoredb/fusion/handlers/files.py +690 -0
  63. singlestoredb/fusion/handlers/job.py +660 -0
  64. singlestoredb/fusion/handlers/models.py +250 -0
  65. singlestoredb/fusion/handlers/stage.py +502 -0
  66. singlestoredb/fusion/handlers/utils.py +324 -0
  67. singlestoredb/fusion/handlers/workspace.py +956 -0
  68. singlestoredb/fusion/registry.py +249 -0
  69. singlestoredb/fusion/result.py +399 -0
  70. singlestoredb/http/__init__.py +27 -0
  71. singlestoredb/http/connection.py +1267 -0
  72. singlestoredb/magics/__init__.py +34 -0
  73. singlestoredb/magics/run_personal.py +137 -0
  74. singlestoredb/magics/run_shared.py +134 -0
  75. singlestoredb/management/__init__.py +9 -0
  76. singlestoredb/management/billing_usage.py +148 -0
  77. singlestoredb/management/cluster.py +462 -0
  78. singlestoredb/management/export.py +295 -0
  79. singlestoredb/management/files.py +1102 -0
  80. singlestoredb/management/inference_api.py +105 -0
  81. singlestoredb/management/job.py +887 -0
  82. singlestoredb/management/manager.py +373 -0
  83. singlestoredb/management/organization.py +226 -0
  84. singlestoredb/management/region.py +169 -0
  85. singlestoredb/management/utils.py +423 -0
  86. singlestoredb/management/workspace.py +1927 -0
  87. singlestoredb/mysql/__init__.py +177 -0
  88. singlestoredb/mysql/_auth.py +298 -0
  89. singlestoredb/mysql/charset.py +214 -0
  90. singlestoredb/mysql/connection.py +2032 -0
  91. singlestoredb/mysql/constants/CLIENT.py +38 -0
  92. singlestoredb/mysql/constants/COMMAND.py +32 -0
  93. singlestoredb/mysql/constants/CR.py +78 -0
  94. singlestoredb/mysql/constants/ER.py +474 -0
  95. singlestoredb/mysql/constants/EXTENDED_TYPE.py +3 -0
  96. singlestoredb/mysql/constants/FIELD_TYPE.py +48 -0
  97. singlestoredb/mysql/constants/FLAG.py +15 -0
  98. singlestoredb/mysql/constants/SERVER_STATUS.py +10 -0
  99. singlestoredb/mysql/constants/VECTOR_TYPE.py +6 -0
  100. singlestoredb/mysql/constants/__init__.py +0 -0
  101. singlestoredb/mysql/converters.py +271 -0
  102. singlestoredb/mysql/cursors.py +896 -0
  103. singlestoredb/mysql/err.py +92 -0
  104. singlestoredb/mysql/optionfile.py +20 -0
  105. singlestoredb/mysql/protocol.py +450 -0
  106. singlestoredb/mysql/tests/__init__.py +19 -0
  107. singlestoredb/mysql/tests/base.py +126 -0
  108. singlestoredb/mysql/tests/conftest.py +37 -0
  109. singlestoredb/mysql/tests/test_DictCursor.py +132 -0
  110. singlestoredb/mysql/tests/test_SSCursor.py +141 -0
  111. singlestoredb/mysql/tests/test_basic.py +452 -0
  112. singlestoredb/mysql/tests/test_connection.py +851 -0
  113. singlestoredb/mysql/tests/test_converters.py +58 -0
  114. singlestoredb/mysql/tests/test_cursor.py +141 -0
  115. singlestoredb/mysql/tests/test_err.py +16 -0
  116. singlestoredb/mysql/tests/test_issues.py +514 -0
  117. singlestoredb/mysql/tests/test_load_local.py +75 -0
  118. singlestoredb/mysql/tests/test_nextset.py +88 -0
  119. singlestoredb/mysql/tests/test_optionfile.py +27 -0
  120. singlestoredb/mysql/tests/thirdparty/__init__.py +6 -0
  121. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/__init__.py +9 -0
  122. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/capabilities.py +323 -0
  123. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/dbapi20.py +865 -0
  124. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_capabilities.py +110 -0
  125. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_dbapi20.py +224 -0
  126. singlestoredb/mysql/tests/thirdparty/test_MySQLdb/test_MySQLdb_nonstandard.py +101 -0
  127. singlestoredb/mysql/times.py +23 -0
  128. singlestoredb/notebook/__init__.py +16 -0
  129. singlestoredb/notebook/_objects.py +213 -0
  130. singlestoredb/notebook/_portal.py +352 -0
  131. singlestoredb/py.typed +0 -0
  132. singlestoredb/pytest.py +352 -0
  133. singlestoredb/server/__init__.py +0 -0
  134. singlestoredb/server/docker.py +452 -0
  135. singlestoredb/server/free_tier.py +267 -0
  136. singlestoredb/tests/__init__.py +0 -0
  137. singlestoredb/tests/alltypes.sql +307 -0
  138. singlestoredb/tests/alltypes_no_nulls.sql +208 -0
  139. singlestoredb/tests/empty.sql +0 -0
  140. singlestoredb/tests/ext_funcs/__init__.py +702 -0
  141. singlestoredb/tests/local_infile.csv +3 -0
  142. singlestoredb/tests/test.ipynb +18 -0
  143. singlestoredb/tests/test.sql +680 -0
  144. singlestoredb/tests/test2.ipynb +18 -0
  145. singlestoredb/tests/test2.sql +1 -0
  146. singlestoredb/tests/test_basics.py +1332 -0
  147. singlestoredb/tests/test_config.py +318 -0
  148. singlestoredb/tests/test_connection.py +3103 -0
  149. singlestoredb/tests/test_dbapi.py +27 -0
  150. singlestoredb/tests/test_exceptions.py +45 -0
  151. singlestoredb/tests/test_ext_func.py +1472 -0
  152. singlestoredb/tests/test_ext_func_data.py +1101 -0
  153. singlestoredb/tests/test_fusion.py +1527 -0
  154. singlestoredb/tests/test_http.py +288 -0
  155. singlestoredb/tests/test_management.py +1599 -0
  156. singlestoredb/tests/test_plugin.py +33 -0
  157. singlestoredb/tests/test_results.py +171 -0
  158. singlestoredb/tests/test_types.py +132 -0
  159. singlestoredb/tests/test_udf.py +737 -0
  160. singlestoredb/tests/test_udf_returns.py +459 -0
  161. singlestoredb/tests/test_vectorstore.py +51 -0
  162. singlestoredb/tests/test_xdict.py +333 -0
  163. singlestoredb/tests/utils.py +141 -0
  164. singlestoredb/types.py +373 -0
  165. singlestoredb/utils/__init__.py +0 -0
  166. singlestoredb/utils/config.py +950 -0
  167. singlestoredb/utils/convert_rows.py +69 -0
  168. singlestoredb/utils/debug.py +13 -0
  169. singlestoredb/utils/dtypes.py +205 -0
  170. singlestoredb/utils/events.py +65 -0
  171. singlestoredb/utils/mogrify.py +151 -0
  172. singlestoredb/utils/results.py +585 -0
  173. singlestoredb/utils/xdict.py +425 -0
  174. singlestoredb/vectorstore.py +192 -0
  175. singlestoredb/warnings.py +5 -0
  176. singlestoredb-1.16.1.dist-info/METADATA +165 -0
  177. singlestoredb-1.16.1.dist-info/RECORD +183 -0
  178. singlestoredb-1.16.1.dist-info/WHEEL +5 -0
  179. singlestoredb-1.16.1.dist-info/entry_points.txt +2 -0
  180. singlestoredb-1.16.1.dist-info/licenses/LICENSE +201 -0
  181. singlestoredb-1.16.1.dist-info/top_level.txt +3 -0
  182. sqlx/__init__.py +4 -0
  183. sqlx/magic.py +113 -0
@@ -0,0 +1,690 @@
1
+ #!/usr/bin/env python3
2
+ from typing import Any
3
+ from typing import Dict
4
+ from typing import Optional
5
+
6
+ from .. import result
7
+ from ..handler import SQLHandler
8
+ from ..result import FusionSQLResult
9
+ from .utils import dt_isoformat
10
+ from .utils import get_file_space
11
+
12
+
13
+ class ShowFilesHandler(SQLHandler):
14
+ """
15
+ Generic handler for listing files in a personal/shared space.
16
+ """ # noqa: E501
17
+
18
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
19
+ file_space = get_file_space(params)
20
+
21
+ res = FusionSQLResult()
22
+ res.add_field('Name', result.STRING)
23
+
24
+ if params['extended']:
25
+ res.add_field('Type', result.STRING)
26
+ res.add_field('Size', result.INTEGER)
27
+ res.add_field('Writable', result.STRING)
28
+ res.add_field('CreatedAt', result.DATETIME)
29
+ res.add_field('LastModifiedAt', result.DATETIME)
30
+
31
+ files = []
32
+ for x in file_space.listdir(
33
+ params['at_path'] or '/',
34
+ recursive=params['recursive'],
35
+ ):
36
+ info = file_space.info(x)
37
+ files.append(
38
+ tuple([
39
+ x, info.type, info.size or 0, info.writable,
40
+ dt_isoformat(info.created_at),
41
+ dt_isoformat(info.last_modified_at),
42
+ ]),
43
+ )
44
+ res.set_rows(files)
45
+
46
+ else:
47
+ res.set_rows([(x,) for x in file_space.listdir(
48
+ params['at_path'] or '/',
49
+ recursive=params['recursive'],
50
+ )])
51
+
52
+ if params['like']:
53
+ res = res.like(Name=params['like'])
54
+
55
+ return res.order_by(**params['order_by']).limit(params['limit'])
56
+
57
+
58
+ class ShowPersonalFilesHandler(ShowFilesHandler):
59
+ """
60
+ SHOW PERSONAL FILES
61
+ [ at_path ] [ <like> ]
62
+ [ <order-by> ]
63
+ [ <limit> ] [ recursive ] [ extended ];
64
+
65
+ # File path to list
66
+ at_path = AT '<path>'
67
+
68
+ # Should the listing be recursive?
69
+ recursive = RECURSIVE
70
+
71
+ # Should extended attributes be shown?
72
+ extended = EXTENDED
73
+
74
+ Description
75
+ -----------
76
+ Displays a list of files in a personal/shared space.
77
+
78
+ Arguments
79
+ ---------
80
+ * ``<path>``: A path in the personal/shared space.
81
+ * ``<pattern>``: A pattern similar to SQL LIKE clause.
82
+ Uses ``%`` as the wildcard character.
83
+
84
+ Remarks
85
+ -------
86
+ * Use the ``LIKE`` clause to specify a pattern and return only the
87
+ files that match the specified pattern.
88
+ * The ``LIMIT`` clause limits the number of results to the
89
+ specified number.
90
+ * Use the ``ORDER BY`` clause to sort the results by the specified
91
+ key. By default, the results are sorted in the ascending order.
92
+ * The ``AT`` clause specifies the path in the personal/shared
93
+ space to list the files from.
94
+ * Use the ``RECURSIVE`` clause to list the files recursively.
95
+ * To return more information about the files, use the ``EXTENDED``
96
+ clause.
97
+
98
+ Examples
99
+ --------
100
+ The following command lists the files at a specific path::
101
+
102
+ SHOW PERSONAL FILES AT "/data/";
103
+
104
+ The following command lists the files recursively with
105
+ additional information::
106
+
107
+ SHOW PERSONAL FILES RECURSIVE EXTENDED;
108
+
109
+ See Also
110
+ --------
111
+ * ``SHOW SHARED FILES``
112
+ * ``UPLOAD PERSONAL FILE``
113
+ * ``UPLOAD SHARED FILE``
114
+ * ``DOWNLOAD PERSONAL FILE``
115
+ * ``DOWNLOAD SHARED FILE``
116
+
117
+ """ # noqa: E501
118
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
119
+ params['file_location'] = 'PERSONAL'
120
+ return super().run(params)
121
+
122
+
123
+ class ShowSharedFilesHandler(ShowFilesHandler):
124
+ """
125
+ SHOW SHARED FILES
126
+ [ at_path ] [ <like> ]
127
+ [ <order-by> ]
128
+ [ <limit> ] [ recursive ] [ extended ];
129
+
130
+ # File path to list
131
+ at_path = AT '<path>'
132
+
133
+ # Should the listing be recursive?
134
+ recursive = RECURSIVE
135
+
136
+ # Should extended attributes be shown?
137
+ extended = EXTENDED
138
+
139
+ Description
140
+ -----------
141
+ Displays a list of files in a personal/shared space.
142
+
143
+ Arguments
144
+ ---------
145
+ * ``<path>``: A path in the personal/shared space.
146
+ * ``<pattern>``: A pattern similar to SQL LIKE clause.
147
+ Uses ``%`` as the wildcard character.
148
+
149
+ Remarks
150
+ -------
151
+ * Use the ``LIKE`` clause to specify a pattern and return only the
152
+ files that match the specified pattern.
153
+ * The ``LIMIT`` clause limits the number of results to the
154
+ specified number.
155
+ * Use the ``ORDER BY`` clause to sort the results by the specified
156
+ key. By default, the results are sorted in the ascending order.
157
+ * The ``AT`` clause specifies the path in the personal/shared
158
+ space to list the files from.
159
+ * Use the ``RECURSIVE`` clause to list the files recursively.
160
+ * To return more information about the files, use the ``EXTENDED``
161
+ clause.
162
+
163
+ Examples
164
+ --------
165
+ The following command lists the files at a specific path::
166
+
167
+ SHOW SHARED FILES AT "/data/";
168
+
169
+ The following command lists the files recursively with
170
+ additional information::
171
+
172
+ SHOW SHARED FILES RECURSIVE EXTENDED;
173
+
174
+ See Also
175
+ --------
176
+ * ``SHOW PERSONAL FILES``
177
+ * ``UPLOAD PERSONAL FILE``
178
+ * ``UPLOAD SHARED FILE``
179
+ * ``DOWNLOAD PERSONAL FILE``
180
+ * ``DOWNLOAD SHARED FILE``
181
+
182
+ """ # noqa: E501
183
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
184
+ params['file_location'] = 'SHARED'
185
+ return super().run(params)
186
+
187
+
188
+ ShowPersonalFilesHandler.register(overwrite=True)
189
+ ShowSharedFilesHandler.register(overwrite=True)
190
+
191
+
192
+ class UploadFileHandler(SQLHandler):
193
+ """
194
+ Generic handler for uploading files to a personal/shared space.
195
+ """ # noqa: E501
196
+
197
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
198
+ file_space = get_file_space(params)
199
+ file_space.upload_file(
200
+ params['local_path'], params['path'],
201
+ overwrite=params['overwrite'],
202
+ )
203
+ return None
204
+
205
+
206
+ class UploadPersonalFileHandler(UploadFileHandler):
207
+ """
208
+ UPLOAD PERSONAL FILE TO path
209
+ FROM local_path [ overwrite ];
210
+
211
+ # Path to file
212
+ path = '<filename>'
213
+
214
+ # Path to local file
215
+ local_path = '<local-path>'
216
+
217
+ # Should an existing file be overwritten?
218
+ overwrite = OVERWRITE
219
+
220
+ Description
221
+ -----------
222
+ Uploads a file to a personal/shared space.
223
+
224
+ Arguments
225
+ ---------
226
+ * ``<filename>``: The filename in the personal/shared space where the file is uploaded.
227
+ * ``<local-path>``: The path to the file to upload in the local
228
+ directory.
229
+
230
+ Remarks
231
+ -------
232
+ * If the ``OVERWRITE`` clause is specified, any existing file at the
233
+ specified path in the personal/shared space is overwritten.
234
+
235
+ Examples
236
+ --------
237
+ The following command uploads a file to a personal/shared space and overwrite any
238
+ existing files at the specified path::
239
+
240
+ UPLOAD PERSONAL FILE TO 'stats.csv'
241
+ FROM '/tmp/user/stats.csv' OVERWRITE;
242
+
243
+ See Also
244
+ --------
245
+ * ``UPLOAD SHARED FILE``
246
+ * ``DOWNLOAD PERSONAL FILE``
247
+ * ``DOWNLOAD SHARED FILE``
248
+
249
+ """ # noqa: E501
250
+
251
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
252
+ params['file_location'] = 'PERSONAL'
253
+ return super().run(params)
254
+
255
+
256
+ class UploadSharedFileHandler(UploadFileHandler):
257
+ """
258
+ UPLOAD SHARED FILE TO path
259
+ FROM local_path [ overwrite ];
260
+
261
+ # Path to file
262
+ path = '<filename>'
263
+
264
+ # Path to local file
265
+ local_path = '<local-path>'
266
+
267
+ # Should an existing file be overwritten?
268
+ overwrite = OVERWRITE
269
+
270
+ Description
271
+ -----------
272
+ Uploads a file to a personal/shared space.
273
+
274
+ Arguments
275
+ ---------
276
+ * ``<filename>``: The filename in the personal/shared space where the file is uploaded.
277
+ * ``<local-path>``: The path to the file to upload in the local
278
+ directory.
279
+
280
+ Remarks
281
+ -------
282
+ * If the ``OVERWRITE`` clause is specified, any existing file at the
283
+ specified path in the personal/shared space is overwritten.
284
+
285
+ Examples
286
+ --------
287
+ The following command uploads a file to a personal/shared space and overwrite any
288
+ existing files at the specified path::
289
+
290
+ UPLOAD SHARED FILE TO 'stats.csv'
291
+ FROM '/tmp/user/stats.csv' OVERWRITE;
292
+
293
+ See Also
294
+ --------
295
+ * ``UPLOAD PERSONAL FILE``
296
+ * ``DOWNLOAD PERSONAL FILE``
297
+ * ``DOWNLOAD SHARED FILE``
298
+
299
+ """ # noqa: E501
300
+
301
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
302
+ params['file_location'] = 'SHARED'
303
+ return super().run(params)
304
+
305
+
306
+ UploadPersonalFileHandler.register(overwrite=True)
307
+ UploadSharedFileHandler.register(overwrite=True)
308
+
309
+
310
+ class DownloadFileHandler(SQLHandler):
311
+ """
312
+ Generic handler for downloading files from a personal/shared space.
313
+ """ # noqa: E501
314
+
315
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
316
+ file_space = get_file_space(params)
317
+
318
+ out = file_space.download_file(
319
+ params['path'],
320
+ local_path=params['local_path'] or None,
321
+ overwrite=params['overwrite'],
322
+ encoding=params['encoding'] or None,
323
+ )
324
+
325
+ if not params['local_path']:
326
+ res = FusionSQLResult()
327
+ if params['encoding']:
328
+ res.add_field('Data', result.STRING)
329
+ else:
330
+ res.add_field('Data', result.BLOB)
331
+ res.set_rows([(out,)])
332
+ return res
333
+
334
+ return None
335
+
336
+
337
+ class DownloadPersonalFileHandler(DownloadFileHandler):
338
+ """
339
+ DOWNLOAD PERSONAL FILE path
340
+ [ local_path ]
341
+ [ overwrite ]
342
+ [ encoding ];
343
+
344
+ # Path to file
345
+ path = '<path>'
346
+
347
+ # Path to local file
348
+ local_path = TO '<local-path>'
349
+
350
+ # Should an existing file be overwritten?
351
+ overwrite = OVERWRITE
352
+
353
+ # File encoding
354
+ encoding = ENCODING '<encoding>'
355
+
356
+ Description
357
+ -----------
358
+ Download a file from a personal/shared space.
359
+
360
+ Arguments
361
+ ---------
362
+ * ``<path>``: The path to the file to download in a personal/shared space.
363
+ * ``<encoding>``: The encoding to apply to the downloaded file.
364
+ * ``<local-path>``: Specifies the path in the local directory
365
+ where the file is downloaded.
366
+
367
+ Remarks
368
+ -------
369
+ * If the ``OVERWRITE`` clause is specified, any existing file at
370
+ the download location is overwritten.
371
+ * By default, files are downloaded in binary encoding. To view
372
+ the contents of the file on the standard output, use the
373
+ ``ENCODING`` clause and specify an encoding.
374
+ * If ``<local-path>`` is not specified, the file is displayed
375
+ on the standard output.
376
+
377
+ Examples
378
+ --------
379
+ The following command displays the contents of the file on the
380
+ standard output::
381
+
382
+ DOWNLOAD PERSONAL FILE '/data/stats.csv' ENCODING 'utf8';
383
+
384
+ The following command downloads a file to a specific location and
385
+ overwrites any existing file with the name ``stats.csv`` on the local storage::
386
+
387
+ DOWNLOAD PERSONAL FILE '/data/stats.csv'
388
+ TO '/tmp/data.csv' OVERWRITE;
389
+
390
+ See Also
391
+ --------
392
+ * ``DOWNLOAD SHARED FILE``
393
+ * ``UPLOAD PERSONAL FILE``
394
+ * ``UPLOAD SHARED FILE``
395
+
396
+ """ # noqa: E501
397
+
398
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
399
+ params['file_location'] = 'PERSONAL'
400
+ return super().run(params)
401
+
402
+
403
+ class DownloadSharedFileHandler(DownloadFileHandler):
404
+ """
405
+ DOWNLOAD SHARED FILE path
406
+ [ local_path ]
407
+ [ overwrite ]
408
+ [ encoding ];
409
+
410
+ # Path to file
411
+ path = '<path>'
412
+
413
+ # Path to local file
414
+ local_path = TO '<local-path>'
415
+
416
+ # Should an existing file be overwritten?
417
+ overwrite = OVERWRITE
418
+
419
+ # File encoding
420
+ encoding = ENCODING '<encoding>'
421
+
422
+ Description
423
+ -----------
424
+ Download a file from a personal/shared space.
425
+
426
+ Arguments
427
+ ---------
428
+ * ``<path>``: The path to the file to download in a personal/shared space.
429
+ * ``<encoding>``: The encoding to apply to the downloaded file.
430
+ * ``<local-path>``: Specifies the path in the local directory
431
+ where the file is downloaded.
432
+
433
+ Remarks
434
+ -------
435
+ * If the ``OVERWRITE`` clause is specified, any existing file at
436
+ the download location is overwritten.
437
+ * By default, files are downloaded in binary encoding. To view
438
+ the contents of the file on the standard output, use the
439
+ ``ENCODING`` clause and specify an encoding.
440
+ * If ``<local-path>`` is not specified, the file is displayed
441
+ on the standard output.
442
+
443
+ Examples
444
+ --------
445
+ The following command displays the contents of the file on the
446
+ standard output::
447
+
448
+ DOWNLOAD SHARED FILE '/data/stats.csv' ENCODING 'utf8';
449
+
450
+ The following command downloads a file to a specific location and
451
+ overwrites any existing file with the name ``stats.csv`` on the local storage::
452
+
453
+ DOWNLOAD SHARED FILE '/data/stats.csv'
454
+ TO '/tmp/data.csv' OVERWRITE;
455
+
456
+ See Also
457
+ --------
458
+ * ``DOWNLOAD PERSONAL FILE``
459
+ * ``UPLOAD PERSONAL FILE``
460
+ * ``UPLOAD SHARED FILE``
461
+
462
+ """ # noqa: E501
463
+
464
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
465
+ params['file_location'] = 'SHARED'
466
+ return super().run(params)
467
+
468
+
469
+ DownloadPersonalFileHandler.register(overwrite=True)
470
+ DownloadSharedFileHandler.register(overwrite=True)
471
+
472
+
473
+ class DropHandler(SQLHandler):
474
+ """
475
+ Generic handler for deleting files/folders from a personal/shared space.
476
+ """ # noqa: E501
477
+
478
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
479
+ file_space = get_file_space(params)
480
+
481
+ file_type = params['file_type']
482
+ if not file_type:
483
+ raise KeyError('file type was not specified')
484
+
485
+ file_type = file_type.lower()
486
+ if file_type not in ['file', 'folder']:
487
+ raise ValueError('file type must be either FILE or FOLDER')
488
+
489
+ if file_type == 'file':
490
+ file_space.remove(params['path'])
491
+ elif file_type == 'folder':
492
+ if params['recursive']:
493
+ file_space.removedirs(params['path'])
494
+ else:
495
+ file_space.rmdir(params['path'])
496
+
497
+ return None
498
+
499
+
500
+ class DropPersonalHandler(DropHandler):
501
+ """
502
+ DROP PERSONAL <file-type> path
503
+ [ recursive ];
504
+
505
+ # Path to file
506
+ path = '<path>'
507
+
508
+ # Should folders be deleted recursively?
509
+ recursive = RECURSIVE
510
+
511
+ Description
512
+ -----------
513
+ Deletes a file/folder from a personal/shared space.
514
+
515
+ Arguments
516
+ ---------
517
+ * ``<file-type>``: The type of the file, it can
518
+ be either 'FILE' or 'FOLDER'.
519
+ * ``<path>``: The path to the file to delete in a personal/shared space.
520
+
521
+ Remarks
522
+ -------
523
+ * The ``RECURSIVE`` clause indicates that the specified folder
524
+ is deleted recursively.
525
+
526
+ Example
527
+ --------
528
+ The following commands delete a file/folder from a personal/shared space::
529
+
530
+ DROP PERSONAL FILE '/data/stats.csv';
531
+ DROP PERSONAL FOLDER '/data/' RECURSIVE;
532
+
533
+ See Also
534
+ --------
535
+ * ``DROP SHARED FILE``
536
+ * ``DROP SHARED FOLDER``
537
+
538
+ """ # noqa: E501
539
+
540
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
541
+ params['file_location'] = 'PERSONAL'
542
+ return super().run(params)
543
+
544
+
545
+ class DropSharedHandler(DropHandler):
546
+ """
547
+ DROP SHARED <file-type> path
548
+ [ recursive ];
549
+
550
+ # Path to file
551
+ path = '<path>'
552
+
553
+ # Should folders be deleted recursively?
554
+ recursive = RECURSIVE
555
+
556
+ Description
557
+ -----------
558
+ Deletes a file/folder from a personal/shared space.
559
+
560
+ Arguments
561
+ ---------
562
+ * ``<file-type>``: The type of the file, it can
563
+ be either 'FILE' or 'FOLDER'.
564
+ * ``<path>``: The path to the file to delete in a personal/shared space.
565
+
566
+ Remarks
567
+ -------
568
+ * The ``RECURSIVE`` clause indicates that the specified folder
569
+ is deleted recursively.
570
+
571
+ Example
572
+ --------
573
+ The following commands delete a file/folder from a personal/shared space::
574
+
575
+ DROP SHARED FILE '/data/stats.csv';
576
+ DROP SHARED FOLDER '/data/' RECURSIVE;
577
+
578
+ See Also
579
+ --------
580
+ * ``DROP PERSONAL FILE``
581
+ * ``DROP PERSONAL FOLDER``
582
+
583
+ """ # noqa: E501
584
+
585
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
586
+ params['file_location'] = 'SHARED'
587
+ return super().run(params)
588
+
589
+
590
+ DropPersonalHandler.register(overwrite=True)
591
+ DropSharedHandler.register(overwrite=True)
592
+
593
+
594
+ class CreateFolderHandler(SQLHandler):
595
+ """
596
+ Generic handler for creating folders in a personal/shared space.
597
+ """
598
+
599
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
600
+ file_space = get_file_space(params)
601
+ file_space.mkdir(params['path'], overwrite=params['overwrite'])
602
+ return None
603
+
604
+
605
+ class CreatePersonalFolderHandler(CreateFolderHandler):
606
+ """
607
+ CREATE PERSONAL FOLDER path
608
+ [ overwrite ];
609
+
610
+ # Path to folder
611
+ path = '<path>'
612
+
613
+ # Should an existing folder be overwritten?
614
+ overwrite = OVERWRITE
615
+
616
+ Description
617
+ -----------
618
+ Creates a new folder at the specified path in a personal/shared space.
619
+
620
+ Arguments
621
+ ---------
622
+ * ``<path>``: The path in a personal/shared space where the folder
623
+ is created. The path must end with a trailing slash (/).
624
+
625
+ Remarks
626
+ -------
627
+ * If the ``OVERWRITE`` clause is specified, any existing
628
+ folder at the specified path is overwritten.
629
+
630
+ Example
631
+ -------
632
+ The following command creates a folder in a personal/shared space::
633
+
634
+ CREATE PERSONAL FOLDER `/data/csv/`;
635
+
636
+ See Also
637
+ --------
638
+ * ``CREATE SHARED FOLDER``
639
+
640
+ """
641
+
642
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
643
+ params['file_location'] = 'PERSONAL'
644
+ return super().run(params)
645
+
646
+
647
+ class CreateSharedFolderHandler(CreateFolderHandler):
648
+ """
649
+ CREATE SHARED FOLDER path
650
+ [ overwrite ];
651
+
652
+ # Path to folder
653
+ path = '<path>'
654
+
655
+ # Should an existing folder be overwritten?
656
+ overwrite = OVERWRITE
657
+
658
+ Description
659
+ -----------
660
+ Creates a new folder at the specified path in a personal/shared space.
661
+
662
+ Arguments
663
+ ---------
664
+ * ``<path>``: The path in a personal/shared space where the folder
665
+ is created. The path must end with a trailing slash (/).
666
+
667
+ Remarks
668
+ -------
669
+ * If the ``OVERWRITE`` clause is specified, any existing
670
+ folder at the specified path is overwritten.
671
+
672
+ Example
673
+ -------
674
+ The following command creates a folder in a personal/shared space::
675
+
676
+ CREATE SHARED FOLDER `/data/csv/`;
677
+
678
+ See Also
679
+ --------
680
+ * ``CREATE PERSONAL FOLDER``
681
+
682
+ """
683
+
684
+ def run(self, params: Dict[str, Any]) -> Optional[FusionSQLResult]:
685
+ params['file_location'] = 'SHARED'
686
+ return super().run(params)
687
+
688
+
689
+ CreatePersonalFolderHandler.register(overwrite=True)
690
+ CreateSharedFolderHandler.register(overwrite=True)