Skip to content

Project

sereto.models.project

Project

Bases: SeretoBaseModel

Source code in sereto/models/project.py
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
class Project(SeretoBaseModel):
    config: Config
    settings: Settings
    path: DirectoryPath

    @staticmethod
    def load_from(path: DirectoryPath | None = None) -> "Project":
        """Load the project from the provided path.

        Args:
            path: The path to the project (sub)directory. Defaults to the current working directory.

        Returns:
            The project object.
        """
        settings = load_settings_function()
        project_path = get_project_path_from_dir(
            dir=path if path is not None else Path.cwd(), dir_subtree=settings.projects_path
        )
        config = Config.load_from(file=project_path / "config.json").update_paths(project_path=project_path)
        return Project(config=config, settings=load_settings_function(), path=project_path)

    @validate_call
    def get_config_path(self) -> Path:
        """Get the path to the project configuration file.

        Returns:
            The path to the project configuration file.
        """
        return self.path / "config.json"

    @staticmethod
    @validate_call
    def is_project_dir(path: Path) -> bool:
        """Check if the provided path is a root directory of a project.

        A project directory contains at least `.sereto` and `config.json` files.

        Args:
            path: The path to examine.

        Returns:
            True if the path is a project directory, False otherwise.
        """
        return path.is_dir() and path.exists() and (path / ".sereto").is_file() and (path / "config.json").is_file()

    @validate_call
    def select_target(
        self,
        version: ProjectVersion | None = None,
        selector: int | str | None = None,
    ) -> Target:
        if version is None:
            version = self.config.last_version()

        cfg = self.config.at_version(version)

        # only single target present
        if selector is None:
            if len(cfg.targets) != 1:
                raise SeretoValueError(
                    f"cannot select target; no selector provided and there are {len(cfg.targets)} targets present"
                )
            return cfg.targets[0]

        # by index
        if isinstance(selector, int) or selector.isnumeric():
            ix = selector - 1 if isinstance(selector, int) else int(selector) - 1
            if not (0 <= ix <= len(cfg.targets) - 1):
                raise SeretoValueError("target index out of range")
            return cfg.targets[ix]

        # by category
        if selector in self.settings.categories:
            targets = [t for t in cfg.targets if t.category == selector]
            match len(targets):
                case 0:
                    raise SeretoValueError(f"category {selector!r} does not contain any target")
                case 1:
                    return targets[0]
                case _:
                    raise SeretoValueError(f"category {selector!r} contains multiple targets, use uname when querying")

        # by uname
        targets = [t for t in cfg.targets if t.uname == selector]
        if len(targets) != 1:
            raise SeretoValueError(f"target with uname {selector!r} not found")
        return targets[0]

get_config_path()

Get the path to the project configuration file.

Returns:

Type Description
Path

The path to the project configuration file.

Source code in sereto/models/project.py
83
84
85
86
87
88
89
90
@validate_call
def get_config_path(self) -> Path:
    """Get the path to the project configuration file.

    Returns:
        The path to the project configuration file.
    """
    return self.path / "config.json"

is_project_dir(path) staticmethod

Check if the provided path is a root directory of a project.

A project directory contains at least .sereto and config.json files.

Parameters:

Name Type Description Default
path Path

The path to examine.

required

Returns:

Type Description
bool

True if the path is a project directory, False otherwise.

Source code in sereto/models/project.py
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
@staticmethod
@validate_call
def is_project_dir(path: Path) -> bool:
    """Check if the provided path is a root directory of a project.

    A project directory contains at least `.sereto` and `config.json` files.

    Args:
        path: The path to examine.

    Returns:
        True if the path is a project directory, False otherwise.
    """
    return path.is_dir() and path.exists() and (path / ".sereto").is_file() and (path / "config.json").is_file()

load_from(path=None) staticmethod

Load the project from the provided path.

Parameters:

Name Type Description Default
path DirectoryPath | None

The path to the project (sub)directory. Defaults to the current working directory.

None

Returns:

Type Description
Project

The project object.

Source code in sereto/models/project.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
@staticmethod
def load_from(path: DirectoryPath | None = None) -> "Project":
    """Load the project from the provided path.

    Args:
        path: The path to the project (sub)directory. Defaults to the current working directory.

    Returns:
        The project object.
    """
    settings = load_settings_function()
    project_path = get_project_path_from_dir(
        dir=path if path is not None else Path.cwd(), dir_subtree=settings.projects_path
    )
    config = Config.load_from(file=project_path / "config.json").update_paths(project_path=project_path)
    return Project(config=config, settings=load_settings_function(), path=project_path)

get_config_path(dir_subtree=Path('/'))

Get the path to the project configuration file.

Parameters:

Name Type Description Default
dir_subtree DirectoryPath

The directory to stop the search at. Defaults to the root directory.

Path('/')

Returns:

Type Description
Path

The path to the project configuration file.

Source code in sereto/models/project.py
48
49
50
51
52
53
54
55
56
57
58
@validate_call
def get_config_path(dir_subtree: DirectoryPath = Path("/")) -> Path:
    """Get the path to the project configuration file.

    Args:
        dir_subtree: The directory to stop the search at. Defaults to the root directory.

    Returns:
        The path to the project configuration file.
    """
    return get_project_path_from_dir(dir_subtree=dir_subtree) / "config.json"

get_project_path_from_dir(dir=None, dir_subtree=Path('/'))

Get the path to the project directory.

Start the search from the 'dir' directory and go up the directory tree until the project directory is found or 'dir_subtree' is reached.

Parameters:

Name Type Description Default
dir DirectoryPath | None

The directory to start the search from. Defaults to the current working directory.

None
dir_subtree DirectoryPath

The directory to stop the search at. Defaults to the root directory.

Path('/')

Raises:

Type Description
SeretoPathError

If the current working directory is not inside the project's (sub)directory.

Returns:

Type Description
Path

The path to the project directory.

Source code in sereto/models/project.py
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
@validate_call
def get_project_path_from_dir(dir: DirectoryPath | None = None, dir_subtree: DirectoryPath = Path("/")) -> Path:
    """Get the path to the project directory.

    Start the search from the 'dir' directory and go up the directory tree until the project directory is
    found or 'dir_subtree' is reached.

    Args:
        dir: The directory to start the search from. Defaults to the current working directory.
        dir_subtree: The directory to stop the search at. Defaults to the root directory.

    Raises:
        SeretoPathError: If the current working directory is not inside the project's (sub)directory.

    Returns:
        The path to the project directory.
    """
    if dir is None:
        dir = Path.cwd()

    # start from the current working directory and go up the directory tree
    for d in [dir] + list(dir.parents):
        # if the current directory is inside the subtree
        if d.is_relative_to(dir_subtree):
            # if the current directory is a project directory
            if Project.is_project_dir(d):
                return d
        else:
            # stop the search before leaving the subtree
            break

    raise SeretoPathError("not inside project's (sub)directory")