From 4cc9876e2da5d1bf911f22f120556a19b0afdee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sat, 5 Sep 2026 06:56:32 +0200 Subject: [PATCH 1/8] Update lock file --- .github/workflows/automaticRelease.yaml | 2 +- .markdownlint.jsonc | 38 ++++ .pre-commit-config.yaml | 93 --------- .python-version | 2 +- prek.toml | 165 +++++++++++++++ pyproject.toml | 154 ++++---------- uv.lock | 257 +++++++++--------------- 7 files changed, 341 insertions(+), 370 deletions(-) create mode 100644 .markdownlint.jsonc delete mode 100644 .pre-commit-config.yaml create mode 100644 prek.toml diff --git a/.github/workflows/automaticRelease.yaml b/.github/workflows/automaticRelease.yaml index 7b32849..7f3c426 100644 --- a/.github/workflows/automaticRelease.yaml +++ b/.github/workflows/automaticRelease.yaml @@ -16,7 +16,7 @@ jobs: contents: write steps: - name: Checkout code - uses: actions/checkout@v6 + uses: actions/checkout@v7 - name: Download artifact uses: actions/download-artifact@v8 - name: Release diff --git a/.markdownlint.jsonc b/.markdownlint.jsonc new file mode 100644 index 0000000..64db463 --- /dev/null +++ b/.markdownlint.jsonc @@ -0,0 +1,38 @@ +// A part of NonVisual Desktop Access (NVDA) +// Copyright (C) 2025 NV Access Limited +// This file may be used under the terms of the GNU General Public License, version 2 or later, as modified by the NVDA license. +// For full terms and any additional permissions, see the NVDA license file: https://github.com/nvaccess/nvda/blob/master/copying.txt +// +// Markdown linting rules. +{ + // Use ATX style headings. E.g. + // # This is a heading + "heading-style": { + "style": "atx" + }, + // Don't complain about using tabs in markdown + "hard_tab": false, + // Don't complain about lines being too long + "line-length": false, + // Only complain about repeated headings in the same part of the document outline + // Needed for the changelog + // We could consider enabling this on a file-by-file basis + "no-duplicate-heading": { + "siblings_only": true + }, + // Several of our markdown files include trailing punctuation in headings + "no-trailing-punctuation": false, + // Rule is incompatible with the anchor style we use in the user guide + "link-fragments": false, + // Many of our code blocks lack a language + // This should probably be fixed gradually + "fenced-code-language": false, + "ul-style": { + "style": "asterisk" + }, + "table-column-style": { + // MD060: Tables use single padding around the column delimiters. + // e.g. | Column 1 | Column 2 | + "style": "compact" + } +} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml deleted file mode 100644 index 81fec6a..0000000 --- a/.pre-commit-config.yaml +++ /dev/null @@ -1,93 +0,0 @@ -# Copied from https://github.com/nvaccess/nvda -# https://pre-commit.ci/ -# Configuration for Continuous Integration service -ci: - # Pyright does not seem to work in pre-commit CI - skip: [pyright] - autoupdate_schedule: monthly - autoupdate_commit_msg: "Pre-commit auto-update" - autofix_commit_msg: "Pre-commit auto-fix" - submodules: true - -default_language_version: - python: python3.13 - -repos: -- repo: https://github.com/pre-commit-ci/pre-commit-ci-config - rev: v1.6.1 - hooks: - - id: check-pre-commit-ci-config - -- repo: meta - hooks: - # ensures that exclude directives apply to any file in the repository. - - id: check-useless-excludes - # ensures that the configured hooks apply to at least one file in the repository. - - id: check-hooks-apply - -- repo: https://github.com/pre-commit/pre-commit-hooks - rev: v6.0.0 - hooks: - # Prevents commits to certain branches - - id: no-commit-to-branch - args: ["--branch", "main", "--branch", "master", ] - # Checks that large files have not been added. Default cut-off for "large" files is 500kb. - - id: check-added-large-files - # Checks python syntax - - id: check-ast - # Checks for filenames that will conflict on case insensitive filesystems (the majority of Windows filesystems, most of the time) - - id: check-case-conflict - # Checks for artifacts from resolving merge conflicts. - - id: check-merge-conflict - # Checks Python files for debug statements, such as python's breakpoint function, or those inserted by some IDEs. - - id: debug-statements - # Removes trailing whitespace. - - id: trailing-whitespace - types_or: [python, c, c++, batch, markdown, toml, yaml, powershell] - # Ensures all files end in 1 (and only 1) newline. - - id: end-of-file-fixer - types_or: [python, c, c++, batch, markdown, toml, yaml, powershell] - # Removes the UTF-8 BOM from files that have it. - # See https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/codingStandards.md#encoding - - id: fix-byte-order-marker - types_or: [python, c, c++, batch, markdown, toml, yaml, powershell] - # Validates TOML files. - - id: check-toml - # Validates YAML files. - - id: check-yaml - # Ensures that links to lines in files under version control point to a particular commit. - - id: check-vcs-permalinks - # Avoids using reserved Windows filenames. - - id: check-illegal-windows-names -- repo: https://github.com/asottile/add-trailing-comma - rev: v4.0.0 - hooks: - # Ruff preserves indent/new-line formatting of function arguments, list items, and similar iterables, - # if a trailing comma is added. - # This adds a trailing comma to args/iterable items in case it was missed. - - id: add-trailing-comma - -- repo: https://github.com/astral-sh/ruff-pre-commit - # Matches Ruff version in pyproject. - rev: v0.12.7 - hooks: - - id: ruff - name: lint with ruff - args: [ --fix ] - - id: ruff-format - name: format with ruff -- repo: https://github.com/astral-sh/uv-pre-commit - rev: 0.9.11 - hooks: - - id: uv-lock - name: Verify uv lock file - # Override python interpreter from .python-versions as that is too strict for pre-commit.ci - args: ["-p3.13"] -- repo: local - hooks: - - - id: pyright - name: type check with pyright - entry: uv run pyright - language: system - types: [python] diff --git a/.python-version b/.python-version index 177facf..3a4f41e 100644 --- a/.python-version +++ b/.python-version @@ -1 +1 @@ -3.13.12 \ No newline at end of file +3.13 \ No newline at end of file diff --git a/prek.toml b/prek.toml new file mode 100644 index 0000000..97d3197 --- /dev/null +++ b/prek.toml @@ -0,0 +1,165 @@ +# Configuration file for `prek`, a git hook framework written in Rust. +# See https://prek.j178.dev for more information. +# Based on the .pre-commit-config.yaml file of the NVDA project, and the prek.toml file of the addon-template repositories +# https://github.com/nvaccess/nvda +# https://github.com/nvaccess/addonTemplate + +#:schema https://www.schemastore.org/prek.json +default_language_version = { python = "python3.13" } + +[[repos]] +repo = "meta" +hooks = [ + { id = "check-useless-excludes" }, + { id = "check-hooks-apply" } +] + + +# Built-in hooks reimplemented in Rust by prek. No repo clone or environment setup required. +[[repos]] +repo = "builtin" +hooks = [ + # Prevents commits to certain branches + { + id = "no-commit-to-branch", + args = [ + "--branch", + "main", + "--branch", + "master" + ] + }, + # Checks that large files have not been added. Default cut-off for "large" files is 500kb. + { id = "check-added-large-files" }, + # Checks for filenames that will conflict on case insensitive filesystems (the majority of Windows filesystems, most of the time) + { id = "check-case-conflict" }, + # Checks for artifacts from resolving merge conflicts. + { id = "check-merge-conflict" }, + # Removes trailing whitespace. + { + id = "trailing-whitespace", + types_or = [ + "python", + "c", + "c++", + "batch", + "markdown", + "toml", + "yaml", + "powershell" + ] + }, + # Ensures all files end in 1 (and only 1) newline. + { + id = "end-of-file-fixer", + types_or = [ + "python", + "c", + "c++", + "batch", + "markdown", + "toml", + "yaml", + "powershell" + ] + }, + # Removes the UTF-8 BOM from files that have it. + # See https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/codingStandards.md#encoding + { + id = "fix-byte-order-marker", + types_or = [ + "python", + "c", + "c++", + "batch", + "markdown", + "toml", + "yaml", + "powershell" + ] + }, + # Validates TOML files. + { id = "check-toml" }, + # Validates YAML files. + { id = "check-yaml" }, + # Ensures that links to lines in files under version control point to a particular commit. + { id = "check-vcs-permalinks" } +] + +[[repos]] +repo = "https://github.com/pre-commit/pre-commit-hooks" +rev = "v6.0.0" +hooks = [ + { id = "check-ast" }, + { id = "debug-statements" }, +] + +[[repos]] +repo = "https://github.com/kjanat/actionlint" +rev = "v1.12.0" +hooks = [ + { id = "actionlint" } +] + +[[repos]] +repo = "https://github.com/asottile/add-trailing-comma" +rev = "v4.0.0" +hooks = [ + { + id = "add-trailing-comma", + groups = ["autofix"] + } +] + +[[repos]] +repo = "https://github.com/astral-sh/ruff-pre-commit" +rev = "v0.16.3" +hooks = [ + { + id = "ruff", + name = "lint with ruff", + groups = ["autofix"], + args = ["--fix"] + }, + { + id = "ruff-format", + name = "format with ruff", + groups = ["autofix"] + } +] + +[[repos]] +repo = "https://github.com/astral-sh/uv-pre-commit" +rev = "0.12.5" +hooks = [ + { + id = "uv-lock", + name = "Verify uv lock file", + groups = ["autofix"], + args = ["-p3.13"] + } +] + +[[repos]] +repo = "https://github.com/DavidAnson/markdownlint-cli2" +rev = "v0.23.2" +hooks = [ + { + id = "markdownlint-cli2", + name = "Lint markdown files", + groups = ["autofix"], + args = ["--fix"] + } +] + +[[repos]] +repo = "https://github.com/astral-sh/ty-pre-commit" +rev = "v0.0.73" +hooks = [ + { + id = "ty", + name = "type check with ty", + always_run = false, + types = ["python"], + } +] diff --git a/pyproject.toml b/pyproject.toml index ef0b17a..54676de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools~=80.9", "wheel"] +requires = ["setuptools~=84.0.0", "wheel"] build-backend = "setuptools.build_meta" [project] name = "nvdaL10n" @@ -21,15 +21,15 @@ readme = "readme.md" license = {file = "license"} dependencies = [ "pyinstaller==6.19.0", - "crowdin-api-client==1.21.0", + "crowdin-api-client==1.28.0", "l2m4m==1.0.4", - "lxml==6.1.0", - "markdown==3.10", + "lxml==6.1.2", + "markdown==3.10.3", "markdown-link-attr-modifier==0.2.1", "mdx-gh-links==0.4", - "mdx-truly-sane-lists==1.3", + "mdx_truly_sane_lists==1.3", "nh3==0.2.19", - "pymdown-extensions==10.16.1", + "pymdown-extensions==11.0.1", "requests==2.33.0", ] [project.urls] @@ -37,9 +37,9 @@ Repository = "https://github.com/nvaccess/nvdaL10n" [dependency-groups] dev = [ - "ruff==0.8.1", - "pre-commit==4.2.0", - "pyright==1.1.396", + "ruff==0.16.3", + "prek==0.4.14", + "ty==0.0.73", ] [tool.setuptools.packages.find] @@ -83,117 +83,35 @@ ignore = [ ] logger-objects = ["logHandler.log"] -[tool.pyright] -venvPath = "." -venv = ".venv" -pythonPlatform = "Windows" -typeCheckingMode = "strict" - -include = [ - "**/*.py", +[tool.ty.environment] +python = ".venv" +python-platform = "win32" +# Tell ty where to load python code from (ported from pyright's extraPaths). +extra-paths = [ + "./source", + # Used internally in NVDA + "./miscDeps/python", ] +[tool.ty.src] +# Appended to ty's default excludes (which already cover e.g. .git, .venv and __pycache__ at any depth). +# Patterns are anchored to the project root. exclude = [ - ".git", - "__pycache__", - ".venv", - # When excluding concrete paths relative to a directory, - # not matching multiple folders by name e.g. `__pycache__`, - # paths are relative to the configuration file. + "build", + "dist", + "./miscDeps", ] -# General config -analyzeUnannotatedFunctions = true -deprecateTypingAliases = true - -# Stricter typing -strictParameterNoneValue = true -strictListInference = true -strictDictionaryInference = true -strictSetInference = true - -# Compliant rules -reportAbstractUsage = true -reportArgumentType = true -reportAssertAlwaysTrue = true -reportAssertTypeFailure = true -reportAssignmentType = true -reportAttributeAccessIssue = true -reportCallInDefaultInitializer = true -reportCallIssue = true -reportConstantRedefinition = true -reportDuplicateImport = true -reportFunctionMemberAccess = true -reportGeneralTypeIssues = true -reportImplicitOverride = true -reportImplicitStringConcatenation = true -reportImportCycles = true -reportIncompatibleMethodOverride = true -reportIncompatibleVariableOverride = true -reportIncompleteStub = true -reportInconsistentConstructor = true -reportInconsistentOverload = true -reportIndexIssue = true -reportInvalidStringEscapeSequence = true -reportInvalidStubStatement = true -reportInvalidTypeArguments = true -reportInvalidTypeForm = true -reportInvalidTypeVarUse = true -reportMatchNotExhaustive = true -reportMissingImports = true -reportMissingModuleSource = true -reportMissingParameterType = true -reportMissingSuperCall = true -reportMissingTypeArgument = true -reportNoOverloadImplementation = true -reportOperatorIssue = true -reportOptionalCall = true -reportOptionalContextManager = true -reportOptionalIterable = true -reportOptionalMemberAccess = true -reportOptionalOperand = true -reportOptionalSubscript = true -reportOverlappingOverload = true -reportPossiblyUnboundVariable = true -reportPrivateImportUsage = true -reportPrivateUsage = true -reportPropertyTypeMismatch = true -reportRedeclaration = true -reportReturnType = true -reportSelfClsParameterName = true -reportShadowedImports = true -reportTypeCommentUsage = true -reportTypedDictNotRequiredAccess = true -reportUnboundVariable = true -reportUndefinedVariable = true -reportUnhashable = true -reportUninitializedInstanceVariable = true -reportUnknownArgumentType = true -reportUnknownLambdaType = true -reportUnknownMemberType = true -reportUnknownParameterType = true -reportUnknownVariableType = true -reportUnnecessaryCast = true -reportUnnecessaryComparison = true -reportUnnecessaryContains = true -reportUnnecessaryIsInstance = true -reportUnnecessaryTypeIgnoreComment = true -reportUnsupportedDunderAll = true -reportUntypedBaseClass = true -reportUntypedClassDecorator = true -reportUntypedFunctionDecorator = true -reportUntypedNamedTuple = true -reportUnusedCallResult = true -reportUnusedClass = true -reportUnusedCoroutine = true -reportUnusedExcept = true -reportUnusedExpression = true -reportUnusedFunction = true -reportUnusedImport = true -reportUnusedVariable = true -reportWildcardImportFromLibrary = true - -reportDeprecated = true - -# Can be enabled by generating type stubs for modules via pyright CLI -reportMissingTypeStubs = false +[tool.ty.terminal] +output-format = "concise" + +[tool.ty.rules] +unresolved-attribute = "ignore" # 3 errors +not-subscriptable = "ignore" # 3 errors +invalid-argument-type = "ignore" # 7 errors +invalid-assignment = "ignore" # 3 errors +unsupported-operator = "ignore" # 3 errors +invalid-return-type = "ignore" # 1 error +unresolved-import = "ignore" # 3 errors +# Non-fatal warnings +deprecated = "ignore" # 3 warnings diff --git a/uv.lock b/uv.lock index 4ed0534..834390a 100644 --- a/uv.lock +++ b/uv.lock @@ -20,15 +20,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/70/7d/9bc192684cea499815ff478dfcdc13835ddf401365057044fb721ec6bddb/certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b", size = 159438, upload-time = "2025-11-12T02:54:49.735Z" }, ] -[[package]] -name = "cfgv" -version = "3.5.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/4e/b5/721b8799b04bf9afe054a3899c6cf4e880fcf8563cc71c15610242490a0c/cfgv-3.5.0.tar.gz", hash = "sha256:d5b1034354820651caa73ede66a6294d6e95c1b00acc5e9b098e917404669132", size = 7334, upload-time = "2025-11-19T20:55:51.612Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/db/3c/33bac158f8ab7f89b2e59426d5fe2e4f63f7ed25df84c036890172b412b5/cfgv-3.5.0-py2.py3-none-any.whl", hash = "sha256:a8dc6b26ad22ff227d2634a65cb388215ce6cc96bbcc5cfde7641ae87e8dacc0", size = 7445, upload-time = "2025-11-19T20:55:50.744Z" }, -] - [[package]] name = "charset-normalizer" version = "3.4.4" @@ -56,15 +47,15 @@ wheels = [ [[package]] name = "crowdin-api-client" -version = "1.21.0" +version = "1.28.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "deprecated" }, { name = "requests" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/39/70/4069412e2e8004a6ad15bf2a3d9085bea50ee932a66ad935285831cf82b4/crowdin_api_client-1.21.0.tar.gz", hash = "sha256:0f957e5de6487a74ac892d524a5e300c1bc971320b67f85ce65741904420d8ec", size = 64729, upload-time = "2025-01-31T15:56:42.179Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/dd/b25b5442ef2f2e550ad438054ff9cc41dd85b0319c3541bb1cf240846f90/crowdin_api_client-1.28.0.tar.gz", hash = "sha256:b4661caa2593cb4a1b6cad1be2f6333ff09b0dd5a617032cbd8df95d3df6293a", size = 73644, upload-time = "2026-08-17T11:15:57.079Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/93/0f/9efc4f6db0b3b97f99015529b5832058ce4f7970d547b23fc04a38d69ddd/crowdin_api_client-1.21.0-py3-none-any.whl", hash = "sha256:85e19557755ebf6a15beda605d25b77de365244d8c636462b0dd8030a6cdfe20", size = 101566, upload-time = "2025-01-31T15:56:40.651Z" }, + { url = "https://files.pythonhosted.org/packages/8f/ba/adc4d4b9191ebc2e1da3cf36f6bc1ae885a2eb94e4fe34e9a4cfa8335488/crowdin_api_client-1.28.0-py3-none-any.whl", hash = "sha256:afddf7b84a7f2f5d31a52da3a2bb1a74d654168c31f3374ec3b638ac6c1358d2", size = 114881, upload-time = "2026-08-17T11:15:55.917Z" }, ] [[package]] @@ -79,33 +70,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/d0/205d54408c08b13550c733c4b85429e7ead111c7f0014309637425520a9a/deprecated-1.3.1-py2.py3-none-any.whl", hash = "sha256:597bfef186b6f60181535a29fbe44865ce137a5079f295b479886c82729d5f3f", size = 11298, upload-time = "2025-10-30T08:19:00.758Z" }, ] -[[package]] -name = "distlib" -version = "0.4.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, -] - -[[package]] -name = "filelock" -version = "3.24.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/02/a8/dae62680be63cbb3ff87cfa2f51cf766269514ea5488479d42fec5aa6f3a/filelock-3.24.2.tar.gz", hash = "sha256:c22803117490f156e59fafce621f0550a7a853e2bbf4f87f112b11d469b6c81b", size = 37601, upload-time = "2026-02-16T02:50:45.614Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e7/04/a94ebfb4eaaa08db56725a40de2887e95de4e8641b9e902c311bfa00aa39/filelock-3.24.2-py3-none-any.whl", hash = "sha256:667d7dc0b7d1e1064dd5f8f8e80bdac157a6482e8d2e02cd16fd3b6b33bd6556", size = 24152, upload-time = "2026-02-16T02:50:44Z" }, -] - -[[package]] -name = "identify" -version = "2.6.16" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/5b/8d/e8b97e6bd3fb6fb271346f7981362f1e04d6a7463abd0de79e1fda17c067/identify-2.6.16.tar.gz", hash = "sha256:846857203b5511bbe94d5a352a48ef2359532bc8f6727b5544077a0dcfb24980", size = 99360, upload-time = "2026-01-12T18:58:58.201Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b8/58/40fbbcefeda82364720eba5cf2270f98496bdfa19ea75b4cccae79c698e6/identify-2.6.16-py2.py3-none-any.whl", hash = "sha256:391ee4d77741d994189522896270b787aed8670389bfd60f326d677d64a6dfb0", size = 99202, upload-time = "2026-01-12T18:58:56.627Z" }, -] - [[package]] name = "idna" version = "3.11" @@ -139,28 +103,28 @@ wheels = [ [[package]] name = "lxml" -version = "6.1.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/28/30/9abc9e34c657c33834eaf6cd02124c61bdf5944d802aa48e69be8da3585d/lxml-6.1.0.tar.gz", hash = "sha256:bfd57d8008c4965709a919c3e9a98f76c2c7cb319086b3d26858250620023b13", size = 4197006, upload-time = "2026-04-18T04:32:51.613Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/08/03/69347590f1cf4a6d5a4944bb6099e6d37f334784f16062234e1f892fdb1d/lxml-6.1.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:a0092f2b107b69601adf562a57c956fbb596e05e3e6651cabd3054113b007e45", size = 8559689, upload-time = "2026-04-18T04:31:57.785Z" }, - { url = "https://files.pythonhosted.org/packages/3f/58/25e00bb40b185c974cfe156c110474d9a8a8390d5f7c92a4e328189bb60e/lxml-6.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:fc7140d7a7386e6b545d41b7358f4d02b656d4053f5fa6859f92f4b9c2572c4d", size = 4617892, upload-time = "2026-04-18T04:32:01.78Z" }, - { url = "https://files.pythonhosted.org/packages/f5/54/92ad98a94ac318dc4f97aaac22ff8d1b94212b2ae8af5b6e9b354bf825f7/lxml-6.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:419c58fc92cc3a2c3fa5f78c63dbf5da70c1fa9c1b25f25727ecee89a96c7de2", size = 4923489, upload-time = "2026-04-18T04:33:31.401Z" }, - { url = "https://files.pythonhosted.org/packages/15/3b/a20aecfab42bdf4f9b390590d345857ad3ffd7c51988d1c89c53a0c73faf/lxml-6.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:37fabd1452852636cf38ecdcc9dd5ca4bba7a35d6c53fa09725deeb894a87491", size = 5082162, upload-time = "2026-04-18T04:33:34.262Z" }, - { url = "https://files.pythonhosted.org/packages/45/26/2cdb3d281ac1bd175603e290cbe4bad6eff127c0f8de90bafd6f8548f0fd/lxml-6.1.0-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2853c8b2170cc6cd54a6b4d50d2c1a8a7aeca201f23804b4898525c7a152cfc", size = 4993247, upload-time = "2026-04-18T04:33:36.674Z" }, - { url = "https://files.pythonhosted.org/packages/f6/05/d735aef963740022a08185c84821f689fc903acb3d50326e6b1e9886cc22/lxml-6.1.0-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:8e369cbd690e788c8d15e56222d91a09c6a417f49cbc543040cba0fe2e25a79e", size = 5613042, upload-time = "2026-04-18T04:33:39.205Z" }, - { url = "https://files.pythonhosted.org/packages/ee/b8/ead7c10efff731738c72e59ed6eb5791854879fbed7ae98781a12006263a/lxml-6.1.0-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e69aa6805905807186eb00e66c6d97a935c928275182eb02ee40ba00da9623b2", size = 5228304, upload-time = "2026-04-18T04:33:41.647Z" }, - { url = "https://files.pythonhosted.org/packages/6b/10/e9842d2ec322ea65f0a7270aa0315a53abed06058b88ef1b027f620e7a5f/lxml-6.1.0-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:4bd1bdb8a9e0e2dd229de19b5f8aebac80e916921b4b2c6ef8a52bc131d0c1f9", size = 5341578, upload-time = "2026-04-18T04:33:44.596Z" }, - { url = "https://files.pythonhosted.org/packages/89/54/40d9403d7c2775fa7301d3ddd3464689bfe9ba71acc17dfff777071b4fdc/lxml-6.1.0-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:cbd7b79cdcb4986ad78a2662625882747f09db5e4cd7b2ae178a88c9c51b3dfe", size = 4700209, upload-time = "2026-04-18T04:33:47.552Z" }, - { url = "https://files.pythonhosted.org/packages/85/b2/bbdcc2cf45dfc7dfffef4fd97e5c47b15919b6a365247d95d6f684ef5e82/lxml-6.1.0-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:43e4d297f11080ec9d64a4b1ad7ac02b4484c9f0e2179d9c4ef78e886e747b88", size = 5232365, upload-time = "2026-04-18T04:33:50.249Z" }, - { url = "https://files.pythonhosted.org/packages/48/5a/b06875665e53aaba7127611a7bed3b7b9658e20b22bc2dd217a0b7ab0091/lxml-6.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cc16682cc987a3da00aa56a3aa3075b08edb10d9b1e476938cfdbee8f3b67181", size = 5043654, upload-time = "2026-04-18T04:33:52.71Z" }, - { url = "https://files.pythonhosted.org/packages/e9/9c/e71a069d09641c1a7abeb30e693f828c7c90a41cbe3d650b2d734d876f85/lxml-6.1.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:d6d8efe71429635f0559579092bb5e60560d7b9115ee38c4adbea35632e7fa24", size = 4769326, upload-time = "2026-04-18T04:33:55.244Z" }, - { url = "https://files.pythonhosted.org/packages/cc/06/7a9cd84b3d4ed79adf35f874750abb697dec0b4a81a836037b36e47c091a/lxml-6.1.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7e39ab3a28af7784e206d8606ec0e4bcad0190f63a492bca95e94e5a4aef7f6e", size = 5635879, upload-time = "2026-04-18T04:33:58.509Z" }, - { url = "https://files.pythonhosted.org/packages/cc/f0/9d57916befc1e54c451712c7ee48e9e74e80ae4d03bdce49914e0aee42cd/lxml-6.1.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:9eb667bf50856c4a58145f8ca2d5e5be160191e79eb9e30855a476191b3c3495", size = 5224048, upload-time = "2026-04-18T04:34:00.943Z" }, - { url = "https://files.pythonhosted.org/packages/99/75/90c4eefda0c08c92221fe0753db2d6699a4c628f76ff4465ec20dea84cc1/lxml-6.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7f4a77d6f7edf9230cee3e1f7f6764722a41604ee5681844f18db9a81ea0ec33", size = 5250241, upload-time = "2026-04-18T04:34:03.365Z" }, - { url = "https://files.pythonhosted.org/packages/5e/73/16596f7e4e38fa33084b9ccbccc22a15f82a290a055126f2c1541236d2ff/lxml-6.1.0-cp313-cp313-win32.whl", hash = "sha256:28902146ffbe5222df411c5d19e5352490122e14447e98cd118907ee3fd6ee62", size = 3596938, upload-time = "2026-04-18T04:31:56.206Z" }, - { url = "https://files.pythonhosted.org/packages/8e/63/981401c5680c1eb30893f00a19641ac80db5d1e7086c62cb4b13ed813038/lxml-6.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:4a1503c56e4e2b38dc76f2f2da7bae69670c0f1933e27cfa34b2fa5876410b16", size = 3995728, upload-time = "2026-04-18T04:31:58.763Z" }, - { url = "https://files.pythonhosted.org/packages/e7/e8/c358a38ac3e541d16a1b527e4e9cb78c0419b0506a070ace11777e5e8404/lxml-6.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:e0af85773850417d994d019741239b901b22c6680206f46a34766926e466141d", size = 3658372, upload-time = "2026-04-18T04:32:03.629Z" }, +version = "6.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ad/a9/970b8fa0ecc4fbf1dfaed0d89bbc1fc1421b25ec26a2038c91e872dc6c8e/lxml-6.1.2.tar.gz", hash = "sha256:1055241852f2b02068af4a625a5d32c087db193c12251928af2562ecd2239f18", size = 4210626, upload-time = "2026-08-19T04:58:15.341Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/61/2a/e9651f47a31a60b5cae031abc23391ed9aa30c8fc07571d1a38f58d6d770/lxml-6.1.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:351318f5c0eb7fcab5b4fdb507c6f88fb2c4b5e67784c7e5911448c91fffb5d4", size = 8590165, upload-time = "2026-08-19T04:58:40.489Z" }, + { url = "https://files.pythonhosted.org/packages/61/87/a8098abaf35118767d1703b84c98940a5d833064e0eca39a00ecfe9840ab/lxml-6.1.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c0edde95e4b4278dcc0175eda06dc8aa2631ad9f83ae5dbdbc4f0925e200b0b0", size = 4632474, upload-time = "2026-08-19T04:58:47.465Z" }, + { url = "https://files.pythonhosted.org/packages/93/cc/fe74d1def7f4fb967c4a825608a074d4dbdbb871b0d6bd59c6ed07d67868/lxml-6.1.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a8326e24ae6c3a6bfb03fa8b4793f9a5d804c125228aa067f652b0428e31b87c", size = 4936196, upload-time = "2026-08-19T04:59:03.477Z" }, + { url = "https://files.pythonhosted.org/packages/b7/ad/b96e6ca926e26726a99aa643602aac7411ecc1731ddb1b25af8cc57edfcd/lxml-6.1.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7c534ed898413f439b048130011e99a4245ee13d62d431f6b4f7f2484d02a93a", size = 5093290, upload-time = "2026-08-19T04:59:17.498Z" }, + { url = "https://files.pythonhosted.org/packages/d2/84/616f5d3b7cd086fcfba3e5add6fccda67f976c1c753ae9ed7bbd317cb9be/lxml-6.1.2-cp313-cp313-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2e37fe49fe2d5aa40a2cb1cc8176673ad7de0d124e6f4a509d9318f5979c7871", size = 4998767, upload-time = "2026-08-19T04:59:28.385Z" }, + { url = "https://files.pythonhosted.org/packages/80/88/d5b453a8d083483c9442ad7f5ac5c560796022eb5c80d60b65d75e449236/lxml-6.1.2-cp313-cp313-manylinux_2_26_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9b52ea73a37fc64aa3357ff8607801d46dd170506d3cf8253a91a1d91639d4f9", size = 5626717, upload-time = "2026-08-19T04:59:40.045Z" }, + { url = "https://files.pythonhosted.org/packages/71/45/31e5aa4d4bae024908ba1d03480c7425cf027a28b7e5c88d1b7202bd80cc/lxml-6.1.2-cp313-cp313-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e8b9a92652e75e7731309ea51db5dee892eef414ce70a6ec3441e5d36bf5189f", size = 5232330, upload-time = "2026-08-19T04:59:46.175Z" }, + { url = "https://files.pythonhosted.org/packages/f5/5a/2627912420df8b2d31ba3014da5539f15ec85add01d42048864ffefda516/lxml-6.1.2-cp313-cp313-manylinux_2_28_i686.whl", hash = "sha256:9088da25ecd609965f838d89fda0465a905b48f4dd90331db9845518f2177372", size = 5347054, upload-time = "2026-08-19T04:59:52.762Z" }, + { url = "https://files.pythonhosted.org/packages/16/86/54ac0f529b22a8f12313726dd49e12961bb46471d9028cc28d2a29408f0b/lxml-6.1.2-cp313-cp313-manylinux_2_31_armv7l.whl", hash = "sha256:0349321a0537d4fdbebb2af06dd1b64676132c72e2ae250de8cdb58f8c43019c", size = 4707275, upload-time = "2026-08-19T05:00:04.836Z" }, + { url = "https://files.pythonhosted.org/packages/3a/42/ffcdc6e4519be90df907cdae7e88409efb25d823ae4de8846f737dae1884/lxml-6.1.2-cp313-cp313-manylinux_2_38_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:b20440e578d269c5e8a722ab602ddd0f0cedb8b080006b3f936da9991a593d3b", size = 5240071, upload-time = "2026-08-19T05:00:19.604Z" }, + { url = "https://files.pythonhosted.org/packages/68/49/5b1d7ab35f013f1127ec48f3108319f58b65b00d5cb26f215adbe86eadfb/lxml-6.1.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7766e525282dd38fd89567311323e441996eb958e8e816d16b38f782e3aecd2a", size = 5050356, upload-time = "2026-08-19T05:00:27.968Z" }, + { url = "https://files.pythonhosted.org/packages/b0/57/1cf049d054189b55c8fe8012269234f6602256949b69cd3ba80608a88219/lxml-6.1.2-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:9221442682c27417f10fe11184ea4cce174b25ab52465570b1f3ee3f85f320fa", size = 4780394, upload-time = "2026-08-19T05:00:39.047Z" }, + { url = "https://files.pythonhosted.org/packages/d5/ad/064488a8fa60e639fd773e421a18bf17541d02a95fbf36238ad7c65f69d4/lxml-6.1.2-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:75530642d8471327e691ab9b0513a5f9c77f38871014ceda40f51bb51765c0a1", size = 5645854, upload-time = "2026-08-19T05:03:42.697Z" }, + { url = "https://files.pythonhosted.org/packages/85/bb/120e56f3cf1c149bb3b014278fb86d0a6dd552403981081f0ee0a0a57be7/lxml-6.1.2-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:678e35f1cbca98f55107511ee21a60568535c950f3c2371819bd64504c980d20", size = 5231132, upload-time = "2026-08-19T05:03:45.466Z" }, + { url = "https://files.pythonhosted.org/packages/b1/2c/7d49aab893c128671a3276580074cce4c002896145b8dd2893da79633bca/lxml-6.1.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5c2bae42b3a09f977330a08f4a8fe72aec58c4bdb89069d3fe7272a71d885881", size = 5256076, upload-time = "2026-08-19T05:03:48.092Z" }, + { url = "https://files.pythonhosted.org/packages/72/28/ddea3aa1fa9acfd384fe34d4a2a93eecc07541dd2d922fa9b140c60d8014/lxml-6.1.2-cp313-cp313-win32.whl", hash = "sha256:5848f3de6a8de8a93cff9f068134393ff5fa69ac2a04399f7d49cd67c61c348c", size = 3602177, upload-time = "2026-08-19T05:03:50.571Z" }, + { url = "https://files.pythonhosted.org/packages/1b/7a/96bac167538748cae2544335855f812fa33e49a9a67bc8b8520dcbd592bd/lxml-6.1.2-cp313-cp313-win_amd64.whl", hash = "sha256:6cb0c87421946030b92b558be416852780a912454e3dcba0998e4497c9c588d5", size = 4004117, upload-time = "2026-08-19T05:03:53.074Z" }, + { url = "https://files.pythonhosted.org/packages/0a/24/9498fa3c84135956e5ef55ea4d8bd11e999e381f7f210fb6f8c6a980ef03/lxml-6.1.2-cp313-cp313-win_arm64.whl", hash = "sha256:648861c19b775b89ebefa14586f85090b10163367476d77f242c4131c835ce73", size = 3665412, upload-time = "2026-08-19T05:03:55.621Z" }, ] [[package]] @@ -177,11 +141,11 @@ wheels = [ [[package]] name = "markdown" -version = "3.10" +version = "3.10.3" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/7d/ab/7dd27d9d863b3376fcf23a5a13cb5d024aed1db46f963f1b5735ae43b3be/markdown-3.10.tar.gz", hash = "sha256:37062d4f2aa4b2b6b32aefb80faa300f82cc790cb949a35b8caede34f2b68c0e", size = 364931, upload-time = "2025-11-03T19:51:15.007Z" } +sdist = { url = "https://files.pythonhosted.org/packages/29/6f/da4c6aea59b3001f2e8c0ec7497475aadaf3b021c10cab5b2858f0f32b26/markdown-3.10.3.tar.gz", hash = "sha256:3589362618f743188b4d955b874402bc814f4f83f544dc207719f4baa7d9c45f", size = 372596, upload-time = "2026-07-30T19:05:29.005Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/70/81/54e3ce63502cd085a0c556652a4e1b919c45a446bd1e5300e10c44c8c521/markdown-3.10-py3-none-any.whl", hash = "sha256:b5b99d6951e2e4948d939255596523444c0e677c669700b1d17aa4a8a464cb7c", size = 107678, upload-time = "2025-11-03T19:51:13.887Z" }, + { url = "https://files.pythonhosted.org/packages/64/69/4a5af2bc115a9a33fefe51709749de8262be3f9ba063d1753a837cdbc49c/markdown-3.10.3-py3-none-any.whl", hash = "sha256:fa6c92a00a4a3c98b22728c64a935ae1928250ae65058a6ded814d2cc29a4cea", size = 110757, upload-time = "2026-07-30T19:05:27.883Z" }, ] [[package]] @@ -251,15 +215,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/58/d6/285df10307f16fcce9afbd133b04b4bc7d7f9b84b02f0f724bab30dacdd9/nh3-0.2.19-cp38-abi3-win_amd64.whl", hash = "sha256:75c7cafb840f24430b009f7368945cb5ca88b2b54bb384ebfba495f16bc9c121", size = 542316, upload-time = "2024-11-29T05:52:01.253Z" }, ] -[[package]] -name = "nodeenv" -version = "1.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, -] - [[package]] name = "nvdal10n" source = { editable = "." } @@ -279,31 +234,31 @@ dependencies = [ [package.dev-dependencies] dev = [ - { name = "pre-commit" }, - { name = "pyright" }, + { name = "prek" }, { name = "ruff" }, + { name = "ty" }, ] [package.metadata] requires-dist = [ - { name = "crowdin-api-client", specifier = "==1.21.0" }, + { name = "crowdin-api-client", specifier = "==1.28.0" }, { name = "l2m4m", specifier = "==1.0.4" }, - { name = "lxml", specifier = "==6.1.0" }, - { name = "markdown", specifier = "==3.10" }, + { name = "lxml", specifier = "==6.1.2" }, + { name = "markdown", specifier = "==3.10.3" }, { name = "markdown-link-attr-modifier", specifier = "==0.2.1" }, { name = "mdx-gh-links", specifier = "==0.4" }, { name = "mdx-truly-sane-lists", specifier = "==1.3" }, { name = "nh3", specifier = "==0.2.19" }, { name = "pyinstaller", specifier = "==6.19.0" }, - { name = "pymdown-extensions", specifier = "==10.16.1" }, + { name = "pymdown-extensions", specifier = "==11.0.1" }, { name = "requests", specifier = "==2.33.0" }, ] [package.metadata.requires-dev] dev = [ - { name = "pre-commit", specifier = "==4.2.0" }, - { name = "pyright", specifier = "==1.1.396" }, - { name = "ruff", specifier = "==0.8.1" }, + { name = "prek", specifier = "==0.4.14" }, + { name = "ruff", specifier = "==0.16.3" }, + { name = "ty", specifier = "==0.0.73" }, ] [[package]] @@ -325,28 +280,27 @@ wheels = [ ] [[package]] -name = "platformdirs" -version = "4.9.2" +name = "prek" +version = "0.4.14" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1b/04/fea538adf7dbbd6d186f551d595961e564a3b6715bdf276b477460858672/platformdirs-4.9.2.tar.gz", hash = "sha256:9a33809944b9db043ad67ca0db94b14bf452cc6aeaac46a88ea55b26e2e9d291", size = 28394, upload-time = "2026-02-16T03:56:10.574Z" } +sdist = { url = "https://files.pythonhosted.org/packages/cf/51/135dc6ba2c021ce32b40700c8c337db72d802893e15291f4b3056076582f/prek-0.4.14.tar.gz", hash = "sha256:f6d0952e31ffd6e508660749dd51b8d8de96e955ed12c40e411f3224f502fed2", size = 537668, upload-time = "2026-08-17T04:27:55.031Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/48/31/05e764397056194206169869b50cf2fee4dbbbc71b344705b9c0d878d4d8/platformdirs-4.9.2-py3-none-any.whl", hash = "sha256:9170634f126f8efdae22fb58ae8a0eaa86f38365bc57897a6c4f781d1f5875bd", size = 21168, upload-time = "2026-02-16T03:56:08.891Z" }, -] - -[[package]] -name = "pre-commit" -version = "4.2.0" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "cfgv" }, - { name = "identify" }, - { name = "nodeenv" }, - { name = "pyyaml" }, - { name = "virtualenv" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/08/39/679ca9b26c7bb2999ff122d50faa301e49af82ca9c066ec061cfbc0c6784/pre_commit-4.2.0.tar.gz", hash = "sha256:601283b9757afd87d40c4c4a9b2b5de9637a8ea02eaff7adc2d0fb4e04841146", size = 193424, upload-time = "2025-03-18T21:35:20.987Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/74/a88bf1b1efeae488a0c0b7bdf71429c313722d1fc0f377537fbe554e6180/pre_commit-4.2.0-py2.py3-none-any.whl", hash = "sha256:a009ca7205f1eb497d10b845e52c838a98b6cdd2102a6c8e4540e94ee75c58bd", size = 220707, upload-time = "2025-03-18T21:35:19.343Z" }, + { url = "https://files.pythonhosted.org/packages/9d/75/727724174d419cab6e11e0c22c3fbcdd083312b0a0202dfa6befdb7f1bcb/prek-0.4.14-py3-none-linux_armv6l.whl", hash = "sha256:cf7fe2e07c99948ca3326fbd4254054cf4caa71a69cf9032be09c3938544e1e3", size = 5878406, upload-time = "2026-08-17T04:27:30.135Z" }, + { url = "https://files.pythonhosted.org/packages/34/b6/82dfb41347342b4c53c1ddd27cfa81d3e1cf4ad0d5d76493c51e8da58dc9/prek-0.4.14-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6c8043aa5555c2ada561f4c69429e5117f370ad92f7d708340613b0965e725bd", size = 6216669, upload-time = "2026-08-17T04:27:31.795Z" }, + { url = "https://files.pythonhosted.org/packages/5b/68/ade0ba8b8c0044a3f7ca1a5cd7c97bc10656398c67466b04235f0f0b7418/prek-0.4.14-py3-none-macosx_11_0_arm64.whl", hash = "sha256:355570f0d8366a56817e55f44edf736ffc9ff2323894e21cd739ab519d343541", size = 5728085, upload-time = "2026-08-17T04:27:33.322Z" }, + { url = "https://files.pythonhosted.org/packages/a0/cc/8ddb67fb000d1ad4c95288e6c7e27989d3c172cd88893e3a6f9cdd7199fb/prek-0.4.14-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:334f48a2b19e63c5ab741e601cb6088caaa11d1b75146900dc298b055452d551", size = 6043650, upload-time = "2026-08-17T04:27:34.699Z" }, + { url = "https://files.pythonhosted.org/packages/5b/49/2780489798147fa1e81fa017af384a40229802cf36680cf72c74478d143c/prek-0.4.14-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5fbb17270df2dcb3c1aa6edfaa68f850d7968862413e58b1572e41c981f644f9", size = 5786094, upload-time = "2026-08-17T04:27:36.282Z" }, + { url = "https://files.pythonhosted.org/packages/6a/2a/27a4cdfa767b46663eb32a2b5f78ebaaeefc6e5caa87a21587216a504e31/prek-0.4.14-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8ec46be0b1b45943a0746fdf69feeede274b0230bad32b11e2489bb600846081", size = 6239874, upload-time = "2026-08-17T04:27:37.984Z" }, + { url = "https://files.pythonhosted.org/packages/e0/ca/5ae58d95bc9dbad75ea13aea83fe0acfaca37d027c6bd7f9f1d1d97f3666/prek-0.4.14-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a21eea6ee996dbba351c1af8c6bd1959a61c37949757c0b97aef3edde82c126a", size = 6968009, upload-time = "2026-08-17T04:27:39.48Z" }, + { url = "https://files.pythonhosted.org/packages/bb/1c/c6a7800406f987559fc8e7c2cfd257a5a68096e806e953f143b488e00e4f/prek-0.4.14-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:34169cb1c8dfbe4b9cb7af164f5c1c3dff68929c61ca1e1de28d378b32720836", size = 6443370, upload-time = "2026-08-17T04:27:41.181Z" }, + { url = "https://files.pythonhosted.org/packages/92/38/4bf84223216ce2d31b500691d1644a9f35d6e468cb8ecb9a7dfbc66bc82c/prek-0.4.14-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:e39772ebf579f957fdbbc66ef6a7f7433bf603128cd60d5c804c70caac5f69c0", size = 6056449, upload-time = "2026-08-17T04:27:42.722Z" }, + { url = "https://files.pythonhosted.org/packages/75/0a/f1980039ab7bf8342c4aa4da2a4cafe40e6a840f456d5bbf86ba024fcdca/prek-0.4.14-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:a79e5940354a789e1311172a960c5daa75e3f643a47ee2be85b7d2ca1d7d980a", size = 5839941, upload-time = "2026-08-17T04:27:44.306Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e2/67f067dcb912e157bc7f4cd2aeb422a0de65e7744c675d7f439676f6c832/prek-0.4.14-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:60b6539c1b28804807849173a6b49d467f6f36ca98bbb4536f5e34114d79942a", size = 5762723, upload-time = "2026-08-17T04:27:45.737Z" }, + { url = "https://files.pythonhosted.org/packages/84/39/6669fff5c3336a2b79cf853c86b95547cf9be720a2ee7e4ae5eaa6cb46a1/prek-0.4.14-py3-none-musllinux_1_1_i686.whl", hash = "sha256:24cfabd9e5b8c5546ecaef562841a41a255a9dec1b7ae7761ce5a7a024ab9dd9", size = 6090040, upload-time = "2026-08-17T04:27:47.185Z" }, + { url = "https://files.pythonhosted.org/packages/2a/23/c23210be4c89795a854e76146c2465aaffc3d85ea83df61c1d4d5bb41bca/prek-0.4.14-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:1f08d368da45439f949885bb0b637bc7dfe6910140d5285fa8bae058697ddd06", size = 6570273, upload-time = "2026-08-17T04:27:48.673Z" }, + { url = "https://files.pythonhosted.org/packages/00/9c/4f10728ed36295347e84f01bb3e4c9078c9e337edc66215f5e2066b30551/prek-0.4.14-py3-none-win32.whl", hash = "sha256:5bfb30808ce2099c67d2a2d4cd68dc031e3fec1eeb61d73ef51a8f7c04d021cb", size = 5586715, upload-time = "2026-08-17T04:27:50.471Z" }, + { url = "https://files.pythonhosted.org/packages/4f/a7/d080a157d4e92927f7618d62d6a23979ef64a10c76a040cb8a8a194c50d7/prek-0.4.14-py3-none-win_amd64.whl", hash = "sha256:29364012d5704475d1092eb8a96ea30b163279096ad5e0c80a620fffa79bc639", size = 5969946, upload-time = "2026-08-17T04:27:51.971Z" }, + { url = "https://files.pythonhosted.org/packages/37/e1/6fc64bb82e7270f61707e00b6d3154a4592ae0b2d3bd308173aa7aabe0a1/prek-0.4.14-py3-none-win_arm64.whl", hash = "sha256:ff588c02e10c8d05150763607671a22d5585c0ff7036c884d3489c2726eb215c", size = 5729906, upload-time = "2026-08-17T04:27:53.52Z" }, ] [[package]] @@ -392,28 +346,15 @@ wheels = [ [[package]] name = "pymdown-extensions" -version = "10.16.1" +version = "11.0.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "markdown" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/55/b3/6d2b3f149bc5413b0a29761c2c5832d8ce904a1d7f621e86616d96f505cc/pymdown_extensions-10.16.1.tar.gz", hash = "sha256:aace82bcccba3efc03e25d584e6a22d27a8e17caa3f4dd9f207e49b787aa9a91", size = 853277, upload-time = "2025-07-28T16:19:34.167Z" } +sdist = { url = "https://files.pythonhosted.org/packages/21/a9/5f0c535ba3b08fe09270c16808e053a968868242ecbd5676d4e3a488bf28/pymdown_extensions-11.0.1.tar.gz", hash = "sha256:dd2905ae6fc5b75582fafb139a1266ffc754705efa902aa50067fa7ff4f94ec0", size = 857113, upload-time = "2026-07-02T17:59:22.955Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/06/43084e6cbd4b3bc0e80f6be743b2e79fbc6eed8de9ad8c629939fa55d972/pymdown_extensions-10.16.1-py3-none-any.whl", hash = "sha256:d6ba157a6c03146a7fb122b2b9a121300056384eafeec9c9f9e584adfdb2a32d", size = 266178, upload-time = "2025-07-28T16:19:31.401Z" }, -] - -[[package]] -name = "pyright" -version = "1.1.396" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nodeenv" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/bd/73/f20cb1dea1bdc1774e7f860fb69dc0718c7d8dea854a345faec845eb086a/pyright-1.1.396.tar.gz", hash = "sha256:142901f5908f5a0895be3d3befcc18bedcdb8cc1798deecaec86ef7233a29b03", size = 3814400, upload-time = "2025-03-02T02:12:16.732Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/80/be/ecb7cfb42d242b7ee764b52e6ff4782beeec00e3b943a3ec832b281f9da6/pyright-1.1.396-py3-none-any.whl", hash = "sha256:c635e473095b9138c471abccca22b9fedbe63858e0b40d4fc4b67da041891844", size = 5689355, upload-time = "2025-03-02T02:12:14.044Z" }, + { url = "https://files.pythonhosted.org/packages/d6/54/da572c98c0b77626a91b5d3b89f0231d8bff5125c225420908632f8b342d/pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", size = 269455, upload-time = "2026-07-02T17:59:21.271Z" }, ] [[package]] @@ -460,27 +401,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.8.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/95/d0/8ff5b189d125f4260f2255d143bf2fa413b69c2610c405ace7a0a8ec81ec/ruff-0.8.1.tar.gz", hash = "sha256:3583db9a6450364ed5ca3f3b4225958b24f78178908d5c4bc0f46251ccca898f", size = 3313222, upload-time = "2024-11-29T03:29:49.986Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a2/d6/1a6314e568db88acdbb5121ed53e2c52cebf3720d3437a76f82f923bf171/ruff-0.8.1-py3-none-linux_armv6l.whl", hash = "sha256:fae0805bd514066f20309f6742f6ee7904a773eb9e6c17c45d6b1600ca65c9b5", size = 10532605, upload-time = "2024-11-29T03:28:41.978Z" }, - { url = "https://files.pythonhosted.org/packages/89/a8/a957a8812e31facffb6a26a30be0b5b4af000a6e30c7d43a22a5232a3398/ruff-0.8.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b8a4f7385c2285c30f34b200ca5511fcc865f17578383db154e098150ce0a087", size = 10278243, upload-time = "2024-11-29T03:28:44.577Z" }, - { url = "https://files.pythonhosted.org/packages/a8/23/9db40fa19c453fabf94f7a35c61c58f20e8200b4734a20839515a19da790/ruff-0.8.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:cd054486da0c53e41e0086e1730eb77d1f698154f910e0cd9e0d64274979a209", size = 9917739, upload-time = "2024-11-29T03:28:53.895Z" }, - { url = "https://files.pythonhosted.org/packages/e2/a0/6ee2d949835d5701d832fc5acd05c0bfdad5e89cfdd074a171411f5ccad5/ruff-0.8.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2029b8c22da147c50ae577e621a5bfbc5d1fed75d86af53643d7a7aee1d23871", size = 10779153, upload-time = "2024-11-29T03:28:59.609Z" }, - { url = "https://files.pythonhosted.org/packages/7a/25/9c11dca9404ef1eb24833f780146236131a3c7941de394bc356912ef1041/ruff-0.8.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2666520828dee7dfc7e47ee4ea0d928f40de72056d929a7c5292d95071d881d1", size = 10304387, upload-time = "2024-11-29T03:29:02.512Z" }, - { url = "https://files.pythonhosted.org/packages/c8/b9/84c323780db1b06feae603a707d82dbbd85955c8c917738571c65d7d5aff/ruff-0.8.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:333c57013ef8c97a53892aa56042831c372e0bb1785ab7026187b7abd0135ad5", size = 11360351, upload-time = "2024-11-29T03:29:04.838Z" }, - { url = "https://files.pythonhosted.org/packages/6b/e1/9d4bbb2ace7aad14ded20e4674a48cda5b902aed7a1b14e6b028067060c4/ruff-0.8.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:288326162804f34088ac007139488dcb43de590a5ccfec3166396530b58fb89d", size = 12022879, upload-time = "2024-11-29T03:29:07.202Z" }, - { url = "https://files.pythonhosted.org/packages/75/28/752ff6120c0e7f9981bc4bc275d540c7f36db1379ba9db9142f69c88db21/ruff-0.8.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b12c39b9448632284561cbf4191aa1b005882acbc81900ffa9f9f471c8ff7e26", size = 11610354, upload-time = "2024-11-29T03:29:09.533Z" }, - { url = "https://files.pythonhosted.org/packages/ba/8c/967b61c2cc8ebd1df877607fbe462bc1e1220b4a30ae3352648aec8c24bd/ruff-0.8.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:364e6674450cbac8e998f7b30639040c99d81dfb5bbc6dfad69bc7a8f916b3d1", size = 12813976, upload-time = "2024-11-29T03:29:12.627Z" }, - { url = "https://files.pythonhosted.org/packages/7f/29/e059f945d6bd2d90213387b8c360187f2fefc989ddcee6bbf3c241329b92/ruff-0.8.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b22346f845fec132aa39cd29acb94451d030c10874408dbf776af3aaeb53284c", size = 11154564, upload-time = "2024-11-29T03:29:16.594Z" }, - { url = "https://files.pythonhosted.org/packages/55/47/cbd05e5a62f3fb4c072bc65c1e8fd709924cad1c7ec60a1000d1e4ee8307/ruff-0.8.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:b2f2f7a7e7648a2bfe6ead4e0a16745db956da0e3a231ad443d2a66a105c04fa", size = 10760604, upload-time = "2024-11-29T03:29:24.553Z" }, - { url = "https://files.pythonhosted.org/packages/bb/ee/4c3981c47147c72647a198a94202633130cfda0fc95cd863a553b6f65c6a/ruff-0.8.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:adf314fc458374c25c5c4a4a9270c3e8a6a807b1bec018cfa2813d6546215540", size = 10391071, upload-time = "2024-11-29T03:29:29.533Z" }, - { url = "https://files.pythonhosted.org/packages/6b/e6/083eb61300214590b188616a8ac6ae1ef5730a0974240fb4bec9c17de78b/ruff-0.8.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:a885d68342a231b5ba4d30b8c6e1b1ee3a65cf37e3d29b3c74069cdf1ee1e3c9", size = 10896657, upload-time = "2024-11-29T03:29:31.87Z" }, - { url = "https://files.pythonhosted.org/packages/77/bd/aacdb8285d10f1b943dbeb818968efca35459afc29f66ae3bd4596fbf954/ruff-0.8.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:d2c16e3508c8cc73e96aa5127d0df8913d2290098f776416a4b157657bee44c5", size = 11228362, upload-time = "2024-11-29T03:29:34.255Z" }, - { url = "https://files.pythonhosted.org/packages/39/72/fcb7ad41947f38b4eaa702aca0a361af0e9c2bf671d7fd964480670c297e/ruff-0.8.1-py3-none-win32.whl", hash = "sha256:93335cd7c0eaedb44882d75a7acb7df4b77cd7cd0d2255c93b28791716e81790", size = 8803476, upload-time = "2024-11-29T03:29:36.483Z" }, - { url = "https://files.pythonhosted.org/packages/e4/ea/cae9aeb0f4822c44651c8407baacdb2e5b4dcd7b31a84e1c5df33aa2cc20/ruff-0.8.1-py3-none-win_amd64.whl", hash = "sha256:2954cdbe8dfd8ab359d4a30cd971b589d335a44d444b6ca2cb3d1da21b75e4b6", size = 9614463, upload-time = "2024-11-29T03:29:38.814Z" }, - { url = "https://files.pythonhosted.org/packages/eb/76/fbb4bd23dfb48fa7758d35b744413b650a9fd2ddd93bca77e30376864414/ruff-0.8.1-py3-none-win_arm64.whl", hash = "sha256:55873cc1a473e5ac129d15eccb3c008c096b94809d693fc7053f588b67822737", size = 8959621, upload-time = "2024-11-29T03:29:43.977Z" }, +version = "0.16.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/61/b3/3213589383f8f1b3938781bd1278713f6d18621a14992b3e81fefb8a5ef9/ruff-0.16.3.tar.gz", hash = "sha256:e76d33a347661a84b5be6d043d0347fdc745dfdcf825a8f4fed64b5e26eebdf2", size = 4891904, upload-time = "2026-08-13T15:17:13.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/bf/96/493770daebd68c0a67f1549fdf519f53be51fc435186c0585bcc272fd76c/ruff-0.16.3-py3-none-linux_armv6l.whl", hash = "sha256:0c5710e247a58a4521e66e124ba9a74655b414f61ba3a2e9e3811e11098f48f7", size = 10902799, upload-time = "2026-08-13T15:16:27.382Z" }, + { url = "https://files.pythonhosted.org/packages/5e/e6/2becf3942fddc29a29b8df47691d456fb1085391a694f74d84513251418c/ruff-0.16.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:fe155130631a2471fd2e14a7a664a4dfbd7194b8229c3d7b2a40b21178639081", size = 11135539, upload-time = "2026-08-13T15:16:30.87Z" }, + { url = "https://files.pythonhosted.org/packages/3e/1e/4b8b72f0d006dbf19326aa99f9ca0ee2ff374187c4d301cf529a51aa06fe/ruff-0.16.3-py3-none-macosx_11_0_arm64.whl", hash = "sha256:e2ed719e14aa64d895c2ee922594a90a43c861a93f0575a95ff8c47cdbd13eb9", size = 10475095, upload-time = "2026-08-13T15:16:33.259Z" }, + { url = "https://files.pythonhosted.org/packages/92/32/2201fa49ba1f6c101ee321e83f051ac7a4b8d07b0ef6b4d3f2772b302275/ruff-0.16.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e0b1da805eb043654645d74d5de1e5ce2edc686e40790d2b86f56d71cc06a84", size = 10668771, upload-time = "2026-08-13T15:16:35.65Z" }, + { url = "https://files.pythonhosted.org/packages/c3/66/4afc5c8363bd04d45effce1b7c8713ca037d7a6740b7451a2403a6e3a972/ruff-0.16.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a37bdea0bbe21780f590bf437d6412c8c4e1b6cd010f91a65c2c40c5e5f5f870", size = 10699568, upload-time = "2026-08-13T15:16:38.195Z" }, + { url = "https://files.pythonhosted.org/packages/53/fd/c67d246bf36bf1698551c56de39e95cd07f70e64433e0098e6267d77061b/ruff-0.16.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09571e6d1288ed9be475207a3ac04ada404f1cd898104be0f6ab8d7df438575b", size = 11499365, upload-time = "2026-08-13T15:16:40.623Z" }, + { url = "https://files.pythonhosted.org/packages/67/0b/00ecbceb99a263af7b12f6f05ac3c92bc47b905e91adc3f207a836e3bc01/ruff-0.16.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c18c5a101eb540010638cc1ff3c84944d3adb3df62b8d98ca8f22ba484d3413", size = 12311728, upload-time = "2026-08-13T15:16:43.564Z" }, + { url = "https://files.pythonhosted.org/packages/54/b2/b7b3bb54f4d3f7db504e476ad4ab8de530dceebe2c061384b2757ee419e8/ruff-0.16.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8457c44f15033c85ddbb77b15d451df9e24e4bd03b628396dd3610cedc3b8f82", size = 11699896, upload-time = "2026-08-13T15:16:46.209Z" }, + { url = "https://files.pythonhosted.org/packages/c7/30/4c468429ac195addc5ee1b717b6ab1b66632786737ca3b2ed3443fb0c26a/ruff-0.16.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:294b95c4ae0cda9388525c2047778aa758d6b8d4bb876fd4e9eaa3ebc92343eb", size = 11058736, upload-time = "2026-08-13T15:16:48.823Z" }, + { url = "https://files.pythonhosted.org/packages/43/67/7a113cdaddf24b64d7f75b1242a99d04c82fcef4f6921fdbb832beaffb5f/ruff-0.16.3-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:3d0c7c40c87c2a820509c31ba007968da6e1306468c067b2d82fbfdbcd0e8474", size = 11586911, upload-time = "2026-08-13T15:16:51.913Z" }, + { url = "https://files.pythonhosted.org/packages/f1/c1/2e66f24c0f3ead25a5e660111778685e505e5da353c82802bf49f0cbe7b9/ruff-0.16.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:9f738c0fdfa8eed0b2ce7fb27ee7258208a92a68d7949e62aa15164bc7b389da", size = 10954265, upload-time = "2026-08-13T15:16:54.763Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ba/4cee23bf52cba9a058d3726de623624daf50ef9638868edd86f4126157f6/ruff-0.16.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fb785f0be25abe69d320415cd4f833b59e17ba7613d9ba6a958023b6bceb0a50", size = 10709886, upload-time = "2026-08-13T15:16:57.339Z" }, + { url = "https://files.pythonhosted.org/packages/82/df/7da7194fa5d9dc0a285f7e6fa5a4722e7c63faac0b45b614ded9314363a1/ruff-0.16.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:c5536e3acfbf9563085aa2be7b13c629c3077e902afc5b941ac44024dbb9f506", size = 11210392, upload-time = "2026-08-13T15:17:00.171Z" }, + { url = "https://files.pythonhosted.org/packages/35/85/7795f6e817af050e7517bf3e7aa9b061cce70ef33d280aad902c956c1ecf/ruff-0.16.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a2d85c02f9b8e165d85e6779184d38c4132de12603dab59c51c28e22584f9e4d", size = 11626910, upload-time = "2026-08-13T15:17:03.299Z" }, + { url = "https://files.pythonhosted.org/packages/78/9b/475b927cf27a5cbbda3c7bafb69ed6ff77e1d7923d5d85f17c2749d7ae32/ruff-0.16.3-py3-none-win32.whl", hash = "sha256:388cdf2166642bd9b13d52b5932d3170f34f8abed7e8d9a855f1d84b83645a0a", size = 10931415, upload-time = "2026-08-13T15:17:05.726Z" }, + { url = "https://files.pythonhosted.org/packages/b2/99/e2a2bfc4fbf0a1e8a916bc9ebe6fe6c58cc34c28e0ffc6ce281d572d1c2e/ruff-0.16.3-py3-none-win_amd64.whl", hash = "sha256:e80a7d69ca2a6d1c4d352ec91458cdca6e56c83cdbcabd93e4abe1e53591d948", size = 11445993, upload-time = "2026-08-13T15:17:08.353Z" }, + { url = "https://files.pythonhosted.org/packages/69/3e/4132e539aed78c148854d4997a2685b0ed4dc4e87110b59ce528564e184e/ruff-0.16.3-py3-none-win_arm64.whl", hash = "sha256:b8ca152da82c1acc1fa8d5874b15951935f0eef46f10e6954c83859011b6178a", size = 11399302, upload-time = "2026-08-13T15:17:10.908Z" }, ] [[package]] @@ -493,12 +434,28 @@ wheels = [ ] [[package]] -name = "typing-extensions" -version = "4.15.0" +name = "ty" +version = "0.0.73" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e5/90/c4e1bb4cead3b644c3e258a27f9b05c7dc5eb0ec96a4f5282194edae9e0d/ty-0.0.73.tar.gz", hash = "sha256:823d4ce0d237bfc7eb6bcee70842f2c0706113813a16951077840743712f4b74", size = 6712739, upload-time = "2026-08-19T03:12:43.381Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, + { url = "https://files.pythonhosted.org/packages/e4/0f/f5e1801e55cc631f2db193276675b30561b963a2403da832bffb5d100267/ty-0.0.73-py3-none-linux_armv6l.whl", hash = "sha256:90a946082bf9bc446b5e72973d9f4ff1222a240b2ca4c9e6eed61eb913e30810", size = 12715452, upload-time = "2026-08-19T03:12:06.673Z" }, + { url = "https://files.pythonhosted.org/packages/54/32/515dd05074c213b433524ab97eb003b0132ae7e358e0d75633ba7a314ed8/ty-0.0.73-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b7d6b5c6a6db7ea95fbbc16af514ef44a27a29a2fe1dc798900790364d170209", size = 12301870, upload-time = "2026-08-19T03:12:08.924Z" }, + { url = "https://files.pythonhosted.org/packages/50/4d/085b4889f0d4bbe4af8b96242d4a1cb209fff95967cfa239ea141983719b/ty-0.0.73-py3-none-macosx_11_0_arm64.whl", hash = "sha256:dd6f657f463e01372d8688f235be164750c8db722c97da27fa4903aa8d40b203", size = 12111741, upload-time = "2026-08-19T03:12:11.067Z" }, + { url = "https://files.pythonhosted.org/packages/95/f6/d6ec277cadfecf03ad4c18551b67c4c6eb7807a0560d801db14be99d7a89/ty-0.0.73-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fc2de468e33fd44c9ff1c43473a7316f4289480f5cba8995a67b6d22aee39ca9", size = 12196124, upload-time = "2026-08-19T03:12:13.14Z" }, + { url = "https://files.pythonhosted.org/packages/75/b7/ce78d8707563af9cae9bbd25328bfbc4931035085bd20089adf0c418f70e/ty-0.0.73-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2942fa0ef795a66034cdc8d75a72f453442f3b58ff2f69b4da05b7b954765b55", size = 12488557, upload-time = "2026-08-19T03:12:15.252Z" }, + { url = "https://files.pythonhosted.org/packages/d8/e8/329b9851b23502758c5c98e8cc875ea2a1b4c9674b4ca3a86da56a5063d3/ty-0.0.73-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e0f1ef14f642e18ac4e7a616a2796dcf7a5d82e28cd17f9796494acc7c4aabb", size = 13215606, upload-time = "2026-08-19T03:12:17.225Z" }, + { url = "https://files.pythonhosted.org/packages/36/38/67fedfd2cb77516ef0066b1642f487dba0eb3006493cf3475b15f5b8b228/ty-0.0.73-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:16981e15fdceedb37d0aff76c5ac25914595dfee2675af95335550064251ad22", size = 13665497, upload-time = "2026-08-19T03:12:19.286Z" }, + { url = "https://files.pythonhosted.org/packages/8e/b3/154f4dd48ec5eebc186ab4b822c6e62f982fc5ddfd262d6e3903c2acba44/ty-0.0.73-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:644b2bec8a2e2e4957a942ae81d6cff5571c489bb5a8675e4d3886de537a694d", size = 13351231, upload-time = "2026-08-19T03:12:21.353Z" }, + { url = "https://files.pythonhosted.org/packages/35/5f/d462496903fbe453fb76363f8478be929c8e6ff21e6928c57dcd7e5fa21f/ty-0.0.73-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:338d565be3186f50ff8e9d10483685549c2d23f0754485d5ede3b54f4319188a", size = 12782586, upload-time = "2026-08-19T03:12:23.667Z" }, + { url = "https://files.pythonhosted.org/packages/87/52/ec6d24b74abe3ec324204c1c71e6d0c6c76a17ffc15fd51d603b0a302abe/ty-0.0.73-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:11c7b6d839309d2c102cb3a4c03d817176bbfab5b2fccc95a75ec5c9597421c9", size = 13247134, upload-time = "2026-08-19T03:12:25.956Z" }, + { url = "https://files.pythonhosted.org/packages/26/20/cc74650fec56a54786c6d7c89e09576fcad3092be34cf21715d39a406a9b/ty-0.0.73-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:488572db7ff97fb50ea36a76250f2d617c9727d143da6c7bf0623276eb0fc507", size = 12309344, upload-time = "2026-08-19T03:12:28.122Z" }, + { url = "https://files.pythonhosted.org/packages/89/bd/4b0a9087f4315d7fbadf77a3ce44c816cc9ffabed1ced06cc5be81fbc414/ty-0.0.73-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:1b958ebceefbbf594e59eb8d3d55bbd033ce634026fcba3e4bc3179e78e45bb7", size = 12502319, upload-time = "2026-08-19T03:12:30.128Z" }, + { url = "https://files.pythonhosted.org/packages/11/80/0a925074911fe111912ea29d9eed309bcc183f43d2fb3eef07db056a0beb/ty-0.0.73-py3-none-musllinux_1_2_i686.whl", hash = "sha256:91a32993b3c34e42c3f323ad6c0399cb596bd1c27e9b7f20db7cd64c1067b68e", size = 12753688, upload-time = "2026-08-19T03:12:32.433Z" }, + { url = "https://files.pythonhosted.org/packages/24/6b/aeccaf89efbc2e112bd415340a22e2669ec998aa397242503e747b712ca4/ty-0.0.73-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bab8a19fbf51f479bddb2a12c5fabfe52f918a5590362321ed5d89b44eb62c15", size = 13069050, upload-time = "2026-08-19T03:12:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/d7/3e/eae485fd86c1585943fd4e1746b0757b2da01e2c43136ebe8c686fe1c7f1/ty-0.0.73-py3-none-win32.whl", hash = "sha256:03347a612f0fa020b19bfd8dbd521db6ecc75d377a3e4d4f6e6c2e62871da4cc", size = 12053187, upload-time = "2026-08-19T03:12:37.565Z" }, + { url = "https://files.pythonhosted.org/packages/a7/01/9b8b983786e3ce34924e372e8b76b92b508273ab65c589fc7e88cc03ee17/ty-0.0.73-py3-none-win_amd64.whl", hash = "sha256:cedd05122ded0b5dcc55431a370e974b747f99c41c290a3d2ab8c1867f197519", size = 12693838, upload-time = "2026-08-19T03:12:39.483Z" }, + { url = "https://files.pythonhosted.org/packages/ea/88/25333bbfea6a5dc064371d2002d3d4807db90b84d5448f9106b2712b0fbc/ty-0.0.73-py3-none-win_arm64.whl", hash = "sha256:e47068f8369dea5d641a26a2ad0a947a320b02ff87099b07e95de0323245a4dc", size = 12443573, upload-time = "2026-08-19T03:12:41.449Z" }, ] [[package]] @@ -510,20 +467,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/39/08/aaaad47bc4e9dc8c725e68f9d04865dbcb2052843ff09c97b08904852d84/urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4", size = 131584, upload-time = "2026-01-07T16:24:42.685Z" }, ] -[[package]] -name = "virtualenv" -version = "20.36.1" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "distlib" }, - { name = "filelock" }, - { name = "platformdirs" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/aa/a3/4d310fa5f00863544e1d0f4de93bddec248499ccf97d4791bc3122c9d4f3/virtualenv-20.36.1.tar.gz", hash = "sha256:8befb5c81842c641f8ee658481e42641c68b5eab3521d8e092d18320902466ba", size = 6032239, upload-time = "2026-01-09T18:21:01.296Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6a/2a/dc2228b2888f51192c7dc766106cd475f1b768c10caaf9727659726f7391/virtualenv-20.36.1-py3-none-any.whl", hash = "sha256:575a8d6b124ef88f6f51d56d656132389f961062a9177016a50e4f507bbcc19f", size = 6008258, upload-time = "2026-01-09T18:20:59.425Z" }, -] - [[package]] name = "wrapt" version = "2.0.1" From 2475d2bc9d84a600547c9d54052c624955f04591 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sat, 5 Sep 2026 13:08:02 +0200 Subject: [PATCH 2/8] Use hyphens for extension name --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 54676de..7ce3ebb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -27,7 +27,7 @@ dependencies = [ "markdown==3.10.3", "markdown-link-attr-modifier==0.2.1", "mdx-gh-links==0.4", - "mdx_truly_sane_lists==1.3", + "mdx-truly-sane-lists==1.3", "nh3==0.2.19", "pymdown-extensions==11.0.1", "requests==2.33.0", From 2397591001e44199d5fcd938dd016af886c9184e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sat, 5 Sep 2026 13:20:56 +0200 Subject: [PATCH 3/8] Run prek with GitHub Actions, and update install uv --- .github/workflows/buildExecutable.yaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/buildExecutable.yaml b/.github/workflows/buildExecutable.yaml index b1323c0..eb3bed8 100644 --- a/.github/workflows/buildExecutable.yaml +++ b/.github/workflows/buildExecutable.yaml @@ -17,10 +17,13 @@ jobs: with: python-version-file: ".python-version" - name: Install the latest version of uv - uses: astral-sh/setup-uv@v7 - - name: Build executable + uses: astral-sh/setup-uv@v10.0.1 + - name: Lint with prek run: | uv sync + uv run prek --all-files + - name: Build executable + run: | uv run pyinstaller l10nUtil.spec - name: Upload artifact uses: actions/upload-artifact@v7 From c56bc665c1b7562fc7db8c66bbd9caf68fb628d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sat, 5 Sep 2026 13:50:58 +0200 Subject: [PATCH 4/8] Lint readme --- readme.md | 60 ++++---- source/keyCommandsDoc.py | 11 +- source/l10nUtil.py | 44 +++--- source/markdownTranslate.py | 269 ++++++++++++------------------------ source/md2html.py | 14 +- 5 files changed, 148 insertions(+), 250 deletions(-) diff --git a/readme.md b/readme.md index 8992233..00beb6a 100644 --- a/readme.md +++ b/readme.md @@ -4,49 +4,49 @@ This repository is intended to support translations for [NVDA](https://github.co The following projects can be selected: -- NVDA: https://crowdin.com/project/nvda -- NVDA add-ons (not maintained by NV Access): https://crowdin.com/project/nvdaaddons +* NVDA: +* NVDA add-ons (not maintained by NV Access): If you want to use a different Crowdin project, store the project and file IDs in a config file with the `writeConfig` command mentioned below. ## Available Commands -- `checkPo` - Check one or more PO files for errors. - - Required: `poFilePaths` — one or more paths to the PO files to check. +* `checkPo` - Check one or more PO files for errors. + * Required: `poFilePaths` — one or more paths to the PO files to check. -- `xliff2md` - Convert an XLIFF file to a Markdown file. - - Required: `xliffPath` — path to the source XLIFF file; `mdPath` — path for the resulting Markdown file. - - Optional: `-u`/`--untranslated` — produce the untranslated version of the Markdown file. +* `xliff2md` - Convert an XLIFF file to a Markdown file. + * Required: `xliffPath` — path to the source XLIFF file; `mdPath` — path for the resulting Markdown file. + * Optional: `-u`/`--untranslated` — produce the untranslated version of the Markdown file. -- `md2xliff` - Convert a Markdown file to XLIFF. - - Required: `mdPath` — path to the Markdown file; `xliffPath` — path for the resulting XLIFF file. - - Optional: `-o`/`--oldXliffPath` — path to a previously generated XLIFF file used as a baseline so existing translated strings are retained and applied to the newly generated XLIFF file. -- `md2html` - Convert a Markdown file to HTML. - - Required: `mdPath` — path to the Markdown file; `htmlPath` — path for the resulting HTML file. - - Optional: `-l`/`--lang` — language code (default: `en`); `-t`/`--docType` — document type, one of `userGuide`, `developerGuide`, `changes`, `keyCommands`. +* `md2xliff` - Convert a Markdown file to XLIFF. + * Required: `mdPath` — path to the Markdown file; `xliffPath` — path for the resulting XLIFF file. + * Optional: `-o`/`--oldXliffPath` — path to a previously generated XLIFF file used as a baseline so existing translated strings are retained and applied to the newly generated XLIFF file. +* `md2html` - Convert a Markdown file to HTML. + * Required: `mdPath` — path to the Markdown file; `htmlPath` — path for the resulting HTML file. + * Optional: `-l`/`--lang` — language code (default: `en`); `-t`/`--docType` — document type, one of `userGuide`, `developerGuide`, `changes`, `keyCommands`. -- `xliff2html` - Convert an XLIFF file directly to HTML (combines `xliff2md` and `md2html`). - - Required: `xliffPath` — path to the source XLIFF file; `htmlPath` — path for the resulting HTML file. - - Optional: `-l`/`--lang` — language code (auto-detected from the XLIFF file if not provided); `-t`/`--docType` — document type, one of `userGuide`, `developerGuide`, `changes`, `keyCommands`; `-u`/`--untranslated` — produce the untranslated version. +* `xliff2html` - Convert an XLIFF file directly to HTML (combines `xliff2md` and `md2html`). + * Required: `xliffPath` — path to the source XLIFF file; `htmlPath` — path for the resulting HTML file. + * Optional: `-l`/`--lang` — language code (auto-detected from the XLIFF file if not provided); `-t`/`--docType` — document type, one of `userGuide`, `developerGuide`, `changes`, `keyCommands`; `-u`/`--untranslated` — produce the untranslated version. -- `downloadTranslationFile` - Download a translation file from Crowdin. - - Required: `language` — language code to download; `crowdinFilePath` — path of the file in Crowdin. - - Optional: `localFilePath` — local path to save the file (defaults to `crowdinFilePath`); `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). +* `downloadTranslationFile` - Download a translation file from Crowdin. + * Required: `language` — language code to download; `crowdinFilePath` — path of the file in Crowdin. + * Optional: `localFilePath` — local path to save the file (defaults to `crowdinFilePath`); `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). -- `uploadTranslationFile` - Upload a translation file to Crowdin. - - Required: `language` — language code to upload; `crowdinFilePath` — path of the file in Crowdin. - - Optional: `localFilePath` — path to the local file to upload (defaults to `crowdinFilePath`); `-o`/`--old` — path to the old unchanged XLIFF file to upload only new or changed translations; `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). +* `uploadTranslationFile` - Upload a translation file to Crowdin. + * Required: `language` — language code to upload; `crowdinFilePath` — path of the file in Crowdin. + * Optional: `localFilePath` — path to the local file to upload (defaults to `crowdinFilePath`); `-o`/`--old` — path to the old unchanged XLIFF file to upload only new or changed translations; `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). -- `uploadSourceFile` - Upload a source file to Crowdin. - - Required: `localFilePath` — local path to the file to upload. - - Optional: `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). +* `uploadSourceFile` - Upload a source file to Crowdin. + * Required: `localFilePath` — local path to the file to upload. + * Optional: `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). -- `exportTranslations` - Export translation files from Crowdin as a bundle. - - Required: `-o`/`--output` — directory to save the exported translation files. - - Optional: `-l`/`--language` — language code to export (exports all languages if not specified); `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). +* `exportTranslations` - Export translation files from Crowdin as a bundle. + * Required: `-o`/`--output` — directory to save the exported translation files. + * Optional: `-l`/`--language` — language code to export (exports all languages if not specified); `-c`/`--config` — path to the configuration file (options: `nvda`, `addon`, `default` for l10nConfig.yaml, or a custom path; defaults to `nvda`). -- `writeConfig` - Write the current Crowdin configuration (project ID and file list) to a YAML file. - - Optional: `-c`/`--configFile` — path for the YAML configuration file to write (defaults to `l10nConfig.yaml`); `-i`/`--id` — Crowdin project ID. +* `writeConfig` - Write the current Crowdin configuration (project ID and file list) to a YAML file. + * Optional: `-c`/`--configFile` — path for the YAML configuration file to write (defaults to `l10nConfig.yaml`); `-i`/`--id` — Crowdin project ID. ## Installation and Building an Executable diff --git a/source/keyCommandsDoc.py b/source/keyCommandsDoc.py index a88b3c2..9950947 100644 --- a/source/keyCommandsDoc.py +++ b/source/keyCommandsDoc.py @@ -1,7 +1,8 @@ +# -*- coding: UTF-8 -*- # A part of NonVisual Desktop Access (NVDA) # Copyright (C) 2010-2024 NV Access Limited, Mesar Hameed, Takuya Nishimoto -# This file may be used under the terms of the GNU General Public License, version 2 or later, as modified by the NVDA license. -# For full terms and any additional permissions, see the NVDA license file: https://github.com/nvaccess/nvda/blob/master/copying.txt +# This file is covered by the GNU General Public License. +# See the file COPYING for more details. """ Generates the Key Commands document from the User Guide. @@ -12,7 +13,7 @@ https://github.com/nvaccess/nvda/blob/master/projectDocs/dev/userGuideStandards.md """ -from enum import auto, Enum, IntEnum, StrEnum +from enum import auto, Enum, IntEnum, StrEnum # noqa: I001 import re from collections.abc import Iterator @@ -174,7 +175,7 @@ def _areHeadingsPending(self) -> bool: def _writeHeadings(self): level = self._kcLastHeadingLevel + 1 # Only write headings we haven't yet written. - for level, heading in enumerate(self._headings[level:], level): + for level, heading in enumerate(self._headings[level:], level): # noqa: B020 self._kcLines.append(heading.group(0)) self._kcLastHeadingLevel = level @@ -194,7 +195,7 @@ def _heading(self, m: re.Match, appendHeading: bool = True): def _handleSetting(self): if not self._settingsHeaderRow: raise KeyCommandsError( - "%d, setting command cannot be used before settingsSection command" % self._lineNum, + "%d, setting command cannot be used before settingsSection command" % self._lineNum, # noqa: UP031 ) tableHeadersRequired = False diff --git a/source/l10nUtil.py b/source/l10nUtil.py index de5a658..b3648ca 100644 --- a/source/l10nUtil.py +++ b/source/l10nUtil.py @@ -5,26 +5,27 @@ # See the file COPYING for more details. -import crowdin_api as crowdin -import tempfile -import lxml.etree -import os -import shutil import argparse -import markdownTranslate -import md2html -import requests import codecs +import os import re +import shutil import subprocess import sys -import zipfile +import tempfile import time -import yaml +import zipfile from dataclasses import dataclass, field from enum import StrEnum from pathlib import Path +import crowdin_api as crowdin +import lxml.etree +import markdownTranslate +import md2html +import requests +import yaml + POLLING_INTERVAL_SECONDS = 5 EXPORT_TIMEOUT_SECONDS = 60 * 10 # 10 minutes @@ -83,7 +84,7 @@ def path(self) -> str: return str(Path(self.value).resolve()) if hasattr(sys, "_MEIPASS"): # PyInstaller bundled executable. - basePath = Path(getattr(sys, "_MEIPASS")) + basePath = Path(sys._MEIPASS) else: # Development environment. basePath = Path(__file__).parent.parent / "config" @@ -254,7 +255,7 @@ def stripXliff(xliffPath: str, outputPath: str, oldXliffPath: str | None = None) f"./xliff:file/xliff:unit[@id='{unitID}']/xliff:segment/xliff:target", namespaces=namespace, ) - if oldTarget is not None and oldTarget.getparent().get("state") != "initial": + if oldTarget is not None and oldTarget.getparent().get("state") != "initial": # noqa: SIM102 if oldTarget.text == targetText: file.remove(unit) existingTranslationCount += 1 @@ -350,7 +351,7 @@ def uploadSourceFile(localFilePath: str | None) -> None: if res is None or "data" not in res or "id" not in res["data"]: raise ValueError("Crowdin storage upload failed or invalid response") storageId = res["data"]["id"] - except Exception as e: + except Exception as e: # noqa: BLE001 raise RuntimeError(f"Failed to upload file to Crowdin storage: {e}") print(f"Stored with ID {storageId}") fileId = files.get(filename) @@ -386,7 +387,7 @@ def uploadSourceFile(localFilePath: str | None) -> None: if res is None: raise ValueError("Crowdin update_file failed") print(f"Updated to revision {res['data']['revisionId']}") - except Exception as e: + except Exception as e: # noqa: BLE001 raise RuntimeError(f"Failed to add or update file in Crowdin: {e}") @@ -462,8 +463,7 @@ def exportTranslations(outputDir: str, language: str | None = None): response.raise_for_status() with open(zip_path, "wb") as f: - for chunk in response.iter_content(chunk_size=8192): - f.write(chunk) + f.writelines(response.iter_content(chunk_size=8192)) print(f"Archive saved to {zip_path}") print("Extracting translations...") @@ -629,7 +629,7 @@ def _checkSyntax(self) -> None: This will set the hasSyntaxError attribute to True if there is a syntax error. """ - result = subprocess.run( + result = subprocess.run( # noqa: PLW1510 (self.MSGFMT_PATH, "-o", "-", self._poPath), stdout=subprocess.DEVNULL, stderr=subprocess.PIPE, @@ -718,9 +718,7 @@ def check(self) -> bool: if self.alerts: return False self._checkMessages() - if self.alerts: - return False - return True + return not self.alerts # e.g. %s %d %10.2f %-5s (but not %%) or %%(name)s %(name)d RE_UNNAMED_PERCENT = re.compile( @@ -1069,7 +1067,7 @@ def main(): ) case "md2xliff": if args.oldXliffPath is not None: - temp_oldXliffFile = tempfile.NamedTemporaryFile( + temp_oldXliffFile = tempfile.NamedTemporaryFile( # noqa: SIM115 suffix=Path(args.oldXliffPath).suffix or ".xliff", delete=False, ) @@ -1098,7 +1096,7 @@ def main(): args.xliffPath, source=args.untranslated, ) - temp_mdFile = tempfile.NamedTemporaryFile( + temp_mdFile = tempfile.NamedTemporaryFile( # noqa: SIM115 suffix=".md", delete=False, mode="w", @@ -1148,7 +1146,7 @@ def main(): localFilePath = args.localFilePath or args.crowdinFilePath needsDelete = False if args.crowdinFilePath.endswith(".xliff"): - tmp = tempfile.NamedTemporaryFile( + tmp = tempfile.NamedTemporaryFile( # noqa: SIM115 suffix=".xliff", delete=False, mode="w", diff --git a/source/markdownTranslate.py b/source/markdownTranslate.py index 5e82869..ee466ca 100644 --- a/source/markdownTranslate.py +++ b/source/markdownTranslate.py @@ -1,10 +1,9 @@ # A part of NonVisual Desktop Access (NVDA) -# Copyright (C) 2024 NV Access Limited. -# This file is covered by the GNU General Public License. -# See the file COPYING for more details. +# Copyright (C) 2024-2026 NV Access Limited +# This file may be used under the terms of the GNU General Public License, version 2 or later, as modified by the NVDA license. +# For full terms and any additional permissions, see the NVDA license file: https://github.com/nvaccess/nvda/blob/master/copying.txt -from typing import Generator -from collections.abc import Iterable +from collections.abc import Generator # noqa: I001 import tempfile import os import contextlib @@ -29,14 +28,12 @@ re_postTableHeaderLine = re.compile(r"^(\|\s*-+\s*)+\|$") re_tableRow = re.compile(r"^(\|)(.+)(\|)$") re_translationID = re.compile(r"^(.*)\$\(ID:([0-9a-f-]+)\)(.*)$") -re_inlineMarkdownLintComment = re.compile(r"^(.*?)(?:\s*)(\s*)$") +re_inlineMarkdownLintComment = re.compile(r"^(.*?)(\s*)(\s*)$") def prettyPathString(path: str) -> str: cwd = os.getcwd() - if os.path.normcase(os.path.splitdrive(path)[0]) != os.path.normcase( - os.path.splitdrive(cwd)[0], - ): + if os.path.normcase(os.path.splitdrive(path)[0]) != os.path.normcase(os.path.splitdrive(cwd)[0]): return path return os.path.relpath(path, cwd) @@ -46,14 +43,9 @@ def createAndDeleteTempFilePath_contextManager( dir: str | None = None, prefix: str | None = None, suffix: str | None = None, -) -> Generator[str, None, None]: +) -> Generator[str]: """A context manager that creates a temporary file and deletes it when the context is exited""" - with tempfile.NamedTemporaryFile( - dir=dir, - prefix=prefix, - suffix=suffix, - delete=False, - ) as tempFile: + with tempfile.NamedTemporaryFile(dir=dir, prefix=prefix, suffix=suffix, delete=False) as tempFile: tempFilePath = tempFile.name tempFile.close() yield tempFilePath @@ -89,17 +81,15 @@ def getGitDir() -> str: def getRawGithubURLForPath(filePath: str) -> str: - rawGithubRepoURL = getGithubRepoURL() gitDirPath = getGitDir() commitID = getLastCommitID(filePath) relativePath = os.path.relpath(os.path.abspath(filePath), gitDirPath) relativePath = relativePath.replace("\\", "/") - return f"{rawGithubRepoURL}/{commitID}/{relativePath}" + return f"{getGithubRepoURL()}/{commitID}/{relativePath}" def getGithubRepoURL() -> str: """Get the base ``raw.githubusercontent.com`` URL for the repository. - Reads the ``origin`` remote from the local git config and converts either an SSH (``git@github.com:…``) or HTTPS (``https://github.com/…``) URL to ``https://raw.githubusercontent.com/{owner}/{repo}``. @@ -115,30 +105,33 @@ def getGithubRepoURL() -> str: ) remote_url = result.stdout.strip() # Convert SSH or HTTPS URL to raw GitHub URL format - if match := re.match(r"git@github\.com:(.+?)(?:\.git)?$", remote_url): - repo_path = match.group(1) - elif match := re.match(r"https://github\.com/(.+?)(?:\.git)?$", remote_url): + if (match := re.match(r"git@github\.com:(.+?)(?:\.git)?$", remote_url)) or ( + match := re.match(r"https://github\.com/(.+?)(?:\.git)?$", remote_url) + ): repo_path = match.group(1) else: raise ValueError(f"Cannot parse GitHub URL from git remote: {remote_url}") return f"https://raw.githubusercontent.com/{repo_path}" -def preprocessMarkdownLines(mdLines: Iterable[str]) -> Iterable[str]: - """ - Preprocess markdown lines such as removing inline markdown lint comments.\ - :param mdLines: The markdown lines to preprocess - :returns: The preprocessed markdown lines - """ - for mdLine in mdLines: - # #18982: Remove markdown lint comments completely - not needed for intermediate markdown or final html. - mdLine = re_inlineMarkdownLintComment.sub(r"\1\2", mdLine) - yield mdLine +def getSkeletonContentFromXliffText(skeletonText: str | None) -> str: + """Return skeleton content while preserving meaningful leading/trailing whitespace.""" + if skeletonText is None: + return "" + # Skeleton content is written as \n{content}\n. + # Remove only wrapper newlines, not significant whitespace inside the skeleton itself. + skeletonText = skeletonText.removeprefix("\n") + skeletonText = skeletonText.removesuffix("\n") + return skeletonText def skeletonizeLine(mdLine: str) -> str | None: prefix = "" suffix = "" + markdownLintComment = "" + if m := re_inlineMarkdownLintComment.match(mdLine): + mdLine, markdownLintComment, trailingWhitespace = m.groups() + mdLine = f"{mdLine}{trailingWhitespace}" if ( mdLine.isspace() or mdLine.strip() == "[TOC]" @@ -148,20 +141,18 @@ def skeletonizeLine(mdLine: str) -> str | None: return None elif m := re_heading.match(mdLine): prefix, content, suffix = m.groups() - elif m := re_bullet.match(mdLine): + elif (m := re_bullet.match(mdLine)) or (m := re_number.match(mdLine)): prefix, content = m.groups() - elif m := re_number.match(mdLine): - prefix, content = m.groups() - elif m := re_tableRow.match(mdLine): - prefix, content, suffix = m.groups() - elif m := re_kcTitle.match(mdLine): - prefix, content, suffix = m.groups() - elif m := re_kcSettingsSection.match(mdLine): - prefix, content, suffix = m.groups() + elif ( + (m := re_tableRow.match(mdLine)) + or (m := re_kcTitle.match(mdLine)) + or (m := re_kcSettingsSection.match(mdLine)) + ): + prefix, content, suffix = m.groups() # noqa: RUF059 elif re_comment.match(mdLine): return None ID = str(uuid.uuid4()) - return f"{prefix}$(ID:{ID}){suffix}\n" + return f"{prefix}$(ID:{ID}){suffix}{markdownLintComment}\n" @dataclass @@ -171,15 +162,13 @@ class Result_generateSkeleton: def generateSkeleton(mdPath: str, outputPath: str) -> Result_generateSkeleton: - print( - f"Generating skeleton file {prettyPathString(outputPath)} from {prettyPathString(mdPath)}...", - ) + print(f"Generating skeleton file {prettyPathString(outputPath)} from {prettyPathString(mdPath)}...") res = Result_generateSkeleton() with ( open(mdPath, "r", encoding="utf8") as mdFile, open(outputPath, "w", encoding="utf8", newline="") as outputFile, ): - for mdLine in preprocessMarkdownLines(mdFile.readlines()): + for mdLine in mdFile: res.numTotalLines += 1 skelLine = skeletonizeLine(mdLine) if skelLine: @@ -204,25 +193,18 @@ class Result_updateSkeleton: def extractSkeleton(xliffPath: str, outputPath: str): - print( - f"Extracting skeleton from {prettyPathString(xliffPath)} to {prettyPathString(outputPath)}...", - ) + print(f"Extracting skeleton from {prettyPathString(xliffPath)} to {prettyPathString(outputPath)}...") with contextlib.ExitStack() as stack: - outputFile = stack.enter_context( - open(outputPath, "w", encoding="utf8", newline=""), - ) + outputFile = stack.enter_context(open(outputPath, "w", encoding="utf8", newline="")) xliff = lxml.etree.parse(xliffPath) xliffRoot = xliff.getroot() namespace = {"xliff": "urn:oasis:names:tc:xliff:document:2.0"} if xliffRoot.tag != "{urn:oasis:names:tc:xliff:document:2.0}xliff": raise ValueError("Not an xliff file") - skeletonNode = xliffRoot.find( - "./xliff:file/xliff:skeleton", - namespaces=namespace, - ) + skeletonNode = xliffRoot.find("./xliff:file/xliff:skeleton", namespaces=namespace) if skeletonNode is None: raise ValueError("No skeleton found in xliff file") - skeletonContent = skeletonNode.text.strip() + skeletonContent = getSkeletonContentFromXliffText(skeletonNode.text) outputFile.write(skeletonContent) print(f"Extracted skeleton to {prettyPathString(outputPath)}") @@ -241,11 +223,9 @@ def updateSkeleton( origMdFile = stack.enter_context(open(origMdPath, "r", encoding="utf8")) newMdFile = stack.enter_context(open(newMdPath, "r", encoding="utf8")) origSkelFile = stack.enter_context(open(origSkelPath, "r", encoding="utf8")) - outputFile = stack.enter_context( - open(outputPath, "w", encoding="utf8", newline=""), - ) - origMdLines = preprocessMarkdownLines(origMdFile.readlines()) - newMdLines = preprocessMarkdownLines(newMdFile.readlines()) + outputFile = stack.enter_context(open(outputPath, "w", encoding="utf8", newline="")) + origMdLines = origMdFile.readlines() + newMdLines = newMdFile.readlines() mdDiff = difflib.ndiff(list(origMdLines), list(newMdLines)) origSkelLines = iter(origSkelFile.readlines()) for mdDiffLine in mdDiff: @@ -254,6 +234,10 @@ def updateSkeleton( if mdDiffLine.startswith(" "): res.numUnchangedLines += 1 skelLine = next(origSkelLines) + # Extracted skeletons may lack a trailing newline on the last line. + # Preserve line boundaries when this unchanged line is followed by additions. + if mdDiffLine[2:].endswith("\n") and not skelLine.endswith("\n"): + skelLine = f"{skelLine}\n" if re_translationID.match(skelLine): res.numUnchangedTranslationPlaceholders += 1 outputFile.write(skelLine) @@ -310,9 +294,7 @@ def generateXliff( ) with contextlib.ExitStack() as stack: mdFile = stack.enter_context(open(mdPath, "r", encoding="utf8")) - outputFile = stack.enter_context( - open(outputPath, "w", encoding="utf8", newline=""), - ) + outputFile = stack.enter_context(open(outputPath, "w", encoding="utf8", newline="")) fileID = os.path.basename(mdPath) mdUri = getRawGithubURLForPath(mdPath) print(f"Including Github raw URL: {mdUri}") @@ -325,7 +307,7 @@ def generateXliff( res.numTranslatableStrings = 0 for lineNo, (mdLine, skelLine) in enumerate( zip_longest( - preprocessMarkdownLines(mdFile.readlines()), + mdFile.readlines(), skelContent.splitlines(keepends=True), ), start=1, @@ -336,41 +318,29 @@ def generateXliff( res.numTranslatableStrings += 1 prefix, ID, suffix = m.groups() if prefix and not mdLine.startswith(prefix): - raise ValueError( - f'Line {lineNo}: does not start with "{prefix}", {mdLine=}, {skelLine=}', - ) + raise ValueError(f'Line {lineNo}: does not start with "{prefix}", {mdLine=}, {skelLine=}') if suffix and not mdLine.endswith(suffix): - raise ValueError( - f'Line {lineNo}: does not end with "{suffix}", {mdLine=}, {skelLine=}', - ) + raise ValueError(f'Line {lineNo}: does not end with "{suffix}", {mdLine=}, {skelLine=}') source = mdLine[len(prefix) : len(mdLine) - len(suffix)] outputFile.write( f'\n\nline: {lineNo + 1}\n', ) if prefix: - outputFile.write( - f'prefix: {xmlEscape(prefix)}\n', - ) + outputFile.write(f'prefix: {xmlEscape(prefix)}\n') if suffix: - outputFile.write( - f'suffix: {xmlEscape(suffix)}\n', - ) + outputFile.write(f'suffix: {xmlEscape(suffix)}\n') outputFile.write( "\n" f"\n" f"{xmlEscape(source)}\n" "\n" - "\n", # fmt: skip + "\n", # fmt: skip # noqa: RUF028 ) else: if mdLine != skelLine: - raise ValueError( - f"Line {lineNo}: {mdLine=} does not match {skelLine=}", - ) + raise ValueError(f"Line {lineNo}: {mdLine=} does not match {skelLine=}") outputFile.write("\n") - print( - f"Generated xliff file with {res.numTranslatableStrings} translatable strings", - ) + print(f"Generated xliff file with {res.numTranslatableStrings} translatable strings") return res @@ -391,27 +361,15 @@ def updateXliff( ) with contextlib.ExitStack() as stack: origMdPath = stack.enter_context( - createAndDeleteTempFilePath_contextManager( - dir=outputDir, - prefix="generated_", - suffix=".md", - ), + createAndDeleteTempFilePath_contextManager(dir=outputDir, prefix="generated_", suffix=".md"), ) generateMarkdown(xliffPath=xliffPath, outputPath=origMdPath, translated=False) origSkelPath = stack.enter_context( - createAndDeleteTempFilePath_contextManager( - dir=outputDir, - prefix="extracted_", - suffix=".skel", - ), + createAndDeleteTempFilePath_contextManager(dir=outputDir, prefix="extracted_", suffix=".skel"), ) extractSkeleton(xliffPath=xliffPath, outputPath=origSkelPath) updatedSkelPath = stack.enter_context( - createAndDeleteTempFilePath_contextManager( - dir=outputDir, - prefix="updated_", - suffix=".skel", - ), + createAndDeleteTempFilePath_contextManager(dir=outputDir, prefix="updated_", suffix=".skel"), ) updateSkeleton( origMdPath=origMdPath, @@ -439,26 +397,21 @@ def translateXliff( ) res = Result_translateXliff() with contextlib.ExitStack() as stack: - pretranslatedMdFile = stack.enter_context( - open(pretranslatedMdPath, "r", encoding="utf8"), - ) + pretranslatedMdFile = stack.enter_context(open(pretranslatedMdPath, "r", encoding="utf8")) xliff = lxml.etree.parse(xliffPath) xliffRoot = xliff.getroot() namespace = {"xliff": "urn:oasis:names:tc:xliff:document:2.0"} if xliffRoot.tag != "{urn:oasis:names:tc:xliff:document:2.0}xliff": raise ValueError("Not an xliff file") xliffRoot.set("trgLang", lang) - skeletonNode = xliffRoot.find( - "./xliff:file/xliff:skeleton", - namespaces=namespace, - ) + skeletonNode = xliffRoot.find("./xliff:file/xliff:skeleton", namespaces=namespace) if skeletonNode is None: raise ValueError("No skeleton found in xliff file") - skeletonContent = skeletonNode.text.strip() + skeletonContent = getSkeletonContentFromXliffText(skeletonNode.text) for lineNo, (skelLine, pretranslatedLine) in enumerate( zip_longest( skeletonContent.splitlines(), - preprocessMarkdownLines(pretranslatedMdFile.readlines()), + pretranslatedMdFile.readlines(), ), start=1, ): @@ -470,11 +423,9 @@ def translateXliff( raise ValueError( f'Line {lineNo} of translation does not start with "{prefix}", {pretranslatedLine=}, {skelLine=}', ) - if suffix and not pretranslatedLine.endswith(suffix): + if suffix and not pretranslatedLine.endswith(suffix): # noqa: SIM102 if allowBadAnchors and (m := re_heading.match(pretranslatedLine)): - print( - f"Warning: ignoring bad anchor in line {lineNo}: {pretranslatedLine}", - ) + print(f"Warning: ignoring bad anchor in line {lineNo}: {pretranslatedLine}") suffix = m.group(3) if suffix and not pretranslatedLine.endswith(suffix): raise ValueError( @@ -482,10 +433,7 @@ def translateXliff( ) translation = pretranslatedLine[len(prefix) : len(pretranslatedLine) - len(suffix)] try: - unit = xliffRoot.find( - f'./xliff:file/xliff:unit[@id="{ID}"]', - namespaces=namespace, - ) + unit = xliffRoot.find(f'./xliff:file/xliff:unit[@id="{ID}"]', namespaces=namespace) if unit is not None: segment = unit.find("./xliff:segment", namespaces=namespace) if segment is not None: @@ -506,9 +454,7 @@ def translateXliff( f"Line {lineNo}: pretranslated line {pretranslatedLine!r}, does not match skeleton line {skelLine!r}", ) xliff.write(outputPath, encoding="utf8", xml_declaration=True) - print( - f"Translated xliff file with {res.numTranslatedStrings} translated strings", - ) + print(f"Translated xliff file with {res.numTranslatedStrings} translated strings") return res @@ -520,40 +466,26 @@ class Result_generateMarkdown: numBadTranslationStrings = 0 -def generateMarkdown( - xliffPath: str, - outputPath: str, - translated: bool = True, -) -> Result_generateMarkdown: - print( - f"Generating markdown file {prettyPathString(outputPath)} from {prettyPathString(xliffPath)}...", - ) +def generateMarkdown(xliffPath: str, outputPath: str, translated: bool = True) -> Result_generateMarkdown: + print(f"Generating markdown file {prettyPathString(outputPath)} from {prettyPathString(xliffPath)}...") res = Result_generateMarkdown() with contextlib.ExitStack() as stack: - outputFile = stack.enter_context( - open(outputPath, "w", encoding="utf8", newline=""), - ) + outputFile = stack.enter_context(open(outputPath, "w", encoding="utf8", newline="")) xliff = lxml.etree.parse(xliffPath) xliffRoot = xliff.getroot() namespace = {"xliff": "urn:oasis:names:tc:xliff:document:2.0"} if xliffRoot.tag != "{urn:oasis:names:tc:xliff:document:2.0}xliff": raise ValueError("Not an xliff file") - skeletonNode = xliffRoot.find( - "./xliff:file/xliff:skeleton", - namespaces=namespace, - ) + skeletonNode = xliffRoot.find("./xliff:file/xliff:skeleton", namespaces=namespace) if skeletonNode is None: raise ValueError("No skeleton found in xliff file") - skeletonContent = skeletonNode.text.strip() + skeletonContent = getSkeletonContentFromXliffText(skeletonNode.text) for lineNum, line in enumerate(skeletonContent.splitlines(keepends=True), 1): res.numTotalLines += 1 if m := re_translationID.match(line): prefix, ID, suffix = m.groups() res.numTranslatableStrings += 1 - unit = xliffRoot.find( - f'./xliff:file/xliff:unit[@id="{ID}"]', - namespaces=namespace, - ) + unit = xliffRoot.find(f'./xliff:file/xliff:unit[@id="{ID}"]', namespaces=namespace) if unit is None: raise ValueError(f"Cannot locate Unit {ID} in xliff file") segment = unit.find("./xliff:segment", namespaces=namespace) @@ -597,16 +529,14 @@ def generateMarkdown( def ensureMarkdownFilesMatch(path1: str, path2: str, allowBadAnchors: bool = False): - print( - f"Ensuring files {prettyPathString(path1)} and {prettyPathString(path2)} match...", - ) + print(f"Ensuring files {prettyPathString(path1)} and {prettyPathString(path2)} match...") with contextlib.ExitStack() as stack: file1 = stack.enter_context(open(path1, "r", encoding="utf8")) file2 = stack.enter_context(open(path2, "r", encoding="utf8")) for lineNo, (line1, line2) in enumerate( zip_longest( - preprocessMarkdownLines(file1.readlines()), - preprocessMarkdownLines(file2.readlines()), + file1.readlines(), + file2.readlines(), ), start=1, ): @@ -632,15 +562,11 @@ def ensureMarkdownFilesMatch(path1: str, path2: str, allowBadAnchors: bool = Fal ) continue if allowBadAnchors and (m1 := re_heading.match(line1)) and (m2 := re_heading.match(line2)): - print( - f"Warning: ignoring bad anchor in headings at line {lineNo}: {line1}, {line2}", - ) + print(f"Warning: ignoring bad anchor in headings at line {lineNo}: {line1}, {line2}") line1 = m1.group(1) + m1.group(2) line2 = m2.group(1) + m2.group(2) if line1 != line2: - raise ValueError( - f"Files do not match at line {lineNo}: {line1=} {line2=}", - ) + raise ValueError(f"Files do not match at line {lineNo}: {line1=} {line2=}") print("Files match") @@ -680,7 +606,7 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): outputPath=langXliffPath, allowBadAnchors=True, ) - except Exception as e: + except Exception as e: # noqa: BLE001 print(f"Failed to translate {langDir}: {e}") continue rebuiltLangMdPath = os.path.join(langDirPath, f"rebuilt_{mdBaseName}.md") @@ -689,20 +615,14 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): xliffPath=langXliffPath, outputPath=rebuiltLangMdPath, ) - except Exception as e: + except Exception as e: # noqa: BLE001 print(f"Failed to rebuild {langDir} markdown: {e}") os.remove(langXliffPath) continue try: - ensureMarkdownFilesMatch( - rebuiltLangMdPath, - langPretranslatedMdPath, - allowBadAnchors=True, - ) - except Exception as e: - print( - f"Rebuilt {langDir} markdown does not match pretranslated markdown: {e}", - ) + ensureMarkdownFilesMatch(rebuiltLangMdPath, langPretranslatedMdPath, allowBadAnchors=True) + except Exception as e: # noqa: BLE001 + print(f"Rebuilt {langDir} markdown does not match pretranslated markdown: {e}") os.remove(langXliffPath) continue os.remove(rebuiltLangMdPath) @@ -710,18 +630,12 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): succeededLangs.add(langDir) if len(skippedLangs) > 0: print(f"Skipped {len(skippedLangs)} languages already pretranslated.") - print( - f"Pretranslated {len(succeededLangs)} out of {len(allLangs) - len(skippedLangs)} languages.", - ) + print(f"Pretranslated {len(succeededLangs)} out of {len(allLangs) - len(skippedLangs)} languages.") if __name__ == "__main__": mainParser = argparse.ArgumentParser() - commandParser = mainParser.add_subparsers( - title="commands", - dest="command", - required=True, - ) + commandParser = mainParser.add_subparsers(title="commands", dest="command", required=True) generateXliffParser = commandParser.add_parser("generateXliff") generateXliffParser.add_argument( "-m", @@ -821,9 +735,7 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): action="store_false", help="Generate the markdown file with the untranslated strings", ) - ensureMarkdownFilesMatchParser = commandParser.add_parser( - "ensureMarkdownFilesMatch", - ) + ensureMarkdownFilesMatchParser = commandParser.add_parser("ensureMarkdownFilesMatch") ensureMarkdownFilesMatchParser.add_argument( dest="path1", type=str, @@ -862,11 +774,7 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): outputPath=args.output, ) case "generateMarkdown": - generateMarkdown( - xliffPath=args.xliff, - outputPath=args.output, - translated=args.translated, - ) + generateMarkdown(xliffPath=args.xliff, outputPath=args.output, translated=args.translated) case "translateXliff": translateXliff( xliffPath=args.xliff, @@ -875,10 +783,7 @@ def pretranslateAllPossibleLanguages(langsDir: str, mdBaseName: str): outputPath=args.output, ) case "pretranslateLangs": - pretranslateAllPossibleLanguages( - langsDir=args.langsDir, - mdBaseName=args.mdBaseName, - ) + pretranslateAllPossibleLanguages(langsDir=args.langsDir, mdBaseName=args.mdBaseName) case "ensureMarkdownFilesMatch": ensureMarkdownFilesMatch(path1=args.path1, path2=args.path2) case _: diff --git a/source/md2html.py b/source/md2html.py index 457ab97..52e8935 100644 --- a/source/md2html.py +++ b/source/md2html.py @@ -3,7 +3,7 @@ # This file may be used under the terms of the GNU General Public License, version 2 or later. # For more details see: https://www.gnu.org/licenses/gpl-2.0.html -import argparse +import argparse # noqa: I001 from copy import deepcopy import io import re @@ -46,7 +46,7 @@ def __getattr__(attrName: str) -> Any: ) # Return a frozenset to match the API of the deprecated DEFAULT_EXTENSIONS symbol. return frozenset(_DEFAULT_EXTENSIONS_ORDERED) - raise AttributeError(f"module {repr(__name__)} has no attribute {repr(attrName)}") + raise AttributeError(f"module {__name__!r} has no attribute {attrName!r}") EXTENSIONS_CONFIG = { @@ -85,7 +85,7 @@ def _getTitle(mdBuffer: io.StringIO, isKeyCommands: bool = False) -> str: TITLE_RE = re.compile(r"^$") # Make next read at start of buffer mdBuffer.seek(0) - for line in mdBuffer.readlines(): + for line in mdBuffer: match = TITLE_RE.match(line.strip()) if match: return match.group(1) @@ -231,13 +231,7 @@ def main(source: str, dest: str, lang: str = "en", docType: str | None = None): if __name__ == "__main__": args = argparse.ArgumentParser() - args.add_argument( - "-l", - "--lang", - help="Language code", - action="store", - default="en", - ) + args.add_argument("-l", "--lang", help="Language code", action="store", default="en") args.add_argument( "-t", "--docType", From a7c997d771a667c22d6499dddd672089cc392d07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sat, 5 Sep 2026 13:55:20 +0200 Subject: [PATCH 5/8] Update config for add-on template --- config/addonTemplate.yaml | 76 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 2 deletions(-) diff --git a/config/addonTemplate.yaml b/config/addonTemplate.yaml index 3becfb5..bc59810 100644 --- a/config/addonTemplate.yaml +++ b/config/addonTemplate.yaml @@ -5,15 +5,31 @@ files: BMI.po: 300 BMI.pot: 300 BMI.xliff: 302 + BrailleExtender.po: 592 + BrailleExtender.pot: 592 + IndentNav.po: 578 + IndentNav.pot: 578 MSEdgeDiscardAnnouncements.po: 372 MSEdgeDiscardAnnouncements.pot: 372 MSEdgeDiscardAnnouncements.xliff: 374 SentenceNav.po: 360 SentenceNav.pot: 360 SentenceNav.xliff: 362 + TeleNVDA.po: 588 + TeleNVDA.pot: 588 + TeleNVDA.xliff: 616 + VLC.po: 582 + VLC.pot: 582 + askOpenRouter.po: 458 + askOpenRouter.pot: 458 + askOpenRouter.xliff: 456 beepKeyboard.po: 408 beepKeyboard.pot: 408 beepKeyboard.xliff: 410 + brailleEssentials.po: 627 + brailleEssentials.pot: 627 + calibre.po: 586 + calibre.pot: 586 charInfo.po: 296 charInfo.pot: 296 charInfo.xliff: 298 @@ -26,12 +42,18 @@ files: columnsReview.po: 332 columnsReview.pot: 332 columnsReview.xliff: 334 + contactsManager.po: 645 + contactsManager.pot: 645 + contactsManager.xliff: 647 controlUsageAssistant.po: 260 controlUsageAssistant.pot: 260 controlUsageAssistant.xliff: 262 cursorLocator.po: 224 cursorLocator.pot: 224 cursorLocator.xliff: 436 + customBrowseMode.po: 629 + customBrowseMode.pot: 629 + customBrowseMode.xliff: 631 customNotifications.po: 244 customNotifications.pot: 244 customNotifications.xliff: 268 @@ -41,6 +63,11 @@ files: debugHelper.po: 428 debugHelper.pot: 428 debugHelper.xliff: 430 + dengjen_neural_voices.po: 661 + dengjen_neural_voices.pot: 661 + dotPad.po: 663 + dotPad.pot: 663 + dotPad.xliff: 665 dropbox.po: 416 dropbox.pot: 416 dropbox.xliff: 418 @@ -62,6 +89,9 @@ files: evtTracker.po: 438 evtTracker.pot: 438 evtTracker.xliff: 440 + favoriteLinks.po: 643 + favoriteLinks.pot: 643 + favoriteLinks.xliff: 637 goldenCursor.po: 368 goldenCursor.pot: 368 goldenCursor.xliff: 370 @@ -77,6 +107,12 @@ files: mp3DirectCut.po: 404 mp3DirectCut.pot: 404 mp3DirectCut.xliff: 406 + noBeepsSpeechMode.po: 570 + noBeepsSpeechMode.pot: 570 + noBeepsSpeechMode.xliff: 602 + notepadMarkdownBrowseMode.po: 659 + notepadMarkdownBrowseMode.pot: 659 + notepadMarkdownBrowseMode.xliff: 657 numpadNavMode.po: 412 numpadNavMode.pot: 412 numpadNavMode.xliff: 414 @@ -95,16 +131,23 @@ files: pcKbBrl.po: 228 pcKbBrl.pot: 228 pcKbBrl.xliff: 276 + perky.po: 633 + perky.pot: 633 + perky.xliff: 635 + placeMarkers.po: 576 + placeMarkers.pot: 576 + placeMarkers.xliff: 610 proxy.po: 384 proxy.pot: 384 proxy.xliff: 386 rdAccess.po: 288 rdAccess.pot: 288 rdAccess.xliff: 290 - readFeeds.md: 450 readFeeds.po: 232 readFeeds.pot: 232 readFeeds.xliff: 278 + readonlyProfiles.po: 618 + readonlyProfiles.pot: 618 readonlyProfiles.xliff: 270 reportSymbols.po: 236 reportSymbols.pot: 236 @@ -127,6 +170,12 @@ files: searchWith.po: 388 searchWith.pot: 388 searchWith.xliff: 390 + showSelectionWhenBrailleTetheredToReview.po: 568 + showSelectionWhenBrailleTetheredToReview.pot: 568 + showSelectionWhenBrailleTetheredToReview.xliff: 600 + soundSplitter.po: 584 + soundSplitter.pot: 584 + soundSplitter.xliff: 614 speechLogger.po: 348 speechLogger.pot: 348 speechLogger.xliff: 350 @@ -136,10 +185,21 @@ files: systrayList.po: 340 systrayList.pot: 340 systrayList.xliff: 342 + terminalAccess.po: 590 + terminalAccess.pot: 590 + thunderbirdPlus.po: 572 + thunderbirdPlus.pot: 572 + thunderbirdPlus.xliff: 604 + toneMaster.po: 574 + toneMaster.pot: 574 + toneMaster.xliff: 608 tonysEnhancements.po: 304 tonysEnhancements.pot: 304 tonysEnhancements.xliff: 306 - translateNvdaAddonsWithCrowdin.md: 448 + toolbarsExplorer.po: 580 + toolbarsExplorer.pot: 580 + toolbarsExplorer.xliff: 612 + trainingKeyboardCommands.xliff: 606 translateNvdaAddonsWithCrowdin.po: 446 translateNvdaAddonsWithCrowdin.pot: 446 unicodeBrailleInput.po: 328 @@ -160,7 +220,19 @@ files: winWizard.po: 344 winWizard.pot: 344 winWizard.xliff: 346 + windowState.po: 653 + windowState.pot: 653 + windowState.xliff: 655 + wintenApps.po: 639 + wintenApps.pot: 639 + wintenApps.xliff: 641 wordNav.po: 364 wordNav.pot: 364 wordNav.xliff: 366 + wordPredictor.po: 649 + wordPredictor.pot: 649 + wordPredictor.xliff: 651 + zoomEnhancements.po: 623 + zoomEnhancements.pot: 623 + zoomEnhancements.xliff: 625 projectId: 780748 From 56e98a5f938af540bccb4f42bc4a077fcdf96cf8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Sun, 6 Sep 2026 05:50:37 +0200 Subject: [PATCH 6/8] Update pyproject --- pyproject.toml | 7 +++--- uv.lock | 64 +++++++++++++++++++++++++++----------------------- 2 files changed, 37 insertions(+), 34 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7ce3ebb..4d660e7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,9 +28,10 @@ dependencies = [ "markdown-link-attr-modifier==0.2.1", "mdx-gh-links==0.4", "mdx-truly-sane-lists==1.3", - "nh3==0.2.19", + "nh3==0.3.6", "pymdown-extensions==11.0.1", - "requests==2.33.0", + "pyphen==0.18.1", + "requests==2.34.2", ] [project.urls] Repository = "https://github.com/nvaccess/nvdaL10n" @@ -89,8 +90,6 @@ python-platform = "win32" # Tell ty where to load python code from (ported from pyright's extraPaths). extra-paths = [ "./source", - # Used internally in NVDA - "./miscDeps/python", ] [tool.ty.src] diff --git a/uv.lock b/uv.lock index 834390a..69028b5 100644 --- a/uv.lock +++ b/uv.lock @@ -186,33 +186,26 @@ wheels = [ [[package]] name = "nh3" -version = "0.2.19" +version = "0.3.6" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/1d/32/3b8d8471d006333bac3175ad37402414d985ed3f8650a01a33e0e86b9824/nh3-0.2.19.tar.gz", hash = "sha256:790056b54c068ff8dceb443eaefb696b84beff58cca6c07afd754d17692a4804", size = 17327, upload-time = "2024-11-30T04:05:56.854Z" } +sdist = { url = "https://files.pythonhosted.org/packages/5e/1b/ef84624f14954d270f74060a19fc550dd4f06656399447569afb584d8c06/nh3-0.3.6.tar.gz", hash = "sha256:f3736c9dd3d1856f80cd031715b84ca75cda2bbb1ac802c3da26bfce590838d7", size = 24684, upload-time = "2026-06-22T00:47:02.008Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/e8/1d/cbd75a2313d96cd3903111667d3d07548fb45c8ecf5c315f37a8f6c202fa/nh3-0.2.19-cp313-cp313t-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:ec9c8bf86e397cb88c560361f60fdce478b5edb8b93f04ead419b72fbe937ea6", size = 1205181, upload-time = "2024-11-29T05:50:02.802Z" }, - { url = "https://files.pythonhosted.org/packages/f0/30/8e9ec472ce575fa6b98935920c91df637bf9342862bd943745441aec99eb/nh3-0.2.19-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0adf00e2b2026fa10a42537b60d161e516f206781c7515e4e97e09f72a8c5d0", size = 739174, upload-time = "2024-11-29T05:50:10.157Z" }, - { url = "https://files.pythonhosted.org/packages/5c/b5/d1f81c5ec5695464b69d8aa4529ecb5fd872cbfb29f879b4063bb9397da8/nh3-0.2.19-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:3805161c4e12088bd74752ba69630e915bc30fe666034f47217a2f16b16efc37", size = 758660, upload-time = "2024-11-29T05:50:13.97Z" }, - { url = "https://files.pythonhosted.org/packages/a0/5e/295a3a069f3b9dc35527eedd7b212f31311ef1f66a0e5f5f0acad6db9456/nh3-0.2.19-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:e3dedd7858a21312f7675841529941035a2ac91057db13402c8fe907aa19205a", size = 924377, upload-time = "2024-11-29T05:50:15.716Z" }, - { url = "https://files.pythonhosted.org/packages/71/e2/0f189d5054f22cdfdb16d16a2a41282f411a4c03f8418be47e0480bd5bfd/nh3-0.2.19-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:0b6820fc64f2ff7ef3e7253a093c946a87865c877b3889149a6d21d322ed8dbd", size = 992124, upload-time = "2024-11-29T05:50:17.637Z" }, - { url = "https://files.pythonhosted.org/packages/0d/87/2907edd61a2172527c5322036aa95ce6c18432ff280fc5cf78fe0f934c65/nh3-0.2.19-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:833b3b5f1783ce95834a13030300cea00cbdfd64ea29260d01af9c4821da0aa9", size = 913939, upload-time = "2024-11-29T05:50:20.435Z" }, - { url = "https://files.pythonhosted.org/packages/c7/a2/e0d3ea0175f28032d7d2bab765250f4e94ef131a7b3293e3df4cb254a5b2/nh3-0.2.19-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5d4f5e2189861b352b73acb803b5f4bb409c2f36275d22717e27d4e0c217ae55", size = 909051, upload-time = "2024-11-29T05:50:31.116Z" }, - { url = "https://files.pythonhosted.org/packages/5e/e1/f52cb1d54ba965b7d8bb1c884ca982be31d7f75ad9e7e5817f4af20002b3/nh3-0.2.19-cp313-cp313t-win32.whl", hash = "sha256:2b926f179eb4bce72b651bfdf76f8aa05d167b2b72bc2f3657fd319f40232adc", size = 540566, upload-time = "2024-11-29T05:50:38.437Z" }, - { url = "https://files.pythonhosted.org/packages/70/85/91a66edfab0adbf22468973d8abd4b93c951bbcbbe2121675ee468b912a2/nh3-0.2.19-cp313-cp313t-win_amd64.whl", hash = "sha256:ac536a4b5c073fdadd8f5f4889adabe1cbdae55305366fb870723c96ca7f49c3", size = 542368, upload-time = "2024-11-29T05:50:41.418Z" }, - { url = "https://files.pythonhosted.org/packages/32/9c/f8808cf6683d4852ba8862e25b98aa9116067ddec517938a1b6e8faadb43/nh3-0.2.19-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:c2e3f0d18cc101132fe10ab7ef5c4f41411297e639e23b64b5e888ccaad63f41", size = 1205140, upload-time = "2024-11-29T05:50:54.582Z" }, - { url = "https://files.pythonhosted.org/packages/04/0e/268401d9244a84935342d9f3ba5d22bd7d2fc10cfc7a8f59bde8f6721466/nh3-0.2.19-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:11270b16c1b012677e3e2dd166c1aa273388776bf99a3e3677179db5097ee16a", size = 763571, upload-time = "2024-11-29T05:51:03.504Z" }, - { url = "https://files.pythonhosted.org/packages/6f/0d/8be706feb6637d6e5db0eed09fd3f4e1008aee3d5d7161c9973d7aae1d13/nh3-0.2.19-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fc483dd8d20f8f8c010783a25a84db3bebeadced92d24d34b40d687f8043ac69", size = 750319, upload-time = "2024-11-29T05:51:05.512Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ce/1f5f9ba0194f6a882e4bda89ae831678e4b68aa3de91e11e2629a1e6a613/nh3-0.2.19-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:d53a4577b6123ca1d7e8483fad3e13cb7eda28913d516bd0a648c1a473aa21a9", size = 857636, upload-time = "2024-11-29T05:51:06.872Z" }, - { url = "https://files.pythonhosted.org/packages/e9/5d/5661a66f2950879a81fde5fbb6beb650c5647776aaec1a676e6b3ff4b6e5/nh3-0.2.19-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fdb20740d24ab9f2a1341458a00a11205294e97e905de060eeab1ceca020c09c", size = 821081, upload-time = "2024-11-29T05:51:08.202Z" }, - { url = "https://files.pythonhosted.org/packages/22/f8/454828f6f21516bf0c8c578e8bc2ab4f045e6b6fe5179602fe4dc2479da6/nh3-0.2.19-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d8325d51e47cb5b11f649d55e626d56c76041ba508cd59e0cb1cf687cc7612f1", size = 894452, upload-time = "2024-11-29T05:51:19.841Z" }, - { url = "https://files.pythonhosted.org/packages/2e/5d/36f5b78cbc631cac1c993bdc4608a0fe3148214bdb6d2c1266e228a2686a/nh3-0.2.19-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8eb7affc590e542fa7981ef508cd1644f62176bcd10d4429890fc629b47f0bc", size = 748281, upload-time = "2024-11-29T05:51:29.021Z" }, - { url = "https://files.pythonhosted.org/packages/98/da/d04f5f0e7ee8edab8ceecdbba9f1c614dc8cf07374141ff6ea3b615b3479/nh3-0.2.19-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2eb021804e9df1761abeb844bb86648d77aa118a663c82f50ea04110d87ed707", size = 767109, upload-time = "2024-11-29T05:51:31.222Z" }, - { url = "https://files.pythonhosted.org/packages/0e/5b/1232fb35c7d1182adb7d513fede644a81b5361259749781e6075c40a9125/nh3-0.2.19-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:a7b928862daddb29805a1010a0282f77f4b8b238a37b5f76bc6c0d16d930fd22", size = 924295, upload-time = "2024-11-29T05:51:33.078Z" }, - { url = "https://files.pythonhosted.org/packages/3c/fd/ae622d08518fd31360fd87a515700bc09913f2e57e7f010063f2193ea610/nh3-0.2.19-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:ed06ed78f6b69d57463b46a04f68f270605301e69d80756a8adf7519002de57d", size = 992038, upload-time = "2024-11-29T05:51:34.414Z" }, - { url = "https://files.pythonhosted.org/packages/56/78/226577c5e3fe379cb95265aa77736e191d859032c974169e6879c51c156f/nh3-0.2.19-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:df8eac98fec80bd6f5fd0ae27a65de14f1e1a65a76d8e2237eb695f9cd1121d9", size = 913866, upload-time = "2024-11-29T05:51:35.727Z" }, - { url = "https://files.pythonhosted.org/packages/a8/ca/bbd2b2dab31ceae38cfa673861cab81df5ed5be1fe47b6c4f5aa41729aa2/nh3-0.2.19-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:00810cd5275f5c3f44b9eb0e521d1a841ee2f8023622de39ffc7d88bd533d8e0", size = 908976, upload-time = "2024-11-29T05:51:43.698Z" }, - { url = "https://files.pythonhosted.org/packages/4c/8f/6452eb1184ad87cdd2cac7ee3ebd67a2aadb554d25572c1778efdf807e1e/nh3-0.2.19-cp38-abi3-win32.whl", hash = "sha256:7e98621856b0a911c21faa5eef8f8ea3e691526c2433f9afc2be713cb6fbdb48", size = 540528, upload-time = "2024-11-29T05:51:45.312Z" }, - { url = "https://files.pythonhosted.org/packages/58/d6/285df10307f16fcce9afbd133b04b4bc7d7f9b84b02f0f724bab30dacdd9/nh3-0.2.19-cp38-abi3-win_amd64.whl", hash = "sha256:75c7cafb840f24430b009f7368945cb5ca88b2b54bb384ebfba495f16bc9c121", size = 542316, upload-time = "2024-11-29T05:52:01.253Z" }, + { url = "https://files.pythonhosted.org/packages/f3/ab/a7653bce9a3b204be6a6931767a9e23595807bb84790ce6685e4d7e5bd08/nh3-0.3.6-cp38-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:a43ebd7543555c3ac1bc353023d0794e75cb76f6f18f19c32e95441496c0cc25", size = 1443564, upload-time = "2026-06-22T00:46:36.66Z" }, + { url = "https://files.pythonhosted.org/packages/41/21/e1084ab18eb589506335c7c7576f2d4643e9a0c0e33983ef0e549a256b96/nh3-0.3.6-cp38-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1b160831c9cdb06a6c79c2f9cdb11386602938f9af260d1c457a85add4f6f69", size = 838002, upload-time = "2026-06-22T00:46:38.101Z" }, + { url = "https://files.pythonhosted.org/packages/b0/94/f48d08e6f72a406300fa11d8acd929fea1a80d4bf750fa292cb10785f126/nh3-0.3.6-cp38-abi3-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d14bf7982e7a77c0c775634c29c07ce08b38a046df73e1c1f139b3e82f18a38e", size = 823045, upload-time = "2026-06-22T00:46:39.495Z" }, + { url = "https://files.pythonhosted.org/packages/25/bb/431615ba1d1d3eb63cde0f974f2114edf863a8a3f6049a12fed23fc241d3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:44673b27010051ab5a5e438a86ec31bbda61d4a77d7e900af6b7be3037c1abae", size = 1093171, upload-time = "2026-06-22T00:46:41.21Z" }, + { url = "https://files.pythonhosted.org/packages/0e/24/a0d80182a18919665fefd19c1c06f1d1df1c9a6455d0252de40c034a0bc3/nh3-0.3.6-cp38-abi3-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e6b7beece07525dc6e6b0fc2f104442de2ba328360ad00e50cbe2e1fd620447d", size = 1049217, upload-time = "2026-06-22T00:46:42.804Z" }, + { url = "https://files.pythonhosted.org/packages/0a/13/6f1e302ca674ac74362e150848ad56a1be5145391204f74facdb8e94df12/nh3-0.3.6-cp38-abi3-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:455469a29951edc92bc48b47ac2281c3f2609e6c4f6a047056449f8c2c23facf", size = 917372, upload-time = "2026-06-22T00:46:44.495Z" }, + { url = "https://files.pythonhosted.org/packages/5b/67/314f6151bad77a93d751978a344033e1fc890822f05f0416079338e34231/nh3-0.3.6-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:905f877dc66dd7aea4a76e54bcb26acb5ff8216f720c0017ccf63e0e6035698e", size = 806699, upload-time = "2026-06-22T00:46:45.99Z" }, + { url = "https://files.pythonhosted.org/packages/3c/a6/bfaa00046e58603507dcfc266c4778e3ab7adf68a5dedd73b6274b8d9314/nh3-0.3.6-cp38-abi3-manylinux_2_31_riscv64.whl", hash = "sha256:25c733bee928530556b1db0ea46c52cf5aa686146e38e60a6fc7cb801ef91cec", size = 835165, upload-time = "2026-06-22T00:46:47.617Z" }, + { url = "https://files.pythonhosted.org/packages/30/a8/fb2c38845efb703a9173bffdfc745fc64d2b0e55cfc73a3647d2f028250c/nh3-0.3.6-cp38-abi3-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f90d9a0cfdbee218994fdaaeeb5a0fde62d08f35e4eef0378ec1e2200172fd0", size = 858282, upload-time = "2026-06-22T00:46:49.276Z" }, + { url = "https://files.pythonhosted.org/packages/68/17/06e72a18ee9b572914447338237ca7eb164c0df901f141bc10d1282247a2/nh3-0.3.6-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:82ca5bf427ad1b216b65ede1a2e2d87dc49bec417ceba0f297213107d3cd9d78", size = 1014328, upload-time = "2026-06-22T00:46:51.026Z" }, + { url = "https://files.pythonhosted.org/packages/11/f9/3966c61455668c08853bf5e33b4bed93c421f3194ce4de896dc248d6f6ce/nh3-0.3.6-cp38-abi3-musllinux_1_2_armv7l.whl", hash = "sha256:f5ed5fe84aee7f39db95c214a7421bf0499fbf500fec6d86a4e29bfc37971438", size = 1098207, upload-time = "2026-06-22T00:46:52.674Z" }, + { url = "https://files.pythonhosted.org/packages/19/d3/479cb4ae440424825735d60525b53e3c77fd60fd6e6afc0e984f00eb0178/nh3-0.3.6-cp38-abi3-musllinux_1_2_i686.whl", hash = "sha256:082675ff87b9385ec430ffe6d5847ba7456cc39b73720cd4add472f9f4cffd56", size = 1056961, upload-time = "2026-06-22T00:46:54.335Z" }, + { url = "https://files.pythonhosted.org/packages/17/0c/6cdb5ee1e127be50dc8391e54bddc1f64e87bf4bfad0c55633320e2e02db/nh3-0.3.6-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36d06341bd501240d320f5942481ed5e6846136b666e1ba4faf802b78ebc875f", size = 1033829, upload-time = "2026-06-22T00:46:56.258Z" }, + { url = "https://files.pythonhosted.org/packages/e9/55/9de666ad975d6ccd77d799ea0add55ee2347aa81286ce21b2a97c070746b/nh3-0.3.6-cp38-abi3-win32.whl", hash = "sha256:5276ef17bdba9ad8040575c74072008b13aae429436e9d0429e718bb5f90f4da", size = 609081, upload-time = "2026-06-22T00:46:57.665Z" }, + { url = "https://files.pythonhosted.org/packages/82/fa/2b5d684e3edf1e81bfd02d298c78c3e3da77ca1d8a2be3183a79544a7548/nh3-0.3.6-cp38-abi3-win_amd64.whl", hash = "sha256:f338ac7d594c067679f1e99b4f5ec3906842979560f9d8f15d6bdfa39a353b10", size = 624461, upload-time = "2026-06-22T00:46:59.163Z" }, + { url = "https://files.pythonhosted.org/packages/7b/e5/7cafee2f0413ca4cb0ef3bd111e94d408a48810008b283ad8aee00dd1809/nh3-0.3.6-cp38-abi3-win_arm64.whl", hash = "sha256:69f365963f63a1e9bff53bdbb3c542c7c2efed3e163c9d5d83a772a2ac468c21", size = 603060, upload-time = "2026-06-22T00:47:00.596Z" }, ] [[package]] @@ -229,6 +222,7 @@ dependencies = [ { name = "nh3" }, { name = "pyinstaller" }, { name = "pymdown-extensions" }, + { name = "pyphen" }, { name = "requests" }, ] @@ -248,10 +242,11 @@ requires-dist = [ { name = "markdown-link-attr-modifier", specifier = "==0.2.1" }, { name = "mdx-gh-links", specifier = "==0.4" }, { name = "mdx-truly-sane-lists", specifier = "==1.3" }, - { name = "nh3", specifier = "==0.2.19" }, + { name = "nh3", specifier = "==0.3.6" }, { name = "pyinstaller", specifier = "==6.19.0" }, { name = "pymdown-extensions", specifier = "==11.0.1" }, - { name = "requests", specifier = "==2.33.0" }, + { name = "pyphen", specifier = "==0.18.1" }, + { name = "requests", specifier = "==2.34.2" }, ] [package.metadata.requires-dev] @@ -357,6 +352,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d6/54/da572c98c0b77626a91b5d3b89f0231d8bff5125c225420908632f8b342d/pymdown_extensions-11.0.1-py3-none-any.whl", hash = "sha256:db3943a62bab7e03af1364f0c4083e64b91fb097675a4b6cceccfbe9a77e5eb2", size = 269455, upload-time = "2026-07-02T17:59:21.271Z" }, ] +[[package]] +name = "pyphen" +version = "0.18.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/47/8430452269cd28863d73b903d07d329d058cf762527ff211b3864ba61fc7/pyphen-0.18.1.tar.gz", hash = "sha256:dbae6fbbe4f01cb206108b43573d857c67107be9d0e38eb1b08d6fa2210634a7", size = 2116411, upload-time = "2026-08-14T11:30:12.083Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/1d/23801cf008f71575f0a4800463f349afa5f04b27fe783178a45cdc4d5edf/pyphen-0.18.1-py3-none-any.whl", hash = "sha256:0aa9051e15928cecadd4c632cea0258ba57215b2a197a39baa46abcdb0f47e84", size = 2116143, upload-time = "2026-08-14T11:30:10.428Z" }, +] + [[package]] name = "pywin32-ctypes" version = "0.2.3" @@ -386,7 +390,7 @@ wheels = [ [[package]] name = "requests" -version = "2.33.0" +version = "2.34.2" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "certifi" }, @@ -394,9 +398,9 @@ dependencies = [ { name = "idna" }, { name = "urllib3" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/34/64/8860370b167a9721e8956ae116825caff829224fbca0ca6e7bf8ddef8430/requests-2.33.0.tar.gz", hash = "sha256:c7ebc5e8b0f21837386ad0e1c8fe8b829fa5f544d8df3b2253bff14ef29d7652", size = 134232, upload-time = "2026-03-25T15:10:41.586Z" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/c3/e2a2b89f2d3e2179abd6d00ebd70bff6273f37fb3e0cc209f48b39d00cbf/requests-2.34.2.tar.gz", hash = "sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed", size = 142856, upload-time = "2026-05-14T19:25:27.735Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/56/5d/c814546c2333ceea4ba42262d8c4d55763003e767fa169adc693bd524478/requests-2.33.0-py3-none-any.whl", hash = "sha256:3324635456fa185245e24865e810cecec7b4caf933d7eb133dcde67d48cee69b", size = 65017, upload-time = "2026-03-25T15:10:40.382Z" }, + { url = "https://files.pythonhosted.org/packages/a0/f4/c67b0b3f1b9245e8d266f0f112c500d50e5b4e83cb6f3b71b6528104182a/requests-2.34.2-py3-none-any.whl", hash = "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", size = 73075, upload-time = "2026-05-14T19:25:26.443Z" }, ] [[package]] From fe738ec18447f6b94a1e83c5bd101c0ac14f24c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Wed, 9 Sep 2026 05:05:09 +0200 Subject: [PATCH 7/8] Update spec collecting modules to run scons source user_docs in NVDA --- l10nUtil.spec | 81 ++++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 40 deletions(-) diff --git a/l10nUtil.spec b/l10nUtil.spec index 8981f7a..852fa91 100644 --- a/l10nUtil.spec +++ b/l10nUtil.spec @@ -1,49 +1,50 @@ -from PyInstaller.utils.hooks import collect_submodules +# -*- mode: python ; coding: utf-8 -*- +from PyInstaller.utils.hooks import collect_all, collect_submodules -hiddenimports_pymdownx = collect_submodules('pymdownx') -hiddenimports_mdx_truly_sane_lists = collect_submodules('mdx_truly_sane_lists') -hiddenimports_mdx_gh_links = collect_submodules('mdx_gh_links') -hiddenimports_markdown_link_attr_modifier = collect_submodules('markdown_link_attr_modifier') - -all_hiddenimports = ( - hiddenimports_pymdownx - + hiddenimports_mdx_truly_sane_lists - + hiddenimports_mdx_gh_links - + hiddenimports_markdown_link_attr_modifier +datas = [('config/addonTemplate.yaml', '.'), ('config/nvda.yaml', '.')] +binaries = [('miscDeps/tools/msgfmt.exe', '.')] +hiddenimports = ( + collect_submodules('mdx_truly_sane_lists') + + collect_submodules('mdx_gh_links') + + collect_submodules('markdown_link_attr_modifier') ) +tmp_ret = collect_all('latex2mathml') +datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] +tmp_ret = collect_all('pymdownx') +datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2] a = Analysis( - ['source\\l10nUtil.py'], - pathex=[], - binaries=[('miscDeps/tools/msgfmt.exe', '.')], - datas=[('config/addonTemplate.yaml', '.'), ('config/nvda.yaml', '.')], - hiddenimports=all_hiddenimports, - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - noarchive=False, - optimize=0, + ['source\\l10nUtil.py'], + pathex=[], + binaries=binaries, + datas=datas, + hiddenimports=hiddenimports, + hookspath=[], + hooksconfig={}, + runtime_hooks=[], + excludes=[], + noarchive=False, + optimize=0, ) pyz = PYZ(a.pure) exe = EXE( - pyz, - a.scripts, - a.binaries, - a.datas, - [], - name='l10nUtil', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, + pyz, + a.scripts, + a.binaries, + a.datas, + [], + name='l10nUtil', + debug=False, + bootloader_ignore_signals=False, + strip=False, + upx=True, + upx_exclude=[], + runtime_tmpdir=None, + console=True, + disable_windowed_traceback=False, + argv_emulation=False, + target_arch=None, + codesign_identity=None, + entitlements_file=None, ) From ca1c70e7846e8d2940758f6a9506b26fa06735d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Noelia=20Ruiz=20Mart=C3=ADnez?= Date: Fri, 18 Sep 2026 11:04:35 +0200 Subject: [PATCH 8/8] Reset addonTemplate.yaml to main branch --- config/addonTemplate.yaml | 76 ++------------------------------------- 1 file changed, 2 insertions(+), 74 deletions(-) diff --git a/config/addonTemplate.yaml b/config/addonTemplate.yaml index bc59810..3becfb5 100644 --- a/config/addonTemplate.yaml +++ b/config/addonTemplate.yaml @@ -5,31 +5,15 @@ files: BMI.po: 300 BMI.pot: 300 BMI.xliff: 302 - BrailleExtender.po: 592 - BrailleExtender.pot: 592 - IndentNav.po: 578 - IndentNav.pot: 578 MSEdgeDiscardAnnouncements.po: 372 MSEdgeDiscardAnnouncements.pot: 372 MSEdgeDiscardAnnouncements.xliff: 374 SentenceNav.po: 360 SentenceNav.pot: 360 SentenceNav.xliff: 362 - TeleNVDA.po: 588 - TeleNVDA.pot: 588 - TeleNVDA.xliff: 616 - VLC.po: 582 - VLC.pot: 582 - askOpenRouter.po: 458 - askOpenRouter.pot: 458 - askOpenRouter.xliff: 456 beepKeyboard.po: 408 beepKeyboard.pot: 408 beepKeyboard.xliff: 410 - brailleEssentials.po: 627 - brailleEssentials.pot: 627 - calibre.po: 586 - calibre.pot: 586 charInfo.po: 296 charInfo.pot: 296 charInfo.xliff: 298 @@ -42,18 +26,12 @@ files: columnsReview.po: 332 columnsReview.pot: 332 columnsReview.xliff: 334 - contactsManager.po: 645 - contactsManager.pot: 645 - contactsManager.xliff: 647 controlUsageAssistant.po: 260 controlUsageAssistant.pot: 260 controlUsageAssistant.xliff: 262 cursorLocator.po: 224 cursorLocator.pot: 224 cursorLocator.xliff: 436 - customBrowseMode.po: 629 - customBrowseMode.pot: 629 - customBrowseMode.xliff: 631 customNotifications.po: 244 customNotifications.pot: 244 customNotifications.xliff: 268 @@ -63,11 +41,6 @@ files: debugHelper.po: 428 debugHelper.pot: 428 debugHelper.xliff: 430 - dengjen_neural_voices.po: 661 - dengjen_neural_voices.pot: 661 - dotPad.po: 663 - dotPad.pot: 663 - dotPad.xliff: 665 dropbox.po: 416 dropbox.pot: 416 dropbox.xliff: 418 @@ -89,9 +62,6 @@ files: evtTracker.po: 438 evtTracker.pot: 438 evtTracker.xliff: 440 - favoriteLinks.po: 643 - favoriteLinks.pot: 643 - favoriteLinks.xliff: 637 goldenCursor.po: 368 goldenCursor.pot: 368 goldenCursor.xliff: 370 @@ -107,12 +77,6 @@ files: mp3DirectCut.po: 404 mp3DirectCut.pot: 404 mp3DirectCut.xliff: 406 - noBeepsSpeechMode.po: 570 - noBeepsSpeechMode.pot: 570 - noBeepsSpeechMode.xliff: 602 - notepadMarkdownBrowseMode.po: 659 - notepadMarkdownBrowseMode.pot: 659 - notepadMarkdownBrowseMode.xliff: 657 numpadNavMode.po: 412 numpadNavMode.pot: 412 numpadNavMode.xliff: 414 @@ -131,23 +95,16 @@ files: pcKbBrl.po: 228 pcKbBrl.pot: 228 pcKbBrl.xliff: 276 - perky.po: 633 - perky.pot: 633 - perky.xliff: 635 - placeMarkers.po: 576 - placeMarkers.pot: 576 - placeMarkers.xliff: 610 proxy.po: 384 proxy.pot: 384 proxy.xliff: 386 rdAccess.po: 288 rdAccess.pot: 288 rdAccess.xliff: 290 + readFeeds.md: 450 readFeeds.po: 232 readFeeds.pot: 232 readFeeds.xliff: 278 - readonlyProfiles.po: 618 - readonlyProfiles.pot: 618 readonlyProfiles.xliff: 270 reportSymbols.po: 236 reportSymbols.pot: 236 @@ -170,12 +127,6 @@ files: searchWith.po: 388 searchWith.pot: 388 searchWith.xliff: 390 - showSelectionWhenBrailleTetheredToReview.po: 568 - showSelectionWhenBrailleTetheredToReview.pot: 568 - showSelectionWhenBrailleTetheredToReview.xliff: 600 - soundSplitter.po: 584 - soundSplitter.pot: 584 - soundSplitter.xliff: 614 speechLogger.po: 348 speechLogger.pot: 348 speechLogger.xliff: 350 @@ -185,21 +136,10 @@ files: systrayList.po: 340 systrayList.pot: 340 systrayList.xliff: 342 - terminalAccess.po: 590 - terminalAccess.pot: 590 - thunderbirdPlus.po: 572 - thunderbirdPlus.pot: 572 - thunderbirdPlus.xliff: 604 - toneMaster.po: 574 - toneMaster.pot: 574 - toneMaster.xliff: 608 tonysEnhancements.po: 304 tonysEnhancements.pot: 304 tonysEnhancements.xliff: 306 - toolbarsExplorer.po: 580 - toolbarsExplorer.pot: 580 - toolbarsExplorer.xliff: 612 - trainingKeyboardCommands.xliff: 606 + translateNvdaAddonsWithCrowdin.md: 448 translateNvdaAddonsWithCrowdin.po: 446 translateNvdaAddonsWithCrowdin.pot: 446 unicodeBrailleInput.po: 328 @@ -220,19 +160,7 @@ files: winWizard.po: 344 winWizard.pot: 344 winWizard.xliff: 346 - windowState.po: 653 - windowState.pot: 653 - windowState.xliff: 655 - wintenApps.po: 639 - wintenApps.pot: 639 - wintenApps.xliff: 641 wordNav.po: 364 wordNav.pot: 364 wordNav.xliff: 366 - wordPredictor.po: 649 - wordPredictor.pot: 649 - wordPredictor.xliff: 651 - zoomEnhancements.po: 623 - zoomEnhancements.pot: 623 - zoomEnhancements.xliff: 625 projectId: 780748