Skip to content

Commit

Permalink
Use ruff instead of flake8 and isort
Browse files Browse the repository at this point in the history
  • Loading branch information
liZe committed Mar 16, 2024
1 parent 3a49fd0 commit 1c90cf9
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 78 deletions.
4 changes: 1 addition & 3 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,4 @@ jobs:
- name: Launch tests
run: python -m pytest
- name: Check coding style
run: python -m flake8 --exclude tests/css-parsing-tests
- name: Check imports order
run: python -m isort . --check --diff
run: python -m ruff check
14 changes: 9 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ Donation = 'https://opencollective.com/courtbouillon'

[project.optional-dependencies]
doc = ['sphinx', 'sphinx_rtd_theme']
test = ['pytest', 'isort', 'flake8']
test = ['pytest', 'ruff']

[tool.flit.sdist]
exclude = ['.*']
Expand All @@ -56,7 +56,11 @@ include = ['tests/*', 'tinycss2/*']
exclude_lines = ['pragma: no cover', 'def __repr__', 'raise NotImplementedError']
omit = ['.*']

[tool.isort]
default_section = 'FIRSTPARTY'
multi_line_output = 4
extend_skip = ['tests/css-parsing-tests']
[tool.ruff]
extend-exclude = ['tests/css-parsing-tests']

[tool.ruff.lint]
select = ['E', 'F', 'I']

[tool.ruff.lint.isort]
known-first-party = ['tinycss2']
77 changes: 40 additions & 37 deletions tests/test_tinycss2.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@
from pathlib import Path

import pytest
from webencodings import Encoding, lookup

from tinycss2 import (
parse_component_value_list, parse_declaration_list,
parse_one_component_value, parse_one_declaration, parse_one_rule,
parse_rule_list, parse_stylesheet, parse_stylesheet_bytes, serialize)
from tinycss2.ast import (
AtKeywordToken, AtRule, Comment, CurlyBracketsBlock, Declaration,
DimensionToken, FunctionBlock, HashToken, IdentToken, LiteralToken,
NumberToken, ParenthesesBlock, ParseError, PercentageToken, QualifiedRule,
SquareBracketsBlock, StringToken, UnicodeRangeToken, URLToken,
WhitespaceToken)
ast,
parse_component_value_list,
parse_declaration_list,
parse_one_component_value,
parse_one_declaration,
parse_one_rule,
parse_rule_list,
parse_stylesheet,
parse_stylesheet_bytes,
serialize,
)
from tinycss2.color3 import RGBA, parse_color
from tinycss2.nth import parse_nth
from webencodings import Encoding, lookup


def generic(func):
Expand All @@ -42,33 +45,33 @@ def numeric(t):
list: lambda li: [to_json(el) for el in li],
tuple: lambda li: [to_json(el) for el in li],
Encoding: lambda e: e.name,
ParseError: lambda e: ['error', e.kind],

Comment: lambda t: '/* … */',
WhitespaceToken: lambda t: ' ',
LiteralToken: lambda t: t.value,
IdentToken: lambda t: ['ident', t.value],
AtKeywordToken: lambda t: ['at-keyword', t.value],
HashToken: lambda t: ['hash', t.value,
'id' if t.is_identifier else 'unrestricted'],
StringToken: lambda t: ['string', t.value],
URLToken: lambda t: ['url', t.value],
NumberToken: lambda t: ['number'] + numeric(t),
PercentageToken: lambda t: ['percentage'] + numeric(t),
DimensionToken: lambda t: ['dimension'] + numeric(t) + [t.unit],
UnicodeRangeToken: lambda t: ['unicode-range', t.start, t.end],

CurlyBracketsBlock: lambda t: ['{}'] + to_json(t.content),
SquareBracketsBlock: lambda t: ['[]'] + to_json(t.content),
ParenthesesBlock: lambda t: ['()'] + to_json(t.content),
FunctionBlock: lambda t: ['function', t.name] + to_json(t.arguments),

Declaration: lambda d: ['declaration', d.name,
to_json(d.value), d.important],
AtRule: lambda r: ['at-rule', r.at_keyword, to_json(r.prelude),
to_json(r.content)],
QualifiedRule: lambda r: ['qualified rule', to_json(r.prelude),
to_json(r.content)],
ast.ParseError: lambda e: ['error', e.kind],

ast.Comment: lambda t: '/* … */',
ast.WhitespaceToken: lambda t: ' ',
ast.LiteralToken: lambda t: t.value,
ast.IdentToken: lambda t: ['ident', t.value],
ast.AtKeywordToken: lambda t: ['at-keyword', t.value],
ast.HashToken: lambda t: ['hash', t.value,
'id' if t.is_identifier else 'unrestricted'],
ast.StringToken: lambda t: ['string', t.value],
ast.URLToken: lambda t: ['url', t.value],
ast.NumberToken: lambda t: ['number'] + numeric(t),
ast.PercentageToken: lambda t: ['percentage'] + numeric(t),
ast.DimensionToken: lambda t: ['dimension'] + numeric(t) + [t.unit],
ast.UnicodeRangeToken: lambda t: ['unicode-range', t.start, t.end],

ast.CurlyBracketsBlock: lambda t: ['{}'] + to_json(t.content),
ast.SquareBracketsBlock: lambda t: ['[]'] + to_json(t.content),
ast.ParenthesesBlock: lambda t: ['()'] + to_json(t.content),
ast.FunctionBlock: lambda t: ['function', t.name] + to_json(t.arguments),

ast.Declaration: lambda d: ['declaration', d.name,
to_json(d.value), d.important],
ast.AtRule: lambda r: ['at-rule', r.at_keyword, to_json(r.prelude),
to_json(r.content)],
ast.QualifiedRule: lambda r: ['qualified rule', to_json(r.prelude),
to_json(r.content)],

RGBA: lambda v: [round(c, 10) for c in v],
}
Expand Down
2 changes: 1 addition & 1 deletion tinycss2/nth.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ def parse_b(tokens, a):
def parse_signless_b(tokens, a, b_sign):
token = _next_significant(tokens)
if (token.type == 'number' and token.is_integer and
not token.representation[0] in '-+'):
token.representation[0] not in '-+'):
return parse_end(tokens, a, b_sign * token.int_value)


Expand Down
60 changes: 28 additions & 32 deletions tinycss2/tokenizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,7 @@

from webencodings import ascii_lower

from .ast import (
AtKeywordToken, Comment, CurlyBracketsBlock, DimensionToken, FunctionBlock,
HashToken, IdentToken, LiteralToken, NumberToken, ParenthesesBlock,
ParseError, PercentageToken, SquareBracketsBlock, StringToken,
UnicodeRangeToken, URLToken, WhitespaceToken)
from . import ast
from .serializer import serialize_string_value, serialize_url

_NUMBER_RE = re.compile(r'[-+]?([0-9]*\.)?[0-9]+([eE][+-]?[0-9]+)?')
Expand Down Expand Up @@ -53,21 +49,21 @@ def parse_component_value_list(css, skip_comments=False):
while css.startswith((' ', '\n', '\t'), pos):
pos += 1
value = css[token_start_pos:pos]
tokens.append(WhitespaceToken(line, column, value))
tokens.append(ast.WhitespaceToken(line, column, value))
continue
elif (c in 'Uu' and pos + 2 < length and css[pos + 1] == '+' and
css[pos + 2] in '0123456789abcdefABCDEF?'):
start, end, pos = _consume_unicode_range(css, pos + 2)
tokens.append(UnicodeRangeToken(line, column, start, end))
tokens.append(ast.UnicodeRangeToken(line, column, start, end))
continue
elif css.startswith('-->', pos): # Check before identifiers
tokens.append(LiteralToken(line, column, '-->'))
tokens.append(ast.LiteralToken(line, column, '-->'))
pos += 3
continue
elif _is_ident_start(css, pos):
value, pos = _consume_ident(css, pos)
if not css.startswith('(', pos): # Not a function
tokens.append(IdentToken(line, column, value))
tokens.append(ast.IdentToken(line, column, value))
continue
pos += 1 # Skip the '('
if ascii_lower(value) == 'url':
Expand All @@ -85,12 +81,12 @@ def parse_component_value_list(css, skip_comments=False):
else:
assert error_key == 'eof-in-url'
repr = repr[:-1]
tokens.append(URLToken(line, column, value, repr))
tokens.append(ast.URLToken(line, column, value, repr))
if error is not None:
tokens.append(ParseError(line, column, *error))
tokens.append(ast.ParseError(line, column, *error))
continue
arguments = []
tokens.append(FunctionBlock(line, column, value, arguments))
tokens.append(ast.FunctionBlock(line, column, value, arguments))
stack.append((tokens, end_char))
end_char = ')'
tokens = arguments
Expand All @@ -104,22 +100,22 @@ def parse_component_value_list(css, skip_comments=False):
int_value = int(repr_) if not any(match.groups()) else None
if pos < length and _is_ident_start(css, pos):
unit, pos = _consume_ident(css, pos)
tokens.append(DimensionToken(
tokens.append(ast.DimensionToken(
line, column, value, int_value, repr_, unit))
elif css.startswith('%', pos):
pos += 1
tokens.append(PercentageToken(
tokens.append(ast.PercentageToken(
line, column, value, int_value, repr_))
else:
tokens.append(NumberToken(
tokens.append(ast.NumberToken(
line, column, value, int_value, repr_))
elif c == '@':
pos += 1
if pos < length and _is_ident_start(css, pos):
value, pos = _consume_ident(css, pos)
tokens.append(AtKeywordToken(line, column, value))
tokens.append(ast.AtKeywordToken(line, column, value))
else:
tokens.append(LiteralToken(line, column, '@'))
tokens.append(ast.LiteralToken(line, column, '@'))
elif c == '#':
pos += 1
if pos < length and (
Expand All @@ -130,26 +126,26 @@ def parse_component_value_list(css, skip_comments=False):
(css[pos] == '\\' and not css.startswith('\\\n', pos))):
is_identifier = _is_ident_start(css, pos)
value, pos = _consume_ident(css, pos)
tokens.append(HashToken(line, column, value, is_identifier))
tokens.append(ast.HashToken(line, column, value, is_identifier))
else:
tokens.append(LiteralToken(line, column, '#'))
tokens.append(ast.LiteralToken(line, column, '#'))
elif c == '{':
content = []
tokens.append(CurlyBracketsBlock(line, column, content))
tokens.append(ast.CurlyBracketsBlock(line, column, content))
stack.append((tokens, end_char))
end_char = '}'
tokens = content
pos += 1
elif c == '[':
content = []
tokens.append(SquareBracketsBlock(line, column, content))
tokens.append(ast.SquareBracketsBlock(line, column, content))
stack.append((tokens, end_char))
end_char = ']'
tokens = content
pos += 1
elif c == '(':
content = []
tokens.append(ParenthesesBlock(line, column, content))
tokens.append(ast.ParenthesesBlock(line, column, content))
stack.append((tokens, end_char))
end_char = ')'
tokens = content
Expand All @@ -160,43 +156,43 @@ def parse_component_value_list(css, skip_comments=False):
tokens, end_char = stack.pop()
pos += 1
elif c in '}])':
tokens.append(ParseError(line, column, c, 'Unmatched ' + c))
tokens.append(ast.ParseError(line, column, c, 'Unmatched ' + c))
pos += 1
elif c in ('"', "'"):
value, pos, error = _consume_quoted_string(css, pos)
if value is not None:
repr = '"{}"'.format(serialize_string_value(value))
if error is not None:
repr = repr[:-1]
tokens.append(StringToken(line, column, value, repr))
tokens.append(ast.StringToken(line, column, value, repr))
if error is not None:
tokens.append(ParseError(line, column, *error))
tokens.append(ast.ParseError(line, column, *error))
elif css.startswith('/*', pos): # Comment
pos = css.find('*/', pos + 2)
if pos == -1:
if not skip_comments:
tokens.append(
Comment(line, column, css[token_start_pos + 2:]))
ast.Comment(line, column, css[token_start_pos + 2:]))
break
if not skip_comments:
tokens.append(
Comment(line, column, css[token_start_pos + 2:pos]))
ast.Comment(line, column, css[token_start_pos + 2:pos]))
pos += 2
elif css.startswith('<!--', pos):
tokens.append(LiteralToken(line, column, '<!--'))
tokens.append(ast.LiteralToken(line, column, '<!--'))
pos += 4
elif css.startswith('||', pos):
tokens.append(LiteralToken(line, column, '||'))
tokens.append(ast.LiteralToken(line, column, '||'))
pos += 2
elif c in '~|^$*':
pos += 1
if css.startswith('=', pos):
pos += 1
tokens.append(LiteralToken(line, column, c + '='))
tokens.append(ast.LiteralToken(line, column, c + '='))
else:
tokens.append(LiteralToken(line, column, c))
tokens.append(ast.LiteralToken(line, column, c))
else:
tokens.append(LiteralToken(line, column, c))
tokens.append(ast.LiteralToken(line, column, c))
pos += 1
return root

Expand Down

0 comments on commit 1c90cf9

Please sign in to comment.