pyaws-s3 1.0.24__tar.gz → 1.0.27__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.
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/PKG-INFO +1 -1
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3/s3.py +117 -25
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3.egg-info/PKG-INFO +1 -1
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyproject.toml +1 -1
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/LICENSE.md +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/README.md +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3/__init__.py +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3.egg-info/SOURCES.txt +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3.egg-info/dependency_links.txt +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3.egg-info/requires.txt +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/pyaws_s3.egg-info/top_level.txt +0 -0
- {pyaws_s3-1.0.24 → pyaws_s3-1.0.27}/setup.cfg +0 -0
@@ -42,6 +42,25 @@ class S3Client:
|
|
42
42
|
self.region_name = kwargs.get("region_name", os.getenv("AWS_REGION"))
|
43
43
|
self.bucket_name = kwargs.get("bucket_name", os.getenv("AWS_BUCKET_NAME"))
|
44
44
|
|
45
|
+
# crea una funzione per verifica la presenza di un file nel bucket
|
46
|
+
def file_exists(self, object_name: str) -> bool:
|
47
|
+
"""
|
48
|
+
Check if a file exists in the S3 bucket.
|
49
|
+
|
50
|
+
Args:
|
51
|
+
object_name (str): The name of the S3 object to check.
|
52
|
+
|
53
|
+
Returns:
|
54
|
+
bool: True if the file exists, False otherwise.
|
55
|
+
"""
|
56
|
+
s3_client = self._get_s3_client()
|
57
|
+
try:
|
58
|
+
s3_client.head_object(Bucket=self.bucket_name, Key=object_name)
|
59
|
+
return True
|
60
|
+
except Exception as e:
|
61
|
+
logger.error(f"Error checking file existence: {str(e)}")
|
62
|
+
return False
|
63
|
+
|
45
64
|
def _bytes_from_figure(self, f: Figure, **kwargs) -> bytes:
|
46
65
|
"""
|
47
66
|
Convert a Plotly Figure to a PNG image as bytes.
|
@@ -173,7 +192,7 @@ class S3Client:
|
|
173
192
|
|
174
193
|
return temp_url
|
175
194
|
|
176
|
-
def upload_bytes(self, *args, **kwargs: Any):
|
195
|
+
def upload_bytes(self, *args, **kwargs: Any) -> tuple[str, bool]:
|
177
196
|
"""
|
178
197
|
Upload a Plotly Figure as a PNG image to an S3 bucket and generate a pre-signed URL.
|
179
198
|
|
@@ -181,6 +200,8 @@ class S3Client:
|
|
181
200
|
bytes_data (bytes): The bytes data of the image to upload.
|
182
201
|
object_name (str): The name of the S3 object.
|
183
202
|
format_file (str): Format of the image. Defaults to 'pdf' ["png", "jpeg", "svg", "html", "pdf"].
|
203
|
+
overwrite (bool): If True, overwrite the existing file in S3. Defaults to False.
|
204
|
+
presigned_url (bool): If True, generate a pre-signed URL for the uploaded image. Defaults to False.
|
184
205
|
Raises:
|
185
206
|
Exception: If there is an error uploading the image.
|
186
207
|
|
@@ -198,6 +219,9 @@ class S3Client:
|
|
198
219
|
else:
|
199
220
|
bytes_data = kwargs.get("bytes_data", None)
|
200
221
|
object_name = kwargs.get("object_name", None)
|
222
|
+
|
223
|
+
overwrite = kwargs.get("overwrite", False)
|
224
|
+
presigned_url = kwargs.get("presigned_url", False)
|
201
225
|
|
202
226
|
if bytes_data is None:
|
203
227
|
raise Exception("Figure is None")
|
@@ -208,6 +232,16 @@ class S3Client:
|
|
208
232
|
format_file : FormatFile = kwargs.get("format_file", "pdf")
|
209
233
|
mimetypes = "application/pdf"
|
210
234
|
|
235
|
+
# Get S3 client and resource
|
236
|
+
s3_client = self._get_s3_client()
|
237
|
+
s3_resource = self._get_s3_resource()
|
238
|
+
|
239
|
+
if not overwrite and self.file_exists(object_name):
|
240
|
+
print(f"File {object_name} already exists in the bucket {self.bucket_name}. Use overwrite=True to overwrite it.")
|
241
|
+
if presigned_url:
|
242
|
+
return self._create_url(s3_client, self.bucket_name, object_name), False
|
243
|
+
return object_name, False
|
244
|
+
|
211
245
|
if format_file not in ["png", "jpeg", "svg", "html", "pdf"]:
|
212
246
|
raise Exception("Invalid format_file provided. Supported formats are: png, jpeg, svg, html, pdf")
|
213
247
|
if format_file == "png":
|
@@ -223,15 +257,13 @@ class S3Client:
|
|
223
257
|
else:
|
224
258
|
raise Exception("Invalid MIME type provided")
|
225
259
|
|
226
|
-
s3_resource = self._get_s3_resource()
|
227
|
-
|
228
260
|
s3_resource.Bucket(self.bucket_name).Object(object_name).put(Body=bytes_data, ContentType=mimetypes)
|
229
|
-
|
261
|
+
return self._create_url(s3_client, self.bucket_name, object_name), True
|
230
262
|
except Exception as e:
|
231
263
|
logger.error(f"Error uploading image: {str(e)}")
|
232
264
|
raise Exception(f"Error uploading image: {str(e)}")
|
233
265
|
|
234
|
-
def upload_image(self, *args, **kwargs: Any) -> str:
|
266
|
+
def upload_image(self, *args, **kwargs: Any) -> tuple[str, bool]:
|
235
267
|
"""
|
236
268
|
Upload a Plotly Figure as a PNG image to an S3 bucket and generate a pre-signed URL.
|
237
269
|
|
@@ -239,6 +271,11 @@ class S3Client:
|
|
239
271
|
fig (Figure): The Plotly Figure object to upload.
|
240
272
|
bucket_name (str): The name of the S3 bucket.
|
241
273
|
object_name (str): The name of the S3 object.
|
274
|
+
format_file (str): Format of the image. Defaults to 'png' ["png", "jpeg", "svg", "html"].
|
275
|
+
overwrite (bool): If True, overwrite the existing file in S3. Defaults to False.
|
276
|
+
presigned_url (bool): If True, generate a pre-signed URL for the uploaded image. Defaults to False.
|
277
|
+
Raises:
|
278
|
+
Exception: If there is an error uploading the image.
|
242
279
|
|
243
280
|
Keyword Args:
|
244
281
|
format_file (str): Format of the image. Defaults to 'png'.
|
@@ -257,6 +294,13 @@ class S3Client:
|
|
257
294
|
else:
|
258
295
|
fig = kwargs.get("fig", None)
|
259
296
|
object_name = kwargs.get("object_name", None)
|
297
|
+
|
298
|
+
overwrite = kwargs.get("overwrite", False)
|
299
|
+
presigned_url = kwargs.get("presigned_url", False)
|
300
|
+
|
301
|
+
# Get S3 client and resource
|
302
|
+
s3_client = self._get_s3_client()
|
303
|
+
s3_resource = self._get_s3_resource()
|
260
304
|
|
261
305
|
if fig is None:
|
262
306
|
raise Exception("Figure is None")
|
@@ -267,6 +311,12 @@ class S3Client:
|
|
267
311
|
format_file : FormatFile = kwargs.get("format_file", "svg")
|
268
312
|
mimetypes = "image/svg+xml"
|
269
313
|
|
314
|
+
if not overwrite and self.file_exists(object_name):
|
315
|
+
print(f"File {object_name} already exists in the bucket {self.bucket_name}. Use overwrite=True to overwrite it.")
|
316
|
+
if presigned_url:
|
317
|
+
return self._create_url(s3_client, self.bucket_name, object_name), False
|
318
|
+
return object_name, False
|
319
|
+
|
270
320
|
if format_file not in ["png", "jpeg", "svg", "html"]:
|
271
321
|
raise Exception("Invalid format_file provided. Supported formats are: png, jpeg, svg, html")
|
272
322
|
if format_file == "png":
|
@@ -280,10 +330,6 @@ class S3Client:
|
|
280
330
|
else:
|
281
331
|
raise Exception("Invalid MIME type provided")
|
282
332
|
|
283
|
-
# Get S3 client and resource
|
284
|
-
s3_client = self._get_s3_client()
|
285
|
-
s3_resource = self._get_s3_resource()
|
286
|
-
|
287
333
|
if format_file == "html":
|
288
334
|
# Convert the figure to SVG
|
289
335
|
file_text = self._html_from_figure(fig)
|
@@ -296,13 +342,13 @@ class S3Client:
|
|
296
342
|
s3_resource.Bucket(self.bucket_name).Object(object_name).put(Body=file_buffer, ContentType=mimetypes)
|
297
343
|
|
298
344
|
# Generate and return a pre-signed URL for the uploaded image
|
299
|
-
return self._create_url(s3_client, self.bucket_name, object_name)
|
345
|
+
return self._create_url(s3_client, self.bucket_name, object_name), True
|
300
346
|
|
301
347
|
except Exception as e:
|
302
348
|
logger.error(f"Error uploading image: {str(e)}")
|
303
349
|
raise Exception(f"Error uploading image: {str(e)}")
|
304
350
|
|
305
|
-
def upload_from_dataframe(self, *args : Any, **kwargs: Any) -> str:
|
351
|
+
def upload_from_dataframe(self, *args : Any, **kwargs: Any) -> tuple[str, bool]:
|
306
352
|
"""
|
307
353
|
Upload a DataFrame as an Excel file to an S3 bucket and generate a pre-signed URL.
|
308
354
|
|
@@ -311,6 +357,10 @@ class S3Client:
|
|
311
357
|
**kwargs (Any): Additional keyword arguments for AWS credentials, bucket name, and object name.
|
312
358
|
Keyword Args:
|
313
359
|
format_file (str): Format of the file. Defaults to 'xlsx'.
|
360
|
+
overwrite (bool): If True, overwrite the existing file in S3. Defaults to False.
|
361
|
+
presigned_url (bool): If True, generate a pre-signed URL for the uploaded file. Defaults to False.
|
362
|
+
Raises:
|
363
|
+
Exception: If there is an error uploading the file.
|
314
364
|
|
315
365
|
Returns:
|
316
366
|
str: Pre-signed URL for the uploaded file.
|
@@ -328,6 +378,9 @@ class S3Client:
|
|
328
378
|
# Get the DataFrame and object name from the keyword arguments
|
329
379
|
df = kwargs.get("df", None)
|
330
380
|
object_name = kwargs.get("object_name", None)
|
381
|
+
|
382
|
+
overwrite = kwargs.get("overwrite", False)
|
383
|
+
presigned_url = kwargs.get("presigned_url", False)
|
331
384
|
|
332
385
|
if df is None:
|
333
386
|
raise Exception("Figure is None")
|
@@ -349,8 +402,15 @@ class S3Client:
|
|
349
402
|
else:
|
350
403
|
raise Exception("Invalid MIME type provided")
|
351
404
|
|
405
|
+
# Get S3 client and resource
|
352
406
|
s3_client = self._get_s3_client()
|
353
407
|
s3_resource = self._get_s3_resource()
|
408
|
+
|
409
|
+
if not overwrite and self.file_exists(object_name):
|
410
|
+
print(f"File {object_name} already exists in the bucket {self.bucket_name}. Use overwrite=True to overwrite it.")
|
411
|
+
if presigned_url:
|
412
|
+
return self._create_url(s3_client, self.bucket_name, object_name), False
|
413
|
+
return object_name, False
|
354
414
|
|
355
415
|
# Create a file buffer
|
356
416
|
ext: str = ""
|
@@ -381,7 +441,7 @@ class S3Client:
|
|
381
441
|
|
382
442
|
logger.info(f"Uploaded file to S3: {object_name}")
|
383
443
|
|
384
|
-
return self._create_url(s3_client, self.bucket_name, object_name)
|
444
|
+
return self._create_url(s3_client, self.bucket_name, object_name), True
|
385
445
|
except Exception as e:
|
386
446
|
logger.error(f"Error uploading file: {str(e)}")
|
387
447
|
raise Exception(f"Error uploading file: {str(e)}")
|
@@ -412,15 +472,19 @@ class S3Client:
|
|
412
472
|
logger.error(f"Error deleting files: {str(e)}")
|
413
473
|
raise Exception(f"Error deleting files: {str(e)}")
|
414
474
|
|
415
|
-
def upload_to_pdf(self, *args: Any, **kwargs: Any) -> str:
|
475
|
+
def upload_to_pdf(self, *args: Any, **kwargs: Any) -> tuple[str, bool]:
|
416
476
|
"""
|
417
477
|
Export the given text as a PDF and upload it to the S3 bucket.
|
418
478
|
|
419
479
|
Args:
|
420
480
|
text (str): The text to write in the PDF.
|
421
481
|
object_name (str): The name of the S3 object.
|
482
|
+
presigned_url (bool): If True, generate a pre-signed URL for the uploaded PDF. Defaults to False.
|
483
|
+
overwrite (bool): If True, overwrite the existing file in S3. Defaults to False
|
484
|
+
|
422
485
|
Raises:
|
423
486
|
Exception: If there is an error exporting the PDF.
|
487
|
+
|
424
488
|
Returns:
|
425
489
|
str: Pre-signed URL for the uploaded PDF.
|
426
490
|
"""
|
@@ -431,6 +495,9 @@ class S3Client:
|
|
431
495
|
else:
|
432
496
|
text = kwargs.get("text", None)
|
433
497
|
object_name = kwargs.get("object_name", None)
|
498
|
+
|
499
|
+
overwrite = kwargs.get("overwrite", False)
|
500
|
+
presigned_url = kwargs.get("presigned_url", False)
|
434
501
|
|
435
502
|
if text is None:
|
436
503
|
raise Exception("Text is None")
|
@@ -439,8 +506,15 @@ class S3Client:
|
|
439
506
|
raise Exception("Object name is None")
|
440
507
|
|
441
508
|
mimetypes = "application/pdf"
|
509
|
+
# Get S3 client and resource
|
442
510
|
s3_client = self._get_s3_client()
|
443
511
|
s3_resource = self._get_s3_resource()
|
512
|
+
|
513
|
+
if not overwrite and self.file_exists(object_name):
|
514
|
+
print(f"File {object_name} already exists in the bucket {self.bucket_name}. Use overwrite=True to overwrite it.")
|
515
|
+
if presigned_url:
|
516
|
+
return self._create_url(s3_client, self.bucket_name, object_name), False
|
517
|
+
return object_name, False
|
444
518
|
|
445
519
|
# Crea il PDF in memoria
|
446
520
|
pdf_buffer = BytesIO()
|
@@ -449,29 +523,47 @@ class S3Client:
|
|
449
523
|
c.setFont("Helvetica", 10)
|
450
524
|
x_margin = 20 * mm
|
451
525
|
y = height - 20 * mm
|
526
|
+
max_width = width - 2 * x_margin
|
527
|
+
|
528
|
+
def split_line(line, font_name, font_size):
|
529
|
+
# Divide la riga in più righe se supera la larghezza massima
|
530
|
+
words = line.split()
|
531
|
+
lines = []
|
532
|
+
current = ""
|
533
|
+
for word in words:
|
534
|
+
test = current + (" " if current else "") + word
|
535
|
+
if c.stringWidth(test, font_name, font_size) <= max_width:
|
536
|
+
current = test
|
537
|
+
else:
|
538
|
+
if current:
|
539
|
+
lines.append(current)
|
540
|
+
current = word
|
541
|
+
if current:
|
542
|
+
lines.append(current)
|
543
|
+
return lines
|
452
544
|
|
453
545
|
for line in text.strip().split('\n'):
|
454
546
|
line = line.strip()
|
455
|
-
if y < 20 * mm:
|
456
|
-
c.showPage()
|
457
|
-
c.setFont("Helvetica", 10)
|
458
|
-
y = height - 20 * mm
|
459
|
-
|
460
547
|
# Markdown-style header detection
|
461
548
|
if line.startswith("### "):
|
462
|
-
|
549
|
+
font_name, font_size = "Helvetica-Bold", 11
|
463
550
|
line = line[4:]
|
464
551
|
elif line.startswith("## "):
|
465
|
-
|
552
|
+
font_name, font_size = "Helvetica-Bold", 12
|
466
553
|
line = line[3:]
|
467
554
|
elif line.startswith("# "):
|
468
|
-
|
555
|
+
font_name, font_size = "Helvetica-Bold", 14
|
469
556
|
line = line[2:]
|
470
557
|
else:
|
471
|
-
|
558
|
+
font_name, font_size = "Helvetica", 10
|
472
559
|
|
473
|
-
|
474
|
-
|
560
|
+
for subline in split_line(line, font_name, font_size):
|
561
|
+
if y < 20 * mm + font_size:
|
562
|
+
c.showPage()
|
563
|
+
y = height - 20 * mm
|
564
|
+
c.setFont(font_name, font_size)
|
565
|
+
c.drawString(x_margin, y, subline)
|
566
|
+
y -= font_size + 2 # Spazio tra le righe
|
475
567
|
|
476
568
|
c.save()
|
477
569
|
pdf_buffer.seek(0)
|
@@ -481,7 +573,7 @@ class S3Client:
|
|
481
573
|
Body=pdf_buffer,
|
482
574
|
ContentType=mimetypes
|
483
575
|
)
|
484
|
-
return self._create_url(s3_client, self.bucket_name, object_name)
|
576
|
+
return self._create_url(s3_client, self.bucket_name, object_name), True
|
485
577
|
|
486
578
|
except Exception as e:
|
487
579
|
logger.error(f"Error exporting PDF: {str(e)}")
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|