|
3 | 3 |
|
4 | 4 | # SPDX-License-Identifier: GPL-3.0-or-later |
5 | 5 | # treecript, a process tree metrics gatherer. |
6 | | -# Copyright (C) 2025 Barcelona Supercomputing Center, José M. Fernández |
| 6 | +# Copyright (C) 2026 Barcelona Supercomputing Center, José M. Fernández |
7 | 7 | # |
8 | 8 | # This program is free software: you can redistribute it and/or modify |
9 | 9 | # it under the terms of the GNU General Public License as published by |
|
23 | 23 | import sys |
24 | 24 | import setuptools |
25 | 25 |
|
| 26 | +from typing import ( |
| 27 | + cast, |
| 28 | + TYPE_CHECKING, |
| 29 | +) |
| 30 | + |
| 31 | +if TYPE_CHECKING: |
| 32 | + from typing import ( |
| 33 | + Final, |
| 34 | + MutableMapping, |
| 35 | + MutableSequence, |
| 36 | + Sequence, |
| 37 | + ) |
| 38 | + |
26 | 39 | # In this way, we are sure we are getting |
27 | 40 | # the installer's version of the library |
28 | 41 | # not the system's one |
|
33 | 46 | from treecript import __author__ as epmc_author # noqa: E402 |
34 | 47 | from treecript import __license__ as epmc_license # noqa: E402 |
35 | 48 |
|
| 49 | +EGG_PAT = re.compile(r"#[^#]*egg=([^=&]+)") |
| 50 | +OTHER_REQ_PAT = re.compile(r"^-r\s+(.+)") |
| 51 | +REQ_SECT_PAT = re.compile(r"^requirements-([^.]+)\.txt$") |
| 52 | + |
| 53 | +CORE_REQUIREMENTS: "Final[str]" = "core" |
| 54 | + |
| 55 | + |
| 56 | +def populate_extra_requirements( |
| 57 | + requirements_path: "str", section: "str" = CORE_REQUIREMENTS |
| 58 | +) -> "MutableMapping[str, Sequence[str]]": |
| 59 | + extra_requirements: "MutableMapping[str, MutableSequence[str]]" = {} |
| 60 | + if os.path.exists(requirements_path): |
| 61 | + # Be sure the path is an absolute one |
| 62 | + if not os.path.isabs(requirements_path): |
| 63 | + requirements_path = os.path.abspath(requirements_path) |
| 64 | + |
| 65 | + with open(requirements_path, mode="r", encoding="utf-8") as f: |
| 66 | + for line in f.read().splitlines(): |
| 67 | + rm = OTHER_REQ_PAT.search(line) |
| 68 | + if rm is None: |
| 69 | + print(f"R {line}") |
| 70 | + m = EGG_PAT.search(line) |
| 71 | + extra_requirements.setdefault(section, []).append( |
| 72 | + line if m is None else m.group(1) |
| 73 | + ) |
| 74 | + else: |
| 75 | + # This is needed for cases like -r |
| 76 | + other_requirements_path = os.path.realpath( |
| 77 | + os.path.join(os.path.dirname(requirements_path), rm.group(1)) |
| 78 | + ) |
| 79 | + other_requirements_basename = os.path.basename( |
| 80 | + other_requirements_path |
| 81 | + ) |
| 82 | + |
| 83 | + nested_section = section |
| 84 | + rsmatch = REQ_SECT_PAT.search(other_requirements_basename) |
| 85 | + if rsmatch is not None: |
| 86 | + nested_section = rsmatch.group(1) |
| 87 | + |
| 88 | + nested_extra_requirements = populate_extra_requirements( |
| 89 | + other_requirements_path, section=nested_section |
| 90 | + ) |
| 91 | + for nested_sect, nested_deps in nested_extra_requirements.items(): |
| 92 | + extra_requirements.setdefault(nested_sect, []).extend( |
| 93 | + nested_deps |
| 94 | + ) |
| 95 | + |
| 96 | + return cast("MutableMapping[str, Sequence[str]]", extra_requirements) |
| 97 | + |
| 98 | + |
36 | 99 | # Populating the long description |
37 | 100 | readme_path = os.path.join(setupDir, "README.md") |
38 | 101 | with open(readme_path, "r") as fh: |
39 | 102 | long_description = fh.read() |
40 | 103 |
|
41 | 104 | # Populating the install requirements |
42 | | -requirements = [] |
43 | 105 | requirements_path = os.path.join(setupDir, "installation", "requirements.txt") |
44 | | -if os.path.exists(requirements_path): |
45 | | - with open(requirements_path, mode="r", encoding="utf-8") as f: |
46 | | - egg = re.compile(r"#[^#]*egg=([^=&]+)") |
47 | | - for line in f.read().splitlines(): |
48 | | - print(f"R {line}") |
49 | | - m = egg.search(line) |
50 | | - requirements.append(line if m is None else m.group(1)) |
| 106 | +extra_requirements = populate_extra_requirements(requirements_path) |
| 107 | +requirements = extra_requirements.pop(CORE_REQUIREMENTS, []) |
51 | 108 |
|
52 | 109 | setuptools.setup( |
53 | 110 | name="treecript", |
|
78 | 135 | "legacy/plotGraph.sh", |
79 | 136 | "legacy/plot-metrics.sh", |
80 | 137 | ], |
| 138 | + entry_points={ |
| 139 | + "console_scripts": [ |
| 140 | + "execution-metrics-collector = treecript.collector:main__commandline", |
| 141 | + "process-metrics-collector = treecript.collector:main", |
| 142 | + "cpuinfo-tdp-finder = treecript.tdp_finder:main_cpuinfo_tdp_finder", |
| 143 | + "modelname-tdp-finder = treecript.tdp_finder:main_modelname_tdp_finder", |
| 144 | + "tdp-finder = treecript.tdp_finder:main_tdp_finder", |
| 145 | + "metrics-aggregator = treecript.aggregator:main [analytics]", |
| 146 | + "plotGraph = treecript.plot_graph:main [analytics]", |
| 147 | + ], |
| 148 | + }, |
81 | 149 | install_requires=requirements, |
| 150 | + extras_require=extra_requirements, |
82 | 151 | # See https://pypi.org/classifiers/ |
83 | 152 | classifiers=[ |
84 | 153 | "Programming Language :: Python :: 3", |
|
0 commit comments