| #!/usr/bin/env python |
| |
| # |
| # Copyright (C) 2024 The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| # |
| |
| """Build Font instance with validating JSON contents.""" |
| |
| import dataclasses |
| |
| from custom_json import _load_json_with_comment |
| from validators import check_enum_or_none |
| from validators import check_float |
| from validators import check_int_or_none |
| from validators import check_str |
| from validators import check_str_or_none |
| from validators import check_tag |
| from validators import check_weight_or_none |
| |
| |
| @dataclasses.dataclass |
| class Font: |
| file: str |
| weight: int | None |
| style: str | None |
| index: int | None |
| supported_axes: str | None |
| post_script_name: str | None |
| axes: dict[str | float] |
| |
| |
| _FONT_KEYS = set([ |
| "file", |
| "weight", |
| "style", |
| "index", |
| "supportedAxes", |
| "postScriptName", |
| "axes", |
| ]) |
| |
| |
| def _check_axes(axes) -> dict[str | float] | None: |
| """Sanitize the variation axes.""" |
| if axes is None: |
| return None |
| assert isinstance(axes, dict), "axes must be dict" |
| |
| sanitized = {} |
| for key in axes.keys(): |
| sanitized[check_tag(key)] = check_float(axes, key) |
| |
| return sanitized |
| |
| |
| def _parse_font(obj, for_sanitization_test=False) -> Font: |
| """Convert given dict object to Font instance.""" |
| unknown_keys = obj.keys() - _FONT_KEYS |
| assert not unknown_keys, "Unknown keys found: %s" % unknown_keys |
| font = Font( |
| file=check_str(obj, "file"), |
| weight=check_weight_or_none(obj, "weight"), |
| style=check_enum_or_none(obj, "style", ["normal", "italic"]), |
| index=check_int_or_none(obj, "index"), |
| supported_axes=check_enum_or_none( |
| obj, "supportedAxes", ["wght", "wght,ital"] |
| ), |
| post_script_name=check_str_or_none(obj, "postScriptName"), |
| axes=_check_axes(obj.get("axes")), |
| ) |
| |
| if not for_sanitization_test: |
| assert font.file, "file must be specified" |
| if not font.supported_axes: |
| assert font.weight, ( |
| "If supported_axes is not specified, weight should be specified: %s" |
| % obj |
| ) |
| assert font.style, ( |
| "If supported_axes is not specified, style should be specified: %s" |
| % obj |
| ) |
| |
| return font |
| |
| |
| def parse_fonts(objs) -> Font: |
| assert isinstance(objs, list), "fonts must be list: %s" % (objs) |
| assert objs, "At least one font should be added." |
| return [_parse_font(obj) for obj in objs] |
| |
| |
| def parse_font_from_json_for_sanitization_test(json_str: str) -> Font: |
| """For testing purposes.""" |
| return _parse_font( |
| _load_json_with_comment(json_str), for_sanitization_test=False |
| ) |
| |
| |
| def parse_fonts_from_json_for_validation_test(json_str: str) -> [Font]: |
| """For testing purposes.""" |
| return parse_fonts(_load_json_with_comment(json_str)) |