Meta: Make CSS dimension loading reusable
Aside from the existing users this will also be used within the CSSGrammar parser
This commit is contained in:
parent
eaf1078c98
commit
c96e8f15e5
3 changed files with 124 additions and 88 deletions
|
|
@ -6,7 +6,6 @@
|
|||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
|
@ -14,6 +13,8 @@ from typing import TextIO
|
|||
|
||||
sys.path.append(str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from Utils.css_dimensions import get_css_dimensions
|
||||
from Utils.css_dimensions import load_css_dimensions
|
||||
from Utils.utils import make_name_acceptable_cpp
|
||||
from Utils.utils import snake_casify
|
||||
|
||||
|
|
@ -130,8 +131,8 @@ def main():
|
|||
parser.add_argument("-j", "--json", required=True, help="Path to the JSON file to read from")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.json, "r", encoding="utf-8") as input_file:
|
||||
units_data = json.load(input_file)
|
||||
load_css_dimensions(args.json)
|
||||
units_data = get_css_dimensions()
|
||||
|
||||
with open(args.header, "w", encoding="utf-8") as output_file:
|
||||
write_header_file(output_file, units_data)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
# SPDX-License-Identifier: BSD-2-Clause
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
|
||||
from pathlib import Path
|
||||
|
|
@ -14,90 +13,13 @@ from typing import TextIO
|
|||
|
||||
sys.path.append(str(Path(__file__).resolve().parent.parent))
|
||||
|
||||
from Utils.css_dimensions import get_css_dimensions
|
||||
from Utils.css_dimensions import load_css_dimensions
|
||||
from Utils.utils import snake_casify
|
||||
from Utils.utils import title_casify
|
||||
from Utils.utils import underlying_type_for_enum
|
||||
|
||||
|
||||
def json_is_valid(dimensions_data: dict, json_path: str) -> bool:
|
||||
is_valid = True
|
||||
most_recent_dimension_name = ""
|
||||
for dimension_name, units in dimensions_data.items():
|
||||
# Dimensions should be in alphabetical order
|
||||
if dimension_name.lower() < most_recent_dimension_name.lower():
|
||||
print(
|
||||
f"{json_path}: Dimension `{dimension_name}` is in the wrong position. "
|
||||
"Please keep this list alphabetical!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
most_recent_dimension_name = dimension_name
|
||||
|
||||
most_recent_unit_name = ""
|
||||
canonical_unit = None
|
||||
for unit_name, unit in units.items():
|
||||
# Units should be in alphabetical order
|
||||
if unit_name.lower() < most_recent_unit_name.lower():
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is in the wrong position. "
|
||||
"Please keep this list alphabetical!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
most_recent_unit_name = unit_name
|
||||
|
||||
is_canonical_unit = unit.get("is-canonical-unit") is True
|
||||
number_of_canonical_unit = unit.get("number-of-canonical-unit")
|
||||
relative_to = unit.get("relative-to")
|
||||
provided_count = (
|
||||
(1 if is_canonical_unit else 0)
|
||||
+ (1 if number_of_canonical_unit is not None else 0)
|
||||
+ (1 if relative_to is not None else 0)
|
||||
)
|
||||
if provided_count != 1:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` must have exactly 1 of "
|
||||
"`is-canonical-unit: true`, `number-of-canonical-unit`, or `relative-to` provided.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
if is_canonical_unit:
|
||||
if canonical_unit is not None:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` marked canonical, "
|
||||
f"but `{canonical_unit}` was already. Must have exactly 1.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
else:
|
||||
canonical_unit = unit_name
|
||||
if relative_to is not None:
|
||||
if dimension_name == "length":
|
||||
if relative_to not in ("font", "viewport"):
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is marked as relative to "
|
||||
f"`{relative_to}`, which is unsupported.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
else:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is marked as relative, "
|
||||
"but only relative length units are currently supported.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
|
||||
if canonical_unit is None:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} has no unit marked as canonical. Must have exactly 1.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
def canonical_unit_name(units: dict) -> str:
|
||||
for unit_name, unit in units.items():
|
||||
if unit.get("is-canonical-unit") is True:
|
||||
|
|
@ -341,11 +263,8 @@ def main():
|
|||
parser.add_argument("-j", "--json", required=True, help="Path to the JSON file to read from")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.json, "r", encoding="utf-8") as input_file:
|
||||
dimensions_data = json.load(input_file)
|
||||
|
||||
if not json_is_valid(dimensions_data, args.json):
|
||||
sys.exit(1)
|
||||
load_css_dimensions(args.json)
|
||||
dimensions_data = get_css_dimensions()
|
||||
|
||||
with open(args.header, "w", encoding="utf-8") as output_file:
|
||||
write_header_file(output_file, dimensions_data)
|
||||
|
|
|
|||
116
Meta/Utils/css_dimensions.py
Normal file
116
Meta/Utils/css_dimensions.py
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
import json
|
||||
import sys
|
||||
|
||||
from typing import Any
|
||||
|
||||
_css_dimensions: dict[str, Any] | None = None
|
||||
|
||||
|
||||
def json_is_valid(dimensions_data: dict[str, Any], json_path: str) -> bool:
|
||||
is_valid = True
|
||||
most_recent_dimension_name = ""
|
||||
for dimension_name, units in dimensions_data.items():
|
||||
if dimension_name.lower() < most_recent_dimension_name.lower():
|
||||
print(
|
||||
f"{json_path}: Dimension `{dimension_name}` is in the wrong position. "
|
||||
"Please keep this list alphabetical!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
most_recent_dimension_name = dimension_name
|
||||
|
||||
if not isinstance(units, dict):
|
||||
print(f"{json_path}: Dimension `{dimension_name}` is not an object", file=sys.stderr)
|
||||
is_valid = False
|
||||
continue
|
||||
|
||||
most_recent_unit_name = ""
|
||||
canonical_unit = None
|
||||
for unit_name, unit in units.items():
|
||||
# Units should be in alphabetical order
|
||||
if unit_name.lower() < most_recent_unit_name.lower():
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is in the wrong position. "
|
||||
"Please keep this list alphabetical!",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
most_recent_unit_name = unit_name
|
||||
|
||||
if not isinstance(unit, dict):
|
||||
print(f"{json_path}: {dimension_name} unit `{unit_name}` is not an object", file=sys.stderr)
|
||||
is_valid = False
|
||||
continue
|
||||
|
||||
is_canonical_unit = unit.get("is-canonical-unit") is True
|
||||
number_of_canonical_unit = unit.get("number-of-canonical-unit")
|
||||
relative_to = unit.get("relative-to")
|
||||
provided_count = (
|
||||
(1 if is_canonical_unit else 0)
|
||||
+ (1 if number_of_canonical_unit is not None else 0)
|
||||
+ (1 if relative_to is not None else 0)
|
||||
)
|
||||
if provided_count != 1:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` must have exactly 1 of "
|
||||
"`is-canonical-unit: true`, `number-of-canonical-unit`, or `relative-to` provided.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
if is_canonical_unit:
|
||||
if canonical_unit is not None:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` marked canonical, "
|
||||
f"but `{canonical_unit}` was already. Must have exactly 1.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
else:
|
||||
canonical_unit = unit_name
|
||||
if relative_to is not None:
|
||||
if dimension_name == "length":
|
||||
if relative_to not in ("font", "viewport"):
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is marked as relative to "
|
||||
f"`{relative_to}`, which is unsupported.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
else:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} unit `{unit_name}` is marked as relative, "
|
||||
"but only relative length units are currently supported.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
|
||||
if canonical_unit is None:
|
||||
print(
|
||||
f"{json_path}: {dimension_name} has no unit marked as canonical. Must have exactly 1.",
|
||||
file=sys.stderr,
|
||||
)
|
||||
is_valid = False
|
||||
|
||||
return is_valid
|
||||
|
||||
|
||||
def load_css_dimensions(json_path: str) -> None:
|
||||
global _css_dimensions
|
||||
|
||||
with open(json_path, "r", encoding="utf-8") as json_file:
|
||||
dimensions_data = json.load(json_file)
|
||||
|
||||
if not isinstance(dimensions_data, dict):
|
||||
raise RuntimeError(f"{json_path}: expected a JSON object")
|
||||
|
||||
if not json_is_valid(dimensions_data, json_path):
|
||||
raise RuntimeError(f"{json_path}: invalid CSS dimensions data")
|
||||
|
||||
_css_dimensions = dimensions_data
|
||||
|
||||
|
||||
def get_css_dimensions() -> dict[str, Any]:
|
||||
if _css_dimensions is None:
|
||||
raise RuntimeError("CSS dimensions have not been initialized")
|
||||
|
||||
return _css_dimensions
|
||||
Loading…
Reference in a new issue