Skip to content

Add font shorthand property#3631

Merged
freakboy3742 merged 2 commits into
beeware:mainfrom
HalfWhitt:font_shorthand
Jul 28, 2025
Merged

Add font shorthand property#3631
freakboy3742 merged 2 commits into
beeware:mainfrom
HalfWhitt:font_shorthand

Conversation

@HalfWhitt
Copy link
Copy Markdown
Member

Adds the font shorthand property to Pack, and the composite_property class in Travertino that implements it.

The composite_property implementation is largely verbatim from the old PR on Travertino. The only significant change is that I've taken out any facility for string-parsing, which I wanted to ask about.

I have a reasonably competent implementation already for how to parse thefont property from a string, but it definitely doesn't handle all the potential edge cases around mixed quotation marks and escaped characters and whatnot. I'd like to accommodate the feature, either in this PR or a subsequent one, because being able to specify font all as one string would certainly be convenient, but string-parsing is complicated. Presumably, at some point, Colosseum will need to be able to parse entire CSS files, at which point I imagine a dependency on something like pyparsing would probably be justified, but I'm not sure if it is for just this one property. So I'd appreciate some input on these potential avenues:

  • Go with a "good enough" solution now, which covers "reasonable" use cases, and could be improved or replaced later
  • Wait to put out the feature until I've written a robust and tested parser
  • Add a parsing library to help handle this

Even in the absence of string-parsing, though, assigning with a tuple works perfectly well.

P.S. Also adds .ruff_cache/ to .gitignore.

PR Checklist:

  • All new features have been tested
  • All new features have been documented
  • I have read the CONTRIBUTING.md file
  • I will abide by the code of conduct

@HalfWhitt HalfWhitt requested a review from freakboy3742 July 10, 2025 02:44
VALUE2, VALUE3, VALUE4, initial=VALUE2
)

composite_no_optional: tuple[str] = composite_property(
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This incorrect type hint is basically a handwave. I can't imagine it's worth actually laying out all the various possible signatures for a test class, is it, as long there's some hint to trigger dataclass?

I notice I also didn't do the various tuple type hints right on the directional property and its aliases...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - exhaustive hinting here will be exhausting.

Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great - and thanks to all the refactoring that precedes it, the implementation is incredibly straightforward. Nice work.

A couple of really cosmetic things flagged inline, but otherwise, this looks almost ready to land.

Comment thread core/tests/style/pack/test_apply.py Outdated
root = ExampleNode(
"app",
style=Pack(
@pytest.mark.parametrize("use_shorthand", [True, False])
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a stylistic thing - my preference here would be to factor out the arguments to Pack as the parameterised argument - that way, we're testing multiple ways to construct the same thing, rather than two independent constructors that happen to have the same result.

Comment on lines +95 to +96
f"Composite property '{self.name}' must be set with at least "
f"{self.min_num} and no more than {self.max_num} values."
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an error, this is 100% correct... but not especially helpful to an end user. It might be more helpful to elaborate the specific attributes that must be provided (.e.g, "Composite property 'font' must provide a value for 'font_size' and 'font_family', and may also provide a value for 'font_style', 'font_variant' and 'font_weight'.)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh right, people are actually going to use this, aren't they?

Testing this out also alerted me to something else I'd missed — we need to make sure whatever's being assigned is a non-string sequence.

VALUE2, VALUE3, VALUE4, initial=VALUE2
)

composite_no_optional: tuple[str] = composite_property(
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree - exhaustive hinting here will be exhausting.

Comment on lines +62 to +64
assert_composite(style, (None, VALUE2, VALUE2, VALUE3))
assert "different_values_prop" not in style
assert "explicit_none" not in style
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test looks completely correct, but could do with some explanatory notes so it's clear what it's testing.

@HalfWhitt
Copy link
Copy Markdown
Member Author

HalfWhitt commented Jul 28, 2025

Do you have any thoughts on potential future string-parsing?

@HalfWhitt HalfWhitt requested a review from freakboy3742 July 28, 2025 04:07
Copy link
Copy Markdown
Member

@freakboy3742 freakboy3742 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good (and good catch on the 'string as sequence' thing).

As for potential future string parsing... I'm not sure exactly what input you're looking for there. Yes, I think string parsing would be desirable, if only in the context of "we should be able to provide stylesheets as external files"; to that end, anything that currently requires a tuple as input should be possible to provide as a string that will be parsed into a tuple.

However, I can't say I've given the topic much thought beyond that.

@freakboy3742 freakboy3742 merged commit 949afa3 into beeware:main Jul 28, 2025
52 checks passed
@HalfWhitt
Copy link
Copy Markdown
Member Author

Well, I went into it up in the initial post, but basically I'm thinking about the tradeoffs of writing our own parser vs. using some variety of grammar-defining library. Dealing with things like nested and escaped quotes (and single and double quotes) gets hairy pretty fast.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants