from pathlib import PosixPath
from types import NotImplementedType
from typing import Any, Final, Literal, NoReturn, overload, TypeVar

__all__ = list[Literal['DAVOS_CONFIG_DIR', 'DAVOS_PROJECT_DIR', 'Project', 'get_notebook_path', 'get_project',
                       'prune_projects', 'use_default_project']]

DAVOS_CONFIG_DIR: Final[PosixPath]
DAVOS_PROJECT_DIR: Final[PosixPath]
PATHSEP: Final[Literal['/', '\\']]
PATHSEP_REPLACEMENT: Final[Literal['___']]
SITE_PACKAGES_SUFFIX: Final[str]

_P = TypeVar('_P', bound=Project)
_InstalledPkgs = list[tuple[str, str]]

class ProjectChecker(type):
    def __call__(cls, name: PosixPath | str) -> AbstractProject | ConcreteProject: ...

class Project(metaclass=ProjectChecker):
    _installed_packages: _InstalledPkgs
    _site_packages_mtime: float
    name: str
    safe_name: str
    project_dir: PosixPath
    site_packages_dir: PosixPath
    def __init__(self, name: str) -> None: ...
    def __del__(self) -> None: ...
    @overload
    def __eq__(self: _P, other: _P) -> bool: ...
    @overload
    def __eq__(self, other: object) -> bool | Literal[False]: ...
    @overload
    def __lt__(self, other: Project) -> bool: ...
    @overload
    def __lt__(self, other: Any) -> bool | NotImplementedType: ...
    def __repr__(self) -> str: ...
    @property
    def installed_packages(self) -> _InstalledPkgs: ...
    def _refresh_installed_pkgs(self) -> None: ...
    def freeze(self) -> str: ...
    def remove(self, yes: bool = ...) -> None: ...
    def rename(self, new_name: PosixPath | str) -> None: ...

class AbstractProject(Project):
    def __getattr__(self, item: str) -> NoReturn: ...
    def __repr__(self) -> str: ...

class ConcreteProject(Project): ...

def _dir_is_empty(path: PosixPath) -> bool: ...
def _filepath_to_safename(filepath: str) -> str: ...
def _get_project_name_type(project_name: PosixPath | str) -> tuple[str, AbstractProject | ConcreteProject]: ...
def _safename_to_filepath(safename: str) -> str: ...
def cleanup_project_dir_atexit(dirpath: PosixPath) -> None: ...
def get_notebook_path() ->  str: ...
@overload
def get_project(name: PosixPath | str, create: Literal[True] = ...) -> AbstractProject | ConcreteProject: ...
@overload
def get_project(name: PosixPath | str, create: Literal[False] = ...) -> AbstractProject | ConcreteProject | None: ...
def prune_projects(yes: bool = ...) -> None: ...
def use_default_project() -> None: ...
