| 506 | break |
| 507 | |
| 508 | def info(self, path: str, **kwargs) -> S3Object: |
| 509 | refresh = kwargs.pop("refresh", False) |
| 510 | path = self._strip_protocol(path) |
| 511 | bucket, key, path_version_id = self.parse_path(path) |
| 512 | version_id = path_version_id if path_version_id else kwargs.pop("version_id", None) |
| 513 | if path in ["/", ""]: |
| 514 | return S3Object( |
| 515 | init={ |
| 516 | "ContentLength": 0, |
| 517 | "ContentType": None, |
| 518 | "StorageClass": S3StorageClass.S3_STORAGE_CLASS_BUCKET, |
| 519 | "ETag": None, |
| 520 | "LastModified": None, |
| 521 | }, |
| 522 | type=S3ObjectType.S3_OBJECT_TYPE_DIRECTORY, |
| 523 | bucket=bucket, |
| 524 | key=None, |
| 525 | version_id=None, |
| 526 | ) |
| 527 | if not refresh: |
| 528 | caches: list[S3Object] | S3Object | None = self._ls_from_cache(path) |
| 529 | if caches is not None: |
| 530 | if isinstance(caches, list): |
| 531 | cache = next((c for c in caches if c.name == path), None) |
| 532 | elif caches.name == path: |
| 533 | cache = caches |
| 534 | else: |
| 535 | cache = None |
| 536 | |
| 537 | if cache: |
| 538 | if ( |
| 539 | self.version_aware |
| 540 | and not version_id |
| 541 | and cache.get("type") == S3ObjectType.S3_OBJECT_TYPE_FILE |
| 542 | and not cache.get("version_id") |
| 543 | ): |
| 544 | # A version-aware lookup needs the version to pin; |
| 545 | # treat a version-less cached entry (e.g., populated |
| 546 | # by a listing) as stale and head the object again. |
| 547 | refresh = True |
| 548 | else: |
| 549 | return cache |
| 550 | else: |
| 551 | return self._directory_object( |
| 552 | bucket, key.rstrip("/") if key else None, version_id |
| 553 | ) |
| 554 | if key: |
| 555 | object_info = self._head_object(path, refresh=refresh, version_id=version_id) |
| 556 | if object_info: |
| 557 | return object_info |
| 558 | else: |
| 559 | bucket_info = self._head_bucket(path, refresh=refresh) |
| 560 | if bucket_info: |
| 561 | return bucket_info |
| 562 | raise FileNotFoundError(path) |
| 563 | |
| 564 | response = self._call( |
| 565 | self._client.list_objects_v2, |