Update dependency version specifiers inplace.
(dependencies, releases)
| 120 | |
| 121 | |
| 122 | def _update_specifiers(dependencies, releases): |
| 123 | """Update dependency version specifiers inplace.""" |
| 124 | for idx, dep in enumerate(dependencies): |
| 125 | if isinstance(dep, dict): |
| 126 | continue # skip nested dependency groups (e.g., `{'include-group': 'doc'}`) |
| 127 | req = Requirement(dep) |
| 128 | pkg_name = req.name |
| 129 | pkg_spec = req.specifier |
| 130 | if pkg_name in releases.keys(): # check if this is a package to update |
| 131 | # Find package versions matching current specifiers |
| 132 | package_vers = releases[pkg_name].keys() |
| 133 | matches = list(pkg_spec.filter(package_vers)) # drop excluded versions |
| 134 | pre_cutoff_matches = [ |
| 135 | ver for ver in matches if releases[pkg_name][ver]["pre_cutoff"] |
| 136 | ] |
| 137 | if len(pre_cutoff_matches) == 0: |
| 138 | raise RuntimeError( |
| 139 | f"{pkg_name} had no versions available {SUPPORT_TIME.days / 365} " |
| 140 | "years ago compliant with the following specifier(s): " |
| 141 | f"{pkg_spec if pkg_spec else 'None'}", |
| 142 | ) |
| 143 | post_cutoff_matches = [ |
| 144 | ver for ver in matches if not releases[pkg_name][ver]["pre_cutoff"] |
| 145 | ] |
| 146 | |
| 147 | # Find latest pre-cutoff version to pin as the minimum version |
| 148 | min_ver = max(pre_cutoff_matches) |
| 149 | min_ver, min_ver_release = _find_version_to_pin_and_release( |
| 150 | min_ver, pkg_spec, pre_cutoff_matches, releases[pkg_name] |
| 151 | ) |
| 152 | |
| 153 | # Find earliest post-cutoff version to pin next |
| 154 | next_ver = None |
| 155 | next_ver_release = None |
| 156 | for ver in post_cutoff_matches: |
| 157 | if _as_minor_version(ver) > min_ver: # if a new minor version |
| 158 | next_ver, next_ver_release = _find_version_to_pin_and_release( |
| 159 | ver, pkg_spec, post_cutoff_matches, releases[pkg_name] |
| 160 | ) |
| 161 | break |
| 162 | |
| 163 | # Update specifiers with new minimum version |
| 164 | min_ver_spec = SpecifierSet(f">={str(min_ver)}") |
| 165 | new_spec = [str(min_ver_spec)] |
| 166 | for spec in str(pkg_spec).split(","): |
| 167 | spec = spec.strip() |
| 168 | if spec.startswith(">"): |
| 169 | continue # ignore old min ver |
| 170 | if spec.startswith("!=") and not min_ver_spec.contains(spec[2:]): |
| 171 | continue # ignore outdated exclusions |
| 172 | new_spec.append(spec) # keep max vers and in-date exclusions |
| 173 | req.specifier = SpecifierSet(",".join(new_spec)) |
| 174 | |
| 175 | dependencies._value[idx] = _add_date_comment( |
| 176 | dependencies._value[idx], min_ver_release, next_ver, next_ver_release |
| 177 | ) |
| 178 | dependencies[idx] = _prettify_requirement(req) |
| 179 |
no test coverage detected