Skip to content

Technical reference

Public Python package for Maturity meter.

The package exports the small public API that other Python code can import. Implementation details live in named modules and subpackages such as services.

EvaluationRequest

Bases: BaseModel

What to evaluate.

Parameters:

Name Type Description Default
repository str

URL of a GitHub or GitLab repository. Normalized to https://<host>/<path> without a .git suffix or trailing slash.

required
dois list[str]

Optional DOIs of publications about the software. Normalized to the bare 10.xxxx/... form.

required
biotools_id str | None

Optional bio.tools identifier of the software.

required
Source code in src/maturity_meter/models.py
 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
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 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
class EvaluationRequest(BaseModel):
    """What to evaluate.

    Parameters
    ----------
    repository : str
        URL of a GitHub or GitLab repository. Normalized to
        ``https://<host>/<path>`` without a ``.git`` suffix or trailing slash.
    dois : list[str]
        Optional DOIs of publications about the software. Normalized to the
        bare ``10.xxxx/...`` form.
    biotools_id : str | None
        Optional bio.tools identifier of the software.
    """

    model_config = ConfigDict(frozen=True)

    repository: str
    dois: list[str] = Field(default_factory=list)
    biotools_id: str | None = None

    @field_validator("repository")
    @classmethod
    def normalize_repository(cls, value: str) -> str:
        """Validate and canonicalize a repository URL.

        Parameters
        ----------
        value : str
            Repository URL as supplied by the user.

        Returns
        -------
        str
            Canonical ``https`` repository URL.

        Raises
        ------
        ValueError
            If the host is unsupported or the path is not ``owner/repo``.
        """
        parsed = urlparse(value.strip())
        host = (parsed.hostname or "").lower().removeprefix("www.")
        if parsed.scheme not in ("http", "https") or host not in SUPPORTED_HOSTS:
            raise ValueError(
                f"Repository must be an http(s) URL on {' or '.join(SUPPORTED_HOSTS)}"
            )
        path = parsed.path.strip("/").removesuffix(".git")
        if len(path.split("/")) < 2 or not all(path.split("/")):
            raise ValueError("Repository URL must include an owner and a repository")
        return f"https://{host}/{path}"

    @field_validator("dois")
    @classmethod
    def normalize_dois(cls, values: list[str]) -> list[str]:
        """Strip DOI URL prefixes, validate, and drop duplicates.

        Parameters
        ----------
        values : list[str]
            DOIs as supplied by the user.

        Returns
        -------
        list[str]
            Unique bare DOIs in their original order.

        Raises
        ------
        ValueError
            If an entry is not a valid DOI.
        """
        normalized: dict[str, None] = {}
        for value in values:
            doi = _DOI_PREFIX_PATTERN.sub("", value.strip())
            if not _DOI_PATTERN.match(doi):
                raise ValueError(f"Invalid DOI: {value!r}")
            normalized[doi] = None
        return list(normalized)

    @field_validator("biotools_id")
    @classmethod
    def normalize_biotools_id(cls, value: str | None) -> str | None:
        """Validate a bio.tools identifier, treating blank as unset.

        Parameters
        ----------
        value : str | None
            bio.tools identifier as supplied by the user.

        Returns
        -------
        str | None
            Stripped identifier, or ``None`` when blank.

        Raises
        ------
        ValueError
            If the identifier contains unsupported characters.
        """
        if value is None or not value.strip():
            return None
        value = value.strip()
        if not _BIOTOOLS_ID_PATTERN.match(value):
            raise ValueError(f"Invalid bio.tools ID: {value!r}")
        return value

    @property
    def host(self) -> str:
        """Hosting platform domain, e.g. ``github.com``."""
        return urlparse(self.repository).hostname or ""

    @property
    def repo_path(self) -> str:
        """Repository path on the host, e.g. ``owner/repo``."""
        return urlparse(self.repository).path.strip("/")

    @property
    def owner(self) -> str:
        """Repository owner (namespace; may contain subgroups on GitLab)."""
        return self.repo_path.rsplit("/", 1)[0]

    @property
    def repo(self) -> str:
        """Repository name."""
        return self.repo_path.rsplit("/", 1)[1]

host property

Hosting platform domain, e.g. github.com.

owner property

Repository owner (namespace; may contain subgroups on GitLab).

repo property

Repository name.

repo_path property

Repository path on the host, e.g. owner/repo.

normalize_biotools_id(value) classmethod

Validate a bio.tools identifier, treating blank as unset.

Parameters:

Name Type Description Default
value str | None

bio.tools identifier as supplied by the user.

required

Returns:

Type Description
str | None

Stripped identifier, or None when blank.

Raises:

Type Description
ValueError

If the identifier contains unsupported characters.

Source code in src/maturity_meter/models.py
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
@field_validator("biotools_id")
@classmethod
def normalize_biotools_id(cls, value: str | None) -> str | None:
    """Validate a bio.tools identifier, treating blank as unset.

    Parameters
    ----------
    value : str | None
        bio.tools identifier as supplied by the user.

    Returns
    -------
    str | None
        Stripped identifier, or ``None`` when blank.

    Raises
    ------
    ValueError
        If the identifier contains unsupported characters.
    """
    if value is None or not value.strip():
        return None
    value = value.strip()
    if not _BIOTOOLS_ID_PATTERN.match(value):
        raise ValueError(f"Invalid bio.tools ID: {value!r}")
    return value

normalize_dois(values) classmethod

Strip DOI URL prefixes, validate, and drop duplicates.

Parameters:

Name Type Description Default
values list[str]

DOIs as supplied by the user.

required

Returns:

Type Description
list[str]

Unique bare DOIs in their original order.

Raises:

Type Description
ValueError

If an entry is not a valid DOI.

Source code in src/maturity_meter/models.py
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
@field_validator("dois")
@classmethod
def normalize_dois(cls, values: list[str]) -> list[str]:
    """Strip DOI URL prefixes, validate, and drop duplicates.

    Parameters
    ----------
    values : list[str]
        DOIs as supplied by the user.

    Returns
    -------
    list[str]
        Unique bare DOIs in their original order.

    Raises
    ------
    ValueError
        If an entry is not a valid DOI.
    """
    normalized: dict[str, None] = {}
    for value in values:
        doi = _DOI_PREFIX_PATTERN.sub("", value.strip())
        if not _DOI_PATTERN.match(doi):
            raise ValueError(f"Invalid DOI: {value!r}")
        normalized[doi] = None
    return list(normalized)

normalize_repository(value) classmethod

Validate and canonicalize a repository URL.

Parameters:

Name Type Description Default
value str

Repository URL as supplied by the user.

required

Returns:

Type Description
str

Canonical https repository URL.

Raises:

Type Description
ValueError

If the host is unsupported or the path is not owner/repo.

Source code in src/maturity_meter/models.py
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@field_validator("repository")
@classmethod
def normalize_repository(cls, value: str) -> str:
    """Validate and canonicalize a repository URL.

    Parameters
    ----------
    value : str
        Repository URL as supplied by the user.

    Returns
    -------
    str
        Canonical ``https`` repository URL.

    Raises
    ------
    ValueError
        If the host is unsupported or the path is not ``owner/repo``.
    """
    parsed = urlparse(value.strip())
    host = (parsed.hostname or "").lower().removeprefix("www.")
    if parsed.scheme not in ("http", "https") or host not in SUPPORTED_HOSTS:
        raise ValueError(
            f"Repository must be an http(s) URL on {' or '.join(SUPPORTED_HOSTS)}"
        )
    path = parsed.path.strip("/").removesuffix(".git")
    if len(path.split("/")) < 2 or not all(path.split("/")):
        raise ValueError("Repository URL must include an owner and a repository")
    return f"https://{host}/{path}"

MaturityResult dataclass

Result returned by the evaluation service.

Source code in src/maturity_meter/services/processing.py
17
18
19
20
21
@dataclass(frozen=True)
class MaturityResult:
    """Result returned by the evaluation service."""

    maturity_placeholder: Any

evaluate_maturity(request)

Evaluate the maturity of the software described by request.

Parameters:

Name Type Description Default
request EvaluationRequest

Repository and optional publication/bio.tools identifiers.

required

Returns:

Type Description
MaturityResult

Evaluated maturity.

Source code in src/maturity_meter/services/processing.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def evaluate_maturity(request: EvaluationRequest) -> MaturityResult:
    """Evaluate the maturity of the software described by ``request``.

    Parameters
    ----------
    request : EvaluationRequest
        Repository and optional publication/bio.tools identifiers.

    Returns
    -------
    MaturityResult
        Evaluated maturity.
    """
    # This starter transformation is intentionally simple. Replace the body of
    # this function with the real project logic while keeping the typed result.
    logger.debug("Evaluating maturity of %s", request.repository)
    return MaturityResult(maturity_placeholder=combine())

Reusable processing service for Maturity meter.

Service modules contain project logic behind public entry points. Keep framework-specific parsing, rendering, and transport details outside this layer.

MaturityResult dataclass

Result returned by the evaluation service.

Source code in src/maturity_meter/services/processing.py
17
18
19
20
21
@dataclass(frozen=True)
class MaturityResult:
    """Result returned by the evaluation service."""

    maturity_placeholder: Any

evaluate_maturity(request)

Evaluate the maturity of the software described by request.

Parameters:

Name Type Description Default
request EvaluationRequest

Repository and optional publication/bio.tools identifiers.

required

Returns:

Type Description
MaturityResult

Evaluated maturity.

Source code in src/maturity_meter/services/processing.py
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def evaluate_maturity(request: EvaluationRequest) -> MaturityResult:
    """Evaluate the maturity of the software described by ``request``.

    Parameters
    ----------
    request : EvaluationRequest
        Repository and optional publication/bio.tools identifiers.

    Returns
    -------
    MaturityResult
        Evaluated maturity.
    """
    # This starter transformation is intentionally simple. Replace the body of
    # this function with the real project logic while keeping the typed result.
    logger.debug("Evaluating maturity of %s", request.repository)
    return MaturityResult(maturity_placeholder=combine())