Skip to content

Commit a6200cd

Browse files
committed
Merge branches 'integrate-tests' and 'use-strict-mypy'
2 parents 925b18c + a4d9bfa commit a6200cd

4 files changed

Lines changed: 24 additions & 21 deletions

File tree

src/csspring/syntax/parsing.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from itertools import chain
2121

2222
from collections.abc import Iterable, Iterator, MutableSequence, Sequence
23-
from typing import cast, Protocol, runtime_checkable, TypeAlias, Union
23+
from typing import Any, cast, Protocol, runtime_checkable, TypeAlias, Union
2424

2525
class InvalidRuleError(ParseError):
2626
"""See http://drafts.csswg.org/css-syntax/#invalid-rule-error."""
@@ -181,7 +181,7 @@ def contents(self) -> Contents:
181181
def rules(self) -> Sequence[Rule]:
182182
"""The rules (_only_ those directly nested, i.e. "top-level") of the style sheet."""
183183
return self.contents.rules
184-
def __init__(self, *args, location: Location | None = None, **kwargs):
184+
def __init__(self, *args: Any, location: Location | None = None, **kwargs: Any):
185185
"""Initialize the style sheet.
186186
187187
The stylesheet starts empty, only storing specified location."""
@@ -496,7 +496,9 @@ def consume_value_of_unicode_range_descriptor(string: str) -> Sequence[Component
496496
"""Implements http://drafts.csswg.org/css-syntax/#consume-unicode-range-value."""
497497
return consume_list_of_component_values(TokenStream(tokenize(tokenizing.normalize_input(string), unicode_ranges_allowed=True)), to=[])
498498

499-
def normalize_input(input: Input | Iterable[Token] | Iterable[str]) -> Input:
499+
NormalizeInput = Input | Iterable[Token] | Iterable[str]
500+
501+
def normalize_input(input: NormalizeInput) -> Input:
500502
"""Wrap input (if needed) into a "canonical" kind of parser input object which the latter can use directly.
501503
502504
Implements http://drafts.csswg.org/css-syntax/#normalize-into-a-token-stream, with some following caveats.
@@ -508,7 +510,7 @@ def normalize_input(input: Input | Iterable[Token] | Iterable[str]) -> Input:
508510
if isinstance(input, Input):
509511
return input
510512
try:
511-
input = iter(cast(Iterable, input))
513+
input = iter(cast(Iterable[Any], input))
512514
except TypeError:
513515
assert not isinstance(input, Iterable) # Communicate to the type checker that `input` is not iterable
514516
else:
@@ -522,7 +524,7 @@ def normalize_input(input: Input | Iterable[Token] | Iterable[str]) -> Input:
522524
return TokenStream(input)
523525
return TokenStream(tokenize(tokenizing.normalize_input(input)))
524526

525-
def parse_stylesheet(input, *, location: StyleSheet.Location | None = None, **kwargs) -> StyleSheet:
527+
def parse_stylesheet(input: NormalizeInput, *, location: StyleSheet.Location | None = None, **kwargs: Any) -> StyleSheet:
526528
"""Parse a stylesheet.
527529
528530
Attempts to implement http://drafts.csswg.org/css-syntax/#parse-stylesheet with the following exception(s):
@@ -545,7 +547,7 @@ def source(element: Product | Token) -> str:
545547
"""
546548
return element.source if hasattr(element, 'source') else ''.join(source(item) for item in element)
547549

548-
def tokens(product: Iterable | Token) -> Iterator[Token]:
550+
def tokens(product: Product | Token) -> Iterator[Token]:
549551
"""
550552
Yield every token contained in a parser production.
551553

src/csspring/syntax/preprocessing.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from ..utils import CP, is_surrogate_code_point
44

55
from collections.abc import Callable, Iterator
6+
from typing import Any
67

78
class FilteredCodePoint(CP):
89
"""Class of code point derivatives that reference the original (unfiltered) code point sequence.
@@ -12,7 +13,7 @@ class FilteredCodePoint(CP):
1213
Said representation facilitates recovery of original text from a sequence of filtered code points, and by indirection, from token(s).
1314
"""
1415
source: CP
15-
def __new__(cls, *args, source: CP, **kwargs):
16+
def __new__(cls, *args: Any, source: CP, **kwargs: Any) -> 'FilteredCodePoint':
1617
"""Most native primitive types, including `str`, cannot be effectively extended in traditional manner -- by invoking `super` in the subclass constructor -- `__new__` must be overriden instead to yield the object of appropriate type because the super-class does not feature a constructor and objects of the class are constructed with e.g. `str.__new__`.
1718
"""
1819
obj = super().__new__(cls, *args, **kwargs)

src/csspring/utils.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def intersperse(*items: T, separator: T) -> Iterable[T]:
3434
@runtime_checkable
3535
class Reader(Protocol[T_co]):
3636
"""An interface to readable/readers, to assist type checking for the most part."""
37-
def read(self, size: int = -1, /) -> Sequence[T_co]:
37+
def read(self, size: int | None = -1, /) -> Sequence[T_co]:
3838
"""See Python's own `IOBase.read` in the `io` module."""
3939
raise NotImplementedError
4040

@@ -78,17 +78,17 @@ class BufferedPeekingReader(PeekingUnreadingReader[T]):
7878
def __init__(self, source: Reader[T]):
7979
self._source = source
8080
self._buffer = []
81-
def peek(self, size: int, /) -> Sequence[T]:
82-
assert size >= 0 # Reading with negative sizes is defined by `read` defined by Python, but not implemented yet for this class (that would call for a more elaborate implementation, while the reader is never used with negative values)
81+
def peek(self, size: int | None, /) -> Sequence[T]:
82+
assert size is not None and size >= 0 # Reading with negative sizes is defined by `read` defined by Python, but not implemented yet for this class (that would call for a more elaborate implementation, while the reader is never used with negative values)
8383
r = size - len(self._buffer)
8484
if r > 0:
8585
self._buffer += [*self._source.read(r)]
8686
return self._buffer[:size]
87-
def read(self, size: int = -1, /) -> Sequence[T]:
87+
def read(self, size: int | None = -1, /) -> Sequence[T]:
8888
elements = self.peek(size)
8989
del self._buffer[:size]
9090
return elements
91-
def unread(self, items) -> None:
91+
def unread(self, items: Iterable[T]) -> None:
9292
self._buffer[:0] = items
9393

9494
def public_attrs(obj: object) -> Iterable[str]:
@@ -112,7 +112,7 @@ def qualified_type_name(cls: type) -> str:
112112
"""A stable (no reliance on "dunder" property) means to obtain the qualified name for a type."""
113113
return cls.__qualname__
114114

115-
def setattrs(obj: object, **kwargs) -> None:
115+
def setattrs(obj: object, **kwargs: Any) -> None:
116116
"""Set multiple attributes on an object."""
117117
for attr in kwargs.items():
118118
setattr(obj, *attr)
@@ -127,7 +127,7 @@ class IteratorReader(Reader[T]):
127127
_source: Iterator[T]
128128
def __init__(self, source: Iterator[T]):
129129
self._source = source
130-
def read(self, /, size=-1) -> Sequence[T]:
130+
def read(self, /, size: int | None = -1) -> Sequence[T]:
131131
result: list[T] = []
132132
while len(result) != size:
133133
try:

src/csspring/values.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from collections.abc import Iterable, Mapping
99
from functools import singledispatchmethod
1010
import re
11-
from typing import cast
11+
from typing import Any, cast
1212

1313
class Production:
1414
"""An [abstract] class of CSS grammar elements.
@@ -22,7 +22,7 @@ class Production:
2222
Note that a production is not the same as a [parse] product -- the former is an element of some language grammar, while the latter is a result of parsing a sequence of tokens in accordance with a grammar production, in effect expressing one single element from the set of all permutations a production would permit, corresponding to consumed part of the sequence.
2323
"""
2424
name: str
25-
def __set_name__(self, _, name):
25+
def __set_name__(self, _: Any, name: str) -> None:
2626
assert not hasattr(self, "name") or self.name == name # Given the usage context, we don't want to support re-setting the name, not with a different value at least
2727
self.name = name
2828

@@ -111,8 +111,8 @@ class TokenProduction(Production):
111111
"""Class of productions that express a token, optionally one with a matching set of attributes.
112112
"""
113113
type: type[Token]
114-
attributes: Mapping
115-
def __init__(self, type: builtins.type[Token], **attributes):
114+
attributes: Mapping[str, Any]
115+
def __init__(self, type: builtins.type[Token], **attributes: Any):
116116
"""
117117
:param type: The type of token this production will express
118118
:param attributes: Mapping of presumably token attribute values by name, to use for expressing the set of attributes on the token this production will express
@@ -136,7 +136,7 @@ def __init__(self, element: Production, min: int = 1, max: int | None = None):
136136
class Formatter:
137137
"""Class of objects that offer procedures for serializing productions into streams of text formatted per the [value definition syntax](http://drafts.csswg.org/css-values-4/#value-defs)."""
138138
grouping_strings = ('[ ', ' ]') # The kind of grouping symbol to use when a production expression must be surrounded with a pair of brace-like grouping symbols, in its serialized form
139-
def grouping_mode(self, production: Production):
139+
def grouping_mode(self, production: Production) -> bool:
140140
"""Determine whether a given production shall require an explicit pair of grouping symbols when featured as an _operand_ (e.g. in binary/unary operation context).
141141
:returns: `True` if the expression of `production` serialized with this formatter, should feature explicit grouping symbols wrapping it, `False` otherwise
142142
"""
@@ -145,7 +145,7 @@ def grouping_mode(self, production: Production):
145145
case ReferenceProduction() | TokenProduction(): return False
146146
case _:
147147
raise ValueError
148-
def combined(self, productions: Iterable, combinator: str) -> Iterable[str]:
148+
def combined(self, productions: Iterable[Production], combinator: str) -> Iterable[str]:
149149
it = (self.format(production) for production in productions)
150150
yield from next(it)
151151
for item in it:
@@ -202,7 +202,7 @@ def name(self, production: Production) -> str:
202202
:raises AttributeError: if the production does not have a name
203203
"""
204204
return production.name.replace('_', '-')
205-
def operand(self, production) -> Iterable[str]:
205+
def operand(self, production: Production) -> Iterable[str]:
206206
group_start, group_end = self.grouping_strings if self.grouping_mode(production) else ('', '')
207207
yield group_start
208208
yield from self.format(production)

0 commit comments

Comments
 (0)