Skip to content

Commit 8d10426

Browse files
committed
feat: add type annotations
1 parent 8dbf57b commit 8d10426

File tree

17 files changed

+137
-69
lines changed

17 files changed

+137
-69
lines changed

.github/matchers/mypy.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"problemMatcher": [
3+
{
4+
"owner": "mypy",
5+
"pattern": [
6+
{
7+
"regexp": "^([^:]*):(\\d+):(?:(\\d+):)? ([^:]*): (.*?)(?: \\[(\\S+)\\])?$",
8+
"file": 1,
9+
"line": 2,
10+
"column": 3,
11+
"severity": 4,
12+
"message": 5,
13+
"code": 6
14+
}
15+
]
16+
}
17+
]
18+
}

.github/matchers/mypy.json.license

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Copyright © Michal Čihař <[email protected]>
2+
3+
SPDX-License-Identifier: CC0-1.0
4+
5+
This file is maintained in https://github.com/WeblateOrg/meta/

.github/matchers/pytest.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"problemMatcher": [
3+
{
4+
"owner": "pytest",
5+
"severity": "warning",
6+
"pattern": [
7+
{
8+
"regexp": "^ *([^: ]*):(\\d+): ([^ :]*Warning): (.*)$",
9+
"file": 1,
10+
"line": 2,
11+
"code": 3,
12+
"message": 4
13+
}
14+
]
15+
}
16+
]
17+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Copyright © Michal Čihař <[email protected]>
2+
3+
SPDX-License-Identifier: CC0-1.0
4+
5+
This file is maintained in https://github.com/WeblateOrg/meta/

.github/workflows/mypy.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Copyright © Michal Čihař <[email protected]>
2+
#
3+
# SPDX-License-Identifier: CC0-1.0
4+
5+
name: mypy
6+
7+
on:
8+
push:
9+
branches-ignore:
10+
- deepsource-fix-**
11+
- renovate/**
12+
- weblate
13+
pull_request:
14+
15+
permissions:
16+
contents: read
17+
18+
jobs:
19+
mypy:
20+
runs-on: ubuntu-24.04
21+
22+
steps:
23+
- uses: actions/checkout@v4
24+
with:
25+
fetch-depth: 2
26+
27+
- uses: astral-sh/setup-uv@v3
28+
with:
29+
enable-cache: true
30+
cache-dependency-glob: ''
31+
cache-suffix: '3.13'
32+
- name: Setup Python
33+
uses: actions/setup-python@v5
34+
with:
35+
python-version: '3.13'
36+
- name: Install pip dependencies
37+
run: uv pip install --system -e .[dev]
38+
39+
- name: Run mypy
40+
run: |
41+
echo "::add-matcher::.github/matchers/mypy.json"
42+
mypy --show-column-numbers weblate_web
43+
echo "::remove-matcher owner=mypy::"

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ text = "MIT"
3535

3636
[project.optional-dependencies]
3737
dev = [
38-
"weblate-language-data[lint,test]",
38+
"weblate-language-data[lint,test,types]",
3939
"translate-toolkit==3.14.1"
4040
]
4141
django = [
@@ -47,6 +47,10 @@ lint = [
4747
test = [
4848
"twine==5.1.1"
4949
]
50+
types = [
51+
"mypy==1.3.0",
52+
"django-stubs==5.1.1"
53+
]
5054

5155
[project.readme]
5256
content-type = "text/x-rst"

scripts/generate-language-data

Lines changed: 33 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ See https://github.com/WeblateOrg/language-data
1313
import csv
1414
import json
1515
import re
16-
import subprocess
1716
from itertools import chain
1817

1918
SPLIT_RE = re.compile(
@@ -35,19 +34,25 @@ https://github.com/WeblateOrg/language-data
3534
"""
3635
# pylint: disable=line-too-long,too-many-lines
3736
38-
3937
'''
4038

4139
TEMPLATE = """ (
42-
'{0}',
40+
"{0}",
4341
# Translators: Language name for ISO code "{0}". The parenthesis clarifies
4442
# variant of the language. It could contain a region, age (Old, Middle, ...)
4543
# or other variant.
46-
_('{1}'),
44+
_("{1}"),
4745
{2},
48-
'{3}',
46+
"{3}",
4947
),
5048
"""
49+
TYPE_HINT = "tuple[tuple[str, str, int, str], ...]"
50+
51+
52+
def escape(value: str) -> str:
53+
"""Escape string for use in template."""
54+
return value.replace('"', r"\"")
55+
5156

5257
# Read languages
5358
with open("languages.csv") as csvfile:
@@ -150,62 +155,54 @@ with open("weblate_language_data/languages.py", "w") as output:
150155
output.write(HEADER)
151156
output.write("from .utils import gettext_noop as _\n\n")
152157
output.write("# Language definitions\n")
153-
output.write("LANGUAGES = (\n")
158+
output.write(f"LANGUAGES: {TYPE_HINT} = (\n")
154159
for row in LANGUAGES:
155-
output.write(
156-
TEMPLATE.format(row[0], row[1].replace("'", "\\'"), row[2], row[3])
157-
)
160+
output.write(TEMPLATE.format(row[0], escape(row[1]), row[2], row[3]))
158161
output.write(")\n")
159162
with open("weblate_language_data/population.py", "w") as output:
160163
output.write(HEADER)
161164
output.write("# Language definitions\n")
162-
output.write("POPULATION = {\n")
165+
output.write("POPULATION: dict[str, int] = {\n")
163166
for row in LANGUAGES:
164167
code = row[0]
165-
output.write(f" {code!r}: {get_population(code)},\n")
168+
output.write(f' "{escape(code)}": {get_population(code)},\n')
166169
output.write("}\n")
167170
with open("weblate_language_data/plurals.py", "w") as output:
168171
output.write(HEADER)
169172
output.write("from .utils import gettext_noop as _\n\n")
170173
output.write("# Additional plural rules definitions\n")
171-
output.write("EXTRAPLURALS = (\n")
174+
output.write(f"EXTRAPLURALS: {TYPE_HINT} = (\n")
172175
for row in EXTRAPLURALS:
173-
output.write(
174-
TEMPLATE.format(row[0], row[1].replace("'", "\\'"), row[2], row[3])
175-
)
176+
output.write(TEMPLATE.format(row[0], escape(row[1]), row[2], row[3]))
176177
output.write(")\n")
177178
output.write("\n")
178-
output.write("CLDRPLURALS = (\n")
179+
output.write(f"CLDRPLURALS: {TYPE_HINT} = (\n")
179180
for row in CLDRPLURALS:
180-
output.write(
181-
TEMPLATE.format(row[0], row[1].replace("'", "\\'"), row[2], row[3])
182-
)
181+
output.write(TEMPLATE.format(row[0], escape(row[1]), row[2], row[3]))
183182
output.write(")\n")
184183
output.write("\n")
185-
output.write("QTPLURALS = (\n")
184+
output.write(f"QTPLURALS: {TYPE_HINT} = (\n")
186185
for row in QTPLURALS:
187-
output.write(
188-
TEMPLATE.format(row[0], row[1].replace("'", "\\'"), row[2], row[3])
189-
)
186+
output.write(TEMPLATE.format(row[0], escape(row[1]), row[2], row[3]))
190187
output.write(")\n")
191188
with open("weblate_language_data/aliases.py", "w") as output:
192189
output.write(HEADER)
193190
output.write("# Language aliases\n")
194-
output.write("ALIASES = {\n")
191+
output.write("ALIASES: dict[str, str] = {\n")
195192
for row in ALIASES:
196-
output.write(" '{}': '{}',\n".format(*row))
193+
output.write(""" "{}": "{}",\n""".format(*row))
197194
output.write("}\n")
198195
with open("weblate_language_data/countries.py", "w") as output:
199196
output.write(HEADER)
200197
output.write("# List of defaul languages, omitting country code should be okay\n")
201-
output.write("DEFAULT_LANGS = (\n")
198+
output.write("DEFAULT_LANGS: tuple[str, ...] = (\n")
202199
for row in DEFAULT_COUNTRIES:
203-
output.write(" '{}',\n".format(*row))
200+
output.write(f' "{escape(row[0])}",\n')
204201
output.write(")\n")
205202
with open("weblate_language_data/rtl.py", "w") as output:
206203
output.write(HEADER)
207204
output.write("# List of RTL languages\n")
208-
output.write("RTL_LANGS = {\n")
205+
output.write("RTL_LANGS: set[str] = {\n")
209206
for code in sorted(RTL_CODES):
210207
output.write(f' "{code}",\n')
211208
output.write("}\n")
@@ -302,21 +299,19 @@ words.difference_update(
302299
with open("weblate_language_data/check_languages.py", "w") as output:
303300
output.write(HEADER)
304301
output.write("# Language names to ignore in same check\n")
305-
output.write("LANGUAGES = {\n")
306-
content = ", ".join(
307-
"'{}'".format(word.replace("'", "\\'"))
308-
for word in sorted(words)
309-
if len(word) > 2 # noqa: PLR2004
310-
)
311-
output.write(content)
312-
output.write("\n}\n")
302+
output.write("LANGUAGES: set[str] = {\n")
303+
for word in sorted(words):
304+
if len(word) <= 2: # noqa: PLR2004
305+
continue
306+
output.write(f' "{escape(word)}",\n')
307+
output.write("}\n")
313308

314309

315310
# Write language codes
316311
with open("weblate_language_data/language_codes.py", "w") as output:
317312
output.write(HEADER)
318313
output.write("# Known language codes\n")
319-
output.write("LANGUAGES = {\n")
314+
output.write("LANGUAGES: set[str] = {\n")
320315
for word in sorted(CODES):
321316
output.write(' "{}",\n'.format(word.replace('"', '\\"')))
322317
output.write("}\n")
@@ -325,26 +320,7 @@ with open("weblate_language_data/language_codes.py", "w") as output:
325320
with open("weblate_language_data/country_codes.py", "w") as output:
326321
output.write(HEADER)
327322
output.write("# Known country codes\n")
328-
output.write("COUNTRIES = {\n")
323+
output.write("COUNTRIES: set[str] = {\n")
329324
for word in sorted(COUNTRIES):
330325
output.write(' "{}",\n'.format(word.replace('"', '\\"')))
331326
output.write("}\n")
332-
333-
# Apply coding style
334-
subprocess.run(
335-
[
336-
"pre-commit",
337-
"run",
338-
"--files",
339-
"weblate_language_data/rtl.py",
340-
"weblate_language_data/countries.py",
341-
"weblate_language_data/aliases.py",
342-
"weblate_language_data/plurals.py",
343-
"weblate_language_data/languages.py",
344-
"weblate_language_data/population.py",
345-
"weblate_language_data/check_languages.py",
346-
"weblate_language_data/language_codes.py",
347-
"weblate_language_data/country_codes.py",
348-
],
349-
check=False,
350-
)

weblate_language_data/aliases.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# pylint: disable=line-too-long,too-many-lines
1414

1515
# Language aliases
16-
ALIASES = {
16+
ALIASES: dict[str, str] = {
1717
"braz_por": "pt_BR",
1818
"chinese": "zh_Hans",
1919
"chinese_chs": "zh_Hans",

weblate_language_data/check_languages.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# pylint: disable=line-too-long,too-many-lines
1414

1515
# Language names to ignore in same check
16-
LANGUAGES = {
16+
LANGUAGES: set[str] = {
1717
"aak",
1818
"aakkâr",
1919
"aargau",

weblate_language_data/countries.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# pylint: disable=line-too-long,too-many-lines
1414

1515
# List of defaul languages, omitting country code should be okay
16-
DEFAULT_LANGS = (
16+
DEFAULT_LANGS: tuple[str, ...] = (
1717
"af_za",
1818
"am_et",
1919
"ar_aa",

0 commit comments

Comments
 (0)