Skip to content

util

SSB-project utils.

create_error_log(log, calling_function, home_path=HOME_PATH)

Creates a file with log of error in the current folder.

Parameters:

Name Type Description Default
log str

The content of the error log.

required
calling_function str

The function in which the error occurred. Used to give a more descriptive name to error log file.

required
home_path Path

System home path

HOME_PATH
Source code in ssb_project_cli/ssb_project/util.py
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
def create_error_log(
    log: str, calling_function: str, home_path: Path = HOME_PATH
) -> None:
    """Creates a file with log of error in the current folder.

    Args:
        log: The content of the error log.
        calling_function: The function in which the error occurred. Used to give a more descriptive name to error log file.
        home_path: System home path
    """
    try:
        error_logs_path = f"{home_path}/ssb-project-cli/.error_logs"
        if not os.path.exists(error_logs_path):
            os.makedirs(error_logs_path)
        filename = f"{calling_function}-error-{int(time.time())}.txt"
        with open(f"{error_logs_path}/{filename}", "w+") as f:
            f.write(log)
            print(f"Detailed error information saved to {error_logs_path}/{filename}")
            print(
                f"You can find the full debug log here {error_logs_path}/ssb-project-debug.log"
            )
            print(
                f"❗️You can try deleting '.poetry/cache' in your project directory or '{home_path}/.cache/pypoetry'. Cache could be causing problems"
            )
    except Exception as e:
        print(f"Error while attempting to write the log file: {e}")

execute_command(command, command_shortname, success_desc=None, failure_desc=None, cwd=None)

Execute command and handle failure/success cases.

Parameters:

Name Type Description Default
command Union[str, list[str]]

The command to be executed. For example "poetry install".

required
command_shortname str

For example: "poetry-install". Used to create descriptive error log file.

required
success_desc Optional[str]

For example: "Poetry install ran successfully".

None
failure_desc Optional[str]

For example: "Something went wrong while running poetry install".

None
cwd Optional[Path]

The current working directory.

None

Returns:

Type Description
CompletedProcess[bytes]

The result of the subprocess.

Source code in ssb_project_cli/ssb_project/util.py
 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
def execute_command(
    command: Union[str, list[str]],
    command_shortname: str,
    success_desc: Optional[str] = None,
    failure_desc: Optional[str] = None,
    cwd: Optional[Path] = None,
) -> subprocess.CompletedProcess[bytes]:
    """Execute command and handle failure/success cases.

    Args:
        command: The command to be executed. For example "poetry install".
        command_shortname: For example: "poetry-install". Used to create descriptive error log file.
        success_desc: For example: "Poetry install ran successfully".
        failure_desc: For example: "Something went wrong while running poetry install".
        cwd: The current working directory.

    Returns:
        The result of the subprocess.
    """
    if isinstance(command, str):
        command = command.split(" ")
    result = subprocess.run(  # noqa S603
        command,
        capture_output=True,
        cwd=cwd,
    )

    if result.returncode != 0:
        calling_function = command_shortname
        log = str(result)
        if failure_desc:
            print(failure_desc)
        else:
            print("Error while running: " + " ".join(command))
        create_error_log(log, calling_function)
        sys.exit(1)
    else:
        if success_desc:
            print(success_desc)

    return result

get_kernels_dict()

Gets installed kernel specifications.

Returns:

Name Type Description
kernel_dict dict[str, dict[str, str]]

Dictionary of installed kernel specifications

Source code in ssb_project_cli/ssb_project/util.py
107
108
109
110
111
112
113
def get_kernels_dict() -> dict[str, dict[str, str]]:
    """Gets installed kernel specifications.

    Returns:
        kernel_dict: Dictionary of installed kernel specifications
    """
    return kernelspec_manager.get_all_specs()

get_project_name_and_root_path(project_path=None)

Get the name and root of the project.

  • First source: .cruft.json
  • Second source: pyproject.toml
  • Final fallback: project root directory name.

Parameters:

Name Type Description Default
project_path Path | None

Optionally supply a path to the project. If not supplied, use the current working directory.

None

Returns:

Name Type Description
project_name str | None

The name of the project.

project_root Path | None

Path of the root directory of the project.

Source code in ssb_project_cli/ssb_project/util.py
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def get_project_name_and_root_path(
    project_path: Path | None = None,
) -> tuple[str | None, Path | None]:
    """Get the name and root of the project.

    - First source: `.cruft.json`
    - Second source: `pyproject.toml`
    - Final fallback: project root directory name.

    Args:
        project_path: Optionally supply a path to the project. If not supplied, use the current working directory.

    Returns:
        project_name: The name of the project.
        project_root: Path of the root directory of the project.
    """
    cruft_json_name = ".cruft.json"
    pyproject_name = "pyproject.toml"
    origin = project_path or Path.cwd()
    if not origin.exists():
        return None, None
    paths = [origin]
    # List of current path and all parents up to the filesystem root
    paths.extend(origin.parents)

    for path in paths:
        if {i.name for i in path.iterdir()}.intersection(
            {cruft_json_name, pyproject_name, ".git"}
        ):
            try:
                # Attempt to source from Cruft first
                name = json.loads((path / cruft_json_name).read_text())["context"][
                    "cookiecutter"
                ]["project_name"]
                return (
                    name,
                    path,
                )
            except (KeyError, FileNotFoundError, json.JSONDecodeError):
                # Fall back to pyproject.toml
                try:
                    name = tomli.loads((path / pyproject_name).read_text())["tool"][
                        "poetry"
                    ]["name"]
                    return (
                        name,
                        path,
                    )
                except (KeyError, FileNotFoundError):
                    # Final fall back to project root directory name
                    return path.name, path
    return None, None

handle_no_kernel_argument(no_kernel)

Handle the 'no_kernel' parameter and environment variable.

The CLI flag is always prioritised, otherwise it falls back to the environment variable and then lastly defaults to False.

Source code in ssb_project_cli/ssb_project/util.py
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
def handle_no_kernel_argument(no_kernel: bool) -> bool:
    """Handle the 'no_kernel' parameter and environment variable.

    The CLI flag is always prioritised, otherwise it falls back to the environment
    variable and then lastly defaults to False.
    """
    if no_kernel:
        return no_kernel
    env_var_no_kernel = os.environ.get("NO_KERNEL")
    if env_var_no_kernel is None:  # handle NO_KERNEL is undefined case
        return False
    elif env_var_no_kernel not in ["True", "False"]:
        print(
            f"""
              The value of the 'NO_KERNEL' environment variable is {os.environ["NO_KERNEL"]}.
              The only valid values are True and False.
            """
        )
        exit(1)
    else:
        return bool(env_var_no_kernel)

remove_kernel_spec(kernel_name)

Remove a kernel spec.

Source code in ssb_project_cli/ssb_project/util.py
116
117
118
def remove_kernel_spec(kernel_name: str) -> None:
    """Remove a kernel spec."""
    kernelspec_manager.remove_kernel_spec(kernel_name)

set_debug_logging(home_path=HOME_PATH)

Creates a file with log of error in the current folder.

Parameters:

Name Type Description Default
home_path Path

path prefix to use for error logging, defaults to HOME_PATH.

HOME_PATH
Source code in ssb_project_cli/ssb_project/util.py
23
24
25
26
27
28
29
30
31
32
33
def set_debug_logging(home_path: Path = HOME_PATH) -> None:
    """Creates a file with log of error in the current folder.

    Args:
        home_path: path prefix to use for error logging, defaults to HOME_PATH.
    """
    error_logs_path = f"{home_path}/ssb-project-cli/.error_logs/ssb-project-debug.log"
    log_dir = os.path.dirname(error_logs_path)
    if not os.path.exists(log_dir):
        os.makedirs(log_dir)
    logging.basicConfig(filename=error_logs_path, level=logging.DEBUG)