diff --git a/.taskfiles/pre-commit.yml b/.taskfiles/pre-commit.yml index 444115010f..5d0bf5faff 100644 --- a/.taskfiles/pre-commit.yml +++ b/.taskfiles/pre-commit.yml @@ -65,6 +65,8 @@ tasks: cmds: # Auto-fixers first, then the report-only tools (codespell, gitleaks) so a # finding there does not stop the fixers from running. + - task: ruff-format + vars: { FIX: '1' } - task: ruff vars: { FIX: '1' } - task: ruff-format @@ -101,12 +103,12 @@ tasks: ruff: deps: [install] cmds: - - uv run --project engine --locked --group pre-commit ruff check --isolated --line-length=120 {{if .FIX}}--fix {{end}}$(git ls-files {{.PY_FILES}}) + - uv run --project engine --locked --group pre-commit ruff check --isolated --target-version=py313 --line-length=120 {{if .FIX}}--fix {{end}}$(git ls-files {{.PY_FILES}}) ruff-format: deps: [install] cmds: - - uv run --project engine --locked --group pre-commit ruff format --isolated --line-length=120 {{if .FIX}}{{else}}--check {{end}}$(git ls-files {{.PY_FILES}}) + - uv run --project engine --locked --group pre-commit ruff format --isolated --target-version=py313 --line-length=120 {{if .FIX}}{{else}}--check {{end}}$(git ls-files {{.PY_FILES}}) codespell: deps: [install] diff --git a/app/core/src/main/resources/static/python/png_to_webp.py b/app/core/src/main/resources/static/python/png_to_webp.py index 094b1b5033..dcb18185f7 100644 --- a/app/core/src/main/resources/static/python/png_to_webp.py +++ b/app/core/src/main/resources/static/python/png_to_webp.py @@ -61,7 +61,7 @@ def resize_image(input_image_path, output_image_path, max_size=(16383, 16383)): # If dimensions are within the allowed limits, save the image directly image.save(output_image_path, format="WEBP", quality=100) print(f"The image was successfully saved as WebP: {output_image_path}") - except Exception as e: + except (OSError, ValueError) as e: print(f"An error occurred: {e}") diff --git a/engine/pyproject.toml b/engine/pyproject.toml index 87e7cc99c0..95d384110c 100644 --- a/engine/pyproject.toml +++ b/engine/pyproject.toml @@ -26,11 +26,11 @@ engine = [ # Type checking, testing, model generation, and formatting tools for the engine. engine-dev = [ "anyio>=4.14.2", - "datamodel-code-generator[ruff]==0.64.0", + "datamodel-code-generator[ruff]==0.72.3", "pyright>=1.1.411", "pytest>=9.1.1", "referencing>=0.37.0", - "ruff==0.15.5", + "ruff==0.16.2", ] # Dependencies for the Cucumber/Python integration test suite. cucumber = [ @@ -65,7 +65,7 @@ updater-signatures = [ # Pinned repository-wide pre-commit tooling. pre-commit = [ "codespell==2.4.3", - "ruff==0.15.5", + "ruff==0.16.2", "tomli-w==1.2.0", ] diff --git a/engine/src/stirling/api/routes/config.py b/engine/src/stirling/api/routes/config.py index cc06a8d87e..d1bdf222df 100644 --- a/engine/src/stirling/api/routes/config.py +++ b/engine/src/stirling/api/routes/config.py @@ -218,7 +218,7 @@ async def apply_config(request: ConfigPushRequest, http_request: Request) -> Con save_config(request) # Claim the stamp we just wrote so this worker's watcher does not rebuild for it. app.state.config_cache_stamp = cache_stamp() - except Exception: # noqa: BLE001 - best-effort persist, never fail the applied push + except Exception: # best-effort persist, never fail the applied push logger.warning("Applied AI config but failed to persist the encrypted cache", exc_info=True) notes.append( "Config applied on this worker but could not be persisted; it will not survive an" diff --git a/engine/src/stirling/documents/README.md b/engine/src/stirling/documents/README.md index 6848d8a101..e32d6e80b0 100644 --- a/engine/src/stirling/documents/README.md +++ b/engine/src/stirling/documents/README.md @@ -17,6 +17,7 @@ from pydantic_ai import Agent from stirling.services import AppRuntime + class MyAgent: def __init__(self, runtime: AppRuntime) -> None: rag = runtime.rag_capability diff --git a/engine/src/stirling/documents/service.py b/engine/src/stirling/documents/service.py index 0415e9d140..b3f4722791 100644 --- a/engine/src/stirling/documents/service.py +++ b/engine/src/stirling/documents/service.py @@ -139,7 +139,7 @@ class DocumentService: try: results = await self._store.search(col_name, query_embedding, k, principals) all_results.extend(results) - except Exception: # noqa: BLE001 - any backend error on one collection should not stop the others + except Exception: # any backend error on one collection should not stop the others logger.warning( "Skipping collection %s during cross-collection search", col_name, diff --git a/engine/uv.lock b/engine/uv.lock index fbfa665bc6..a788a239db 100644 --- a/engine/uv.lock +++ b/engine/uv.lock @@ -534,7 +534,7 @@ wheels = [ [[package]] name = "datamodel-code-generator" -version = "0.64.0" +version = "0.72.3" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "argcomplete" }, @@ -546,9 +546,9 @@ dependencies = [ { name = "pydantic" }, { name = "pyyaml" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/9c/d2/86c94a2836ed42231653a7ddaefa0a5bc23418167a876bba7376c96b3a35/datamodel_code_generator-0.64.0.tar.gz", hash = "sha256:9c592900a00b20e416494273c22435f5a9aef6ea8c7b9190747522a60497a1cb", size = 1316440, upload-time = "2026-06-14T17:24:50.528Z" } +sdist = { url = "https://files.pythonhosted.org/packages/14/4b/4652f0bb085a564982c3e515a0b02bcee21765ddac967bcf152a70d2af14/datamodel_code_generator-0.72.3.tar.gz", hash = "sha256:a20160de09b76d4a293ccba5a9ee5c341b5365890237ac1ff812f420e4c09f3b", size = 1965678, upload-time = "2026-08-10T18:58:41.636Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/23/94/71338e2f0146ac10747a5537b3a1e45256e66b7c229869eb0ee787111b41/datamodel_code_generator-0.64.0-py3-none-any.whl", hash = "sha256:b7cd8bd41a312aa997aec6150670bad781847c5b674f17e4d70e78208a0fb990", size = 374698, upload-time = "2026-06-14T17:24:48.809Z" }, + { url = "https://files.pythonhosted.org/packages/84/fd/9d8a0594aedcc6ee8133b21dd3543d6021842e013058803a69918720d0aa/datamodel_code_generator-0.72.3-py3-none-any.whl", hash = "sha256:4536f6dd12dd86c9c7a78b16ef83ae9aa7a9cbdb8bef8a3b63baa4ad9d3d3829", size = 554226, upload-time = "2026-08-10T18:58:40.087Z" }, ] [package.optional-dependencies] @@ -711,15 +711,15 @@ engine = [ ] engine-dev = [ { name = "anyio", specifier = ">=4.14.2" }, - { name = "datamodel-code-generator", extras = ["ruff"], specifier = "==0.64.0" }, + { name = "datamodel-code-generator", extras = ["ruff"], specifier = "==0.72.3" }, { name = "pyright", specifier = ">=1.1.411" }, { name = "pytest", specifier = ">=9.1.1" }, { name = "referencing", specifier = ">=0.37.0" }, - { name = "ruff", specifier = "==0.15.5" }, + { name = "ruff", specifier = "==0.16.2" }, ] pre-commit = [ { name = "codespell", specifier = "==2.4.3" }, - { name = "ruff", specifier = "==0.15.5" }, + { name = "ruff", specifier = "==0.16.2" }, { name = "tomli-w", specifier = "==1.2.0" }, ] tools = [ @@ -2791,27 +2791,27 @@ wheels = [ [[package]] name = "ruff" -version = "0.15.5" +version = "0.16.2" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/77/9b/840e0039e65fcf12758adf684d2289024d6140cde9268cc59887dc55189c/ruff-0.15.5.tar.gz", hash = "sha256:7c3601d3b6d76dce18c5c824fc8d06f4eef33d6df0c21ec7799510cde0f159a2", size = 4574214, upload-time = "2026-03-05T20:06:34.946Z" } +sdist = { url = "https://files.pythonhosted.org/packages/73/e1/4508a569211b35599016e84ba65c1a992b7a4004b4b6c4bea02a851cba1b/ruff-0.16.2.tar.gz", hash = "sha256:c3d7828d12e8927a6fc65fe38e2c2541b9e762d360a1786d752cb1b8883b3c9c", size = 4885811, upload-time = "2026-08-07T13:31:01.432Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/47/20/5369c3ce21588c708bcbe517a8fbe1a8dfdb5dfd5137e14790b1da71612c/ruff-0.15.5-py3-none-linux_armv6l.whl", hash = "sha256:4ae44c42281f42e3b06b988e442d344a5b9b72450ff3c892e30d11b29a96a57c", size = 10478185, upload-time = "2026-03-05T20:06:29.093Z" }, - { url = "https://files.pythonhosted.org/packages/44/ed/e81dd668547da281e5dce710cf0bc60193f8d3d43833e8241d006720e42b/ruff-0.15.5-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:6edd3792d408ebcf61adabc01822da687579a1a023f297618ac27a5b51ef0080", size = 10859201, upload-time = "2026-03-05T20:06:32.632Z" }, - { url = "https://files.pythonhosted.org/packages/c4/8f/533075f00aaf19b07c5cd6aa6e5d89424b06b3b3f4583bfa9c640a079059/ruff-0.15.5-py3-none-macosx_11_0_arm64.whl", hash = "sha256:89f463f7c8205a9f8dea9d658d59eff49db05f88f89cc3047fb1a02d9f344010", size = 10184752, upload-time = "2026-03-05T20:06:40.312Z" }, - { url = "https://files.pythonhosted.org/packages/66/0e/ba49e2c3fa0395b3152bad634c7432f7edfc509c133b8f4529053ff024fb/ruff-0.15.5-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba786a8295c6574c1116704cf0b9e6563de3432ac888d8f83685654fe528fd65", size = 10534857, upload-time = "2026-03-05T20:06:19.581Z" }, - { url = "https://files.pythonhosted.org/packages/59/71/39234440f27a226475a0659561adb0d784b4d247dfe7f43ffc12dd02e288/ruff-0.15.5-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fd4b801e57955fe9f02b31d20375ab3a5c4415f2e5105b79fb94cf2642c91440", size = 10309120, upload-time = "2026-03-05T20:06:00.435Z" }, - { url = "https://files.pythonhosted.org/packages/f5/87/4140aa86a93df032156982b726f4952aaec4a883bb98cb6ef73c347da253/ruff-0.15.5-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391f7c73388f3d8c11b794dbbc2959a5b5afe66642c142a6effa90b45f6f5204", size = 11047428, upload-time = "2026-03-05T20:05:51.867Z" }, - { url = "https://files.pythonhosted.org/packages/5a/f7/4953e7e3287676f78fbe85e3a0ca414c5ca81237b7575bdadc00229ac240/ruff-0.15.5-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8dc18f30302e379fe1e998548b0f5e9f4dff907f52f73ad6da419ea9c19d66c8", size = 11914251, upload-time = "2026-03-05T20:06:22.887Z" }, - { url = "https://files.pythonhosted.org/packages/77/46/0f7c865c10cf896ccf5a939c3e84e1cfaeed608ff5249584799a74d33835/ruff-0.15.5-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1cc6e7f90087e2d27f98dc34ed1b3ab7c8f0d273cc5431415454e22c0bd2a681", size = 11333801, upload-time = "2026-03-05T20:05:57.168Z" }, - { url = "https://files.pythonhosted.org/packages/d3/01/a10fe54b653061585e655f5286c2662ebddb68831ed3eaebfb0eb08c0a16/ruff-0.15.5-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c1cb7169f53c1ddb06e71a9aebd7e98fc0fea936b39afb36d8e86d36ecc2636a", size = 11206821, upload-time = "2026-03-05T20:06:03.441Z" }, - { url = "https://files.pythonhosted.org/packages/7a/0d/2132ceaf20c5e8699aa83da2706ecb5c5dcdf78b453f77edca7fb70f8a93/ruff-0.15.5-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:9b037924500a31ee17389b5c8c4d88874cc6ea8e42f12e9c61a3d754ff72f1ca", size = 11133326, upload-time = "2026-03-05T20:06:25.655Z" }, - { url = "https://files.pythonhosted.org/packages/72/cb/2e5259a7eb2a0f87c08c0fe5bf5825a1e4b90883a52685524596bfc93072/ruff-0.15.5-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:65bb414e5b4eadd95a8c1e4804f6772bbe8995889f203a01f77ddf2d790929dd", size = 10510820, upload-time = "2026-03-05T20:06:37.79Z" }, - { url = "https://files.pythonhosted.org/packages/ff/20/b67ce78f9e6c59ffbdb5b4503d0090e749b5f2d31b599b554698a80d861c/ruff-0.15.5-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d20aa469ae3b57033519c559e9bc9cd9e782842e39be05b50e852c7c981fa01d", size = 10302395, upload-time = "2026-03-05T20:05:54.504Z" }, - { url = "https://files.pythonhosted.org/packages/5f/e5/719f1acccd31b720d477751558ed74e9c88134adcc377e5e886af89d3072/ruff-0.15.5-py3-none-musllinux_1_2_i686.whl", hash = "sha256:15388dd28c9161cdb8eda68993533acc870aa4e646a0a277aa166de9ad5a8752", size = 10754069, upload-time = "2026-03-05T20:06:06.422Z" }, - { url = "https://files.pythonhosted.org/packages/c3/9c/d1db14469e32d98f3ca27079dbd30b7b44dbb5317d06ab36718dee3baf03/ruff-0.15.5-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:b30da330cbd03bed0c21420b6b953158f60c74c54c5f4c1dabbdf3a57bf355d2", size = 11304315, upload-time = "2026-03-05T20:06:10.867Z" }, - { url = "https://files.pythonhosted.org/packages/28/3a/950367aee7c69027f4f422059227b290ed780366b6aecee5de5039d50fa8/ruff-0.15.5-py3-none-win32.whl", hash = "sha256:732e5ee1f98ba5b3679029989a06ca39a950cced52143a0ea82a2102cb592b74", size = 10551676, upload-time = "2026-03-05T20:06:13.705Z" }, - { url = "https://files.pythonhosted.org/packages/b8/00/bf077a505b4e649bdd3c47ff8ec967735ce2544c8e4a43aba42ee9bf935d/ruff-0.15.5-py3-none-win_amd64.whl", hash = "sha256:821d41c5fa9e19117616c35eaa3f4b75046ec76c65e7ae20a333e9a8696bc7fe", size = 11678972, upload-time = "2026-03-05T20:06:45.379Z" }, - { url = "https://files.pythonhosted.org/packages/fe/4e/cd76eca6db6115604b7626668e891c9dd03330384082e33662fb0f113614/ruff-0.15.5-py3-none-win_arm64.whl", hash = "sha256:b498d1c60d2fe5c10c45ec3f698901065772730b411f164ae270bb6bfcc4740b", size = 10965572, upload-time = "2026-03-05T20:06:16.984Z" }, + { url = "https://files.pythonhosted.org/packages/14/57/db19951540f98859c956b50bdb4d31089b4d91e9f15e2968e7d5193806d5/ruff-0.16.2-py3-none-linux_armv6l.whl", hash = "sha256:3c8de4cf2181f01d57946d87d777aa52916976fc09942aed89938fab5e013318", size = 10847925, upload-time = "2026-08-07T13:30:14.468Z" }, + { url = "https://files.pythonhosted.org/packages/13/5a/995fe85a8470d3e391ac0f7fa8054bb454eaf33ee138196d6172ed1079c0/ruff-0.16.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9a48cc05c6fbc811ca81b5d7ba95375affea6582d1b8024e455e41afbbf55344", size = 11072662, upload-time = "2026-08-07T13:30:18.143Z" }, + { url = "https://files.pythonhosted.org/packages/32/53/370d767c61c71a971a4ace36703a7ecd8c393956349a7325d7fab2b56827/ruff-0.16.2-py3-none-macosx_11_0_arm64.whl", hash = "sha256:a2c0d14fcbb26c91f0f867a6dc9bd71bbc30b1b6151829c884f23faeab2e5700", size = 10566771, upload-time = "2026-08-07T13:30:20.899Z" }, + { url = "https://files.pythonhosted.org/packages/85/d6/9d96948caf5a632be62d62202d5ec914d6856f204fd79eb036e5915e79ea/ruff-0.16.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:335c621622c4650330be50842561c6586ac6971bb8ab5407fe34dcc9efb16bbe", size = 10975825, upload-time = "2026-08-07T13:30:23.517Z" }, + { url = "https://files.pythonhosted.org/packages/3b/92/ea87129b3414acb0b5770563779c51804d37ac67675c7ba35447ddb14773/ruff-0.16.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e66910f2c37cc753f9ef6580c914a621b80c4fa3549d3e3521e29d0f5bfc3f", size = 10649437, upload-time = "2026-08-07T13:30:26.097Z" }, + { url = "https://files.pythonhosted.org/packages/ac/43/f8f291dcd4af5bb7872b74fdfa41a7cd7c856ca1d4069670971cf1b9f5cb/ruff-0.16.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7e36fbfba65510548156902bcf1350a979a958ce0347ce0f90d73894036b39f", size = 11446761, upload-time = "2026-08-07T13:30:28.752Z" }, + { url = "https://files.pythonhosted.org/packages/71/4a/ef991fb2fcf516ab71f0808adcdd8da5e18c8cde447f4ceaf5f47a5132a5/ruff-0.16.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f0eab35f80df8f134aae5d1630e751901321d317cc8e50dc39e36fa3ed34cd12", size = 12336364, upload-time = "2026-08-07T13:30:31.468Z" }, + { url = "https://files.pythonhosted.org/packages/f3/24/f615e74f307e6ca0e56a482872477b856c70d530aa356abfb6dfe5ca8a80/ruff-0.16.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:40ea8c0594feb894e89c8c61ab9c103d38b0ea72dfde6c594107147ca31b1140", size = 11630720, upload-time = "2026-08-07T13:30:34.426Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d3/8ef50149e8412a77f7ab409efdef0e2b23803707a3863da4fc64cb23d459/ruff-0.16.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab3d62dde0b19facdd632008cc4827fc28ada7736c6bd35ab6f1050f0bfed53f", size = 11466130, upload-time = "2026-08-07T13:30:36.958Z" }, + { url = "https://files.pythonhosted.org/packages/dd/a7/a19334985c4dea8c381981fa252cd854c7ee52dc4b1686dc16f4a911c702/ruff-0.16.2-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:e43e1f5b8388da9eca1b9e88328d47a5cec794633ccf6f7484ac2dd15eee92c0", size = 11523634, upload-time = "2026-08-07T13:30:39.822Z" }, + { url = "https://files.pythonhosted.org/packages/6e/6c/96d192b0e742412ceda08c0a50f9669b253dde9fd6a60ea1a10c9fa79a63/ruff-0.16.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c24788a980581e1d7ea3a0cbe4344c4fbeb0a6a9b1f4713aa46bb104f8294690", size = 10949807, upload-time = "2026-08-07T13:30:42.745Z" }, + { url = "https://files.pythonhosted.org/packages/fa/51/e26599ceca11e79ee255c7df515995561edf87e9ca1893284e44d98f5a86/ruff-0.16.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:81806b08329130005dd4a8a8394a0c9da8c6f4cafb16ba438d2a2ee6a18bedf1", size = 10646891, upload-time = "2026-08-07T13:30:45.522Z" }, + { url = "https://files.pythonhosted.org/packages/68/01/800c4b1f97bc8d7c6029e06b1f20473a3cf1e13c4933d8f3342add83fc55/ruff-0.16.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:4ce4e02bad779bef557f541a1b31f20d6abeae1cc05ed1b1ac019d4ffd1044c8", size = 11162063, upload-time = "2026-08-07T13:30:48.131Z" }, + { url = "https://files.pythonhosted.org/packages/e4/d0/1477ea50fc5a0d4b0b71d1d63d50770bdd794d90b43e37a7618e63ec9894/ruff-0.16.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e0422abdf70070255fc4073ce9dfc814cc03db577013761ddd09bc1e4a9a4fbd", size = 11556038, upload-time = "2026-08-07T13:30:50.686Z" }, + { url = "https://files.pythonhosted.org/packages/b8/76/a7776f32048d991e16d4fa8ff91790b877342d3596cc3ed04acdbf1aaedc/ruff-0.16.2-py3-none-win32.whl", hash = "sha256:bf3a63d78fb39f4bf5ac8ae52051c5520505301abe19ba4e204c453b3f09bb0b", size = 10872850, upload-time = "2026-08-07T13:30:53.471Z" }, + { url = "https://files.pythonhosted.org/packages/00/0d/929c800d920e61397d82a01b60bffc68da3052c17d31de59efaad2e4ed75/ruff-0.16.2-py3-none-win_amd64.whl", hash = "sha256:bcabe2f6d0fc7819f1431793005af4e4de7371927d037345bf941252b195b9fa", size = 12023338, upload-time = "2026-08-07T13:30:56.193Z" }, + { url = "https://files.pythonhosted.org/packages/5b/6c/93e26c22c5f78ff87363e07da49c84955affbeb1098bd1936bf3b3f293bf/ruff-0.16.2-py3-none-win_arm64.whl", hash = "sha256:d614e95cedf38a2053fd351c55b103ba30d017d61688fdbfd40ee0412852a99f", size = 11374065, upload-time = "2026-08-07T13:30:58.775Z" }, ] [[package]] diff --git a/scripts/convert_cff_to_ttf.py b/scripts/convert_cff_to_ttf.py index 0ae480da7a..6629ba6c9c 100644 --- a/scripts/convert_cff_to_ttf.py +++ b/scripts/convert_cff_to_ttf.py @@ -75,7 +75,7 @@ def parse_unicode_mapping(mapping_path): print(f"Parsed ToUnicode CMap: {len(gid_to_unicode)} mappings", file=sys.stderr) return gid_to_unicode - except Exception as e: + except (OSError, UnicodeError, ValueError, TypeError, KeyError) as e: print(f"Warning: Failed to parse Unicode mapping: {e}", file=sys.stderr) return {} @@ -122,7 +122,7 @@ def wrap_cff_as_otf(input_path, output_path, tounicode_path=None): else: # Fallback to CharStrings keys charstrings = cff_font.CharStrings - glyph_order = [".notdef"] + [name for name in charstrings.keys() if name != ".notdef"] + glyph_order = [".notdef"] + [name for name in charstrings if name != ".notdef"] otf.setGlyphOrder(glyph_order) @@ -186,10 +186,10 @@ def wrap_cff_as_otf(input_path, output_path, tounicode_path=None): min_lsb = min(min_lsb, lsb) min_rsb = min(min_rsb, rsb) max_extent = max(max_extent, extent) - except Exception: + except (AttributeError, TypeError, ValueError): pass # Some glyphs may not have outlines - except Exception: + except (AttributeError, KeyError, TypeError, ValueError): pass # Use defaults widths[glyph_name] = width @@ -308,14 +308,14 @@ def wrap_cff_as_otf(input_path, output_path, tounicode_path=None): unicode_val = int(glyph_name[3:], 16) if unicode_val not in unicode_to_glyph: unicode_to_glyph[unicode_val] = glyph_name - except Exception: + except ValueError: pass elif glyph_name.startswith("u") and len(glyph_name) >= 5: try: unicode_val = int(glyph_name[1:], 16) if unicode_val not in unicode_to_glyph: unicode_to_glyph[unicode_val] = glyph_name - except Exception: + except ValueError: pass # === Create cmap table === @@ -476,8 +476,8 @@ def wrap_cff_as_otf(input_path, output_path, tounicode_path=None): return True - except Exception as e: - print(f"ERROR: Conversion failed: {str(e)}", file=sys.stderr) + except (OSError, ValueError, TypeError, KeyError, RuntimeError) as e: + print(f"ERROR: Conversion failed: {e!s}", file=sys.stderr) import traceback traceback.print_exc(file=sys.stderr) diff --git a/scripts/counter_translation_v3.py b/scripts/counter_translation_v3.py index 17f62e2758..241ec2111d 100644 --- a/scripts/counter_translation_v3.py +++ b/scripts/counter_translation_v3.py @@ -116,12 +116,11 @@ def write_readme(progress_list: list[tuple[str, int]]) -> None: for i, line in enumerate(content[2:], start=2): for progress in progress_list: language, value = progress - if language in line: - if match := re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line): - content[i] = line.replace( - match.group(0), - f"![{value}%](https://geps.dev/progress/{value})", - ) + if language in line and (match := re.search(r"\!\[(\d+(\.\d+)?)%\]\(.*\)", line)): + content[i] = line.replace( + match.group(0), + f"![{value}%](https://geps.dev/progress/{value})", + ) with open( os.path.join(os.getcwd(), "devGuide", "HowToAddNewLanguage.md"), @@ -261,12 +260,11 @@ def compare_files( # Missing translation (same as default and not ignored) fails += 1 missing_str_keys.append(default_key) - if default_value != file_value: - if default_key in sort_ignore_translation[language]["ignore"]: - if default_key == "language.direction": - continue - # Remove from ignore if actually translated - sort_ignore_translation[language]["ignore"].remove(default_key) + if default_value != file_value and default_key in sort_ignore_translation[language]["ignore"]: + if default_key == "language.direction": + continue + # Remove from ignore if actually translated + sort_ignore_translation[language]["ignore"].remove(default_key) if show_missing_keys: if len(missing_str_keys) > 0: diff --git a/scripts/coverage-matrix.py b/scripts/coverage-matrix.py index 1cd4e6ad33..d30499ee2c 100644 --- a/scripts/coverage-matrix.py +++ b/scripts/coverage-matrix.py @@ -116,11 +116,7 @@ def _classify_backend(package_name: str) -> str | None: return "saas" if p.startswith("stirling.software.proprietary"): return "proprietary" - if ( - p.startswith("stirling.software.SPDF") - or p.startswith("stirling.software.common") - or p.startswith("org.apache.pdfbox") - ): + if p.startswith(("stirling.software.SPDF", "stirling.software.common", "org.apache.pdfbox")): return "core" return None diff --git a/scripts/coverage-summary.py b/scripts/coverage-summary.py index 11ea7099c1..728bf5ae9f 100644 --- a/scripts/coverage-summary.py +++ b/scripts/coverage-summary.py @@ -80,7 +80,7 @@ def _parse_jacoco_xml(path: Path) -> dict[str, CounterTotals]: def _bar(pct: float, width: int = 20) -> str: """Render a fixed-width ASCII progress bar. Markdown-safe on all consoles.""" - filled = int(round(pct / 100.0 * width)) + filled = round(pct / 100.0 * width) return "[" + "#" * filled + "-" * (width - filled) + "]" diff --git a/scripts/download_pdf_samples.py b/scripts/download_pdf_samples.py index c2ab27a1f9..3825abefbf 100644 --- a/scripts/download_pdf_samples.py +++ b/scripts/download_pdf_samples.py @@ -150,7 +150,7 @@ def download_pdf( output_dir.mkdir(parents=True, exist_ok=True) dest.write_bytes(content) return url, dest, None - except Exception as exc: # pylint: disable=broad-except + except (OSError, ValueError, requests.RequestException) as exc: return url, None, str(exc) diff --git a/scripts/harvest_type3_fonts.py b/scripts/harvest_type3_fonts.py index 380d332d96..be3efd5ddd 100644 --- a/scripts/harvest_type3_fonts.py +++ b/scripts/harvest_type3_fonts.py @@ -118,7 +118,7 @@ def collect_known_signatures(signatures_dir: Path) -> dict[str, dict]: for json_file in signatures_dir.rglob("*.json"): try: payload = load_signature_file(json_file) - except Exception: + except (OSError, ValueError, TypeError, json.JSONDecodeError): continue pdf = payload.get("pdf") for font in payload.get("fonts", []): @@ -148,9 +148,9 @@ def run_signature_tool(gradle_cmd: str, pdf: Path, output_path: Path, pretty: bo cmd, shell=True, cwd=cwd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, + capture_output=True, text=True, + check=False, ) if completed.returncode != 0: raise RuntimeError(f"Gradle Type3SignatureTool failed for {pdf}:\n{completed.stderr.strip()}") @@ -179,7 +179,7 @@ def extract_fonts_from_payload(payload: dict) -> list[dict]: def write_report(report_path: Path, fonts_by_signature: dict[str, dict]) -> None: ordered = sorted(fonts_by_signature.values(), key=lambda entry: entry["signature"]) report = { - "generatedAt": dt.datetime.utcnow().isoformat(timespec="seconds") + "Z", + "generatedAt": dt.datetime.now(dt.UTC).isoformat(timespec="seconds").replace("+00:00", "Z"), "totalSignatures": len(ordered), "fonts": ordered, } @@ -202,13 +202,13 @@ def main() -> None: if signature_path.exists() and not args.force: try: payload = load_signature_file(signature_path) - except Exception as exc: + except (OSError, ValueError, TypeError, json.JSONDecodeError) as exc: print(f"[WARN] Failed to parse cached signature {signature_path}: {exc}") payload = None else: try: run_signature_tool(args.gradle_cmd, pdf, signature_path, args.pretty, REPO_ROOT) - except Exception as exc: + except (OSError, RuntimeError, subprocess.SubprocessError) as exc: print(f"[ERROR] Harvest failed for {pdf}: {exc}", file=sys.stderr) continue payload = load_signature_file(signature_path) diff --git a/scripts/index_type3_catalogue.py b/scripts/index_type3_catalogue.py index 69e7c33e47..31ef27efa4 100644 --- a/scripts/index_type3_catalogue.py +++ b/scripts/index_type3_catalogue.py @@ -8,7 +8,7 @@ from pathlib import Path def run(cmd, cwd=None): - result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True) + result = subprocess.run(cmd, cwd=cwd, capture_output=True, text=True, check=False) if result.returncode != 0: raise RuntimeError(f"Command {' '.join(cmd)} failed: {result.stderr}") return result.stdout @@ -55,7 +55,7 @@ def main(): for pdf in sorted(samples_dir.glob("*.pdf")): try: output = run(["pdffonts", str(pdf)]) - except Exception as exc: + except (OSError, RuntimeError) as exc: print(f"Skipping {pdf.name}: {exc}") continue for font_name, encoding in parse_pdffonts(output): diff --git a/scripts/playwright-coverage-summary.py b/scripts/playwright-coverage-summary.py index 0759156d3f..8379461497 100644 --- a/scripts/playwright-coverage-summary.py +++ b/scripts/playwright-coverage-summary.py @@ -48,11 +48,9 @@ SKIP_URL_FRAGMENTS = ( def _is_app_url(url: str) -> bool: if not url: return False - if not (url.startswith("http://") or url.startswith("https://")): + if not (url.startswith(("http://", "https://"))): return False - if any(frag in url for frag in SKIP_URL_FRAGMENTS): - return False - return True + return not any(frag in url for frag in SKIP_URL_FRAGMENTS) def aggregate(dump_dir: Path) -> dict: diff --git a/scripts/pre-commit/install_gitleaks.py b/scripts/pre-commit/install_gitleaks.py index c331b10b65..372a1d289b 100644 --- a/scripts/pre-commit/install_gitleaks.py +++ b/scripts/pre-commit/install_gitleaks.py @@ -61,7 +61,7 @@ def cached_version() -> str | None: if not BIN.exists(): return None try: - return subprocess.run([str(BIN), "version"], capture_output=True, text=True).stdout.strip() + return subprocess.run([str(BIN), "version"], capture_output=True, text=True, check=False).stdout.strip() except OSError: return None diff --git a/scripts/translations/ai_translation_helper.py b/scripts/translations/ai_translation_helper.py index 03b606f1d9..48fff9db3b 100644 --- a/scripts/translations/ai_translation_helper.py +++ b/scripts/translations/ai_translation_helper.py @@ -11,7 +11,7 @@ import csv import json import re import tomllib -from datetime import datetime +from datetime import UTC, datetime from pathlib import Path from typing import Any @@ -28,7 +28,7 @@ class AITranslationHelper: try: with open(file_path, "rb") as f: return tomllib.load(f) - except (FileNotFoundError, Exception) as e: + except (OSError, tomllib.TOMLDecodeError) as e: print(f"Error loading {file_path}: {e}") return {} @@ -47,7 +47,7 @@ class AITranslationHelper: golden_truth = self._load_translation_file(self.golden_truth_file) batch_data = { "metadata": { - "created_at": datetime.now().isoformat(), + "created_at": datetime.now(UTC).isoformat(), "source_language": "en-US", "target_languages": languages, "max_entries_per_language": max_entries_per_language, @@ -105,9 +105,8 @@ class AITranslationHelper: key not in lang_flat or lang_flat[key] == value or (isinstance(lang_flat[key], str) and lang_flat[key].startswith("[UNTRANSLATED]")) - ): - if not self._is_expected_identical(key, value): - untranslated[key] = value + ) and not self._is_expected_identical(key, value): + untranslated[key] = value return untranslated @@ -286,7 +285,7 @@ class AITranslationHelper: golden_flat = self._flatten_dict(golden_truth) if output_format == "csv": - output_file = Path(f"translations_export_{datetime.now().strftime('%Y%m%d')}.csv") + output_file = Path(f"translations_export_{datetime.now(UTC).strftime('%Y%m%d')}.csv") with open(output_file, "w", newline="", encoding="utf-8") as csvfile: fieldnames = ["key", "context", "en_US"] + languages @@ -322,7 +321,7 @@ class AITranslationHelper: print(f"Exported to {output_file}") elif output_format == "json": - output_file = Path(f"translations_export_{datetime.now().strftime('%Y%m%d')}.json") + output_file = Path(f"translations_export_{datetime.now(UTC).strftime('%Y%m%d')}.json") export_data = {"languages": languages, "translations": {}} for key, en_value in golden_flat.items(): diff --git a/scripts/translations/auto_translate.py b/scripts/translations/auto_translate.py index cabfb9269e..b72a3b1344 100644 --- a/scripts/translations/auto_translate.py +++ b/scripts/translations/auto_translate.py @@ -10,9 +10,9 @@ import json import os import subprocess import sys -from concurrent.futures import ThreadPoolExecutor import time import tomllib +from concurrent.futures import ThreadPoolExecutor from pathlib import Path @@ -23,7 +23,7 @@ def run_command(cmd, description=""): print(f"Step: {description}") print(f"{'=' * 60}") - result = subprocess.run(cmd, shell=True, capture_output=True, text=True) + result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=False) if result.stdout: print(result.stdout) @@ -155,7 +155,7 @@ def translate_batches(batch_files, language_code, api_key, timeout=600, model="g cmd = f'python3 scripts/translations/batch_translator.py "{batch_file}" --language {language_code} --api-key "{api_key}" --model {model}' try: - result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout) + result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=timeout, check=False) except subprocess.TimeoutExpired: print(f"✗ Timed out after {timeout}s: {batch_file}", file=sys.stderr) return None @@ -388,7 +388,7 @@ Examples: except KeyboardInterrupt: print("\n\n⚠ Translation interrupted by user") sys.exit(1) - except Exception as e: + except (OSError, ValueError, RuntimeError, subprocess.SubprocessError) as e: print(f"\n\n✗ Error: {e}") import traceback diff --git a/scripts/translations/batch_translator.py b/scripts/translations/batch_translator.py index 864e580fe0..f518796b34 100644 --- a/scripts/translations/batch_translator.py +++ b/scripts/translations/batch_translator.py @@ -160,7 +160,7 @@ Return ONLY the translated JSON. No markdown, no explanations, just the JSON obj print(f"Error: AI returned invalid JSON: {e}") print(f"Response: {translated_text[:500]}...") raise - except Exception as e: + except (OSError, ValueError, KeyError, RuntimeError) as e: print(f"Error during translation: {e}") raise @@ -182,11 +182,11 @@ Return ONLY the translated JSON. No markdown, no explanations, just the JSON obj placeholder_pattern = r"\{[^}]+\}|\{\{[^}]+\}\}" - for key in original.keys(): + for key, original_value in original.items(): if key not in translated: continue - orig_value = str(original[key]) + orig_value = str(original_value) trans_value = str(translated[key]) # Find all placeholders in original @@ -366,7 +366,7 @@ Examples: if i < len(input_files): time.sleep(args.delay) - except Exception as e: + except (OSError, ValueError, KeyError, RuntimeError) as e: print(f"✗ Failed: {e}") failed += 1 continue diff --git a/scripts/translations/bulk_auto_translate.py b/scripts/translations/bulk_auto_translate.py index 827c44d3dc..2205d4421b 100644 --- a/scripts/translations/bulk_auto_translate.py +++ b/scripts/translations/bulk_auto_translate.py @@ -79,7 +79,7 @@ def get_language_completion(locales_dir: Path, language: str) -> float | None: return (translated / total * 100) if total > 0 else 0.0 - except Exception as e: + except (OSError, TypeError, KeyError, ValueError, tomllib.TOMLDecodeError) as e: print(f"Warning: Could not calculate completion for {language}: {e}") return None @@ -124,6 +124,7 @@ def translate_language( cmd, capture_output=True, text=True, + check=False, timeout=timeout * 5, # Overall timeout = 5x per-batch timeout ) @@ -144,8 +145,8 @@ def translate_language( except subprocess.TimeoutExpired: safe_print(f"[{language}] ✗ Timeout exceeded") return (language, False, "Timeout exceeded") - except Exception as e: - safe_print(f"[{language}] ✗ Error: {str(e)}") + except (OSError, TypeError, KeyError, ValueError, tomllib.TOMLDecodeError) as e: + safe_print(f"[{language}] ✗ Error: {e!s}") return (language, False, str(e)) diff --git a/scripts/translations/compact_translator.py b/scripts/translations/compact_translator.py index 527eca8a12..926af223fb 100644 --- a/scripts/translations/compact_translator.py +++ b/scripts/translations/compact_translator.py @@ -38,7 +38,7 @@ class CompactTranslationExtractor: except FileNotFoundError: print(f"Error: File not found: {file_path}", file=sys.stderr) sys.exit(1) - except Exception as e: + except (OSError, tomllib.TOMLDecodeError) as e: print(f"Error: Invalid TOML file {file_path}: {e}", file=sys.stderr) sys.exit(1) @@ -51,7 +51,7 @@ class CompactTranslationExtractor: with open(self.ignore_file, "rb") as f: ignore_data = tomllib.load(f) return {lang: set(data.get("ignore", [])) for lang, data in ignore_data.items()} - except Exception as e: + except (OSError, tomllib.TOMLDecodeError, TypeError, AttributeError) as e: print( f"Warning: Could not load ignore file {self.ignore_file}: {e}", file=sys.stderr, diff --git a/scripts/translations/toml_beautifier.py b/scripts/translations/toml_beautifier.py index 5d529b8a02..39801ee918 100644 --- a/scripts/translations/toml_beautifier.py +++ b/scripts/translations/toml_beautifier.py @@ -28,7 +28,7 @@ class TOMLBeautifier: except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except Exception as e: + except (OSError, tomllib.TOMLDecodeError) as e: print(f"Error: Invalid TOML in {file_path}: {e}") sys.exit(1) @@ -172,11 +172,11 @@ class TOMLBeautifier: def get_key_order(obj: dict, path: str = "") -> list[str]: keys = [] - for key in obj.keys(): + for key, value in obj.items(): new_path = f"{path}.{key}" if path else key keys.append(new_path) - if isinstance(obj[key], dict): - keys.extend(get_key_order(obj[key], new_path)) + if isinstance(value, dict): + keys.extend(get_key_order(value, new_path)) return keys golden_order = get_key_order(self.golden_structure) diff --git a/scripts/translations/toml_validator.py b/scripts/translations/toml_validator.py index f260871cb1..26b23a145f 100644 --- a/scripts/translations/toml_validator.py +++ b/scripts/translations/toml_validator.py @@ -33,7 +33,7 @@ def get_line_context(file_path, line_num, context_lines=3): context.append(f"{marker}{i + 1:4d}: {lines[i].rstrip()}") return "\n".join(context) - except Exception as e: + except (OSError, UnicodeError, IndexError) as e: return f"Could not read context: {e}" @@ -56,7 +56,7 @@ def get_character_context(file_path, char_pos, context_chars=100): "after": after, "display": f"{before}[{error_char}]{after}", } - except Exception: + except (IndexError, ValueError): return None @@ -90,7 +90,7 @@ def validate_toml_file(file_path): result["valid"] = True result["entry_count"] = count_keys(data) - except Exception as e: + except (OSError, tomllib.TOMLDecodeError, TypeError, ValueError) as e: error_msg = str(e) result["error"] = error_msg diff --git a/scripts/translations/translation_analyzer.py b/scripts/translations/translation_analyzer.py index 9e38c2ad1f..af18e3629e 100644 --- a/scripts/translations/translation_analyzer.py +++ b/scripts/translations/translation_analyzer.py @@ -31,7 +31,7 @@ class TranslationAnalyzer: except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except Exception as e: + except (OSError, tomllib.TOMLDecodeError) as e: print(f"Error: Invalid file {file_path}: {e}") sys.exit(1) @@ -51,7 +51,7 @@ class TranslationAnalyzer: for patterns in [data.get("ignore", [])] if patterns } - except Exception as e: + except (OSError, tomllib.TOMLDecodeError, TypeError, AttributeError) as e: print(f"Warning: Could not load ignore file {self.ignore_file}: {e}") return {} @@ -165,9 +165,8 @@ class TranslationAnalyzer: for key in relevant_keys: if key in target_flat: value = target_flat[key] - if not (isinstance(value, str) and value.startswith("[UNTRANSLATED]")): - if key not in untranslated: # Not identical to en-US (unless expected) - properly_translated += 1 + if not (isinstance(value, str) and value.startswith("[UNTRANSLATED]")) and key not in untranslated: + properly_translated += 1 completion_rate = (properly_translated / total_keys) * 100 if total_keys > 0 else 0 diff --git a/scripts/translations/translation_merger.py b/scripts/translations/translation_merger.py index 10b4a99d14..2e9a39b7c1 100644 --- a/scripts/translations/translation_merger.py +++ b/scripts/translations/translation_merger.py @@ -12,7 +12,7 @@ import os import shutil import sys import tomllib -from datetime import datetime +from datetime import UTC, datetime from pathlib import Path from typing import Any @@ -39,14 +39,14 @@ class TranslationMerger: except FileNotFoundError: print(f"Error: File not found: {file_path}") sys.exit(1) - except Exception as e: + except (OSError, tomllib.TOMLDecodeError) as e: print(f"Error: Invalid file {file_path}: {e}") sys.exit(1) def _save_translation_file(self, data: dict[str, Any], file_path: Path, backup: bool = False) -> None: """Save TOML translation file with backup option.""" if backup and file_path.exists(): - backup_path = file_path.with_suffix(f".backup.{datetime.now().strftime('%Y%m%d_%H%M%S')}.toml") + backup_path = file_path.with_suffix(f".backup.{datetime.now(UTC).strftime('%Y%m%d_%H%M%S')}.toml") shutil.copy2(file_path, backup_path) print(f"Backup created: {backup_path}") @@ -64,7 +64,7 @@ class TranslationMerger: # Convert to sets for faster lookup return {lang: set(data.get("ignore", [])) for lang, data in ignore_data.items()} - except Exception as e: + except (OSError, tomllib.TOMLDecodeError, TypeError, AttributeError) as e: print(f"Warning: Could not load ignore file {self.ignore_file}: {e}") return {} @@ -264,7 +264,7 @@ class TranslationMerger: self._set_nested_value(target_data, key, translation) applied_count += 1 - except Exception as e: + except (KeyError, TypeError, ValueError) as e: errors.append(f"Error setting {key}: {e}") if applied_count > 0: @@ -316,7 +316,7 @@ class TranslationMerger: "source_language": "en-US", "target_language": target_file.parent.name, "total_entries": len(untranslated), - "created_at": datetime.now().isoformat(), + "created_at": datetime.now(UTC).isoformat(), "instructions": 'Translate the "original" values to the target language. Keep the same keys.', }, "translations": {}, diff --git a/scripts/translations/validate_json_structure.py b/scripts/translations/validate_json_structure.py index 5f083632e1..d9c7ff9ebb 100644 --- a/scripts/translations/validate_json_structure.py +++ b/scripts/translations/validate_json_structure.py @@ -37,8 +37,8 @@ def validate_translation_file(file_path: Path) -> tuple[bool, str]: with open(file_path, "rb") as f: tomllib.load(f) return True, "Valid TOML" - except Exception as e: - return False, f"Error reading file: {str(e)}" + except (OSError, tomllib.TOMLDecodeError) as e: + return False, f"Error reading file: {e!s}" def validate_structure(en_us_keys: set[str], lang_keys: set[str], lang_code: str) -> dict: @@ -139,9 +139,8 @@ def main(): # Validate all languages except en-US languages = [] for d in locales_dir.iterdir(): - if d.is_dir() and d.name != "en-US": - if (d / "translation.toml").exists(): - languages.append(d.name) + if d.is_dir() and d.name != "en-US" and (d / "translation.toml").exists(): + languages.append(d.name) results = [] json_errors = [] diff --git a/scripts/translations/validate_placeholders.py b/scripts/translations/validate_placeholders.py index 440439ea7a..61d5c1fca0 100644 --- a/scripts/translations/validate_placeholders.py +++ b/scripts/translations/validate_placeholders.py @@ -40,11 +40,11 @@ def validate_language(en_us_flat: dict[str, str], lang_flat: dict[str, str], lan """Validate placeholders for a language against en-US.""" issues = [] - for key in en_us_flat: + for key, en_text in en_us_flat.items(): if key not in lang_flat: continue - en_placeholders = find_placeholders(en_us_flat[key]) + en_placeholders = find_placeholders(en_text) lang_placeholders = find_placeholders(lang_flat[key]) if en_placeholders != lang_placeholders: @@ -56,7 +56,7 @@ def validate_language(en_us_flat: dict[str, str], lang_flat: dict[str, str], lan "key": key, "missing": missing, "extra": extra, - "en_text": en_us_flat[key], + "en_text": en_text, "lang_text": lang_flat[key], } issues.append(issue) @@ -127,9 +127,8 @@ def main(): # Validate all languages except en-US languages = [] for d in locales_dir.iterdir(): - if d.is_dir() and d.name != "en-US": - if (d / "translation.toml").exists(): - languages.append(d.name) + if d.is_dir() and d.name != "en-US" and (d / "translation.toml").exists(): + languages.append(d.name) all_issues = [] diff --git a/scripts/type3_to_cff.py b/scripts/type3_to_cff.py index 48fe89c70c..dc96694c37 100644 --- a/scripts/type3_to_cff.py +++ b/scripts/type3_to_cff.py @@ -74,7 +74,7 @@ def load_json(path: Path) -> dict[str, object]: try: with path.open("r", encoding="utf-8") as handle: return json.load(handle) - except Exception as exc: # pragma: no cover - fatal configuration error + except (OSError, UnicodeError, json.JSONDecodeError) as exc: # pragma: no cover - fatal configuration error print(f"ERROR: Failed to load glyph JSON '{path}': {exc}", file=sys.stderr) sys.exit(2) @@ -298,7 +298,7 @@ def build_ttf_glyph(glyph: GlyphSource, max_error: float) -> object | None: try: glyph_obj = pen.glyph() - except Exception: + except (AttributeError, TypeError, ValueError): return None return glyph_obj @@ -472,7 +472,7 @@ def main() -> None: units_per_em=args.units_per_em, cu2qu_error=args.cu2qu_error, ) - except Exception as exc: + except (OSError, ValueError, TypeError, RuntimeError) as exc: print(f"ERROR: Failed to generate fonts: {exc}", file=sys.stderr) if otf_output.exists(): otf_output.unlink() diff --git a/scripts/update_type3_library.py b/scripts/update_type3_library.py index a0d5515573..fd2de895cb 100644 --- a/scripts/update_type3_library.py +++ b/scripts/update_type3_library.py @@ -100,7 +100,7 @@ def normalize_source_path(pdf_path: str | None) -> str | None: try: source = Path(pdf_path) rel = source.relative_to(REPO_ROOT) - except Exception: + except ValueError: rel = Path(pdf_path) return str(rel).replace("\\", "/")