pyaws-s3 1.0.24__py3-none-any.whl → 1.0.27__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.
pyaws_s3/s3.py CHANGED
@@ -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
- c.setFont("Helvetica-Bold", 11)
549
+ font_name, font_size = "Helvetica-Bold", 11
463
550
  line = line[4:]
464
551
  elif line.startswith("## "):
465
- c.setFont("Helvetica-Bold", 12)
552
+ font_name, font_size = "Helvetica-Bold", 12
466
553
  line = line[3:]
467
554
  elif line.startswith("# "):
468
- c.setFont("Helvetica-Bold", 14)
555
+ font_name, font_size = "Helvetica-Bold", 14
469
556
  line = line[2:]
470
557
  else:
471
- c.setFont("Helvetica", 10)
558
+ font_name, font_size = "Helvetica", 10
472
559
 
473
- c.drawString(x_margin, y, line)
474
- y -= 12
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)}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyaws-s3
3
- Version: 1.0.24
3
+ Version: 1.0.27
4
4
  Summary: A Python package for AWS S3 utilities
5
5
  Author-email: Giuseppe Zileni <giuseppe.zileni@gmail.com>
6
6
  Keywords: aws,s3,utilities
@@ -0,0 +1,7 @@
1
+ pyaws_s3/__init__.py,sha256=Tr7xJiCKOMWYydOJ4kxHlA7AR1X3pRsJ8MjxJev2wsw,24
2
+ pyaws_s3/s3.py,sha256=x_7M_3qTPyoExn6-Hw790YI4DQLFbIyBInXTYjDY3jQ,27780
3
+ pyaws_s3-1.0.27.dist-info/licenses/LICENSE.md,sha256=7WXohDebeZpcVn_nH2aIaLhFZRvZBdcPSqWsO12lhwM,1074
4
+ pyaws_s3-1.0.27.dist-info/METADATA,sha256=aHF-ijVr5cQGXQYOBIMeBT9MEjNmZx-pJ9zPIO_D5kc,5464
5
+ pyaws_s3-1.0.27.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
+ pyaws_s3-1.0.27.dist-info/top_level.txt,sha256=MxSSC4Q8Vr32wKgrUAlwT4BTXwqUaG_CAWoBuPeXYjQ,9
7
+ pyaws_s3-1.0.27.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- pyaws_s3/__init__.py,sha256=Tr7xJiCKOMWYydOJ4kxHlA7AR1X3pRsJ8MjxJev2wsw,24
2
- pyaws_s3/s3.py,sha256=OQ5z69f2n3JpayVhPg99J6weAaw0r0vI3gpqjZe3104,22707
3
- pyaws_s3-1.0.24.dist-info/licenses/LICENSE.md,sha256=7WXohDebeZpcVn_nH2aIaLhFZRvZBdcPSqWsO12lhwM,1074
4
- pyaws_s3-1.0.24.dist-info/METADATA,sha256=THZAeKqA7zEVk6cRZ5LQDV2tD22aHjQ2hHpACivKpys,5464
5
- pyaws_s3-1.0.24.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
6
- pyaws_s3-1.0.24.dist-info/top_level.txt,sha256=MxSSC4Q8Vr32wKgrUAlwT4BTXwqUaG_CAWoBuPeXYjQ,9
7
- pyaws_s3-1.0.24.dist-info/RECORD,,