# Path: etils/epath/abstract_path.py
# T = TypeVar('T')
# def abstractmethod(fn: T) -> T:
#   def __new__(cls: Type[T], *args: PathLike) -> T:
#   def is_relative_to(self, *other: PathLike) -> bool:
#   def format(self: T, *args: Any, **kwargs: Any) -> T:
#   def exists(self) -> bool:
#   def is_dir(self) -> bool:
#   def is_file(self) -> bool:
#   def iterdir(self: T) -> Iterator[T]:
#   def glob(self: T, pattern: str) -> Iterator[T]:
#   def rglob(self: T, pattern: str) -> Iterator[T]:
#   def expanduser(self: T) -> T:
#   def resolve(self: T, strict: bool = False) -> T:
#   def open(
#       self,
#       mode: str = 'r',
#       encoding: Optional[str] = None,
#       errors: Optional[str] = None,
#       **kwargs: Any,
#   ) -> typing.IO[AnyStr]:
#   def read_bytes(self) -> bytes:
#   def read_text(self, encoding: Optional[str] = None) -> str:
#   def mkdir(
#       self,
#       mode: int = 0o777,
#       parents: bool = False,
#       exist_ok: bool = False,
#   ) -> None:
#   def rmdir(self) -> None:
#   def rmtree(self) -> None:
#   def unlink(self, missing_ok: bool = False) -> None:
#   def write_bytes(self, data: bytes) -> int:
#   def write_text(
#       self,
#       data: str,
#       encoding: Optional[str] = None,
#       errors: Optional[str] = None,
#   ) -> int:
#   def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None:
#   def rename(self: T, target: PathLike) -> T:
#   def replace(self: T, target: PathLike) -> T:
#   def copy(self: T, dst: PathLike, overwrite: bool = False) -> T:
# class Path(pathlib.PurePosixPath):
# 
# Path: etils/epath/register.py
# _T = TypeVar('_T')
# _PATHLIKE_CLS: Tuple[Type[abstract_path.Path], ...] = (
#     gpath.PosixGPath,
#     gpath.WindowsGPath,
# )
# _URI_PREFIXES_TO_CLS: Dict[str, Type[abstract_path.Path]] = {
#     # Even on Windows, `gs://`,... are PosixPath
#     uri_prefix: gpath.PosixGPath for uri_prefix in gpath.URI_PREFIXES
# }
#     _PATHLIKE_CLS = _PATHLIKE_CLS + (path_cls_or_uri_prefix,)
# def register_path_cls(path_cls_or_uri_prefix: str) -> Callable[[_T], _T]:
# def register_path_cls(path_cls_or_uri_prefix: _T) -> _T:
# def register_path_cls(path_cls_or_uri_prefix):
#     def register_path_cls_decorator(cls: _T) -> _T:
# def make_path(path: PathLike) -> abstract_path.Path:
# 
# Path: etils/epath/typing.py



import itertools
import os
import pathlib
import sys
import types
import typing
  import importlib.resources as importlib_resources
  import importlib_resources
  import zipfile
  import zipp as zipfile  # Before 3.8, importlib_resources uses backport
from typing import Union
from etils.epath import abstract_path
from etils.epath import register
from etils.epath.typing import PathLike
      return type(self)(self.root, at)  # pytype: disable=attribute-error  # py39-upgrade

    # Before 3.10, joinpath only accept a single arg
    def joinpath(self, *parts: PathLike) -> 'ResourcePath':
      """Overwrite `joinpath` to be consistent with `pathlib.Path`."""
      if not parts:
        return self
      else:
        return super().joinpath(os.path.join(*parts))  # pylint: disable=no-value-for-parameter  # pytype: disable=bad-return-type  # py39-upgrade


def resource_path(package: Union[str, types.ModuleType]) -> abstract_path.Path:
  """Returns `importlib.resources.files`."""
  path = importlib_resources.files(package)  # pytype: disable=module-attr
  if isinstance(path, pathlib.Path):
    # TODO(etils): To ensure compatibility with zipfile.Path, we should ensure
    # that the returned `pathlib.Path` isn't missused. More specifically:
    # * `os.fspath` should only be called on files (not directories)
    # * `str(path)` should be forbidden (only `__format__` allowed).
    # In practice, it is trickier to do as `__fspath__` and `__str__` are
    # called internally.
    # Convert to `GPath` for consistency and compatibility with `MockFs`.
    return abstract_path.Path(path)
  elif isinstance(path, zipfile.Path):
    path = ResourcePath(path.root, path.at)
    return typing.cast(abstract_path.Path, path)
  else:
    raise TypeError(f'Unknown resource path: {type(path)}: {path}')



# Path: etils/epath/abstract_path.py
# T = TypeVar('T')
# def abstractmethod(fn: T) -> T:
#   def __new__(cls: Type[T], *args: PathLike) -> T:
#   def is_relative_to(self, *other: PathLike) -> bool:
#   def format(self: T, *args: Any, **kwargs: Any) -> T:
#   def exists(self) -> bool:
#   def is_dir(self) -> bool:
#   def is_file(self) -> bool:
#   def iterdir(self: T) -> Iterator[T]:
#   def glob(self: T, pattern: str) -> Iterator[T]:
#   def rglob(self: T, pattern: str) -> Iterator[T]:
#   def expanduser(self: T) -> T:
#   def resolve(self: T, strict: bool = False) -> T:
#   def open(
#       self,
#       mode: str = 'r',
#       encoding: Optional[str] = None,
#       errors: Optional[str] = None,
#       **kwargs: Any,
#   ) -> typing.IO[AnyStr]:
#   def read_bytes(self) -> bytes:
#   def read_text(self, encoding: Optional[str] = None) -> str:
#   def mkdir(
#       self,
#       mode: int = 0o777,
#       parents: bool = False,
#       exist_ok: bool = False,
#   ) -> None:
#   def rmdir(self) -> None:
#   def rmtree(self) -> None:
#   def unlink(self, missing_ok: bool = False) -> None:
#   def write_bytes(self, data: bytes) -> int:
#   def write_text(
#       self,
#       data: str,
#       encoding: Optional[str] = None,
#       errors: Optional[str] = None,
#   ) -> int:
#   def touch(self, mode: int = 0o666, exist_ok: bool = True) -> None:
#   def rename(self: T, target: PathLike) -> T:
#   def replace(self: T, target: PathLike) -> T:
#   def copy(self: T, dst: PathLike, overwrite: bool = False) -> T:
# class Path(pathlib.PurePosixPath):
# 
# Path: etils/epath/register.py
# _T = TypeVar('_T')
# _PATHLIKE_CLS: Tuple[Type[abstract_path.Path], ...] = (
#     gpath.PosixGPath,
#     gpath.WindowsGPath,
# )
# _URI_PREFIXES_TO_CLS: Dict[str, Type[abstract_path.Path]] = {
#     # Even on Windows, `gs://`,... are PosixPath
#     uri_prefix: gpath.PosixGPath for uri_prefix in gpath.URI_PREFIXES
# }
#     _PATHLIKE_CLS = _PATHLIKE_CLS + (path_cls_or_uri_prefix,)
# def register_path_cls(path_cls_or_uri_prefix: str) -> Callable[[_T], _T]:
# def register_path_cls(path_cls_or_uri_prefix: _T) -> _T:
# def register_path_cls(path_cls_or_uri_prefix):
#     def register_path_cls_decorator(cls: _T) -> _T:
# def make_path(path: PathLike) -> abstract_path.Path:
# 
# Path: etils/epath/typing.py



# Path: etils/epath/resource_utils.py
import itertools
import os
import pathlib
import sys
import types
import typing
  import importlib.resources as importlib_resources
  import importlib_resources
  import zipfile
  import zipp as zipfile  # Before 3.8, importlib_resources uses backport
from typing import Union
from etils.epath import abstract_path
from etils.epath import register
from etils.epath.typing import PathLike

      return type(self)(self.root, at)  # pytype: disable=attribute-error  # py39-upgrade

    # Before 3.10, joinpath only accept a single arg
    def joinpath(self, *parts: PathLike) -> 'ResourcePath':
      """Overwrite `joinpath` to be consistent with `pathlib.Path`."""
      if not parts:
        return self
      else:
        return super().joinpath(os.path.join(*parts))  # pylint: disable=no-value-for-parameter  # pytype: disable=bad-return-type  # py39-upgrade


def resource_path(package: Union[str, types.ModuleType]) -> abstract_path.Path:
  """Returns `importlib.resources.files`."""
  path = importlib_resources.files(package)  # pytype: disable=module-attr
  if isinstance(path, pathlib.Path):
    # TODO(etils): To ensure compatibility with zipfile.Path, we should ensure
    # that the returned `pathlib.Path` isn't missused. More specifically:
    # * `os.fspath` should only be called on files (not directories)
    # * `str(path)` should be forbidden (only `__format__` allowed).
    # In practice, it is trickier to do as `__fspath__` and `__str__` are
    # called internally.
    # Convert to `GPath` for consistency and compatibility with `MockFs`.
    return abstract_path.Path(path)
  elif isinstance(path, zipfile.Path):
    path = ResourcePath(path.root, path.at)
    return typing.cast(abstract_path.Path, path)
  else:
    raise TypeError(f'Unknown resource path: {type(path)}: {path}')



def to_write_path(path: abstract_path.Path) -> abstract_path.Path: