|
30 | 30 | from trove_classifiers import all_classifiers, deprecated_classifiers
|
31 | 31 | from webob.multidict import MultiDict
|
32 | 32 |
|
| 33 | +from warehouse.packaging.models import DynamicFieldsEnum |
33 | 34 | from warehouse.utils import http
|
34 | 35 |
|
35 | 36 | SUPPORTED_METADATA_VERSIONS = {"1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"}
|
@@ -141,7 +142,7 @@ def _validate_metadata(metadata: Metadata, *, backfill: bool = False):
|
141 | 142 | InvalidMetadata("classifier", f"{classifier!r} is not a valid classifier.")
|
142 | 143 | )
|
143 | 144 |
|
144 |
| - # Validate that no deprecated classifers are being used. |
| 145 | + # Validate that no deprecated classifiers are being used. |
145 | 146 | # NOTE: We only check this is we're not doing a backfill, because backfill
|
146 | 147 | # operations may legitimately use deprecated classifiers.
|
147 | 148 | if not backfill:
|
@@ -235,6 +236,19 @@ def _validate_metadata(metadata: Metadata, *, backfill: bool = False):
|
235 | 236 | )
|
236 | 237 | )
|
237 | 238 |
|
| 239 | + # Validate that any `dynamic` fields passed are in the allowed list |
| 240 | + # TODO: This probably should be lifted up to packaging.metadata |
| 241 | + for field in {"dynamic"}: |
| 242 | + if (value := getattr(metadata, field)) is not None: |
| 243 | + for key in value: |
| 244 | + if key not in map(str.lower, DynamicFieldsEnum.enums): |
| 245 | + errors.append( |
| 246 | + InvalidMetadata( |
| 247 | + _RAW_TO_EMAIL_MAPPING.get(field, field), |
| 248 | + f"Dynamic field {key!r} is not a valid dynamic field.", |
| 249 | + ) |
| 250 | + ) |
| 251 | + |
238 | 252 | # Ensure that License and License-Expression are mutually exclusive
|
239 | 253 | # See https://peps.python.org/pep-0639/#deprecate-license-field
|
240 | 254 | if metadata.license and metadata.license_expression:
|
@@ -263,12 +277,12 @@ def _validate_metadata(metadata: Metadata, *, backfill: bool = False):
|
263 | 277 |
|
264 | 278 |
|
265 | 279 | def parse_form_metadata(data: MultiDict) -> Metadata:
|
266 |
| - # We construct a RawMetdata using the form data, which we will later pass |
| 280 | + # We construct a RawMetadata using the form data, which we will later pass |
267 | 281 | # to Metadata to get a validated metadata.
|
268 | 282 | #
|
269 |
| - # NOTE: Form data is very similiar to the email format where the only difference |
| 283 | + # NOTE: Form data is very similar to the email format where the only difference |
270 | 284 | # between a list and a single value is whether or not the same key is used
|
271 |
| - # multiple times. Thus we will handle things in a similiar way, always |
| 285 | + # multiple times. Thus, we will handle things in a similar way, always |
272 | 286 | # fetching things as a list and then determining what to do based on the
|
273 | 287 | # field type and how many values we found.
|
274 | 288 | #
|
|
0 commit comments