Standardize on Black for Python code in mozilla-central.

Allow-list all Python code in tree for use with the black linter, and re-format all code in-tree accordingly.

To produce this patch I did all of the following:

1. Make changes to tools/lint/black.yml to remove include: stanza and update list of source extensions.

2. Run ./mach lint --linter black --fix

3. Make some ad-hoc manual updates to python/mozbuild/mozbuild/test/configure/test_configure.py -- it has some hard-coded line numbers that the reformat breaks.

4. Add a set of exclusions to black.yml. These will be deleted in a follow-up bug (1672023).


Differential Revision: https://phabricator.services.mozilla.com/D94045
This commit is contained in:
Ricky Stewart 2020-10-21 21:27:27 +00:00 committed by Emilio Cobos Álvarez
parent a497b033dc
commit 8a723d48d5
4 changed files with 318 additions and 191 deletions

View file

@ -17,16 +17,18 @@ def main(filename):
or 'data-dfn-for="<counter-style>"' in line or 'data-dfn-for="<counter-style>"' in line
] ]
with open(filename, "wb") as f: with open(filename, "wb") as f:
f.write("""\ f.write(
"""\
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
predefined! { predefined! {
""") """
)
for name in names: for name in names:
f.write(' "%s",\n' % name) f.write(' "%s",\n' % name)
f.write('}\n') f.write("}\n")
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -10,21 +10,33 @@ import sys
from io import BytesIO from io import BytesIO
GECKO_DIR = os.path.dirname(__file__.replace('\\', '/')) GECKO_DIR = os.path.dirname(__file__.replace("\\", "/"))
sys.path.insert(0, os.path.join(os.path.dirname(GECKO_DIR), "properties")) sys.path.insert(0, os.path.join(os.path.dirname(GECKO_DIR), "properties"))
import build import build
# Matches lines like `GK_ATOM(foo, "foo", 0x12345678, true, nsStaticAtom, PseudoElementAtom)`. # Matches lines like `GK_ATOM(foo, "foo", 0x12345678, true, nsStaticAtom, PseudoElementAtom)`.
PATTERN = re.compile('^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*(0x[0-9a-f]+),\s*[^,]*,\s*([^,]*),\s*([^)]*)\)', PATTERN = re.compile(
re.MULTILINE) '^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*(0x[0-9a-f]+),\s*[^,]*,\s*([^,]*),\s*([^)]*)\)',
re.MULTILINE,
)
FILE = "include/nsGkAtomList.h" FILE = "include/nsGkAtomList.h"
def map_atom(ident): def map_atom(ident):
if ident in {"box", "loop", "match", "mod", "ref", if ident in {
"self", "type", "use", "where", "in"}: "box",
"loop",
"match",
"mod",
"ref",
"self",
"type",
"use",
"where",
"in",
}:
return ident + "_" return ident + "_"
return ident return ident
@ -42,7 +54,11 @@ class Atom:
# or "InheritingAnonBox". # or "InheritingAnonBox".
self.atom_type = atom_type self.atom_type = atom_type
if self.is_pseudo_element() or self.is_anon_box() or self.is_tree_pseudo_element(): if (
self.is_pseudo_element()
or self.is_anon_box()
or self.is_tree_pseudo_element()
):
self.pseudo_ident = (ident.split("_", 1))[1] self.pseudo_ident = (ident.split("_", 1))[1]
if self.is_anon_box(): if self.is_anon_box():
@ -82,34 +98,42 @@ def collect_atoms(objdir):
with open(path) as f: with open(path) as f:
content = f.read() content = f.read()
for result in PATTERN.finditer(content): for result in PATTERN.finditer(content):
atoms.append(Atom(result.group(1), result.group(2), result.group(3), atoms.append(
result.group(4), result.group(5))) Atom(
result.group(1),
result.group(2),
result.group(3),
result.group(4),
result.group(5),
)
)
return atoms return atoms
class FileAvoidWrite(BytesIO): class FileAvoidWrite(BytesIO):
"""File-like object that buffers output and only writes if content changed.""" """File-like object that buffers output and only writes if content changed."""
def __init__(self, filename): def __init__(self, filename):
BytesIO.__init__(self) BytesIO.__init__(self)
self.name = filename self.name = filename
def write(self, buf): def write(self, buf):
if isinstance(buf, str): if isinstance(buf, str):
buf = buf.encode('utf-8') buf = buf.encode("utf-8")
BytesIO.write(self, buf) BytesIO.write(self, buf)
def close(self): def close(self):
buf = self.getvalue() buf = self.getvalue()
BytesIO.close(self) BytesIO.close(self)
try: try:
with open(self.name, 'rb') as f: with open(self.name, "rb") as f:
old_content = f.read() old_content = f.read()
if old_content == buf: if old_content == buf:
print("{} is not changed, skip".format(self.name)) print("{} is not changed, skip".format(self.name))
return return
except IOError: except IOError:
pass pass
with open(self.name, 'wb') as f: with open(self.name, "wb") as f:
f.write(buf) f.write(buf)
def __enter__(self): def __enter__(self):
@ -120,45 +144,57 @@ class FileAvoidWrite(BytesIO):
self.close() self.close()
PRELUDE = ''' PRELUDE = """
/* This Source Code Form is subject to the terms of the Mozilla Public /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
// Autogenerated file created by components/style/gecko/regen_atoms.py. // Autogenerated file created by components/style/gecko/regen_atoms.py.
// DO NOT EDIT DIRECTLY // DO NOT EDIT DIRECTLY
'''[1:] """[
1:
]
RULE_TEMPLATE = ''' RULE_TEMPLATE = """
("{atom}") => {{{{ ("{atom}") => {{{{
#[allow(unsafe_code)] #[allow(unused_unsafe)] #[allow(unsafe_code)] #[allow(unused_unsafe)]
unsafe {{ $crate::string_cache::Atom::from_index_unchecked({index}) }} unsafe {{ $crate::string_cache::Atom::from_index_unchecked({index}) }}
}}}}; }}}};
'''[1:] """[
1:
]
MACRO_TEMPLATE = ''' MACRO_TEMPLATE = """
/// Returns a static atom by passing the literal string it represents. /// Returns a static atom by passing the literal string it represents.
#[macro_export] #[macro_export]
macro_rules! atom {{ macro_rules! atom {{
{body}\ {body}\
}} }}
''' """
def write_atom_macro(atoms, file_name): def write_atom_macro(atoms, file_name):
with FileAvoidWrite(file_name) as f: with FileAvoidWrite(file_name) as f:
f.write(PRELUDE) f.write(PRELUDE)
macro_rules = [RULE_TEMPLATE.format(atom=atom.value, name=atom.ident, index=i) macro_rules = [
for (i, atom) in enumerate(atoms)] RULE_TEMPLATE.format(atom=atom.value, name=atom.ident, index=i)
f.write(MACRO_TEMPLATE.format(body=''.join(macro_rules))) for (i, atom) in enumerate(atoms)
]
f.write(MACRO_TEMPLATE.format(body="".join(macro_rules)))
def write_pseudo_elements(atoms, target_filename): def write_pseudo_elements(atoms, target_filename):
pseudos = [] pseudos = []
for atom in atoms: for atom in atoms:
if atom.type() == "nsCSSPseudoElementStaticAtom" or atom.type() == "nsCSSAnonBoxPseudoStaticAtom": if (
atom.type() == "nsCSSPseudoElementStaticAtom"
or atom.type() == "nsCSSAnonBoxPseudoStaticAtom"
):
pseudos.append(atom) pseudos.append(atom)
pseudo_definition_template = os.path.join(GECKO_DIR, "pseudo_element_definition.mako.rs") pseudo_definition_template = os.path.join(
GECKO_DIR, "pseudo_element_definition.mako.rs"
)
print("cargo:rerun-if-changed={}".format(pseudo_definition_template)) print("cargo:rerun-if-changed={}".format(pseudo_definition_template))
contents = build.render(pseudo_definition_template, PSEUDOS=pseudos) contents = build.render(pseudo_definition_template, PSEUDOS=pseudos)

View file

@ -7,7 +7,7 @@ import os.path
import re import re
import sys import sys
BASE = os.path.dirname(__file__.replace('\\', '/')) BASE = os.path.dirname(__file__.replace("\\", "/"))
sys.path.insert(0, os.path.join(BASE, "Mako-1.1.2-py2.py3-none-any.whl")) sys.path.insert(0, os.path.join(BASE, "Mako-1.1.2-py2.py3-none-any.whl"))
sys.path.insert(0, BASE) # For importing `data.py` sys.path.insert(0, BASE) # For importing `data.py`
@ -17,7 +17,7 @@ from mako.template import Template
import data import data
RE_PYTHON_ADDR = re.compile(r'<.+? object at 0x[0-9a-fA-F]+>') RE_PYTHON_ADDR = re.compile(r"<.+? object at 0x[0-9a-fA-F]+>")
OUT_DIR = os.environ.get("OUT_DIR", "") OUT_DIR = os.environ.get("OUT_DIR", "")
@ -48,15 +48,20 @@ STYLE_STRUCT_LIST = [
def main(): def main():
usage = ("Usage: %s [ servo-2013 | servo-2020 | gecko ] [ style-crate | geckolib <template> | html ]" % usage = (
sys.argv[0]) "Usage: %s [ servo-2013 | servo-2020 | gecko ] [ style-crate | geckolib <template> | html ]"
% sys.argv[0]
)
if len(sys.argv) < 3: if len(sys.argv) < 3:
abort(usage) abort(usage)
engine = sys.argv[1] engine = sys.argv[1]
output = sys.argv[2] output = sys.argv[2]
if engine not in ["servo-2013", "servo-2020", "gecko"] \ if engine not in ["servo-2013", "servo-2020", "gecko"] or output not in [
or output not in ["style-crate", "geckolib", "html"]: "style-crate",
"geckolib",
"html",
]:
abort(usage) abort(usage)
properties = data.PropertiesData(engine=engine) properties = data.PropertiesData(engine=engine)
@ -103,19 +108,19 @@ def main():
pref_attr = "servo_2020_pref" pref_attr = "servo_2020_pref"
properties_dict = { properties_dict = {
kind: { kind: {
p.name: { p.name: {"pref": getattr(p, pref_attr)}
"pref": getattr(p, pref_attr)
}
for prop in properties_list for prop in properties_list
if prop.enabled_in_content() if prop.enabled_in_content()
for p in [prop] + prop.alias for p in [prop] + prop.alias
} }
for kind, properties_list in [ for kind, properties_list in [
("longhands", properties.longhands), ("longhands", properties.longhands),
("shorthands", properties.shorthands) ("shorthands", properties.shorthands),
] ]
} }
as_html = render(os.path.join(BASE, "properties.html.mako"), properties=properties_dict) as_html = render(
os.path.join(BASE, "properties.html.mako"), properties=properties_dict
)
as_json = json.dumps(properties_dict, indent=4, sort_keys=True) as_json = json.dumps(properties_dict, indent=4, sort_keys=True)
doc_servo = os.path.join(BASE, "..", "..", "..", "target", "doc", "servo") doc_servo = os.path.join(BASE, "..", "..", "..", "target", "doc", "servo")
write(doc_servo, "css-properties.html", as_html) write(doc_servo, "css-properties.html", as_html)
@ -136,14 +141,16 @@ def abort(message):
def render(filename, **context): def render(filename, **context):
try: try:
lookup = TemplateLookup(directories=[BASE], lookup = TemplateLookup(
input_encoding="utf8", directories=[BASE], input_encoding="utf8", strict_undefined=True
strict_undefined=True) )
template = Template(open(filename, "rb").read(), template = Template(
filename=filename, open(filename, "rb").read(),
input_encoding="utf8", filename=filename,
lookup=lookup, input_encoding="utf8",
strict_undefined=True) lookup=lookup,
strict_undefined=True,
)
# Uncomment to debug generated Python code: # Uncomment to debug generated Python code:
# write("/tmp", "mako_%s.py" % os.path.basename(filename), template.code) # write("/tmp", "mako_%s.py" % os.path.basename(filename), template.code)
return template.render(**context) return template.render(**context)
@ -161,7 +168,7 @@ def write(directory, filename, content):
python_addr = RE_PYTHON_ADDR.search(content) python_addr = RE_PYTHON_ADDR.search(content)
if python_addr: if python_addr:
abort("Found \"{}\" in {} ({})".format(python_addr.group(0), filename, full_path)) abort('Found "{}" in {} ({})'.format(python_addr.group(0), filename, full_path))
if __name__ == "__main__": if __name__ == "__main__":

View file

@ -15,10 +15,18 @@ PHYSICAL_AXES = ["x", "y"]
LOGICAL_AXES = ["inline", "block"] LOGICAL_AXES = ["inline", "block"]
# bool is True when logical # bool is True when logical
ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [(side, True) for side in LOGICAL_SIDES] ALL_SIDES = [(side, False) for side in PHYSICAL_SIDES] + [
ALL_SIZES = [(size, False) for size in PHYSICAL_SIZES] + [(size, True) for size in LOGICAL_SIZES] (side, True) for side in LOGICAL_SIDES
ALL_CORNERS = [(corner, False) for corner in PHYSICAL_CORNERS] + [(corner, True) for corner in LOGICAL_CORNERS] ]
ALL_AXES = [(axis, False) for axis in PHYSICAL_AXES] + [(axis, True) for axis in LOGICAL_AXES] ALL_SIZES = [(size, False) for size in PHYSICAL_SIZES] + [
(size, True) for size in LOGICAL_SIZES
]
ALL_CORNERS = [(corner, False) for corner in PHYSICAL_CORNERS] + [
(corner, True) for corner in LOGICAL_CORNERS
]
ALL_AXES = [(axis, False) for axis in PHYSICAL_AXES] + [
(axis, True) for axis in LOGICAL_AXES
]
SYSTEM_FONT_LONGHANDS = """font_family font_size font_style SYSTEM_FONT_LONGHANDS = """font_family font_size font_style
font_variant_caps font_stretch font_kerning font_variant_caps font_stretch font_kerning
@ -50,7 +58,9 @@ def to_snake_case(ident):
def to_camel_case(ident): def to_camel_case(ident):
return re.sub("(^|_|-)([a-z0-9])", lambda m: m.group(2).upper(), ident.strip("_").strip("-")) return re.sub(
"(^|_|-)([a-z0-9])", lambda m: m.group(2).upper(), ident.strip("_").strip("-")
)
def to_camel_case_lower(ident): def to_camel_case_lower(ident):
@ -72,23 +82,32 @@ def parse_aliases(value):
class Keyword(object): class Keyword(object):
def __init__(self, name, values, gecko_constant_prefix=None, def __init__(
gecko_enum_prefix=None, custom_consts=None, self,
extra_gecko_values=None, name,
extra_servo_2013_values=None, values,
extra_servo_2020_values=None, gecko_constant_prefix=None,
gecko_aliases=None, gecko_enum_prefix=None,
servo_2013_aliases=None, custom_consts=None,
servo_2020_aliases=None, extra_gecko_values=None,
gecko_strip_moz_prefix=None, extra_servo_2013_values=None,
gecko_inexhaustive=None): extra_servo_2020_values=None,
gecko_aliases=None,
servo_2013_aliases=None,
servo_2020_aliases=None,
gecko_strip_moz_prefix=None,
gecko_inexhaustive=None,
):
self.name = name self.name = name
self.values = values.split() self.values = values.split()
if gecko_constant_prefix and gecko_enum_prefix: if gecko_constant_prefix and gecko_enum_prefix:
raise TypeError("Only one of gecko_constant_prefix and gecko_enum_prefix " raise TypeError(
"can be specified") "Only one of gecko_constant_prefix and gecko_enum_prefix "
self.gecko_constant_prefix = gecko_constant_prefix or \ "can be specified"
"NS_STYLE_" + self.name.upper().replace("-", "_") )
self.gecko_constant_prefix = (
gecko_constant_prefix or "NS_STYLE_" + self.name.upper().replace("-", "_")
)
self.gecko_enum_prefix = gecko_enum_prefix self.gecko_enum_prefix = gecko_enum_prefix
self.extra_gecko_values = (extra_gecko_values or "").split() self.extra_gecko_values = (extra_gecko_values or "").split()
self.extra_servo_2013_values = (extra_servo_2013_values or "").split() self.extra_servo_2013_values = (extra_servo_2013_values or "").split()
@ -97,8 +116,9 @@ class Keyword(object):
self.servo_2013_aliases = parse_aliases(servo_2013_aliases or "") self.servo_2013_aliases = parse_aliases(servo_2013_aliases or "")
self.servo_2020_aliases = parse_aliases(servo_2020_aliases or "") self.servo_2020_aliases = parse_aliases(servo_2020_aliases or "")
self.consts_map = {} if custom_consts is None else custom_consts self.consts_map = {} if custom_consts is None else custom_consts
self.gecko_strip_moz_prefix = True \ self.gecko_strip_moz_prefix = (
if gecko_strip_moz_prefix is None else gecko_strip_moz_prefix True if gecko_strip_moz_prefix is None else gecko_strip_moz_prefix
)
self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None) self.gecko_inexhaustive = gecko_inexhaustive or (gecko_enum_prefix is None)
def values_for(self, engine): def values_for(self, engine):
@ -122,11 +142,14 @@ class Keyword(object):
raise Exception("Bad engine: " + engine) raise Exception("Bad engine: " + engine)
def gecko_constant(self, value): def gecko_constant(self, value):
moz_stripped = (value.replace("-moz-", '') moz_stripped = (
if self.gecko_strip_moz_prefix else value.replace("-moz-", 'moz-')) value.replace("-moz-", "")
if self.gecko_strip_moz_prefix
else value.replace("-moz-", "moz-")
)
mapped = self.consts_map.get(value) mapped = self.consts_map.get(value)
if self.gecko_enum_prefix: if self.gecko_enum_prefix:
parts = moz_stripped.replace('-', '_').split('_') parts = moz_stripped.replace("-", "_").split("_")
parts = mapped if mapped else [p.title() for p in parts] parts = mapped if mapped else [p.title() for p in parts]
return self.gecko_enum_prefix + "::" + "".join(parts) return self.gecko_enum_prefix + "::" + "".join(parts)
else: else:
@ -146,13 +169,19 @@ class Keyword(object):
if self.gecko_enum_prefix is None: if self.gecko_enum_prefix is None:
return cast_type.upper() + "_" + self.gecko_constant(value) return cast_type.upper() + "_" + self.gecko_constant(value)
else: else:
return cast_type.upper() + "_" + self.gecko_constant(value).upper().replace("::", "_") return (
cast_type.upper()
+ "_"
+ self.gecko_constant(value).upper().replace("::", "_")
)
def arg_to_bool(arg): def arg_to_bool(arg):
if isinstance(arg, bool): if isinstance(arg, bool):
return arg return arg
assert arg in ["True", "False"], "Unexpected value for boolean arguement: " + repr(arg) assert arg in ["True", "False"], "Unexpected value for boolean arguement: " + repr(
arg
)
return arg == "True" return arg == "True"
@ -170,20 +199,36 @@ def to_phys(name, logical, physical):
class Longhand(object): class Longhand(object):
def __init__(self, style_struct, name, spec=None, animation_value_type=None, keyword=None, def __init__(
predefined_type=None, self,
servo_2013_pref=None, style_struct,
servo_2020_pref=None, name,
gecko_pref=None, spec=None,
enabled_in="content", need_index=False, animation_value_type=None,
gecko_ffi_name=None, keyword=None,
has_effect_on_gecko_scrollbars=None, predefined_type=None,
allowed_in_keyframe_block=True, cast_type='u8', servo_2013_pref=None,
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False, servo_2020_pref=None,
flags=None, allowed_in_page_rule=False, allow_quirks="No", gecko_pref=None,
ignored_when_colors_disabled=False, enabled_in="content",
simple_vector_bindings=False, need_index=False,
vector=False, servo_restyle_damage="repaint"): gecko_ffi_name=None,
has_effect_on_gecko_scrollbars=None,
allowed_in_keyframe_block=True,
cast_type="u8",
logical=False,
logical_group=None,
alias=None,
extra_prefixes=None,
boxed=False,
flags=None,
allowed_in_page_rule=False,
allow_quirks="No",
ignored_when_colors_disabled=False,
simple_vector_bindings=False,
vector=False,
servo_restyle_damage="repaint",
):
self.name = name self.name = name
if not spec: if not spec:
raise TypeError("Spec should be specified for %s" % name) raise TypeError("Spec should be specified for %s" % name)
@ -235,20 +280,26 @@ class Longhand(object):
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property # > The <declaration-list> inside of <keyframe-block> accepts any CSS property
# > except those defined in this specification, # > except those defined in this specification,
# > but does accept the `animation-play-state` property and interprets it specially. # > but does accept the `animation-play-state` property and interprets it specially.
self.allowed_in_keyframe_block = allowed_in_keyframe_block \ self.allowed_in_keyframe_block = (
and allowed_in_keyframe_block != "False" allowed_in_keyframe_block and allowed_in_keyframe_block != "False"
)
# This is done like this since just a plain bool argument seemed like # This is done like this since just a plain bool argument seemed like
# really random. # really random.
if animation_value_type is None: if animation_value_type is None:
raise TypeError("animation_value_type should be specified for (" + name + ")") raise TypeError(
"animation_value_type should be specified for (" + name + ")"
)
self.animation_value_type = animation_value_type self.animation_value_type = animation_value_type
self.animatable = animation_value_type != "none" self.animatable = animation_value_type != "none"
self.transitionable = animation_value_type != "none" \ self.transitionable = (
and animation_value_type != "discrete" animation_value_type != "none" and animation_value_type != "discrete"
self.is_animatable_with_computed_value = animation_value_type == "ComputedValue" \ )
self.is_animatable_with_computed_value = (
animation_value_type == "ComputedValue"
or animation_value_type == "discrete" or animation_value_type == "discrete"
)
# See compute_damage for the various values this can take # See compute_damage for the various values this can take
self.servo_restyle_damage = servo_restyle_damage self.servo_restyle_damage = servo_restyle_damage
@ -263,17 +314,25 @@ class Longhand(object):
if not self.logical: if not self.logical:
return [] return []
candidates = [s for s in LOGICAL_SIDES + LOGICAL_SIZES + LOGICAL_CORNERS candidates = [
if s in self.name] + [s for s in LOGICAL_AXES if self.name.endswith(s)] s for s in LOGICAL_SIDES + LOGICAL_SIZES + LOGICAL_CORNERS if s in self.name
assert(len(candidates) == 1) ] + [s for s in LOGICAL_AXES if self.name.endswith(s)]
assert len(candidates) == 1
logical_side = candidates[0] logical_side = candidates[0]
physical = PHYSICAL_SIDES if logical_side in LOGICAL_SIDES \ physical = (
else PHYSICAL_SIZES if logical_side in LOGICAL_SIZES \ PHYSICAL_SIDES
else PHYSICAL_AXES if logical_side in LOGICAL_AXES \ if logical_side in LOGICAL_SIDES
else PHYSICAL_SIZES
if logical_side in LOGICAL_SIZES
else PHYSICAL_AXES
if logical_side in LOGICAL_AXES
else LOGICAL_CORNERS else LOGICAL_CORNERS
return [data.longhands_by_name[to_phys(self.name, logical_side, physical_side)] )
for physical_side in physical] return [
data.longhands_by_name[to_phys(self.name, logical_side, physical_side)]
for physical_side in physical
]
def experimental(self, engine): def experimental(self, engine):
if engine == "gecko": if engine == "gecko":
@ -299,9 +358,15 @@ class Longhand(object):
if engine == "gecko": if engine == "gecko":
return self.gecko_pref and self.gecko_pref != shorthand.gecko_pref return self.gecko_pref and self.gecko_pref != shorthand.gecko_pref
elif engine == "servo-2013": elif engine == "servo-2013":
return self.servo_2013_pref and self.servo_2013_pref != shorthand.servo_2013_pref return (
self.servo_2013_pref
and self.servo_2013_pref != shorthand.servo_2013_pref
)
elif engine == "servo-2020": elif engine == "servo-2020":
return self.servo_2020_pref and self.servo_2020_pref != shorthand.servo_2020_pref return (
self.servo_2020_pref
and self.servo_2020_pref != shorthand.servo_2020_pref
)
else: else:
raise Exception("Bad engine: " + engine) raise Exception("Bad engine: " + engine)
@ -412,13 +477,21 @@ class Longhand(object):
class Shorthand(object): class Shorthand(object):
def __init__(self, name, sub_properties, spec=None, def __init__(
servo_2013_pref=None, self,
servo_2020_pref=None, name,
gecko_pref=None, sub_properties,
enabled_in="content", spec=None,
allowed_in_keyframe_block=True, alias=None, extra_prefixes=None, servo_2013_pref=None,
allowed_in_page_rule=False, flags=None): servo_2020_pref=None,
gecko_pref=None,
enabled_in="content",
allowed_in_keyframe_block=True,
alias=None,
extra_prefixes=None,
allowed_in_page_rule=False,
flags=None,
):
self.name = name self.name = name
if not spec: if not spec:
raise TypeError("Spec should be specified for %s" % name) raise TypeError("Spec should be specified for %s" % name)
@ -440,8 +513,9 @@ class Shorthand(object):
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property # > The <declaration-list> inside of <keyframe-block> accepts any CSS property
# > except those defined in this specification, # > except those defined in this specification,
# > but does accept the `animation-play-state` property and interprets it specially. # > but does accept the `animation-play-state` property and interprets it specially.
self.allowed_in_keyframe_block = allowed_in_keyframe_block \ self.allowed_in_keyframe_block = (
and allowed_in_keyframe_block != "False" allowed_in_keyframe_block and allowed_in_keyframe_block != "False"
)
def get_animatable(self): def get_animatable(self):
for sub in self.sub_properties: for sub in self.sub_properties:
@ -580,7 +654,9 @@ class PropertiesData(object):
self.shorthands = [] self.shorthands = []
self.shorthands_by_name = {} self.shorthands_by_name = {}
self.shorthand_aliases = [] self.shorthand_aliases = []
self.counted_unknown_properties = [CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES] self.counted_unknown_properties = [
CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES
]
def new_style_struct(self, *args, **kwargs): def new_style_struct(self, *args, **kwargs):
style_struct = StyleStruct(*args, **kwargs) style_struct = StyleStruct(*args, **kwargs)
@ -595,7 +671,7 @@ class PropertiesData(object):
# See servo/servo#14941. # See servo/servo#14941.
if self.engine == "gecko": if self.engine == "gecko":
for (prefix, pref) in property.extra_prefixes: for (prefix, pref) in property.extra_prefixes:
property.alias.append(('-%s-%s' % (prefix, property.name), pref)) property.alias.append(("-%s-%s" % (prefix, property.name), pref))
def declare_longhand(self, name, engines=None, **kwargs): def declare_longhand(self, name, engines=None, **kwargs):
engines = engines.split() engines = engines.split()
@ -610,7 +686,9 @@ class PropertiesData(object):
self.longhands.append(longhand) self.longhands.append(longhand)
self.longhands_by_name[name] = longhand self.longhands_by_name[name] = longhand
if longhand.logical_group: if longhand.logical_group:
self.longhands_by_logical_group.setdefault(longhand.logical_group, []).append(longhand) self.longhands_by_logical_group.setdefault(
longhand.logical_group, []
).append(longhand)
return longhand return longhand
@ -686,31 +764,31 @@ class PropertyRestrictions:
# https://drafts.csswg.org/css-pseudo/#first-letter-styling # https://drafts.csswg.org/css-pseudo/#first-letter-styling
@staticmethod @staticmethod
def first_letter(data): def first_letter(data):
props = set([ props = set(
"color", [
"opacity", "color",
"float", "opacity",
"initial-letter", "float",
"initial-letter",
# Kinda like css-fonts? # Kinda like css-fonts?
"-moz-osx-font-smoothing", "-moz-osx-font-smoothing",
# Kinda like css-text?
# Kinda like css-text? "-webkit-text-stroke-width",
"-webkit-text-stroke-width", "-webkit-text-fill-color",
"-webkit-text-fill-color", "-webkit-text-stroke-color",
"-webkit-text-stroke-color", "vertical-align",
"vertical-align", "line-height",
"line-height", # Kinda like css-backgrounds?
"background-blend-mode",
# Kinda like css-backgrounds? ]
"background-blend-mode", + PropertyRestrictions.shorthand(data, "padding")
] + PropertyRestrictions.shorthand(data, "padding") + PropertyRestrictions.shorthand(data, "margin")
+ PropertyRestrictions.shorthand(data, "margin") + PropertyRestrictions.spec(data, "css-fonts")
+ PropertyRestrictions.spec(data, "css-fonts") + PropertyRestrictions.spec(data, "css-backgrounds")
+ PropertyRestrictions.spec(data, "css-backgrounds") + PropertyRestrictions.spec(data, "css-text")
+ PropertyRestrictions.spec(data, "css-text") + PropertyRestrictions.spec(data, "css-shapes")
+ PropertyRestrictions.spec(data, "css-shapes") + PropertyRestrictions.spec(data, "css-text-decor")
+ PropertyRestrictions.spec(data, "css-text-decor")) )
_add_logical_props(data, props) _add_logical_props(data, props)
@ -720,27 +798,27 @@ class PropertyRestrictions:
# https://drafts.csswg.org/css-pseudo/#first-line-styling # https://drafts.csswg.org/css-pseudo/#first-line-styling
@staticmethod @staticmethod
def first_line(data): def first_line(data):
props = set([ props = set(
# Per spec. [
"color", # Per spec.
"opacity", "color",
"opacity",
# Kinda like css-fonts? # Kinda like css-fonts?
"-moz-osx-font-smoothing", "-moz-osx-font-smoothing",
# Kinda like css-text?
# Kinda like css-text? "-webkit-text-stroke-width",
"-webkit-text-stroke-width", "-webkit-text-fill-color",
"-webkit-text-fill-color", "-webkit-text-stroke-color",
"-webkit-text-stroke-color", "vertical-align",
"vertical-align", "line-height",
"line-height", # Kinda like css-backgrounds?
"background-blend-mode",
# Kinda like css-backgrounds? ]
"background-blend-mode", + PropertyRestrictions.spec(data, "css-fonts")
] + PropertyRestrictions.spec(data, "css-fonts") + PropertyRestrictions.spec(data, "css-backgrounds")
+ PropertyRestrictions.spec(data, "css-backgrounds") + PropertyRestrictions.spec(data, "css-text")
+ PropertyRestrictions.spec(data, "css-text") + PropertyRestrictions.spec(data, "css-text-decor")
+ PropertyRestrictions.spec(data, "css-text-decor")) )
# These are probably Gecko bugs and should be supported per spec. # These are probably Gecko bugs and should be supported per spec.
for prop in PropertyRestrictions.shorthand(data, "border"): for prop in PropertyRestrictions.shorthand(data, "border"):
@ -770,42 +848,46 @@ class PropertyRestrictions:
# https://drafts.csswg.org/css-pseudo/#marker-pseudo # https://drafts.csswg.org/css-pseudo/#marker-pseudo
@staticmethod @staticmethod
def marker(data): def marker(data):
return set([ return set(
"color", [
"text-combine-upright", "color",
"text-transform", "text-combine-upright",
"unicode-bidi", "text-transform",
"direction", "unicode-bidi",
"content", "direction",
"-moz-osx-font-smoothing", "content",
] + PropertyRestrictions.spec(data, "css-fonts") "-moz-osx-font-smoothing",
+ PropertyRestrictions.spec(data, "css-animations") ]
+ PropertyRestrictions.spec(data, "css-transitions")) + PropertyRestrictions.spec(data, "css-fonts")
+ PropertyRestrictions.spec(data, "css-animations")
+ PropertyRestrictions.spec(data, "css-transitions")
)
# https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element # https://www.w3.org/TR/webvtt1/#the-cue-pseudo-element
@staticmethod @staticmethod
def cue(data): def cue(data):
return set([ return set(
"color", [
"opacity", "color",
"visibility", "opacity",
"text-shadow", "visibility",
"white-space", "text-shadow",
"text-combine-upright", "white-space",
"ruby-position", "text-combine-upright",
"ruby-position",
# XXX Should these really apply to cue? # XXX Should these really apply to cue?
"font-synthesis", "font-synthesis",
"-moz-osx-font-smoothing", "-moz-osx-font-smoothing",
# FIXME(emilio): background-blend-mode should be part of the
# FIXME(emilio): background-blend-mode should be part of the # background shorthand, and get reset, per
# background shorthand, and get reset, per # https://drafts.fxtf.org/compositing/#background-blend-mode
# https://drafts.fxtf.org/compositing/#background-blend-mode "background-blend-mode",
"background-blend-mode", ]
] + PropertyRestrictions.shorthand(data, "text-decoration") + PropertyRestrictions.shorthand(data, "text-decoration")
+ PropertyRestrictions.shorthand(data, "background") + PropertyRestrictions.shorthand(data, "background")
+ PropertyRestrictions.shorthand(data, "outline") + PropertyRestrictions.shorthand(data, "outline")
+ PropertyRestrictions.shorthand(data, "font")) + PropertyRestrictions.shorthand(data, "font")
)
class CountedUnknownProperty: class CountedUnknownProperty: