pos3 0.2.0__py3-none-any.whl → 0.2.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.
pos3/__init__.py CHANGED
@@ -709,26 +709,35 @@ class _Mirror:
709
709
  def _list_s3_objects(self, bucket: str, key: str, profile: Profile | None = None) -> Iterator[dict]:
710
710
  logger.debug("Listing S3 objects: bucket=%s, key=%s", bucket, key)
711
711
  client = self._get_client(profile)
712
- # Skip head_object for directory-like keys ending with '/'
713
- # as we want to list contents, not check if the directory marker exists
714
- if not key.endswith("/"):
712
+
713
+ # Determine the listing prefix - ensure it ends with "/" for directory-like operations
714
+ # This prevents "droid/recovery" from matching "droid/recovery_towels"
715
+ list_prefix = key
716
+
717
+ # If key doesn't end with "/", try to fetch it as a single object first
718
+ if key and not key.endswith("/"):
715
719
  try:
716
720
  obj = client.head_object(Bucket=bucket, Key=key)
717
721
  except ClientError as exc:
718
722
  error_code = exc.response["Error"]["Code"]
719
723
  if error_code != "404":
720
724
  raise
725
+ # Not a single file - treat as directory by adding "/"
726
+ list_prefix = key + "/"
721
727
  else:
728
+ # Found single object
722
729
  logger.debug("Found single object via head_object: %s", key)
723
730
  if "ContentLength" in obj and "Size" not in obj:
724
731
  obj["Size"] = obj["ContentLength"]
725
732
  yield {**obj, "Key": key}
726
733
  return
734
+ # If key already ends with "/", skip head_object - it's clearly a directory prefix
727
735
 
736
+ # List with the directory prefix (guaranteed to end with "/")
728
737
  paginator = client.get_paginator("list_objects_v2")
729
- for page in paginator.paginate(Bucket=bucket, Prefix=key):
738
+ for page in paginator.paginate(Bucket=bucket, Prefix=list_prefix):
730
739
  objects = page.get("Contents", [])
731
- logger.debug("Listed %d objects with prefix %s", len(objects), key)
740
+ logger.debug("Listed %d objects with prefix %s", len(objects), list_prefix)
732
741
  yield from objects
733
742
 
734
743
  def _scan_s3(self, bucket: str, prefix: str, profile: Profile | None = None) -> Iterator[FileInfo]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pos3
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: S3 Simple Sync - Make using S3 as simple as using local files
5
5
  Author-email: Positronic Robotics <hi@positronic.ro>
6
6
  License: Apache-2.0
@@ -0,0 +1,6 @@
1
+ pos3/__init__.py,sha256=PUaRocvB4EnSoX2boF5VcQ6OCREhySCr0DSIOsgo3l0,37730
2
+ pos3-0.2.1.dist-info/licenses/LICENSE,sha256=e815_YqPTxHS3WrNI7dotEuLkgHFAgsf9avLhDYBj9s,11354
3
+ pos3-0.2.1.dist-info/METADATA,sha256=Cmm9JAGaEZF5RkYJEnOR1LDQqWy26HevlD3IRYlVz_s,8637
4
+ pos3-0.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ pos3-0.2.1.dist-info/top_level.txt,sha256=JWOpXHz1F6cbH0nfanGWLaozt8RJFRmv5H3eKkxz7e8,5
6
+ pos3-0.2.1.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- pos3/__init__.py,sha256=ByRzIJ3ggRKFU6j8HtzDv7D3RW_6NZkbjp3etoMilys,37261
2
- pos3-0.2.0.dist-info/licenses/LICENSE,sha256=e815_YqPTxHS3WrNI7dotEuLkgHFAgsf9avLhDYBj9s,11354
3
- pos3-0.2.0.dist-info/METADATA,sha256=LF6o86VvogFSbkcsfy39yVmf-37IjbZdqJZ3guem4CA,8637
4
- pos3-0.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
- pos3-0.2.0.dist-info/top_level.txt,sha256=JWOpXHz1F6cbH0nfanGWLaozt8RJFRmv5H3eKkxz7e8,5
6
- pos3-0.2.0.dist-info/RECORD,,
File without changes