reach_commons 0.17.1__py3-none-any.whl → 0.17.3__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.
@@ -46,7 +46,7 @@ def add_deprecation_headers(
46
46
  )
47
47
 
48
48
  elif current_date >= removal_date:
49
- logger.error(
49
+ logger.warning(
50
50
  f"Access to removed endpoint: {method} {path}. "
51
51
  f"Removal date was {removal_date_str}."
52
52
  + (f" Replacement endpoint: {replacement_url}" if replacement_url else "")
@@ -1,5 +1,6 @@
1
1
  from functools import cached_property
2
2
  from io import BytesIO
3
+ from urllib.parse import unquote, urlparse
3
4
 
4
5
  import boto3
5
6
 
@@ -25,13 +26,48 @@ class S3Client:
25
26
 
26
27
  return session.client("s3")
27
28
 
29
+ def _parse_s3_url(self, url: str) -> tuple[str, str]:
30
+ """
31
+ Support various S3 URL formats:
32
+ - s3://bucket/key
33
+ - https://bucket.s3.amazonaws.com/key
34
+ - https://bucket.s3.<region>.amazonaws.com/key
35
+ - https://s3.<region>.amazonaws.com/bucket/key (path-style)
36
+ - https://s3.amazonaws.com/bucket/key (path-style)
37
+ """
38
+ p = urlparse(url)
39
+
40
+ if p.scheme == "s3":
41
+ bucket = p.netloc
42
+ key = p.path.lstrip("/")
43
+ return bucket, unquote(key)
44
+
45
+ host = p.netloc
46
+ path = p.path.lstrip("/")
47
+
48
+ # Path-style: s3.<region>.amazonaws.com/bucket/key ou s3.amazonaws.com/bucket/key
49
+ if host.startswith("s3.") or host == "s3.amazonaws.com":
50
+ parts = path.split("/", 1)
51
+ if not parts or not parts[0]:
52
+ raise ValueError(f"Invalid S3 URL (missing bucket in path): {url}")
53
+ bucket = parts[0]
54
+ key = parts[1] if len(parts) > 1 else ""
55
+ return bucket, unquote(key)
56
+
57
+ # Virtual-hosted: bucket.s3[.<region>].amazonaws.com/key
58
+ bucket = host.split(".")[0]
59
+ key = path
60
+ if not bucket:
61
+ raise ValueError(f"Invalid S3 URL (missing bucket in host): {url}")
62
+ return bucket, unquote(key)
63
+
28
64
  def get_object(self, s3_bucket_name, s3_key):
29
65
  try:
30
66
  s3_object = self.client.get_object(Bucket=s3_bucket_name, Key=s3_key)
31
67
  actual_message_body = s3_object["Body"].read().decode("utf-8")
32
68
 
33
69
  self.logger.info(
34
- f"Retrieved object from S3: {s3_key} from bucket: {s3_bucket_name}"
70
+ f"Retrieved object from S3: {s3_key} in bucket: {s3_bucket_name}"
35
71
  )
36
72
  return actual_message_body
37
73
  except Exception as e:
@@ -61,3 +97,17 @@ class S3Client:
61
97
  f"Error uploading object {s3_key} to bucket: {s3_bucket_name}: {str(e)}"
62
98
  )
63
99
  return None
100
+
101
+ def delete_object_by_url(self, url: str) -> bool:
102
+ """
103
+ Deleta um objeto no S3 recebendo apenas a URL direta.
104
+ Retorna True se deletou (ou o objeto não existia) e False se falhou.
105
+ """
106
+ try:
107
+ bucket, key = self._parse_s3_url(url)
108
+ self.client.delete_object(Bucket=bucket, Key=key)
109
+ self.logger.info(f"Deleted object from S3: {key} in bucket: {bucket}")
110
+ return True
111
+ except Exception as e:
112
+ self.logger.error(f"Error deleting S3 object from url '{url}': {e}")
113
+ return False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: reach_commons
3
- Version: 0.17.1
3
+ Version: 0.17.3
4
4
  Summary: Reach Commons is a versatile utility library designed to streamline and enhance development workflows within the Reach ecosystem.
5
5
  License: MIT
6
6
  Author: Wilson Moraes
@@ -1,7 +1,7 @@
1
1
  reach_commons/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  reach_commons/app_logging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  reach_commons/app_logging/http_logger.py,sha256=mljQCdmsmtD2HsC_gsFwZAxPlAiLPYVirVrCjXFxitY,2541
4
- reach_commons/app_logging/log_deprecated_endpoints.py,sha256=MDGWr998TCWdGGf2L3r-NmnNhuKFDgKqRnkeAbgdkr4,2018
4
+ reach_commons/app_logging/log_deprecated_endpoints.py,sha256=yXs9Jh7V0_0cMnzwXV9WRgCdFXe_tybcFE1eQl2KNC4,2020
5
5
  reach_commons/app_logging/logger.py,sha256=Iq2XTl1zLgHDmVsTMdlFadcYJOqQNhBcFSscacKs_Xs,2295
6
6
  reach_commons/app_logging/logging_config.py,sha256=Y1JaZOoQBWgQjkOqYmeDRIm0p2eCOl3yTzgsgqyqm8I,1539
7
7
  reach_commons/clients/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -20,13 +20,13 @@ reach_commons/reach_aws/dynamo_db.py,sha256=ndwLlaDwb96IlsnpAeeKPg-2DOjxe0JSM0y-
20
20
  reach_commons/reach_aws/exceptions.py,sha256=x0RL5ktNtzxg0KykhEVWReBq_dEtciK6B2vMs_s4C9k,915
21
21
  reach_commons/reach_aws/firehose.py,sha256=1xFKLWMv3bNo3PPW5gtaL6NqzUDyVil6B768slj2wbY,5674
22
22
  reach_commons/reach_aws/kms.py,sha256=HDJ3lnKm6Jah2asizUDtQErlVSjrcV9lOfBPHzUVguY,4526
23
- reach_commons/reach_aws/s3.py,sha256=KLWvlQVakaaGfFg3110QHc1PlxCb1pUhmJQ-VggLEj4,1962
23
+ reach_commons/reach_aws/s3.py,sha256=2MLlDNFx0SROJBpE_KjJefyrB7lMqTlrYuRhSZx4iKs,3945
24
24
  reach_commons/reach_aws/sqs.py,sha256=LKQ42vRJko2HTE8gO_lRvftnstIMI3DeFZakvLUM0BQ,15864
25
25
  reach_commons/reach_base_model.py,sha256=uMmDGjwKTZ3h7f8Pfvc99FCsAt5eZNlUJnLLbB5EqGY,2907
26
26
  reach_commons/redis_manager.py,sha256=tK-kBw1fO1f-phsxGI-7W_MEtHQsRz7JY9LEN8OBcNY,2600
27
27
  reach_commons/sms_smart_encoding.py,sha256=92y0RmZ0l4ONHpC9qeO5KfViSNq64yE2rc7lhNDSZqE,1241
28
28
  reach_commons/utils.py,sha256=dMgKIGqTgoSItuBI8oz81gKtW3qi21Jkljv9leS_V88,8475
29
29
  reach_commons/validations.py,sha256=jc78boM62S9Z0Ip_nV1z7I983gGpW2Y7vOCQtmia8OU,964
30
- reach_commons-0.17.1.dist-info/METADATA,sha256=R71WCJeoNjTYXBd60arLnk2CbhRlqYVlGuVfBmMdOUY,1860
31
- reach_commons-0.17.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
32
- reach_commons-0.17.1.dist-info/RECORD,,
30
+ reach_commons-0.17.3.dist-info/METADATA,sha256=-YbAMsDaqbipOI9jxccdrqgNWoKRoeAE1A5nivPqWGQ,1860
31
+ reach_commons-0.17.3.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
32
+ reach_commons-0.17.3.dist-info/RECORD,,