files-com 1.6.208__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.

Potentially problematic release.


This version of files-com might be problematic. Click here for more details.

Files changed (126) hide show
  1. README.md +758 -0
  2. _VERSION +1 -0
  3. files_com-1.6.208.dist-info/METADATA +770 -0
  4. files_com-1.6.208.dist-info/RECORD +126 -0
  5. files_com-1.6.208.dist-info/WHEEL +5 -0
  6. files_com-1.6.208.dist-info/licenses/LICENSE +21 -0
  7. files_com-1.6.208.dist-info/top_level.txt +1 -0
  8. files_sdk/__init__.py +309 -0
  9. files_sdk/api.py +63 -0
  10. files_sdk/api_client.py +336 -0
  11. files_sdk/error.py +2981 -0
  12. files_sdk/list_obj.py +42 -0
  13. files_sdk/models/__init__.py +119 -0
  14. files_sdk/models/account_line_item.py +51 -0
  15. files_sdk/models/action.py +49 -0
  16. files_sdk/models/action_notification_export.py +153 -0
  17. files_sdk/models/action_notification_export_result.py +88 -0
  18. files_sdk/models/agent_push_update.py +44 -0
  19. files_sdk/models/api_key.py +318 -0
  20. files_sdk/models/api_request_log.py +105 -0
  21. files_sdk/models/app.py +89 -0
  22. files_sdk/models/as2_incoming_message.py +117 -0
  23. files_sdk/models/as2_outgoing_message.py +113 -0
  24. files_sdk/models/as2_partner.py +415 -0
  25. files_sdk/models/as2_station.py +282 -0
  26. files_sdk/models/auto.py +36 -0
  27. files_sdk/models/automation.py +823 -0
  28. files_sdk/models/automation_log.py +94 -0
  29. files_sdk/models/automation_run.py +112 -0
  30. files_sdk/models/bandwidth_snapshot.py +91 -0
  31. files_sdk/models/behavior.py +340 -0
  32. files_sdk/models/bundle.py +686 -0
  33. files_sdk/models/bundle_action.py +93 -0
  34. files_sdk/models/bundle_download.py +94 -0
  35. files_sdk/models/bundle_notification.py +252 -0
  36. files_sdk/models/bundle_path.py +37 -0
  37. files_sdk/models/bundle_recipient.py +133 -0
  38. files_sdk/models/bundle_registration.py +82 -0
  39. files_sdk/models/child_site_management_policy.py +278 -0
  40. files_sdk/models/clickwrap.py +268 -0
  41. files_sdk/models/dns_record.py +59 -0
  42. files_sdk/models/email_incoming_message.py +102 -0
  43. files_sdk/models/email_log.py +84 -0
  44. files_sdk/models/errors.py +37 -0
  45. files_sdk/models/exavault_api_request_log.py +102 -0
  46. files_sdk/models/external_event.py +148 -0
  47. files_sdk/models/file.py +851 -0
  48. files_sdk/models/file_action.py +39 -0
  49. files_sdk/models/file_comment.py +191 -0
  50. files_sdk/models/file_comment_reaction.py +125 -0
  51. files_sdk/models/file_migration.py +69 -0
  52. files_sdk/models/file_migration_log.py +88 -0
  53. files_sdk/models/file_upload_part.py +54 -0
  54. files_sdk/models/folder.py +186 -0
  55. files_sdk/models/form_field.py +43 -0
  56. files_sdk/models/form_field_set.py +265 -0
  57. files_sdk/models/ftp_action_log.py +104 -0
  58. files_sdk/models/gpg_key.py +333 -0
  59. files_sdk/models/group.py +338 -0
  60. files_sdk/models/group_user.py +235 -0
  61. files_sdk/models/history.py +236 -0
  62. files_sdk/models/history_export.py +238 -0
  63. files_sdk/models/history_export_result.py +98 -0
  64. files_sdk/models/holiday_region.py +58 -0
  65. files_sdk/models/image.py +37 -0
  66. files_sdk/models/inbound_s3_log.py +95 -0
  67. files_sdk/models/inbox_recipient.py +124 -0
  68. files_sdk/models/inbox_registration.py +79 -0
  69. files_sdk/models/inbox_upload.py +80 -0
  70. files_sdk/models/invoice.py +91 -0
  71. files_sdk/models/invoice_line_item.py +51 -0
  72. files_sdk/models/ip_address.py +119 -0
  73. files_sdk/models/key_lifecycle_rule.py +243 -0
  74. files_sdk/models/lock.py +174 -0
  75. files_sdk/models/message.py +244 -0
  76. files_sdk/models/message_comment.py +223 -0
  77. files_sdk/models/message_comment_reaction.py +181 -0
  78. files_sdk/models/message_reaction.py +170 -0
  79. files_sdk/models/notification.py +451 -0
  80. files_sdk/models/outbound_connection_log.py +105 -0
  81. files_sdk/models/partner.py +307 -0
  82. files_sdk/models/payment.py +91 -0
  83. files_sdk/models/payment_line_item.py +42 -0
  84. files_sdk/models/permission.py +190 -0
  85. files_sdk/models/preview.py +40 -0
  86. files_sdk/models/priority.py +63 -0
  87. files_sdk/models/project.py +205 -0
  88. files_sdk/models/public_hosting_request_log.py +101 -0
  89. files_sdk/models/public_ip_address.py +42 -0
  90. files_sdk/models/public_key.py +269 -0
  91. files_sdk/models/remote_bandwidth_snapshot.py +91 -0
  92. files_sdk/models/remote_mount_backend.py +438 -0
  93. files_sdk/models/remote_server.py +1854 -0
  94. files_sdk/models/remote_server_configuration_file.py +73 -0
  95. files_sdk/models/remote_server_credential.py +855 -0
  96. files_sdk/models/request.py +184 -0
  97. files_sdk/models/restore.py +142 -0
  98. files_sdk/models/scim_log.py +88 -0
  99. files_sdk/models/session.py +100 -0
  100. files_sdk/models/settings_change.py +71 -0
  101. files_sdk/models/sftp_action_log.py +108 -0
  102. files_sdk/models/sftp_host_key.py +215 -0
  103. files_sdk/models/share_group.py +228 -0
  104. files_sdk/models/share_group_member.py +41 -0
  105. files_sdk/models/siem_http_destination.py +1074 -0
  106. files_sdk/models/site.py +1289 -0
  107. files_sdk/models/snapshot.py +255 -0
  108. files_sdk/models/sso_strategy.py +168 -0
  109. files_sdk/models/status.py +42 -0
  110. files_sdk/models/style.py +152 -0
  111. files_sdk/models/sync.py +588 -0
  112. files_sdk/models/sync_log.py +86 -0
  113. files_sdk/models/sync_run.py +124 -0
  114. files_sdk/models/usage_by_top_level_dir.py +41 -0
  115. files_sdk/models/usage_daily_snapshot.py +93 -0
  116. files_sdk/models/usage_snapshot.py +73 -0
  117. files_sdk/models/user.py +1232 -0
  118. files_sdk/models/user_cipher_use.py +91 -0
  119. files_sdk/models/user_lifecycle_rule.py +355 -0
  120. files_sdk/models/user_request.py +166 -0
  121. files_sdk/models/user_sftp_client_use.py +68 -0
  122. files_sdk/models/web_dav_action_log.py +104 -0
  123. files_sdk/models/webhook_test.py +116 -0
  124. files_sdk/models/workspace.py +202 -0
  125. files_sdk/path_util.py +42 -0
  126. files_sdk/util.py +34 -0
@@ -0,0 +1,851 @@
1
+ import builtins # noqa: F401
2
+ from builtins import open as builtin_open
3
+ from datetime import datetime
4
+ import io
5
+ from pathlib import Path
6
+ from files_sdk.models.file_action import FileAction
7
+ from files_sdk.models.file_upload_part import FileUploadPart
8
+ from files_sdk.api import Api # noqa: F401
9
+ from files_sdk.error import ( # noqa: F401
10
+ InvalidParameterError,
11
+ MissingParameterError,
12
+ NotImplementedError,
13
+ )
14
+
15
+
16
+ class File:
17
+ default_attributes = {
18
+ "path": None, # string - File/Folder path. This must be slash-delimited, but it must neither start nor end with a slash. Maximum of 5000 characters.
19
+ "created_by_id": None, # int64 - User ID of the User who created the file/folder
20
+ "created_by_api_key_id": None, # int64 - ID of the API key that created the file/folder
21
+ "created_by_as2_incoming_message_id": None, # int64 - ID of the AS2 Incoming Message that created the file/folder
22
+ "created_by_automation_id": None, # int64 - ID of the Automation that created the file/folder
23
+ "created_by_bundle_registration_id": None, # int64 - ID of the Bundle Registration that created the file/folder
24
+ "created_by_inbox_id": None, # int64 - ID of the Inbox that created the file/folder
25
+ "created_by_remote_server_id": None, # int64 - ID of the Remote Server that created the file/folder
26
+ "created_by_sync_id": None, # int64 - ID of the Sync that created the file/folder
27
+ "custom_metadata": None, # object - Custom metadata map of keys and values. Limited to 32 keys, 256 characters per key and 1024 characters per value.
28
+ "display_name": None, # string - File/Folder display name
29
+ "type": None, # string - Type: `directory` or `file`.
30
+ "size": None, # int64 - File/Folder size
31
+ "created_at": None, # date-time - File created date/time
32
+ "last_modified_by_id": None, # int64 - User ID of the User who last modified the file/folder
33
+ "last_modified_by_api_key_id": None, # int64 - ID of the API key that last modified the file/folder
34
+ "last_modified_by_automation_id": None, # int64 - ID of the Automation that last modified the file/folder
35
+ "last_modified_by_bundle_registration_id": None, # int64 - ID of the Bundle Registration that last modified the file/folder
36
+ "last_modified_by_remote_server_id": None, # int64 - ID of the Remote Server that last modified the file/folder
37
+ "last_modified_by_sync_id": None, # int64 - ID of the Sync that last modified the file/folder
38
+ "mtime": None, # date-time - File last modified date/time, according to the server. This is the timestamp of the last Files.com operation of the file, regardless of what modified timestamp was sent.
39
+ "provided_mtime": None, # date-time - File last modified date/time, according to the client who set it. Files.com allows desktop, FTP, SFTP, and WebDAV clients to set modified at times. This allows Desktop<->Cloud syncing to preserve modified at times.
40
+ "crc32": None, # string - File CRC32 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
41
+ "md5": None, # string - File MD5 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
42
+ "sha1": None, # string - File SHA1 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
43
+ "sha256": None, # string - File SHA256 checksum. This is sometimes delayed, so if you get a blank response, wait and try again.
44
+ "mime_type": None, # string - MIME Type. This is determined by the filename extension and is not stored separately internally.
45
+ "region": None, # string - Region location
46
+ "permissions": None, # string - A short string representing the current user's permissions. Can be `r` (Read),`w` (Write),`d` (Delete), `l` (List) or any combination
47
+ "subfolders_locked?": None, # boolean - Are subfolders locked and unable to be modified?
48
+ "is_locked": None, # boolean - Is this folder locked and unable to be modified?
49
+ "download_uri": None, # string - Link to download file. Provided only in response to a download request.
50
+ "priority_color": None, # string - Bookmark/priority color of file/folder
51
+ "preview_id": None, # int64 - File preview ID
52
+ "preview": None, # Preview - File preview
53
+ "action": None, # string - The action to perform. Can be `append`, `attachment`, `end`, `upload`, `put`, or may not exist
54
+ "length": None, # int64 - Length of file.
55
+ "mkdir_parents": None, # boolean - Create parent directories if they do not exist?
56
+ "part": None, # int64 - Part if uploading a part.
57
+ "parts": None, # int64 - How many parts to fetch?
58
+ "ref": None, # string -
59
+ "restart": None, # int64 - File byte offset to restart from.
60
+ "structure": None, # string - If copying folder, copy just the structure?
61
+ "with_rename": None, # boolean - Allow file rename instead of overwrite?
62
+ "buffered_upload": None, # boolean - If true, and the path refers to a destination not stored on Files.com (such as a remote server mount), the upload will be uploaded first to Files.com before being sent to the remote server mount. This can allow clients to upload using parallel parts to a remote server destination that does not offer parallel parts support natively.
63
+ }
64
+
65
+ def __init__(self, *args):
66
+ self.set_attributes({})
67
+ self.options = {}
68
+ self.mode = "r"
69
+ self.upload = None
70
+ self.etags = None
71
+ self.io_obj = io.StringIO()
72
+ self.closed = True
73
+
74
+ self.bytes_written = 0
75
+ if len(args) >= 1:
76
+ if isinstance(args[0], dict):
77
+ self.set_attributes(args[0])
78
+ elif isinstance(args[0], str):
79
+ self.set_attributes({"path": args[0]})
80
+ if len(args) >= 2:
81
+ if isinstance(args[1], dict):
82
+ self.options = args[1]
83
+ elif isinstance(args[1], str):
84
+ self.mode = args[1]
85
+ if len(args) >= 3:
86
+ if isinstance(args[2], dict):
87
+ self.options = args[2]
88
+
89
+ def set_attributes(self, attributes):
90
+ for attribute, default_value in File.default_attributes.items():
91
+ setattr(self, attribute, attributes.get(attribute, default_value))
92
+
93
+ def get_attributes(self):
94
+ return {
95
+ k: getattr(self, k, None)
96
+ for k in File.default_attributes
97
+ if getattr(self, k, None) is not None
98
+ }
99
+
100
+ def __enter__(self):
101
+ return self
102
+
103
+ def __exit__(self, type, value, traceback):
104
+ self.close()
105
+
106
+ def __del__(self):
107
+ if not self.io_obj.closed:
108
+ self.io_obj.close()
109
+
110
+ def close(self):
111
+ self.flush()
112
+
113
+ if self.upload:
114
+ end_options = {
115
+ "action": "end",
116
+ "etags": self.etags,
117
+ "provided_mtime": datetime.now().isoformat(),
118
+ "ref": self.upload.ref,
119
+ "size": self.bytes_written,
120
+ }
121
+
122
+ file = create(self.path, end_options, self.options)
123
+ self.set_attributes(file.get_attributes())
124
+ self.mode = "r"
125
+ self.upload = None
126
+ self.etags = None
127
+ self.io_obj = io.StringIO()
128
+ self.io_obj.close
129
+ self.closed = True
130
+
131
+ def fileno(self):
132
+ raise OSError
133
+
134
+ def flush(self, *_args):
135
+ if "w" in self.mode:
136
+ if self.io_obj.seekable():
137
+ self.io_obj.seek(0)
138
+
139
+ self.upload, self.etags, bytes_written = upload_chunks(
140
+ self.io_obj, self.path, self.options, self.upload, self.etags
141
+ )
142
+ self.bytes_written += bytes_written
143
+ elif "a" in self.mode:
144
+ raise io.UnsupportedOperation("Append is not a supported mode")
145
+
146
+ def isatty(self):
147
+ return False
148
+
149
+ def read(self):
150
+ if self.readable():
151
+ self.download_content(
152
+ self.io_obj, False if "b" in self.mode else True
153
+ )
154
+ self.io_obj.seek(0)
155
+ return self.io_obj.read()
156
+ else:
157
+ raise OSError("read mode not indicated")
158
+
159
+ def readable(self):
160
+ if "r" in self.mode and not self.closed:
161
+ return True
162
+ return False
163
+
164
+ def readall(self):
165
+ self.read()
166
+
167
+ def readinto(self):
168
+ return NotImplementedError
169
+
170
+ def readline(self):
171
+ return NotImplementedError
172
+
173
+ def seek(self):
174
+ raise OSError
175
+
176
+ def seekable(self):
177
+ return False
178
+
179
+ def tell(self):
180
+ raise OSError
181
+
182
+ def truncate(self):
183
+ raise OSError
184
+
185
+ def writeable(self):
186
+ if "w" in self.mode and not self.closed:
187
+ return True
188
+ return False
189
+
190
+ def write(self, *args):
191
+ if self.writeable():
192
+ self.io_obj.write(*args)
193
+ else:
194
+ raise OSError("write mode not indicated")
195
+
196
+ def download_uri_with_load(self):
197
+ if self.download_uri:
198
+ return self.download_uri
199
+
200
+ f = download(self.path, {}, self.options)
201
+ self.set_attributes(f.get_attributes())
202
+ return self.download_uri
203
+
204
+ def download_content(self, io, is_string_io=False):
205
+ Api.client().stream_download(
206
+ self.download_uri_with_load(), io, is_string_io
207
+ )
208
+
209
+ def download_file(self, output_file):
210
+ with builtin_open(output_file, "wb") as file:
211
+ self.download_content(file)
212
+
213
+ # Download File
214
+ #
215
+ # Parameters:
216
+ # action - string - Can be blank, `redirect` or `stat`. If set to `stat`, we will return file information but without a download URL, and without logging a download. If set to `redirect` we will serve a 302 redirect directly to the file. This is used for integrations with Zapier, and is not recommended for most integrations.
217
+ # preview_size - string - Request a preview size. Can be `small` (default), `large`, `xlarge`, or `pdf`.
218
+ # with_previews - boolean - Include file preview information?
219
+ # with_priority_color - boolean - Include file priority color information?
220
+ def download(self, params=None):
221
+ if not isinstance(params, dict):
222
+ params = {}
223
+
224
+ if hasattr(self, "path") and self.path:
225
+ params["path"] = self.path
226
+ else:
227
+ raise MissingParameterError("Current object doesn't have a path")
228
+ if "path" not in params:
229
+ raise MissingParameterError("Parameter missing: path")
230
+ if "path" in params and not isinstance(params["path"], str):
231
+ raise InvalidParameterError("Bad parameter: path must be an str")
232
+ if "action" in params and not isinstance(params["action"], str):
233
+ raise InvalidParameterError("Bad parameter: action must be an str")
234
+ if "preview_size" in params and not isinstance(
235
+ params["preview_size"], str
236
+ ):
237
+ raise InvalidParameterError(
238
+ "Bad parameter: preview_size must be an str"
239
+ )
240
+ response, _options = Api.send_request(
241
+ "GET",
242
+ "/files/{path}".format(path=params["path"]),
243
+ params,
244
+ self.options,
245
+ )
246
+ return response.data
247
+
248
+ # Parameters:
249
+ # custom_metadata - object - Custom metadata map of keys and values. Limited to 32 keys, 256 characters per key and 1024 characters per value.
250
+ # provided_mtime - string - Modified time of file.
251
+ # priority_color - string - Priority/Bookmark color of file.
252
+ def update(self, params=None):
253
+ if not isinstance(params, dict):
254
+ params = {}
255
+
256
+ if hasattr(self, "path") and self.path:
257
+ params["path"] = self.path
258
+ else:
259
+ raise MissingParameterError("Current object doesn't have a path")
260
+ if "path" not in params:
261
+ raise MissingParameterError("Parameter missing: path")
262
+ if "path" in params and not isinstance(params["path"], str):
263
+ raise InvalidParameterError("Bad parameter: path must be an str")
264
+ if "provided_mtime" in params and not isinstance(
265
+ params["provided_mtime"], str
266
+ ):
267
+ raise InvalidParameterError(
268
+ "Bad parameter: provided_mtime must be an str"
269
+ )
270
+ if "priority_color" in params and not isinstance(
271
+ params["priority_color"], str
272
+ ):
273
+ raise InvalidParameterError(
274
+ "Bad parameter: priority_color must be an str"
275
+ )
276
+ response, _options = Api.send_request(
277
+ "PATCH",
278
+ "/files/{path}".format(path=params["path"]),
279
+ params,
280
+ self.options,
281
+ )
282
+ return response.data
283
+
284
+ # Parameters:
285
+ # recursive - boolean - If true, will recursively delete folders. Otherwise, will error on non-empty folders.
286
+ def delete(self, params=None):
287
+ if not isinstance(params, dict):
288
+ params = {}
289
+
290
+ if hasattr(self, "path") and self.path:
291
+ params["path"] = self.path
292
+ else:
293
+ raise MissingParameterError("Current object doesn't have a path")
294
+ if "path" not in params:
295
+ raise MissingParameterError("Parameter missing: path")
296
+ if "path" in params and not isinstance(params["path"], str):
297
+ raise InvalidParameterError("Bad parameter: path must be an str")
298
+ Api.send_request(
299
+ "DELETE",
300
+ "/files/{path}".format(path=params["path"]),
301
+ params,
302
+ self.options,
303
+ )
304
+
305
+ def destroy(self, params=None):
306
+ self.delete(params)
307
+
308
+ # Copy File/Folder
309
+ #
310
+ # Parameters:
311
+ # destination (required) - string - Copy destination path.
312
+ # structure - boolean - Copy structure only?
313
+ # overwrite - boolean - Overwrite existing file(s) in the destination?
314
+ def copy(self, params=None):
315
+ if not isinstance(params, dict):
316
+ params = {}
317
+
318
+ if hasattr(self, "path") and self.path:
319
+ params["path"] = self.path
320
+ else:
321
+ raise MissingParameterError("Current object doesn't have a path")
322
+ if "path" not in params:
323
+ raise MissingParameterError("Parameter missing: path")
324
+ if "destination" not in params:
325
+ raise MissingParameterError("Parameter missing: destination")
326
+ if "path" in params and not isinstance(params["path"], str):
327
+ raise InvalidParameterError("Bad parameter: path must be an str")
328
+ if "destination" in params and not isinstance(
329
+ params["destination"], str
330
+ ):
331
+ raise InvalidParameterError(
332
+ "Bad parameter: destination must be an str"
333
+ )
334
+ response, _options = Api.send_request(
335
+ "POST",
336
+ "/file_actions/copy/{path}".format(path=params["path"]),
337
+ params,
338
+ self.options,
339
+ )
340
+ return response.data
341
+
342
+ # Move File/Folder
343
+ #
344
+ # Parameters:
345
+ # destination (required) - string - Move destination path.
346
+ # overwrite - boolean - Overwrite existing file(s) in the destination?
347
+ def move(self, params=None):
348
+ if not isinstance(params, dict):
349
+ params = {}
350
+
351
+ if hasattr(self, "path") and self.path:
352
+ params["path"] = self.path
353
+ else:
354
+ raise MissingParameterError("Current object doesn't have a path")
355
+ if "path" not in params:
356
+ raise MissingParameterError("Parameter missing: path")
357
+ if "destination" not in params:
358
+ raise MissingParameterError("Parameter missing: destination")
359
+ if "path" in params and not isinstance(params["path"], str):
360
+ raise InvalidParameterError("Bad parameter: path must be an str")
361
+ if "destination" in params and not isinstance(
362
+ params["destination"], str
363
+ ):
364
+ raise InvalidParameterError(
365
+ "Bad parameter: destination must be an str"
366
+ )
367
+ response, _options = Api.send_request(
368
+ "POST",
369
+ "/file_actions/move/{path}".format(path=params["path"]),
370
+ params,
371
+ self.options,
372
+ )
373
+ return response.data
374
+
375
+ # Begin File Upload
376
+ #
377
+ # Parameters:
378
+ # mkdir_parents - boolean - Create parent directories if they do not exist?
379
+ # part - int64 - Part if uploading a part.
380
+ # parts - int64 - How many parts to fetch?
381
+ # ref - string -
382
+ # restart - int64 - File byte offset to restart from.
383
+ # size - int64 - Total bytes of file being uploaded (include bytes being retained if appending/restarting).
384
+ # with_rename - boolean - Allow file rename instead of overwrite?
385
+ def begin_upload(self, params=None):
386
+ if not isinstance(params, dict):
387
+ params = {}
388
+
389
+ if hasattr(self, "path") and self.path:
390
+ params["path"] = self.path
391
+ else:
392
+ raise MissingParameterError("Current object doesn't have a path")
393
+ if "path" not in params:
394
+ raise MissingParameterError("Parameter missing: path")
395
+ if "path" in params and not isinstance(params["path"], str):
396
+ raise InvalidParameterError("Bad parameter: path must be an str")
397
+ if "part" in params and not isinstance(params["part"], int):
398
+ raise InvalidParameterError("Bad parameter: part must be an int")
399
+ if "parts" in params and not isinstance(params["parts"], int):
400
+ raise InvalidParameterError("Bad parameter: parts must be an int")
401
+ if "ref" in params and not isinstance(params["ref"], str):
402
+ raise InvalidParameterError("Bad parameter: ref must be an str")
403
+ if "restart" in params and not isinstance(params["restart"], int):
404
+ raise InvalidParameterError(
405
+ "Bad parameter: restart must be an int"
406
+ )
407
+ if "size" in params and not isinstance(params["size"], int):
408
+ raise InvalidParameterError("Bad parameter: size must be an int")
409
+ response, _options = Api.send_request(
410
+ "POST",
411
+ "/file_actions/begin_upload/{path}".format(path=params["path"]),
412
+ params,
413
+ self.options,
414
+ )
415
+ return response.data
416
+
417
+ def save(self):
418
+ new_obj = create(self.path, self.get_attributes(), self.options)
419
+ self.set_attributes(new_obj.get_attributes())
420
+ return True
421
+
422
+
423
+ # Download File
424
+ #
425
+ # Parameters:
426
+ # action - string - Can be blank, `redirect` or `stat`. If set to `stat`, we will return file information but without a download URL, and without logging a download. If set to `redirect` we will serve a 302 redirect directly to the file. This is used for integrations with Zapier, and is not recommended for most integrations.
427
+ # preview_size - string - Request a preview size. Can be `small` (default), `large`, `xlarge`, or `pdf`.
428
+ # with_previews - boolean - Include file preview information?
429
+ # with_priority_color - boolean - Include file priority color information?
430
+ def download(path, params=None, options=None):
431
+ if not isinstance(params, dict):
432
+ params = {}
433
+ if not isinstance(options, dict):
434
+ options = {}
435
+ params["path"] = path
436
+ if "path" in params and not isinstance(params["path"], str):
437
+ raise InvalidParameterError("Bad parameter: path must be an str")
438
+ if "action" in params and not isinstance(params["action"], str):
439
+ raise InvalidParameterError("Bad parameter: action must be an str")
440
+ if "preview_size" in params and not isinstance(
441
+ params["preview_size"], str
442
+ ):
443
+ raise InvalidParameterError(
444
+ "Bad parameter: preview_size must be an str"
445
+ )
446
+ if "with_previews" in params and not isinstance(
447
+ params["with_previews"], bool
448
+ ):
449
+ raise InvalidParameterError(
450
+ "Bad parameter: with_previews must be an bool"
451
+ )
452
+ if "with_priority_color" in params and not isinstance(
453
+ params["with_priority_color"], bool
454
+ ):
455
+ raise InvalidParameterError(
456
+ "Bad parameter: with_priority_color must be an bool"
457
+ )
458
+ if "path" not in params:
459
+ raise MissingParameterError("Parameter missing: path")
460
+ response, options = Api.send_request(
461
+ "GET", "/files/{path}".format(path=params["path"]), params, options
462
+ )
463
+ return File(response.data, options)
464
+
465
+
466
+ # Parameters:
467
+ # path (required) - string - Path to operate on.
468
+ # action - string - The action to perform. Can be `append`, `attachment`, `end`, `upload`, `put`, or may not exist
469
+ # etags[etag] (required) - array(string) - etag identifier.
470
+ # etags[part] (required) - array(int64) - Part number.
471
+ # length - int64 - Length of file.
472
+ # mkdir_parents - boolean - Create parent directories if they do not exist?
473
+ # part - int64 - Part if uploading a part.
474
+ # parts - int64 - How many parts to fetch?
475
+ # provided_mtime - string - User provided modification time.
476
+ # ref - string -
477
+ # restart - int64 - File byte offset to restart from.
478
+ # size - int64 - Size of file.
479
+ # structure - string - If copying folder, copy just the structure?
480
+ # with_rename - boolean - Allow file rename instead of overwrite?
481
+ # buffered_upload - boolean - If true, and the path refers to a destination not stored on Files.com (such as a remote server mount), the upload will be uploaded first to Files.com before being sent to the remote server mount. This can allow clients to upload using parallel parts to a remote server destination that does not offer parallel parts support natively.
482
+ def create(path, params=None, options=None):
483
+ if not isinstance(params, dict):
484
+ params = {}
485
+ if not isinstance(options, dict):
486
+ options = {}
487
+ params["path"] = path
488
+ if "path" in params and not isinstance(params["path"], str):
489
+ raise InvalidParameterError("Bad parameter: path must be an str")
490
+ if "action" in params and not isinstance(params["action"], str):
491
+ raise InvalidParameterError("Bad parameter: action must be an str")
492
+ if "length" in params and not isinstance(params["length"], int):
493
+ raise InvalidParameterError("Bad parameter: length must be an int")
494
+ if "mkdir_parents" in params and not isinstance(
495
+ params["mkdir_parents"], bool
496
+ ):
497
+ raise InvalidParameterError(
498
+ "Bad parameter: mkdir_parents must be an bool"
499
+ )
500
+ if "part" in params and not isinstance(params["part"], int):
501
+ raise InvalidParameterError("Bad parameter: part must be an int")
502
+ if "parts" in params and not isinstance(params["parts"], int):
503
+ raise InvalidParameterError("Bad parameter: parts must be an int")
504
+ if "provided_mtime" in params and not isinstance(
505
+ params["provided_mtime"], str
506
+ ):
507
+ raise InvalidParameterError(
508
+ "Bad parameter: provided_mtime must be an str"
509
+ )
510
+ if "ref" in params and not isinstance(params["ref"], str):
511
+ raise InvalidParameterError("Bad parameter: ref must be an str")
512
+ if "restart" in params and not isinstance(params["restart"], int):
513
+ raise InvalidParameterError("Bad parameter: restart must be an int")
514
+ if "size" in params and not isinstance(params["size"], int):
515
+ raise InvalidParameterError("Bad parameter: size must be an int")
516
+ if "structure" in params and not isinstance(params["structure"], str):
517
+ raise InvalidParameterError("Bad parameter: structure must be an str")
518
+ if "with_rename" in params and not isinstance(params["with_rename"], bool):
519
+ raise InvalidParameterError(
520
+ "Bad parameter: with_rename must be an bool"
521
+ )
522
+ if "buffered_upload" in params and not isinstance(
523
+ params["buffered_upload"], bool
524
+ ):
525
+ raise InvalidParameterError(
526
+ "Bad parameter: buffered_upload must be an bool"
527
+ )
528
+ if "path" not in params:
529
+ raise MissingParameterError("Parameter missing: path")
530
+ response, options = Api.send_request(
531
+ "POST", "/files/{path}".format(path=params["path"]), params, options
532
+ )
533
+ return File(response.data, options)
534
+
535
+
536
+ # Parameters:
537
+ # custom_metadata - object - Custom metadata map of keys and values. Limited to 32 keys, 256 characters per key and 1024 characters per value.
538
+ # provided_mtime - string - Modified time of file.
539
+ # priority_color - string - Priority/Bookmark color of file.
540
+ def update(path, params=None, options=None):
541
+ if not isinstance(params, dict):
542
+ params = {}
543
+ if not isinstance(options, dict):
544
+ options = {}
545
+ params["path"] = path
546
+ if "path" in params and not isinstance(params["path"], str):
547
+ raise InvalidParameterError("Bad parameter: path must be an str")
548
+ if "custom_metadata" in params and not isinstance(
549
+ params["custom_metadata"], dict
550
+ ):
551
+ raise InvalidParameterError(
552
+ "Bad parameter: custom_metadata must be an dict"
553
+ )
554
+ if "provided_mtime" in params and not isinstance(
555
+ params["provided_mtime"], str
556
+ ):
557
+ raise InvalidParameterError(
558
+ "Bad parameter: provided_mtime must be an str"
559
+ )
560
+ if "priority_color" in params and not isinstance(
561
+ params["priority_color"], str
562
+ ):
563
+ raise InvalidParameterError(
564
+ "Bad parameter: priority_color must be an str"
565
+ )
566
+ if "path" not in params:
567
+ raise MissingParameterError("Parameter missing: path")
568
+ response, options = Api.send_request(
569
+ "PATCH", "/files/{path}".format(path=params["path"]), params, options
570
+ )
571
+ return File(response.data, options)
572
+
573
+
574
+ # Parameters:
575
+ # recursive - boolean - If true, will recursively delete folders. Otherwise, will error on non-empty folders.
576
+ def delete(path, params=None, options=None):
577
+ if not isinstance(params, dict):
578
+ params = {}
579
+ if not isinstance(options, dict):
580
+ options = {}
581
+ params["path"] = path
582
+ if "path" in params and not isinstance(params["path"], str):
583
+ raise InvalidParameterError("Bad parameter: path must be an str")
584
+ if "recursive" in params and not isinstance(params["recursive"], bool):
585
+ raise InvalidParameterError("Bad parameter: recursive must be an bool")
586
+ if "path" not in params:
587
+ raise MissingParameterError("Parameter missing: path")
588
+ Api.send_request(
589
+ "DELETE", "/files/{path}".format(path=params["path"]), params, options
590
+ )
591
+
592
+
593
+ def destroy(path, params=None, options=None):
594
+ delete(path, params, options)
595
+
596
+
597
+ # Parameters:
598
+ # path (required) - string - Path to operate on.
599
+ # preview_size - string - Request a preview size. Can be `small` (default), `large`, `xlarge`, or `pdf`.
600
+ # with_previews - boolean - Include file preview information?
601
+ # with_priority_color - boolean - Include file priority color information?
602
+ def find(path, params=None, options=None):
603
+ if not isinstance(params, dict):
604
+ params = {}
605
+ if not isinstance(options, dict):
606
+ options = {}
607
+ params["path"] = path
608
+ if "path" in params and not isinstance(params["path"], str):
609
+ raise InvalidParameterError("Bad parameter: path must be an str")
610
+ if "preview_size" in params and not isinstance(
611
+ params["preview_size"], str
612
+ ):
613
+ raise InvalidParameterError(
614
+ "Bad parameter: preview_size must be an str"
615
+ )
616
+ if "with_previews" in params and not isinstance(
617
+ params["with_previews"], bool
618
+ ):
619
+ raise InvalidParameterError(
620
+ "Bad parameter: with_previews must be an bool"
621
+ )
622
+ if "with_priority_color" in params and not isinstance(
623
+ params["with_priority_color"], bool
624
+ ):
625
+ raise InvalidParameterError(
626
+ "Bad parameter: with_priority_color must be an bool"
627
+ )
628
+ if "path" not in params:
629
+ raise MissingParameterError("Parameter missing: path")
630
+ response, options = Api.send_request(
631
+ "GET",
632
+ "/file_actions/metadata/{path}".format(path=params["path"]),
633
+ params,
634
+ options,
635
+ )
636
+ return File(response.data, options)
637
+
638
+
639
+ def get(path, params=None, options=None):
640
+ find(path, params, options)
641
+
642
+
643
+ # Copy File/Folder
644
+ #
645
+ # Parameters:
646
+ # destination (required) - string - Copy destination path.
647
+ # structure - boolean - Copy structure only?
648
+ # overwrite - boolean - Overwrite existing file(s) in the destination?
649
+ def copy(path, params=None, options=None):
650
+ if not isinstance(params, dict):
651
+ params = {}
652
+ if not isinstance(options, dict):
653
+ options = {}
654
+ params["path"] = path
655
+ if "path" in params and not isinstance(params["path"], str):
656
+ raise InvalidParameterError("Bad parameter: path must be an str")
657
+ if "destination" in params and not isinstance(params["destination"], str):
658
+ raise InvalidParameterError(
659
+ "Bad parameter: destination must be an str"
660
+ )
661
+ if "structure" in params and not isinstance(params["structure"], bool):
662
+ raise InvalidParameterError("Bad parameter: structure must be an bool")
663
+ if "overwrite" in params and not isinstance(params["overwrite"], bool):
664
+ raise InvalidParameterError("Bad parameter: overwrite must be an bool")
665
+ if "path" not in params:
666
+ raise MissingParameterError("Parameter missing: path")
667
+ if "destination" not in params:
668
+ raise MissingParameterError("Parameter missing: destination")
669
+ response, options = Api.send_request(
670
+ "POST",
671
+ "/file_actions/copy/{path}".format(path=params["path"]),
672
+ params,
673
+ options,
674
+ )
675
+ return FileAction(response.data, options)
676
+
677
+
678
+ # Move File/Folder
679
+ #
680
+ # Parameters:
681
+ # destination (required) - string - Move destination path.
682
+ # overwrite - boolean - Overwrite existing file(s) in the destination?
683
+ def move(path, params=None, options=None):
684
+ if not isinstance(params, dict):
685
+ params = {}
686
+ if not isinstance(options, dict):
687
+ options = {}
688
+ params["path"] = path
689
+ if "path" in params and not isinstance(params["path"], str):
690
+ raise InvalidParameterError("Bad parameter: path must be an str")
691
+ if "destination" in params and not isinstance(params["destination"], str):
692
+ raise InvalidParameterError(
693
+ "Bad parameter: destination must be an str"
694
+ )
695
+ if "overwrite" in params and not isinstance(params["overwrite"], bool):
696
+ raise InvalidParameterError("Bad parameter: overwrite must be an bool")
697
+ if "path" not in params:
698
+ raise MissingParameterError("Parameter missing: path")
699
+ if "destination" not in params:
700
+ raise MissingParameterError("Parameter missing: destination")
701
+ response, options = Api.send_request(
702
+ "POST",
703
+ "/file_actions/move/{path}".format(path=params["path"]),
704
+ params,
705
+ options,
706
+ )
707
+ return FileAction(response.data, options)
708
+
709
+
710
+ # Begin File Upload
711
+ #
712
+ # Parameters:
713
+ # mkdir_parents - boolean - Create parent directories if they do not exist?
714
+ # part - int64 - Part if uploading a part.
715
+ # parts - int64 - How many parts to fetch?
716
+ # ref - string -
717
+ # restart - int64 - File byte offset to restart from.
718
+ # size - int64 - Total bytes of file being uploaded (include bytes being retained if appending/restarting).
719
+ # with_rename - boolean - Allow file rename instead of overwrite?
720
+ def begin_upload(path, params=None, options=None):
721
+ if not isinstance(params, dict):
722
+ params = {}
723
+ if not isinstance(options, dict):
724
+ options = {}
725
+ params["path"] = path
726
+ if "path" in params and not isinstance(params["path"], str):
727
+ raise InvalidParameterError("Bad parameter: path must be an str")
728
+ if "mkdir_parents" in params and not isinstance(
729
+ params["mkdir_parents"], bool
730
+ ):
731
+ raise InvalidParameterError(
732
+ "Bad parameter: mkdir_parents must be an bool"
733
+ )
734
+ if "part" in params and not isinstance(params["part"], int):
735
+ raise InvalidParameterError("Bad parameter: part must be an int")
736
+ if "parts" in params and not isinstance(params["parts"], int):
737
+ raise InvalidParameterError("Bad parameter: parts must be an int")
738
+ if "ref" in params and not isinstance(params["ref"], str):
739
+ raise InvalidParameterError("Bad parameter: ref must be an str")
740
+ if "restart" in params and not isinstance(params["restart"], int):
741
+ raise InvalidParameterError("Bad parameter: restart must be an int")
742
+ if "size" in params and not isinstance(params["size"], int):
743
+ raise InvalidParameterError("Bad parameter: size must be an int")
744
+ if "with_rename" in params and not isinstance(params["with_rename"], bool):
745
+ raise InvalidParameterError(
746
+ "Bad parameter: with_rename must be an bool"
747
+ )
748
+ if "path" not in params:
749
+ raise MissingParameterError("Parameter missing: path")
750
+ response, options = Api.send_request(
751
+ "POST",
752
+ "/file_actions/begin_upload/{path}".format(path=params["path"]),
753
+ params,
754
+ options,
755
+ )
756
+ return [
757
+ FileUploadPart(entity_data, options) for entity_data in response.data
758
+ ]
759
+
760
+
761
+ def open(path, mode="r", options=None):
762
+ if not isinstance(options, dict):
763
+ options = {}
764
+ file = File(path, mode, options)
765
+
766
+ if "w" in mode:
767
+ if "b" in mode:
768
+ file.io_obj = io.BytesIO()
769
+ else:
770
+ file.io_obj = io.StringIO()
771
+
772
+ if "r" in mode:
773
+ if "b" in mode:
774
+ file.io_obj = io.BytesIO()
775
+ else:
776
+ file.io_obj = io.StringIO()
777
+ file.closed = False
778
+ return file
779
+
780
+
781
+ def upload_chunks(io, path, options, upload=None, etags=None, params=None):
782
+ if not etags:
783
+ etags = []
784
+ if not params:
785
+ params = {}
786
+ bytes_written = 0
787
+ while True:
788
+ chunk_params = (
789
+ {"part": 1}
790
+ if not upload
791
+ else {"ref": upload.ref, "part": upload.part_number + 1}
792
+ )
793
+ params.update(chunk_params)
794
+ upload = begin_upload(path, params, options)[0]
795
+ buf = io.read(upload.partsize)
796
+ if buf is not None: # None means no data but io still open
797
+ bytes_written += len(buf)
798
+ response = Api.client().send_remote_request(
799
+ upload.http_method,
800
+ upload.upload_uri,
801
+ {"Content-Length": str(len(buf))},
802
+ buf,
803
+ )
804
+ if "ETag" in response.headers:
805
+ etags.append(
806
+ {
807
+ "etag": response.headers["ETag"].strip('"'),
808
+ "part": upload.part_number,
809
+ }
810
+ )
811
+ if buf in [b"", ""] or (
812
+ len(buf) < upload.partsize
813
+ ): # Empty bytearray means EOF for BytesIO, Empty String means EOF for StringIO
814
+ return (upload, etags, bytes_written)
815
+
816
+
817
+ def upload_file(path, destination=None, options=None, params=None):
818
+ if not isinstance(options, dict):
819
+ options = {}
820
+ pth = Path(path)
821
+ stat = pth.stat()
822
+ with builtin_open(path, "rb") as local_file:
823
+ if destination is None:
824
+ destination = pth.name
825
+ upload, etags, _bytes_written = upload_chunks(
826
+ local_file, destination, options, params=params
827
+ )
828
+
829
+ final_params = {
830
+ "action": "end",
831
+ "etags": etags,
832
+ "provided_mtime": datetime.utcfromtimestamp(
833
+ stat.st_mtime
834
+ ).isoformat(),
835
+ "ref": upload.ref,
836
+ "size": stat.st_size,
837
+ }
838
+
839
+ create(destination, final_params, options)
840
+
841
+
842
+ def download_file(path, local_path=None, options=None):
843
+ if not isinstance(options, dict):
844
+ options = {}
845
+ if local_path is None:
846
+ local_path = Path(path).name
847
+ return File(path, {}, options).download_file(local_path)
848
+
849
+
850
+ def new(*args, **kwargs):
851
+ return File(*args, **kwargs)