├── .python-version ├── .travis.yml ├── .gitignore ├── pyproject.toml ├── .github └── renovate.json ├── Makefile ├── .circleci └── config.yml ├── LICENSE ├── run-google-java-format.el ├── check-google-java-format.py ├── run-google-java-format.py ├── fixup-google-java-format.py ├── README.md └── uv.lock /.python-version: -------------------------------------------------------------------------------- 1 | 3.14 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | install: true 2 | 3 | # TODO: add some tests 4 | script: true 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .plume-scripts 2 | .markdownlint-cli2.yaml 3 | .pymarkdown 4 | .ruff.toml 5 | # These files are downloaded to this directory from elsewhere. 6 | google-java-format-*-all-deps.jar 7 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "run-google-java-format" 3 | version = "0.1.0" 4 | description = "Add your description here" 5 | readme = "README.md" 6 | requires-python = ">=3.10" 7 | dependencies = [] 8 | 9 | [dependency-groups] 10 | dev = [ 11 | "pymarkdownlnt>=0.9.33", 12 | "ty>=0.0.1a31", 13 | ] 14 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base", 5 | ":automergeAll", 6 | ":automergeRequireAllStatusChecks", 7 | "schedule:nonOfficeHours", 8 | ":disableDependencyDashboard" 9 | ], 10 | "timezone": "America/Los_Angeles" 11 | } 12 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all 2 | 3 | all: style-fix style-check 4 | 5 | type-qualifiers.txt: 6 | grep --recursive --files-with-matches -e '^@Target\b.*TYPE_USE' ${CHECKERFRAMEWORK}/checker/src/test ${CHECKERFRAMEWORK}/checker-qual/src/main/java ${CHECKERFRAMEWORK}/framework/src/main/java ${CHECKERFRAMEWORK}/docs/examples/units-extension ${CHECKERFRAMEWORK}/framework/src/test/java \ 7 | | grep -v '~' | sed 's:.*/::' \ 8 | | awk '{print $$1} END {print "NotNull.java"; print "UbTop.java"; print "LbTop.java"; print "UB_TOP.java"; print "LB_TOP.java";}' \ 9 | | sed 's/\(.*\)\.java/ "\1",/' \ 10 | | LC_COLLATE=C sort | uniq > $@ 11 | 12 | .PHONY: tags 13 | TAGS: tags 14 | tags: 15 | etags *.py 16 | 17 | # Code style; defines `style-check` and `style-fix`. 18 | ifeq (,$(wildcard .plume-scripts)) 19 | dummy := $(shell git clone -q https://github.com/plume-lib/plume-scripts.git .plume-scripts) 20 | endif 21 | include .plume-scripts/code-style.mak 22 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2.1 2 | jobs: 3 | build: 4 | 5 | docker: 6 | - image: cimg/openjdk:25.0-browsers 7 | 8 | environment: 9 | TERM: dumb 10 | 11 | steps: 12 | 13 | - restore_cache: 14 | keys: 15 | - source-v1-{{ .Branch }}-{{ .Revision }} 16 | - source-v1-{{ .Branch }}- 17 | - source-v1- 18 | - checkout 19 | - save_cache: 20 | key: source-v1-{{ .Branch }}-{{ .Revision }} 21 | paths: 22 | - ".git" 23 | 24 | - run: sudo apt update 25 | - run: 26 | name: Install dependencies via apt 27 | command: sudo apt -y install shfmt shellcheck devscripts 28 | - run: 29 | name: Install markdownlint 30 | command: sudo npm install markdownlint-cli2 --global 31 | - run: 32 | name: Install uv 33 | command: curl -LsSf https://astral.sh/uv/install.sh | sh 34 | 35 | - run: make style-check 36 | 37 | - run: echo "TODO add some tests" 38 | 39 | workflows: 40 | build: 41 | jobs: 42 | - build 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 plume-lib 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /run-google-java-format.el: -------------------------------------------------------------------------------- 1 | ;; Emacs Lisp code to automatically format your code when you save it. 2 | 3 | (defun update-java-mode-hook-for-gjf () 4 | (add-hook 'after-save-hook 'run-google-java-format nil 'local)) 5 | (add-hook 'java-mode-hook 'update-java-mode-hook-for-gjf) 6 | 7 | (defun run-google-java-format () 8 | "Run external program run-google-java-format.py on the file, 9 | if it matches a hard-coded list of directories." 10 | (interactive) 11 | (let ((cmd 12 | (cond 13 | ((or (and (string-match-p "/\\(randoop\\)" (buffer-file-name)) 14 | (not (string-match-p "CloneVisitor\\.java$" (buffer-file-name)))) 15 | (and (string-match-p "/daikon" (buffer-file-name)) 16 | (not (string-match-p "\\.jpp$" (buffer-file-name)))) 17 | (and (string-match-p "/toradocu" (buffer-file-name)) 18 | (not (string-match-p "/src/test/resources/" (buffer-file-name)))) 19 | (and (string-match-p "/plume-lib" (buffer-file-name)) 20 | (not (string-match-p "WeakHasherMap.java$\\|WeakIdentityHashMap.java$" 21 | (buffer-file-name)))) 22 | (string-match-p "/org/plumelib/" (buffer-file-name))) 23 | ;; normal formatting 24 | "run-google-java-format.py ") 25 | ((and (string-match-p "/checker-framework" (buffer-file-name)) 26 | (not (string-match-p "/checker-framework-inference" (buffer-file-name))) 27 | (not (string-match-p "/checker/jdk/" (buffer-file-name))) 28 | (not (string-match-p "\\.astub$" (buffer-file-name))) 29 | ) 30 | ;; non-standard cammand-line arguments 31 | "run-google-java-format.py -a ") 32 | (t 33 | ;; for all other projects, don't automatically reformat 34 | nil)))) 35 | (if cmd 36 | (progn 37 | ;; I would like to avoid the "(Shell command succeeded with no output)" 38 | ;; message. 39 | (shell-command (concat cmd (buffer-file-name)) "*run-google-java-format*") 40 | ;; If you use bdiff, use this version instead 41 | ;; (bdiff-revert-buffer-maybe) 42 | (revert-buffer nil t))))) 43 | -------------------------------------------------------------------------------- /check-google-java-format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | """A wrapper around the google-java-format program, with improvements. 4 | 5 | This script checks whether the files supplied on the command line conform 6 | to the Google Java style (as enforced by the google-java-format program, 7 | but with improvements to the formatting of annotations in comments). 8 | If any files would be affected by running run-google-java-format.py, 9 | this script prints their names and returns a non-zero status. 10 | If called with no arguments, it reads from standard input. 11 | You could invoke this program, for example, in a git pre-commit hook. 12 | """ 13 | 14 | # TODO: Thanks to https://github.com/google/google-java-format/pull/106 15 | # this script can be eliminated, or its interface simplified. 16 | 17 | import filecmp 18 | import pathlib 19 | import shutil 20 | import stat 21 | import subprocess 22 | import sys 23 | import tempfile 24 | from pathlib import Path 25 | from shutil import copyfileobj 26 | 27 | try: 28 | from urllib import urlopen # type: ignore[attr-defined] 29 | except ImportError: 30 | from urllib.request import urlopen 31 | 32 | debug = False 33 | # debug = True 34 | 35 | script_dir = Path.resolve(Path(__file__)).parent 36 | run_py_name = "run-google-java-format.py" 37 | run_py_path = script_dir / run_py_name 38 | 39 | 40 | # For some reason, the "git ls-files" must be run from the root. 41 | # (I can run "git ls-files" from the command line in any directory.) 42 | def under_git(directory: Path, filename: str) -> bool: 43 | """Return true if `filename` in `directory` is under git control. 44 | 45 | Args: 46 | directory: the directory 47 | filename: the file name 48 | 49 | Returns: 50 | true if `filename` in `directory` is under git control. 51 | """ 52 | if not shutil.which("git"): 53 | if debug: 54 | print("no git executable found") 55 | return False 56 | with subprocess.Popen( 57 | ["git", "ls-files", filename, "--error-unmatch"], 58 | cwd=directory, 59 | stdout=subprocess.DEVNULL, 60 | stderr=subprocess.STDOUT, 61 | ) as p: 62 | p.wait() 63 | if debug: 64 | print("p.returncode", p.returncode) 65 | return p.returncode == 0 66 | 67 | 68 | def urlretrieve(url: str, filename: Path) -> None: 69 | """Like urllib.urlretrieve.""" 70 | with urlopen(url) as in_stream, pathlib.Path(filename).open("wb") as out_file: 71 | copyfileobj(in_stream, out_file) 72 | 73 | 74 | # Don't replace local with remote if local is under version control. 75 | # It would be better to just test whether the remote is newer than local, 76 | # but raw GitHub URLs don't have the necessary last-modified information. 77 | if not under_git(script_dir, run_py_name): 78 | url = "https://raw.githubusercontent.com/plume-lib/run-google-java-format/master/" + run_py_name 79 | try: 80 | urlretrieve(url, run_py_path) 81 | except Exception: 82 | if run_py_path.exists(): 83 | print("Couldn't retrieve " + run_py_name + " from " + url + "; using cached version") 84 | else: 85 | print("Couldn't retrieve " + run_py_name + " from " + url) 86 | sys.exit(1) 87 | run_py_path.chmod(run_py_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) 88 | 89 | temp_dir = tempfile.mkdtemp(prefix="check-google-java-format-") 90 | 91 | 92 | def temporary_file_name() -> str: 93 | """Return the name of a temporary file. 94 | 95 | Returns: 96 | the name of a temporary file. 97 | """ 98 | return str(Path(temp_dir) / next(tempfile._get_candidate_names())) # type: ignore[attr-defined] # noqa: SLF001 99 | 100 | 101 | def cleanup() -> None: 102 | """Clean up temporary files.""" 103 | shutil.rmtree(temp_dir) 104 | 105 | 106 | files = sys.argv[1:] 107 | if len(files) == 0: 108 | content = sys.stdin.read() 109 | fname = temporary_file_name() + ".java" 110 | with pathlib.Path(fname).open("w") as outfile: 111 | print(content, file=outfile) 112 | files = [fname] 113 | 114 | temps = [] 115 | cmdlineargs = [f for f in files if f.startswith("-")] 116 | files = [f for f in files if not f.startswith("-")] 117 | for fname in files: 118 | ftemp = temporary_file_name() + "_" + pathlib.Path(fname).name 119 | shutil.copyfile(fname, ftemp) 120 | temps.append(ftemp) 121 | 122 | if debug: 123 | print("Running " + run_py_name) 124 | # Problem: if a file is syntactically illegal, this outputs the temporary file 125 | # name rather than the real file name. 126 | # Minor optimization: To save one process creation, could call directly in Python. 127 | result = subprocess.call([run_py_path, *cmdlineargs, *temps]) 128 | if result != 0: 129 | cleanup() 130 | sys.exit(result) 131 | 132 | exit_code = 0 133 | 134 | for i, file in enumerate(files): 135 | if not filecmp.cmp(file, temps[i]): 136 | # TODO: gives temporary file name if reading from stdin 137 | print("Improper formatting:", file) 138 | exit_code = 1 139 | 140 | cleanup() 141 | 142 | sys.exit(exit_code) 143 | -------------------------------------------------------------------------------- /run-google-java-format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Reformat each file supplied on the command line. 3 | 4 | Yields the Google Java style (by calling out to the google-java-format 5 | program, https://github.com/google/google-java-format), but with 6 | improvements to the formatting of type annotations and annotations in 7 | comments. 8 | """ 9 | 10 | import os 11 | import pathlib 12 | import re 13 | import shutil 14 | import stat 15 | import subprocess 16 | import sys 17 | import tempfile 18 | from pathlib import Path 19 | from shutil import copyfileobj 20 | 21 | try: 22 | from urllib import urlopen # type: ignore[attr-defined] 23 | except ImportError: 24 | from urllib.request import urlopen 25 | 26 | debug = False 27 | # debug = True 28 | 29 | script_dir = Path.resolve(Path(__file__)).parent 30 | # Rather than calling out to the shell, it would be better to 31 | # call directly in Python. 32 | fixup_py_name = "fixup-google-java-format.py" 33 | fixup_py_path = script_dir / fixup_py_name 34 | 35 | # java_version_string is either 1.8 or nothing. 36 | # For JDK 8, `java -version` has the form: openjdk version "1.8.0_292" 37 | # For JDK 11, `java -version` has the form: openjdk 11.0.11 2021-04-20 38 | # For JDK 17, `java -version` has the form: java 17 2021-09-14 LTS 39 | java_version_string = subprocess.check_output( 40 | ["java", "-version"], stderr=subprocess.STDOUT 41 | ).decode("utf-8") 42 | if debug: 43 | print("java_version_string =", java_version_string) 44 | match = re.search(r'"(\d+(\.\d+)?).*"', java_version_string) 45 | if not match: 46 | msg = f'no match for java version string "{java_version_string}"' 47 | raise Exception(msg) 48 | java_version = match.groups()[0] 49 | 50 | ## To use an officially released version. 51 | ## (Releases appear at https://github.com/google/google-java-format/releases/ , 52 | ## but I keep this in sync with Spotless.) 53 | # Because formatting is inconsistent between versions of GJF, you should 54 | # enable formatting only on versions of Java that support your version of GJF. 55 | # For example, don't format under Java 8/11 if you also use a later version of Java. 56 | # Version 1.3 and earlier do not wrap line comments. 57 | # Version 1.8 and later require JDK 11. 58 | # Version 1.10.0 and later can run under JDK 16. 59 | # Version 1.25.0 and later require JDK 17. 60 | ## To set this variable: 61 | ## See https://github.com/diffplug/spotless/blob/main/lib/src/main/java/com/diffplug/spotless/java/GoogleJavaFormatStep.java#L75 62 | ## or search for "Bump default google" in https://github.com/diffplug/spotless/blob/main/plugin-gradle/CHANGES.md 63 | if java_version == "1.8": 64 | gjf_version_default = "1.7" 65 | elif java_version == "11": 66 | gjf_version_default = "1.24.0" 67 | else: 68 | gjf_version_default = "1.28.0" 69 | gjf_version = os.getenv("GJF_VERSION", gjf_version_default) 70 | gjf_download_prefix = "v" if re.match(r"^1\.[1-9][0-9]", gjf_version) else "google-java-format-" 71 | gjf_snapshot = os.getenv("GJF_SNAPSHOT", "") 72 | gjf_url_base = os.getenv( 73 | "GJF_URL_BASE", 74 | "https://github.com/google/google-java-format/releases/download/" 75 | + gjf_download_prefix 76 | + gjf_version 77 | + "/", 78 | ) 79 | ## To use a non-official version by default, because an official version is 80 | ## unusably buggy (like 1.1) or no new release has been made in a long time. 81 | ## Never change the file at a URL; make it unique by adding a date. 82 | # gjf_version = "1.5" 83 | # gjf_snapshot = "-SNAPSHOT-20171012" 84 | # gjf_url_base = "http://types.cs.washington.edu/" 85 | # gjf_url_base = "http://homes.cs.washington.edu/~mernst/tmp2/" 86 | 87 | gjf_jar_name = "google-java-format-" + gjf_version + gjf_snapshot + "-all-deps.jar" 88 | gjf_url = gjf_url_base + gjf_jar_name 89 | 90 | 91 | # For some reason, the "git ls-files" must be run from the root. 92 | # (I can run "git ls-files" from the command line in any directory.) 93 | def under_git(directory: Path, filename: str) -> bool: 94 | """Return true if `filename` in `directory` is under git control. 95 | 96 | Args: 97 | directory: the directory 98 | filename: the file name 99 | 100 | Returns: 101 | true if `filename` in `directory` is under git control. 102 | """ 103 | if not shutil.which("git"): 104 | if debug: 105 | print("no git executable found") 106 | return False 107 | with subprocess.Popen( 108 | ["git", "ls-files", filename, "--error-unmatch"], 109 | cwd=directory, 110 | stdout=subprocess.DEVNULL, 111 | stderr=subprocess.STDOUT, 112 | ) as p: 113 | p.wait() 114 | if debug: 115 | print("p.returncode", p.returncode) 116 | return p.returncode == 0 117 | 118 | 119 | def urlretrieve(url: str, filename: Path) -> None: 120 | """Like urllib.urlretrieve.""" 121 | with urlopen(url) as in_stream, pathlib.Path(filename).open("wb") as out_file: 122 | copyfileobj(in_stream, out_file) 123 | 124 | 125 | # Set gjf_jar_path, or retrieve it if it doesn't appear locally. Does not update 126 | # from remove path if remote is newer, so never change files on the server. 127 | candidate1 = script_dir / gjf_jar_name 128 | candidate2 = script_dir.parent / "lib" / gjf_jar_name 129 | if candidate1.is_file(): 130 | gjf_jar_path = candidate1 131 | elif candidate2.is_file(): 132 | gjf_jar_path = candidate2 133 | else: 134 | gjf_jar_path = candidate1 135 | # print("retrieving " + gjf_url + " to " + gjf_jar_path) 136 | try: 137 | # Download to a temporary file, then rename atomically. 138 | # This avoids race conditions with other run-google-java-format processes. 139 | # "delete=False" because the file will be renamed. 140 | with tempfile.NamedTemporaryFile(dir=script_dir, delete=False) as f: 141 | urlretrieve(gjf_url, Path(f.name)) 142 | pathlib.Path(f.name).rename(gjf_jar_path) 143 | except Exception as e: 144 | raise Exception("Problem while retrieving " + gjf_url + " to " + str(gjf_jar_path)) from e 145 | 146 | 147 | # Don't replace local with remote if local is under version control. 148 | # It would be better to just test whether the remote is newer than local, 149 | # but raw GitHub URLs don't have the necessary last-modified information. 150 | if not under_git(script_dir, fixup_py_name): 151 | url = ( 152 | "https://raw.githubusercontent.com/plume-lib/run-google-java-format/master/" + fixup_py_name 153 | ) 154 | try: 155 | urlretrieve(url, fixup_py_path) 156 | except Exception: 157 | if pathlib.Path(fixup_py_path).exists(): 158 | print("Couldn't retrieve " + fixup_py_name + " from " + url + "; using cached version") 159 | else: 160 | print("Couldn't retrieve " + fixup_py_name + " from " + url) 161 | sys.exit(1) 162 | fixup_py_path.chmod(fixup_py_path.stat().st_mode | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) 163 | 164 | if debug: 165 | print("script_dir:", script_dir) 166 | print("fixup_py_path: ", fixup_py_path) 167 | print("gjf_jar_path: ", gjf_jar_path) 168 | 169 | files = sys.argv[1:] 170 | if len(files) == 0: 171 | print("run-google-java-format.py expects 1 or more filenames as arguments") 172 | sys.exit(1) 173 | 174 | if java_version == "1.8": 175 | jdk_opens = [] 176 | else: 177 | # From https://github.com/google/google-java-format/releases/ 178 | # This is no longer required as of GJF version 1.15.0, but users might 179 | # supply a version number lower than that. 180 | jdk_opens = [ 181 | "--add-exports", 182 | "jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", 183 | "--add-exports", 184 | "jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", 185 | "--add-exports", 186 | "jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", 187 | "--add-exports", 188 | "jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", 189 | "--add-exports", 190 | "jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED", 191 | ] 192 | 193 | result = subprocess.call(["java", *jdk_opens, "-jar", str(gjf_jar_path), "--replace", *files]) 194 | 195 | ## This if statement used to be commented out, because google-java-format 196 | ## crashed a lot. It seems more stable now. 197 | # Don't stop if there was an error, because google-java-format won't munge 198 | # files and we still want to run fixup-google-java-format.py. 199 | if result != 0: 200 | print("Error", result, "when running google-java-format") 201 | sys.exit(result) 202 | 203 | # Remove command-line arguments 204 | files = [f for f in files if not f.startswith("-")] 205 | # Exit if no files were supplied (maybe "--help" was supplied) 206 | if not files: 207 | sys.exit(0) 208 | 209 | if debug: 210 | print("Running " + fixup_py_name) 211 | result = subprocess.call([fixup_py_path, *files]) 212 | if result != 0: 213 | print("Error", result, "when running " + fixup_py_name) 214 | sys.exit(result) 215 | -------------------------------------------------------------------------------- /fixup-google-java-format.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Perform fixups after running the google-java-format program. 3 | 4 | The google-java-format program (https://github.com/google/google-java-format) 5 | reformats Java source code, but it creates poor formatting for annotations 6 | in comments. 7 | Run this script on files after running google-java-format, and it will perform 8 | small changes in place to improve formatting of annotations in comments. 9 | If called with no arguments, it reads from and writes to standard output. 10 | 11 | You typically will not run this program directly; it is run by 12 | run-google-java-format.py. 13 | """ 14 | 15 | import pathlib 16 | import re 17 | import sys 18 | from typing import Any, TextIO 19 | 20 | 21 | def eprint(*args: object, **kwargs: Any) -> None: 22 | """Print to standard error.""" 23 | print(*args, file=sys.stderr, **kwargs) 24 | 25 | 26 | # pylint: disable=line-too-long, multiple-statements 27 | 28 | # Keep this list in sync with FormatAnnotationsStep.java in spotless. 29 | # These are type annotations, which should NOT go on their own line. 30 | # A type annotation's @Target annotation contains "TYPE_USE". 31 | # This includes private type annotations used in Checker Framework tests. 32 | # To generate this list, in a file named `type-qualifiers.txt`, run: 33 | # make type-qualifiers.txt 34 | type_annotations = { 35 | "A", 36 | "ACCBottom", 37 | "ACCTop", 38 | "Acceleration", 39 | "AinferBottom", 40 | "AinferDefaultType", 41 | "AinferImplicitAnno", 42 | "AinferParent", 43 | "AinferSibling1", 44 | "AinferSibling2", 45 | "AinferSiblingWithFields", 46 | "AinferTop", 47 | "AlwaysSafe", 48 | "Angle", 49 | "AnnoWithStringArg", 50 | "Area", 51 | "ArrayLen", 52 | "ArrayLenRange", 53 | "ArrayWithoutPackage", 54 | "AwtAlphaCompositingRule", 55 | "AwtColorSpace", 56 | "AwtCursorType", 57 | "AwtFlowLayout", 58 | "B", 59 | "BinaryName", 60 | "BinaryNameOrPrimitiveType", 61 | "BinaryNameWithoutPackage", 62 | "BoolVal", 63 | "Bottom", 64 | "BottomGrowShrink", 65 | "BottomQualifier", 66 | "BottomThis", 67 | "BottomVal", 68 | "C", 69 | "CCBottom", 70 | "CCTop", 71 | "CalledMethods", 72 | "CalledMethodsBottom", 73 | "CalledMethodsPredicate", 74 | "CanonicalName", 75 | "CanonicalNameAndBinaryName", 76 | "CanonicalNameOrEmpty", 77 | "CanonicalNameOrPrimitiveType", 78 | "ClassBound", 79 | "ClassGetName", 80 | "ClassGetSimpleName", 81 | "ClassVal", 82 | "ClassValBottom", 83 | "CompilerMessageKey", 84 | "CompilerMessageKeyBottom", 85 | "Critical", 86 | "Current", 87 | "Det", 88 | "DisbarUseBottom", 89 | "DisbarUseTop", 90 | "DoesNotMatchRegex", 91 | "DotSeparatedIdentifiers", 92 | "DotSeparatedIdentifiersOrPrimitiveType", 93 | "DoubleVal", 94 | "Encrypted", 95 | "EnumVal", 96 | "Even", 97 | "FBCBottom", 98 | "FEBottom", 99 | "FETop", 100 | "Fenum", 101 | "FenumBottom", 102 | "FenumTop", 103 | "FieldDescriptor", 104 | "FieldDescriptorForPrimitive", 105 | "FieldDescriptorWithoutPackage", 106 | "FlowExp", 107 | "Force", 108 | "Format", 109 | "FormatBottom", 110 | "FqBinaryName", 111 | "Frequency", 112 | "FullyQualifiedName", 113 | "GTENegativeOne", 114 | "GrowOnly", 115 | "GuardSatisfied", 116 | "GuardedBy", 117 | "GuardedByBottom", 118 | "GuardedByUnknown", 119 | "H1Bot", 120 | "H1Invalid", 121 | "H1Poly", 122 | "H1S1", 123 | "H1S2", 124 | "H1Top", 125 | "H2Bot", 126 | "H2Poly", 127 | "H2S1", 128 | "H2S2", 129 | "H2Top", 130 | "Hz", 131 | "I18nFormat", 132 | "I18nFormatBottom", 133 | "I18nFormatFor", 134 | "I18nInvalidFormat", 135 | "I18nUnknownFormat", 136 | "Identifier", 137 | "IdentifierOrPrimitiveType", 138 | "IndexFor", 139 | "IndexOrHigh", 140 | "IndexOrLow", 141 | "Initialized", 142 | "InitializedFields", 143 | "InitializedFieldsBottom", 144 | "IntRange", 145 | "IntVal", 146 | "InternalForm", 147 | "Interned", 148 | "InternedDistinct", 149 | "InvalidFormat", 150 | "K", 151 | "KeyFor", 152 | "KeyForBottom", 153 | "LB_TOP", 154 | "LTEqLengthOf", 155 | "LTLengthOf", 156 | "LTOMLengthOf", 157 | "LbTop", 158 | "LeakedToResult", 159 | "Length", 160 | "LengthOf", 161 | "LessThan", 162 | "LessThanBottom", 163 | "LessThanUnknown", 164 | "LocalizableKey", 165 | "LocalizableKeyBottom", 166 | "Localized", 167 | "LowerBoundBottom", 168 | "LowerBoundUnknown", 169 | "LubglbA", 170 | "LubglbB", 171 | "LubglbC", 172 | "LubglbD", 173 | "LubglbE", 174 | "LubglbF", 175 | "Luminance", 176 | "Mass", 177 | "MatchesRegex", 178 | "MaybeAliased", 179 | "MaybePresent", 180 | "MethodDescriptor", 181 | "MethodVal", 182 | "MethodValBottom", 183 | "MinLen", 184 | "MonotonicNonNull", 185 | "MonotonicOdd", 186 | "MustCall", 187 | "MustCallAlias", 188 | "MustCallUnknown", 189 | "N", 190 | "NTDBottom", 191 | "NTDMiddle", 192 | "NTDSide", 193 | "NTDTop", 194 | "NegativeIndexFor", 195 | "NewObject", 196 | "NonDet", 197 | "NonEmpty", 198 | "NonLeaked", 199 | "NonNegative", 200 | "NonNull", 201 | "NotCalledMethods", 202 | "NotNull", 203 | "NotQualifier", 204 | "Nullable", 205 | "Odd", 206 | "OptionalBottom", 207 | "OrderNonDet", 208 | "PatternA", 209 | "PatternAB", 210 | "PatternAC", 211 | "PatternB", 212 | "PatternBC", 213 | "PatternBottomFull", 214 | "PatternC", 215 | "PatternUnknown", 216 | "PolyDet", 217 | "PolyEncrypted", 218 | "PolyFenum", 219 | "PolyGrowShrink", 220 | "PolyIndex", 221 | "PolyInitializedFields", 222 | "PolyInterned", 223 | "PolyKeyFor", 224 | "PolyLength", 225 | "PolyLowerBound", 226 | "PolyLubglb", 227 | "PolyMustCall", 228 | "PolyNonEmpty", 229 | "PolyNull", 230 | "PolyPresent", 231 | "PolyRegex", 232 | "PolySameLen", 233 | "PolySignature", 234 | "PolySigned", 235 | "PolyTainted", 236 | "PolyTestAccumulation", 237 | "PolyTestReflect", 238 | "PolyTypeDeclDefault", 239 | "PolyUI", 240 | "PolyUnit", 241 | "PolyUpperBound", 242 | "PolyValue", 243 | "PolyVariableNameDefault", 244 | "Positive", 245 | "Present", 246 | "PrimitiveType", 247 | "PropertyKey", 248 | "PropertyKeyBottom", 249 | "PurityUnqualified", 250 | "Qualifier", 251 | "Regex", 252 | "RegexBottom", 253 | "ReportUnqualified", 254 | "SameLen", 255 | "SameLenBottom", 256 | "SameLenUnknown", 257 | "SearchIndexBottom", 258 | "SearchIndexFor", 259 | "SearchIndexUnknown", 260 | "Shrinkable", 261 | "SignatureBottom", 262 | "Signed", 263 | "SignedPositive", 264 | "SignednessBottom", 265 | "SignednessGlb", 266 | "Speed", 267 | "SqlEvenQuotes", 268 | "SqlOddQuotes", 269 | "SqlQuotesBottom", 270 | "SqlQuotesUnknown", 271 | "StringVal", 272 | "SubQual", 273 | "Substance", 274 | "SubstringIndexBottom", 275 | "SubstringIndexFor", 276 | "SubstringIndexUnknown", 277 | "SuperQual", 278 | "SwingBoxOrientation", 279 | "SwingCompassDirection", 280 | "SwingElementOrientation", 281 | "SwingHorizontalOrientation", 282 | "SwingSplitPaneOrientation", 283 | "SwingTextOrientation", 284 | "SwingTitleJustification", 285 | "SwingTitlePosition", 286 | "SwingVerticalOrientation", 287 | "Tainted", 288 | "Temperature", 289 | "TestAccumulation", 290 | "TestAccumulationBottom", 291 | "TestAccumulationPredicate", 292 | "TestReflectBottom", 293 | "TestReflectSibling1", 294 | "TestReflectSibling2", 295 | "TestReflectTop", 296 | "This", 297 | "Time", 298 | "TypeDeclDefaultBottom", 299 | "TypeDeclDefaultMiddle", 300 | "TypeDeclDefaultTop", 301 | "UB_TOP", 302 | "UI", 303 | "UbTop", 304 | "UncheckedShrinkable", 305 | "UnderInitialization", 306 | "Unique", 307 | "UnitsBottom", 308 | "UnknownClass", 309 | "UnknownCompilerMessageKey", 310 | "UnknownFormat", 311 | "UnknownInitialization", 312 | "UnknownInterned", 313 | "UnknownKeyFor", 314 | "UnknownLocalizableKey", 315 | "UnknownLocalized", 316 | "UnknownMethod", 317 | "UnknownNonEmpty", 318 | "UnknownPropertyKey", 319 | "UnknownRegex", 320 | "UnknownSignedness", 321 | "UnknownThis", 322 | "UnknownUnits", 323 | "UnknownVal", 324 | "UnshrinkableRef", 325 | "Unsigned", 326 | "Untainted", 327 | "UpperBoundBottom", 328 | "UpperBoundLiteral", 329 | "UpperBoundUnknown", 330 | "ValueTypeAnno", 331 | "VariableNameDefaultBottom", 332 | "VariableNameDefaultMiddle", 333 | "VariableNameDefaultTop", 334 | "Volume", 335 | "WholeProgramInferenceBottom", 336 | "cd", 337 | "degrees", 338 | "g", 339 | "h", 340 | "kHz", 341 | "kN", 342 | "kg", 343 | "km", 344 | "km2", 345 | "km3", 346 | "kmPERh", 347 | "m", 348 | "m2", 349 | "m3", 350 | "mPERs", 351 | "mPERs2", 352 | "min", 353 | "mm", 354 | "mm2", 355 | "mm3", 356 | "mol", 357 | "radians", 358 | "s", 359 | "t", 360 | } 361 | 362 | # File .type-annotations can add to the type_annotations variable. 363 | if pathlib.Path(".type-annotations").is_file(): 364 | with pathlib.Path(".type-annotations").open() as ta: 365 | exec(ta.read()) 366 | 367 | debug = False 368 | # debug = True 369 | 370 | 371 | def debug_print(*args: object, **kwargs: Any) -> None: 372 | """Print, only if the debug variable is set.""" 373 | if debug: 374 | print(*args, **kwargs) 375 | 376 | 377 | # Two annotations in a row, or an annotation abutting array brackets "[]". 378 | # Space is inserted between. 379 | abuttinganno_regex = re.compile(r"(/\*@[A-Za-z0-9_]+\*/)(\[\]|/\*@[A-Za-z0-9_]+\*/)") 380 | # Voodoo annotation with extra space after 381 | voodootrailingspace_regex = re.compile(r"(/\*>>> ?@.*\bthis\*/) (\))") 382 | 383 | # Matches the argument to an annotation. 384 | # 3 cases: 385 | # () 386 | # (".*") 387 | # (.*) 388 | # The regex tries to safely permit "()" within a string in an annotation, such as 389 | # @GuardedBy("c1.getFieldPure2()") 390 | annoarg_regex = r'(?: *(?:\( *\)|\( *"[^"]*" *\)|\([^")][^)]*\)))?' 391 | # Matches an annotation 392 | anno_regex = r"@[A-Za-z0-9_.]+" + annoarg_regex 393 | 394 | # Matches, at the end of its line (in capturing group 2): 395 | # * An annotation 396 | # This is a bit dangerous! It might be within a comment. 397 | # The script tries to heuristically detect this. 398 | # * An annotation in comments 399 | # * a comment like /*offset = */ that should appear right 400 | # before the argument it documents. 401 | # (Supported in main google-java-format as of April 26, 2017, but not yet in a release: 402 | # https://github.com/google/google-java-format/commit/ca0c4d90cdbb46b3a2bf9c2b83d0bd558cccc41e ) 403 | # The annotation will be moved to the beginning of the following line, 404 | # if it appears in type_annotations. 405 | trailinganno_regex = re.compile( 406 | r"^(.*?)[ \t]*(" + anno_regex + r"|/\*" + anno_regex + r"\*/|/\* *[A-Za-z0-9_]+ *= *\*/)$" 407 | ) 408 | 409 | whitespace_regex = re.compile(r"^([ \t]*).*$") 410 | 411 | emptyline_regex = re.compile(r"^[ \t]*$") 412 | 413 | # Heuristic: matches if the line might be within a //, /*, or Javadoc comment. 414 | within_comment_regex = re.compile(r"//|/\*(?!.*\/*/)|^[ \t]*\*[ \t]") 415 | 416 | starts_with_comment_regex = re.compile(r"^[ \t]*(//|/\*$|/\*[^@]|\*|void\b)") 417 | 418 | 419 | def insert_after_whitespace(insertion: str, s: str) -> str: 420 | """Return s, with insertion inserted after its leading whitespace. 421 | 422 | Returns: 423 | s, with insertion inserted after its leading whitespace. 424 | """ 425 | m = re.match(whitespace_regex, s) 426 | if m is None: 427 | raise Exception("error: no match for leading whitespace") 428 | return s[0 : m.end(1)] + insertion + s[m.end(1) :] 429 | 430 | 431 | def fixup_loop(infile: TextIO, outfile: TextIO) -> None: 432 | """Fix up formatting while reading from infile and writing to outfile. 433 | 434 | Args: 435 | infile: the input file 436 | outfile: the output file 437 | """ 438 | prev = "" # previous line, which might end with a type annotation. 439 | for line in infile: 440 | # Handle trailing space after a voodoo comment 441 | line = voodootrailingspace_regex.sub(r"\1\2", line) 442 | # Handle abutting annotations in comments 443 | m = re.search(abuttinganno_regex, line) 444 | while m: 445 | debug_print("found abutting", line) 446 | line = line[0 : m.end(1)] + " " + line[m.start(2) :] 447 | m = re.search(abuttinganno_regex, line) 448 | # Don't move an annotation to the start of a comment line 449 | if re.search(starts_with_comment_regex, line): 450 | m = None 451 | debug_print("Don't prepend to comment", prev, line) 452 | else: 453 | # Handle annotations at end of line that should be at beginning of 454 | # next line. 455 | m = re.search(trailinganno_regex, prev) 456 | debug_print("trailing? (pre-loop)", m, prev, line) 457 | while m: 458 | debug_print("found trailing", prev, line) 459 | anno = m.group(2) 460 | if base_annotation(anno) not in type_annotations: 461 | break 462 | debug_print("prev was:", prev) 463 | candidate_prev = prev[0 : m.end(1)] + prev[m.end(2) :] 464 | debug_print("candidate_prev is :", candidate_prev) 465 | if re.search(within_comment_regex, candidate_prev): 466 | debug_print("within_comment_regex prohibits action") 467 | break 468 | prev = candidate_prev 469 | debug_print("prev is:", prev) 470 | if re.search(emptyline_regex, prev): 471 | prev = "" 472 | debug_print("prev is empty") 473 | debug_print("line was:", line) 474 | line = insert_after_whitespace(anno + " ", line) 475 | debug_print("line is :", line) 476 | m = re.search(trailinganno_regex, prev) 477 | debug_print("trailing? (post-loop-body)", m, prev, line) 478 | if re.search(r" try \($", prev): 479 | candidate_line = prev.rstrip() + line.lstrip() 480 | if len(candidate_line) < 100: 481 | line = candidate_line 482 | prev = "" 483 | debug_print("joined, now line is:", line) 484 | else: 485 | debug_print("no try match for", prev, line) 486 | outfile.write(prev) 487 | prev = line 488 | outfile.write(prev) 489 | 490 | 491 | def base_annotation(annotation: str) -> str: 492 | """Remove leading and trailing comment characters, spaces, arguments, and at sign. 493 | 494 | Example: base_annotation('/*@RequiresNonNull("FileIO.data_trace_state")*/' => 'RequiresNonNull' 495 | 496 | Returns: 497 | the annotation name without arguments or at sign 498 | """ 499 | debug_print("base_annotation <=", annotation) 500 | 501 | # Remove comments 502 | annotation = annotation.removeprefix("/*") 503 | annotation = annotation.removesuffix("*/") 504 | 505 | # Remove arguments 506 | idx = annotation.find("(") 507 | if idx != -1: 508 | annotation = annotation[0:idx] 509 | 510 | # Remove package names 511 | idx = annotation.rfind(".") 512 | if idx != -1: 513 | annotation = annotation[idx + 1 :] 514 | 515 | annotation = annotation.strip() 516 | annotation = annotation.removeprefix("@") 517 | debug_print("base_annotation =>", annotation) 518 | return annotation 519 | 520 | 521 | if len(sys.argv) == 1: 522 | fixup_loop(sys.stdin, sys.stdout) 523 | else: 524 | for fname in sys.argv[1:]: 525 | outfname = fname + ".out" 526 | with pathlib.Path(fname).open("r") as infile, pathlib.Path(outfname).open("w") as outfile: 527 | fixup_loop(infile, outfile) 528 | pathlib.Path(outfname).rename(fname) 529 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # run-google-java-format 2 | 3 | This repository contains the `run-google-java-format.py` and 4 | `check-google-java-format.py` scripts. 5 | They automatically download and run 6 | [google-java-format](https://github.com/google/google-java-format), 7 | they slightly improve its output, and they add checking functionality. 8 | 9 | The [google-java-format](https://github.com/google/google-java-format), or GJF, 10 | program reformats Java source code. It is a good formatter, but 11 | this project (run-google-java-format) improves it: 12 | 13 | * This project creates better formatting for [type annotations](https://github.com/google/google-java-format/issues/5). 14 | * This project creates better formatting for annotations in comments. 15 | * This project can check whether a file is properly formatted, which is 16 | desirable in a pre-commit hook. 17 | (Update: Version 1.5 of GJF can do this, but it is not cognizant of the better 18 | formatting that this project does.) 19 | * This project has a handy script to reformat code; by contrast, GJF requires a 20 | long, hard-to-remember command line. 21 | * You can run this project in a way that automatically uses the latest version of 22 | GJF, if you wish, without having to remember to update your GJF installation 23 | periodically. (You can also control which version of GJF this project uses; see 24 | "Customization" below.) 25 | 26 | The `run-google-java-format.py` and `check-google-java-format.py` scripts 27 | provide these enhancements over plain google-java-format. 28 | 29 | ## run-google-java-format.py 30 | 31 | This script reformats each file supplied on the command line according to 32 | the Google Java style, but with improvements to the formatting of 33 | annotations in comments. 34 | If called with no arguments, it reads from and writes to standard output. 35 | 36 | ## check-google-java-format.py 37 | 38 | Given `.java` file names on the command line, reports any that would be 39 | reformatted by the `run-google-java-format.py` program, and returns 40 | non-zero status if there were any. 41 | If called with no arguments, it reads from standard output. 42 | You could invoke this program, for example, in a [git pre-commit hook](#git-pre-commit-hook). 43 | 44 | ## Installing 45 | 46 | There are two ways to install and use these scripts (see below for integration 47 | with [Make](#makefile), [Ant](#ant-buildxml), [Gradle](#gradle-buildgradle), and 48 | [Git pre-commit hooks](#git-pre-commit-hook) that you can copy-and-paste into 49 | your build file): 50 | 51 | * Clone the repository (run `git clone 52 | https://github.com/plume-lib/run-google-java-format.git`) and run the 53 | scripts from there. 54 | * Download the 55 | [run-google-java-format.py](https://raw.githubusercontent.com/plume-lib/run-google-java-format/master/run-google-java-format.py) 56 | or 57 | [check-google-java-format.py](https://raw.githubusercontent.com/plume-lib/run-google-java-format/master/check-google-java-format.py) 58 | file and run it. The file will automatically download any additional 59 | needed files. 60 | 61 | ## Customization 62 | 63 | To control which version of google-java-format to use, 64 | set environment variable `GJF_VERSION`. For example: 65 | 66 | ```export GJF_VERSION=1.7``` 67 | 68 | ## Integrating with a build system 69 | 70 | Add the following targets to your build system. 71 | 72 | Integration with other build systems is similar. (Feel free to contribute 73 | concrete examples for build systems that are not listed here.) 74 | 75 | Some of these commands have only been tested on Unix; 76 | if you can create a version that also works on Windows, please contribute it. 77 | 78 | ### Makefile 79 | 80 | 81 | 82 | 83 | ```make 84 | JAVA_FILES_TO_FORMAT ?= $(shell find src -name '*.java' -print | grep -v '\.\#' \ 85 | | grep -v WeakHasherMap.java | grep -v WeakIdentityHashMap.java \ 86 | | grep -v MathMDE.java | sort) 87 | 88 | update-run-google-java-format: 89 | @[ -d .run-google-java-format ] \ 90 | && (cd .run-google-java-format && git pull -q) \ 91 | || git clone -q https://github.com/plume-lib/run-google-java-format.git .run-google-java-format 92 | 93 | # Requires Java 8 94 | reformat: 95 | ${MAKE} update-run-google-java-format 96 | @./.run-google-java-format/run-google-java-format.py ${JAVA_FILES_TO_FORMAT} 97 | 98 | # Requires Java 8 99 | check-format: 100 | ${MAKE} update-run-google-java-format 101 | @./.run-google-java-format/check-google-java-format.py ${JAVA_FILES_TO_FORMAT} \ 102 | || (echo "Try running: make reformat" && /bin/false) 103 | ``` 104 | 105 | 106 | 107 | 108 | ### Ant `build.xml` 109 | 110 | At the top of your Ant `build.xml` file, augment the `` block: 111 | 112 | ```xml 113 | 115 | ``` 116 | 117 | Then, add this: 118 | 119 | 120 | 121 | 122 | ```xml 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 146 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 158 | 160 | 161 | 162 | 163 | 164 | 165 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 175 | 178 | 179 | 180 | 181 | ${check.format.stdout} 182 | ${check.format.stderr} 183 | Fix syntax errors, then re-run: ant check-format 184 | Try running: ant reformat 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | ``` 194 | 195 | 196 | 197 | 198 | ### Gradle `build.gradle` 199 | 200 | Customize per your requirements, such as excluding generated `.java` files from formatting. 201 | 202 | 203 | 204 | 205 | ```gradle 206 | task getCodeFormatScripts { 207 | description "Obtain the run-google-java-format scripts" 208 | doLast { 209 | def rgjfDir = "$projectDir/.run-google-java-format" 210 | if (! new File(rgjfDir).exists()) { 211 | exec { 212 | commandLine 'git', 'clone', '--filter=tree:0', 213 | "https://github.com/plume-lib/run-google-java-format.git", rgjfDir 214 | } 215 | } else { 216 | // Ignore exit value: do not halt the build when not connected to the Internet. 217 | exec { 218 | workingDir rgjfDir 219 | ignoreExitValue true 220 | commandLine 'git', 'pull', '-q' 221 | } 222 | } 223 | } 224 | } 225 | 226 | task pythonIsInstalled(type: Exec) { 227 | description "Check that the python3 executable is installed." 228 | executable = "python3" 229 | args "--version" 230 | } 231 | 232 | task checkFormat(type: Exec, dependsOn: [getCodeFormatScripts, pythonIsInstalled], group: 'Formatting') { 233 | description "Check whether the Java source code is properly formatted" 234 | def javaFiles = fileTree("$projectDir").matching{ include "**/*.java" } as List 235 | def pythonArgs = javaFiles.clone() 236 | pythonArgs.add(0, "$projectDir/.run-google-java-format/check-google-java-format.py") 237 | 238 | commandLine "python3" 239 | args pythonArgs 240 | ignoreExitValue true 241 | 242 | doLast { 243 | if (!executionResult.isPresent() || executionResult.get().getExitValue() != 0) { 244 | throw new GradleException("Found improper formatting, try running: ./gradlew reformat") 245 | } 246 | } 247 | } 248 | 249 | task reformat(type: Exec, dependsOn: [getCodeFormatScripts, pythonIsInstalled], group: 'Formatting') { 250 | description "Format the Java source code according to the Google Java Format style" 251 | def javaFiles = fileTree("$projectDir").matching{ include "**/*.java" } as List 252 | def pythonArgs = javaFiles.clone() 253 | pythonArgs.add(0, "$projectDir/.run-google-java-format/run-google-java-format.py") 254 | 255 | commandLine "python3" 256 | args pythonArgs 257 | } 258 | ``` 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 295 | 296 | 297 | 298 | 299 | ### Git pre-commit hook 300 | 301 | Here is an example of what you might put in a Git pre-commit hook. 302 | This only checks the files that are being comitted, 303 | which is much faster than checking all files. 304 | 305 | 306 | 307 | 308 | ```sh 309 | CHANGED_JAVA_FILES=`git diff --staged --name-only --diff-filter=ACM \ 310 | | grep '\.java$' | grep -v '/ignored-directory/' ` || true 311 | if [ ! -z "$CHANGED_JAVA_FILES" ]; then 312 | # Choose one of these lines, depending on your build system; adjust the final echo statement too: 313 | ant -silent update-run-google-java-format 314 | make --silent update-run-google-java-format 315 | ## For debugging: 316 | # echo "CHANGED_JAVA_FILES: ${CHANGED_JAVA_FILES}" 317 | ./.run-google-java-format/check-google-java-format.py ${CHANGED_JAVA_FILES} \ 318 | || (echo "Try running: make reformat" && /bin/false) 319 | fi 320 | ``` 321 | 322 | 323 | 324 | 325 | You will also want to add `.run-google-java-format` to your 326 | `~/.gitignore-global` file or your project's `.gitignore` file. 327 | 328 | #### Finding trailing spaces 329 | 330 | google-java-format will complain about Java files with trailing spaces. 331 | Here is code for your Git pre-commit hook that finds all files that have 332 | trailing spaces. 333 | 334 | 335 | 336 | 337 | ```sh 338 | CHANGED_FILES=`git diff --staged --name-only --diff-filter=ACM \ 339 | | grep -v '.class$' | grep -v '.gz$'` | grep -v '.jar$'` \ 340 | | grep -v '.png$' | grep -v '.xcf$'` || true 341 | if [ ! -z "$CHANGED_FILES" ]; then 342 | # echo "CHANGED_FILES: ${CHANGED_FILES}" 343 | FILES_WITH_TRAILING_SPACES=`grep -l -s '[[:blank:]]$' ${CHANGED_FILES} 2>&1` || true 344 | if [ ! -z "$FILES_WITH_TRAILING_SPACES" ]; then 345 | echo "Some files have trailing whitespace: ${FILES_WITH_TRAILING_SPACES}" && exit 1 346 | fi 347 | fi 348 | ``` 349 | 350 | 351 | 352 | 353 | ## Dealing with large changes when reformatting your codebase 354 | 355 | When you first apply standard formatting, that may be disruptive to people 356 | who have changes in their own branches/clones/forks. 357 | (But, once you settle on consistent formatting, you will enjoy a number of 358 | benefits. Applying standard formatting to your codebase makes the code easier 359 | to read. It eases code review by eliminating comments about code style. 360 | It also simplifies use of a version control system: it reduces the 361 | likelihood of merge conflicts due to formatting changes, and it ensures 362 | that commits and pull requests don't intermingle substantive changes with 363 | formatting changes.) 364 | 365 | Here is a way to deal with upstream reformatting. 366 | 367 | ### For the person doing the reformatting 368 | 369 | 1. Create a new branch and do your work there. 370 | 371 | ```git checkout -b reformat-gjf``` 372 | 373 | 2. Tag the commit before the whitespace change as "before reformatting". 374 | 375 | ```git tag -a before-reformatting -m "Code before running google-java-format"``` 376 | 377 | 3. Reformat by running a command such as 378 | `make reformat`, 379 | `ant reformat`, or 380 | `./gradlew reformat` (or whatever buildfile target you have set up). 381 | 4. Examine the diffs to look for poor reformatting: 382 | 383 | ```git diff -w -b | grep -v '^[-+]import' | grep -v '^[-+]$'``` 384 | 385 | (You may wish to use `grep -v` to exclude some additional lines, 386 | depending on your project.) 387 | 388 | Here are two examples of poor reformatting to look out for: 389 | 390 | * A single statement 391 | that is the body of an `if`/`for`/`while` statement. google-java-format 392 | will move this onto the previous line with the boolean expression. It's 393 | better to use curly braces `{}` on every `then` clause, `else` clause, 394 | and `for`/`while` body. To find the poor reformatting (regexps in Emacs 395 | syntax): 396 | 397 | * Search for occurrences of `^\+.*\) return`. 398 | * Search for occurrences of `^\+.*\(if\|while\|for\) (.*) [^{]`. 399 | * Search for hunks that have fewer `+` than `-` lines. 400 | 401 | Add curly braces to get the body back on its own line. 402 | 403 | * Formatted Javadoc. To preserve line breaks and horizontal formatting, 404 | you may wish to enclose parts of your Javadoc comments in `
...
` 405 | or use `
    ` to format lists. 406 | 407 | (You can work in the branch where you are doing reformatting. 408 | Alternately, you might want to change your source code in the master 409 | branch, move the `before-reformatting` tag, and then start over with 410 | formatting.) 411 | 5. Run tests 412 | 6. Commit changes: 413 | 414 | ```git commit -m "Reformat code using google-java-format"``` 415 | 416 | 7. Tag the commit that does the whitespace change as "after reformatting". 417 | 418 | ```git tag -a after-reformatting -m "Code after running google-java-format"``` 419 | 420 | 8. Push both the commits and the tags: 421 | 422 | ```git push --tags``` 423 | 424 | ### For a client to merge the massive upstream changes 425 | 426 | Assuming before-reformatting is the last commit before reformatting 427 | and after-reformatting is the reformatting commit: 428 | 429 | 1. Merge in the commit before the reformatting into your branch. 430 | 431 | ```sh 432 | git merge before-reformatting 433 | ``` 434 | 435 | Or, if you have "myremote" configured as a remote, run these commands: 436 | 437 | ```sh 438 | git fetch myremote after-reformatting:after-reformatting 439 | git fetch myremote before-reformatting:before-reformatting 440 | ``` 441 | 442 | 2. Resolve any conflicts, run tests, and commit your changes. 443 | 3. Merge in the reformatting commit, preferring all your own changes. 444 | 445 | ```sh 446 | git merge after-reformatting -s recursive -X ours 447 | ``` 448 | 449 | 4. Reformat the code by running a command such as 450 | `make reformat`, 451 | `ant reformat`, or 452 | `./gradlew reformat` (or whatever buildfile target you have set up). 453 | 5. Commit any formatting changes. 454 | 6. Verify that this contains only changes you made (that is, the formatting 455 | changes were ignored): 456 | 457 | ```git diff after-reformatting...HEAD``` 458 | 459 | For a client of a client (such as a fork of a fork), 460 | the above instructions must be revised. 461 | 462 | ## Troubleshooting 463 | 464 | If you get an error in 465 | ```urllib.urlretrieve(gjf_url, gjf_jar_path)``` 466 | then there is a problem with your installation of Python. 467 | 468 | On MacOS Sierra, you can correct the problem by running these commands: 469 | 470 | ```sh 471 | brew install openssl 472 | brew install python@3 --with-brewed-openssl 473 | brew link --overwrite python@3 474 | ``` 475 | -------------------------------------------------------------------------------- /uv.lock: -------------------------------------------------------------------------------- 1 | version = 1 2 | revision = 3 3 | requires-python = ">=3.10" 4 | 5 | [[package]] 6 | name = "application-properties" 7 | version = "0.9.0" 8 | source = { registry = "https://pypi.org/simple" } 9 | dependencies = [ 10 | { name = "pyjson5" }, 11 | { name = "pyyaml" }, 12 | { name = "tomli" }, 13 | { name = "typing-extensions" }, 14 | ] 15 | sdist = { url = "https://files.pythonhosted.org/packages/1f/95/86e4c6faea022a96a7d15de1aca384e7a32400539338cc1d22fa72f0371c/application_properties-0.9.0.tar.gz", hash = "sha256:98a623210f82c2ca3911b19ba00bddedf15a84133ad8aad03b317e9e1ce56666", size = 36441, upload-time = "2025-07-02T02:06:44.948Z" } 16 | wheels = [ 17 | { url = "https://files.pythonhosted.org/packages/69/4c/18c89dabeaa60ebabffe53375aa3b9853ef10c47fdb3dfa979b5dbbfe4f7/application_properties-0.9.0-py3-none-any.whl", hash = "sha256:2f3d4cba46c4807c0dad5df632c379f1676d2c3b1a45a962f4f4527ce2713c97", size = 22433, upload-time = "2025-07-02T02:06:43.781Z" }, 18 | ] 19 | 20 | [[package]] 21 | name = "columnar" 22 | version = "1.4.1" 23 | source = { registry = "https://pypi.org/simple" } 24 | dependencies = [ 25 | { name = "toolz" }, 26 | { name = "wcwidth" }, 27 | ] 28 | sdist = { url = "https://files.pythonhosted.org/packages/5e/0d/a0b2fd781050d29c9df64ac6df30b5f18b775724b79779f56fc5a8298fe9/Columnar-1.4.1.tar.gz", hash = "sha256:c3cb57273333b2ff9cfaafc86f09307419330c97faa88dcfe23df05e6fbb9c72", size = 11386, upload-time = "2021-12-27T21:58:56.123Z" } 29 | wheels = [ 30 | { url = "https://files.pythonhosted.org/packages/06/00/a17a5657bf090b9dffdb310ac273c553a38f9252f60224da9fe62d9b60e9/Columnar-1.4.1-py3-none-any.whl", hash = "sha256:8efb692a7e6ca07dcc8f4ea889960421331a5dffa8e5af81f0a67ad8ea1fc798", size = 11845, upload-time = "2021-12-27T21:58:54.388Z" }, 31 | ] 32 | 33 | [[package]] 34 | name = "pyjson5" 35 | version = "2.0.0" 36 | source = { registry = "https://pypi.org/simple" } 37 | sdist = { url = "https://files.pythonhosted.org/packages/6e/d9/005aaaf5077cde946282b22da9404965477fb140fa6836b52d2e0955a391/pyjson5-2.0.0.tar.gz", hash = "sha256:7ccc98586cf87dfeadfa76de8df4c9cb0c3d21d1b559e28812dd9633748d6e25", size = 305865, upload-time = "2025-10-02T00:23:02.154Z" } 38 | wheels = [ 39 | { url = "https://files.pythonhosted.org/packages/32/98/a758a7c7985ea50a0ea9680181070928cc8ea2a0f71a9ad13be3f581ce25/pyjson5-2.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:176099c7db0197039eb70f21dbf072cf5d4be8e0c065e96d6d6171275398a1b1", size = 297332, upload-time = "2025-10-02T00:18:50.825Z" }, 40 | { url = "https://files.pythonhosted.org/packages/e0/83/ac464728b541489e92f338e7db958ba998fa1bab6d821306ead3d163d09a/pyjson5-2.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c7182c67a6fa58931550d7e1d60e485825e75d0e50592ab8674e3eebe2e75e99", size = 156205, upload-time = "2025-10-02T00:18:52.746Z" }, 41 | { url = "https://files.pythonhosted.org/packages/06/17/1f3192eca83e191611aabf6b7531acb8cd4fb83688a4202de40d4730b0dd/pyjson5-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:44d5bb544a955aa30016b743fdce88954673df4c1ab72aeae60ca56bc8c0ea1b", size = 150663, upload-time = "2025-10-02T00:18:54.017Z" }, 42 | { url = "https://files.pythonhosted.org/packages/5b/c7/252d0659ae0b823b48f1432c941c55ddc704863d2d3ae3f7f1517643261f/pyjson5-2.0.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f038bf94aa0e4885d1cbaf67fcb02a34f799185a2df1ac24786b820431ba397", size = 192706, upload-time = "2025-10-02T00:18:55.255Z" }, 43 | { url = "https://files.pythonhosted.org/packages/eb/82/e90e15cd9399f3d643da07788f31cabae6cdfedd05b73376c700ef4f4a4a/pyjson5-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:54e6cee0282be21a12edf08f9007682bc00b15aa8bf47e5e6af165bce87ecad4", size = 172039, upload-time = "2025-10-02T00:18:56.372Z" }, 44 | { url = "https://files.pythonhosted.org/packages/2e/48/b90c8c81178f211feeebe270161e3603fcc73e5c1ceece45bb70772f9cc2/pyjson5-2.0.0-cp310-cp310-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:f63536df8a1626e38ac9d9f764a31fe514289de9787b6c0d9b824acac24bfe97", size = 168962, upload-time = "2025-10-02T00:18:57.762Z" }, 45 | { url = "https://files.pythonhosted.org/packages/f1/dc/620ab56078b7ba42530b6efe0df880288991e948b805cc0e4f0c781dc8a9/pyjson5-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b5bc1ce2bf8765c9509f4c07c3df8bdbb64052950690e8b624b85eae763b6c0", size = 194931, upload-time = "2025-10-02T00:18:59.134Z" }, 46 | { url = "https://files.pythonhosted.org/packages/82/50/4eea4b37d825199aef5739397e1ccd1413922f66ae06846a8559f47ad3ea/pyjson5-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05e95dab489ddf85308165ef1d537493b70ae0631311e600a3aa5562c4583f3a", size = 197298, upload-time = "2025-10-02T00:19:00.286Z" }, 47 | { url = "https://files.pythonhosted.org/packages/51/d9/456a0d08e44b70d39d719dba1b51be64b69a22e7bb01d91857030afd3a8b/pyjson5-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:979090533eb8a37378188c851cb579f3101698a2293eb09c1f1a58cfea236ea4", size = 184148, upload-time = "2025-10-02T00:19:01.613Z" }, 48 | { url = "https://files.pythonhosted.org/packages/4a/b5/f35560c31834f914d4b01da6bb5915e9eaca06d7e796ea7805aef0c6e65b/pyjson5-2.0.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:93403e053c58eb3cda23824664514061d2398990cb7f71e4d6112b9c82eff9ef", size = 182742, upload-time = "2025-10-02T00:19:02.994Z" }, 49 | { url = "https://files.pythonhosted.org/packages/fb/62/4ee6c2cf29d3edb6f2922b9ca63dc6f73403773b4ed014f6790ec3b72033/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:0cfa8d5514a37a6f610116bf140922c635a79aefb0d6e61459320d4dff942140", size = 1153989, upload-time = "2025-10-02T00:19:04.177Z" }, 50 | { url = "https://files.pythonhosted.org/packages/40/98/7dc3ba18b064bd9b62be48050bd0fc814855f78fa27ee385f8b5c7c93c14/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_armv7l.whl", hash = "sha256:acc3810d446edc05c892e1ac43e6b223b11b1ccc1c6b7787f85641695f1b869a", size = 1013908, upload-time = "2025-10-02T00:19:05.814Z" }, 51 | { url = "https://files.pythonhosted.org/packages/c4/b1/d9af0d2205db46458dd45c0551fc0188b3f8578d4f43e9a8a54357388bc4/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:bfd1e0a4d6155f2cea51ccac5b7eccd506123f7eccddf9c6cd2cd56369fc16a9", size = 1328108, upload-time = "2025-10-02T00:19:07.184Z" }, 52 | { url = "https://files.pythonhosted.org/packages/06/ae/d29b930bc0ae2b98f2c7c4a7de7afb110b9cde9abe9e6fc853e3b4440176/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:2369d36c68fcf016859396ef14a4f6176fa63e2567aff9baf1eb9ef51fb46835", size = 1253739, upload-time = "2025-10-02T00:19:08.752Z" }, 53 | { url = "https://files.pythonhosted.org/packages/af/69/f4f352cfc0faad6ed25de3485be75c5040ebe6c6c69925ec42e54081dc7e/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:c37d4a744eadfe2be569c96ef0acd07ecf021d05b3801c9d7b967e70fb6937e1", size = 1189958, upload-time = "2025-10-02T00:19:10.304Z" }, 54 | { url = "https://files.pythonhosted.org/packages/de/b0/1b373a9c28a4510a54e868ce707910f5a8fb53fc6d9610d770dfdadb691a/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c4e058bb5626940266c55a52d49233fd94d8f7f3b0ca491ea356cd6aab3d09bb", size = 1366103, upload-time = "2025-10-02T00:19:11.7Z" }, 55 | { url = "https://files.pythonhosted.org/packages/0e/16/3e94e78254c2d035ad66767d5d7afbdaf249d69e24f72137b7be1a72a3ed/pyjson5-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c0d9f4167e11a57b4366f9a6dc0fe1fa573ff95b30eb8bffcc4f0da183680452", size = 1216945, upload-time = "2025-10-02T00:19:13.427Z" }, 56 | { url = "https://files.pythonhosted.org/packages/6c/a6/d810dda12512905fb716e3199230b60cc8c3f9951a804f74a7463b4c991e/pyjson5-2.0.0-cp310-cp310-win32.whl", hash = "sha256:7d4a839694ef4e7e3729d3b9d82da3ab6458b075678b2f1603dd46c85ad93923", size = 114285, upload-time = "2025-10-02T00:19:14.922Z" }, 57 | { url = "https://files.pythonhosted.org/packages/b1/5b/4695d0a529bee729510f349dfad545cff0923807177f74607d5bc9c5dd7f/pyjson5-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:4f2ce61b582edf57e10c3181ff4e3c59d13382adb22e9810665def9d60d077f7", size = 133126, upload-time = "2025-10-02T00:19:16.253Z" }, 58 | { url = "https://files.pythonhosted.org/packages/97/d3/2d68a7f743fd5151f2317796306423afd85620b86bb8c1d4efabe3deb824/pyjson5-2.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:e9e686faff89765ad99c7f5602a99703bd7432db04e0f541b7c91ff7d3499cd8", size = 116698, upload-time = "2025-10-02T00:19:17.534Z" }, 59 | { url = "https://files.pythonhosted.org/packages/c2/2b/2cb73dba9ffeabd91d67577f5fc7fa67040eae6876c632214145893844da/pyjson5-2.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1e6870507311765249f6cb533d8d53e0c9b1837f2e1b0b2ba7825181bd980a48", size = 299572, upload-time = "2025-10-02T00:19:18.448Z" }, 60 | { url = "https://files.pythonhosted.org/packages/e1/1b/ebf7d13d57fffccb2d5b7bbf609800ccf8ff09678a8a7ae6c0764b04b1c8/pyjson5-2.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:68f931934d736bfd0d9d9c666b9495a10807821c44a7c58069b2f6a12ceb47ae", size = 157385, upload-time = "2025-10-02T00:19:19.905Z" }, 61 | { url = "https://files.pythonhosted.org/packages/29/7c/eb6fcb6e94075bea4ab56c50d1bfb8a66d43fdc2fb67001181928dd7ddb1/pyjson5-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:47eda4d30024bfa8074a6f17145e55e60cf74a43215db99685fe6998cd0130aa", size = 151838, upload-time = "2025-10-02T00:19:20.91Z" }, 62 | { url = "https://files.pythonhosted.org/packages/c2/7c/478456b8683bc3d964cf1ca060188b1d4bc03d01548d1449d033542aee91/pyjson5-2.0.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5cc27c08bf33c7be0622ada8ff6dc7aa203287d1e585e343e90d2f2c19f31977", size = 192102, upload-time = "2025-10-02T00:19:22.238Z" }, 63 | { url = "https://files.pythonhosted.org/packages/0f/17/bce2b2641aa140c761807d50cf30a7e09c53d0bd8737bf63dada0e8613f4/pyjson5-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3af072ff4cb1046c17d6108fd01f4c39519c95e8aa5b2084fd6fea57379eafc", size = 176766, upload-time = "2025-10-02T00:19:23.181Z" }, 64 | { url = "https://files.pythonhosted.org/packages/30/61/7e51cd104e4514edd21b6e0c7e841da14ba80d3372d028b62719d8cb3f9e/pyjson5-2.0.0-cp311-cp311-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:eec8b9067aa041a177a07596c8e800e7616e5ad87ce97836c3489f977231dc1a", size = 170313, upload-time = "2025-10-02T00:19:24.602Z" }, 65 | { url = "https://files.pythonhosted.org/packages/7e/7e/2398eeffafc924809d4a708588f7f697398ca095b6c399849bfd0867780a/pyjson5-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e91417ead40a468698d0eb6654685986c03afc53290b8dd58d51f28803451506", size = 196097, upload-time = "2025-10-02T00:19:25.536Z" }, 66 | { url = "https://files.pythonhosted.org/packages/98/70/550d7d634e46a71bf00b93ec2c4a8a7d63f9629e1a5117cbf249995c0e3a/pyjson5-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:023466521ce06f314979589fcd7fa01cdcff4d7a0cd32d1545ca0d566bca7761", size = 198474, upload-time = "2025-10-02T00:19:26.495Z" }, 67 | { url = "https://files.pythonhosted.org/packages/0f/3c/e4ef8f3ef83254de96aba69f24fa613bc1277cf34802c6b4e82cc311121f/pyjson5-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:913488fb34610b900bef4244bf99d8585b3d1431a7ba28d9538fb6b3bc34150c", size = 186299, upload-time = "2025-10-02T00:19:27.525Z" }, 68 | { url = "https://files.pythonhosted.org/packages/e7/35/60c473c7970e4239149e7e4dcf7b10ca8712779e47be47b9d9fd076e54ea/pyjson5-2.0.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e25ca44bcb3ce47938d739c5b2bbecdefca919132b7f46a3f57a6d06a38c02f0", size = 185624, upload-time = "2025-10-02T00:19:28.532Z" }, 69 | { url = "https://files.pythonhosted.org/packages/b5/15/876e53cc43c98ff036c05c90fa8a9ccbf704478a69ffc6efe2c9f898bf77/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c3192eaf57cd17c367dd1726354e992c10dfb810b4c2b87284f55f00840b2245", size = 1158339, upload-time = "2025-10-02T00:19:30.089Z" }, 70 | { url = "https://files.pythonhosted.org/packages/82/57/2ef4f05a29c04ae1beceae2739b3428bca064f963758284b1633fccc5190/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_armv7l.whl", hash = "sha256:6ecc3f3216aa9795a80836a1f206fc87c4d2d71f0d90228ff10f1f55b16f72c2", size = 1013974, upload-time = "2025-10-02T00:19:31.486Z" }, 71 | { url = "https://files.pythonhosted.org/packages/fb/9a/28b8655c6c6715e15c20ab98574a793f6b3435badd0ddf67ba3ea1bd420c/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0e9f21938060afe6f6cd64e76f2f4849c22a7aa61ee794e9885b0a760064deb4", size = 1329463, upload-time = "2025-10-02T00:19:32.824Z" }, 72 | { url = "https://files.pythonhosted.org/packages/6a/6a/e427b03a02ff45cc7432a7d1e16066512321f643457039c2b955449f4148/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:78133797816d47780b25a1cf55e66ee9cd3e00a9e3abae66040fb975c39b1d23", size = 1255206, upload-time = "2025-10-02T00:19:34.778Z" }, 73 | { url = "https://files.pythonhosted.org/packages/28/2b/d2b4a3137842de3ba66195fa5e3da96ac8c93790c77a8d76b1d30245b327/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:19d7dfb9d5d32839e1b77506c6b8023f83c72f531e2d6248400ca832efdb2349", size = 1190884, upload-time = "2025-10-02T00:19:36.24Z" }, 74 | { url = "https://files.pythonhosted.org/packages/7c/6a/e590e10b7e9f145d0e7b02fde0b0b3ffec45998fc7d454e5c64f98aff6d5/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:95012228c10803512f515e70af06ec11a8621ce3742226ba507ebf6e91020d8d", size = 1367769, upload-time = "2025-10-02T00:19:37.74Z" }, 75 | { url = "https://files.pythonhosted.org/packages/df/3b/705305653470ef31f177ba8f70df6d5d85858e2f2bf3df7624a1c454b7cb/pyjson5-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4facf0fc1bcdd7d57308bbc3dfa2ad0498c8e4d76672c35f1e7976f02d3f7df8", size = 1219001, upload-time = "2025-10-02T00:19:39.586Z" }, 76 | { url = "https://files.pythonhosted.org/packages/ca/b9/1a072afcfba936d3dabc9db08d18ca3aec03b82002be7b1d6d781019b317/pyjson5-2.0.0-cp311-cp311-win32.whl", hash = "sha256:6fb1bba20ebd3a0b26bca5ee906757a9d82652ca31730d40cd921b88245ec780", size = 114294, upload-time = "2025-10-02T00:19:41.05Z" }, 77 | { url = "https://files.pythonhosted.org/packages/28/4d/303b9ad667d7440cfd4a45c75408cb868281b60864b917b285aba668a6f3/pyjson5-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:58b17386a96a308c8295e2c2a82526aefaa33ed2abaff84a916f90484b047cc4", size = 134665, upload-time = "2025-10-02T00:19:41.972Z" }, 78 | { url = "https://files.pythonhosted.org/packages/8a/eb/29d8d48730b1ad0a6b3762190dd2c3f43c39f4f89e20be1b8c0015b24246/pyjson5-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:4f4cde947ea68da7df8fb91b682491bcc0b916e3adb942febe866703853d8301", size = 117666, upload-time = "2025-10-02T00:19:42.861Z" }, 79 | { url = "https://files.pythonhosted.org/packages/d0/25/429e6cc1b6ba7a1ce730f172d8653f16dfff991de7c1122627b5d9a7dfd6/pyjson5-2.0.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:dbb701b2b19ef5860a2409baf7fd576af8619fdaffa96ca37e0e8e0b2f030be8", size = 300589, upload-time = "2025-10-02T00:19:44.285Z" }, 80 | { url = "https://files.pythonhosted.org/packages/1f/58/251cc5bfcced1f18dbe36ad54b25f376ab47e8a4bcd6239c7bd69b86218e/pyjson5-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c0f29297836f4a4f8090f5bfc7b0e2b70af235c8dcfd9476a159814f734441d3", size = 159389, upload-time = "2025-10-02T00:19:45.39Z" }, 81 | { url = "https://files.pythonhosted.org/packages/aa/4b/4e69ccbf34f2f303e32dc0dc8853d82282f109ba41b7a9366d518751e500/pyjson5-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76d4c8d8bf56696c5b9bc3b18f51c840499e7b485817ddba89ae399fcc25c923", size = 150788, upload-time = "2025-10-02T00:19:46.454Z" }, 82 | { url = "https://files.pythonhosted.org/packages/49/67/caa7dd84ab554d83bb68a7a27f09ed750681cd305d13feb38c2df90ccdbe/pyjson5-2.0.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e94e1a05c8a42a4828a50c520eb2330fe5732d5d04f3ebe771680f7db16f7df3", size = 188298, upload-time = "2025-10-02T00:19:47.456Z" }, 83 | { url = "https://files.pythonhosted.org/packages/ba/39/26fffaff9ebf720a05e2867c40e2023cebe33a41e1f511e3c1b42452fe7d/pyjson5-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9ab533ccd75bfda9ffd34a818f283b481e78c5c315919c4f620f69639044bdd3", size = 168159, upload-time = "2025-10-02T00:19:48.459Z" }, 84 | { url = "https://files.pythonhosted.org/packages/cd/c9/f7170d4903cb1526836a458f7e4650f0ff465001b7ef7066bc4b0577e601/pyjson5-2.0.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:16e9295bf9f80fc5fb63046a0df4a3adef4e945d27f61f0f6e5db0a4f1510a15", size = 169039, upload-time = "2025-10-02T00:19:49.478Z" }, 85 | { url = "https://files.pythonhosted.org/packages/2c/d1/b84322897a861e85528c9621372441c4db57b8af615a647a9a8223e7e00a/pyjson5-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4191eced0e77207afc2f82782ef3dbee88c38ec386da8c0af9190653e8c8557f", size = 185596, upload-time = "2025-10-02T00:19:50.5Z" }, 86 | { url = "https://files.pythonhosted.org/packages/56/3c/fea02294217c0b93f017ddc032bbacc805e669014c784b42b5cf366d4aa1/pyjson5-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:9efc441991cd31a5d1fea04d8a024649bbd9a005d7e0ec6a870670b47adf43e8", size = 187665, upload-time = "2025-10-02T00:19:51.513Z" }, 87 | { url = "https://files.pythonhosted.org/packages/10/39/de2423e6a13fb2f44ecf068df41ff1c7368ecd8b06f728afa1fb30f4ff0a/pyjson5-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:467c5e0856152bbe539e38f126f698189f1ecc4feb5292d47ad0f20472d24b6d", size = 178950, upload-time = "2025-10-02T00:19:52.591Z" }, 88 | { url = "https://files.pythonhosted.org/packages/d4/9c/3de848f4441b95ad5f8499f7aed9b86da1c7eee776b0e673d85703416f15/pyjson5-2.0.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a2fc21d0f59c75dd3cc0a9943fface3729a4cf2e4dfbd14a90680a97bbfe23d1", size = 175149, upload-time = "2025-10-02T00:19:53.655Z" }, 89 | { url = "https://files.pythonhosted.org/packages/44/b8/fb33760617875852f299e06aa9cd9bbaf68d2f939189736ebf9099f4f305/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7a4887291c830dbc30528833eb8cdcc44d0531626a61ac9bac80b17df369cb33", size = 1149408, upload-time = "2025-10-02T00:19:54.885Z" }, 90 | { url = "https://files.pythonhosted.org/packages/8c/b2/ea1806e14704b5087a637a0b126ce63376f39e3762099614bca446dc7fa4/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:4a1497408a18ddd2501b1c6bdd1dd01d69809450d145c13c42913f98dfa59d20", size = 1012047, upload-time = "2025-10-02T00:19:56.254Z" }, 91 | { url = "https://files.pythonhosted.org/packages/8d/79/bbd9e037d2758b3da79a4bf02d6234e88908ad62fd6fc299144d4efe7466/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:9617abb9022fcd3d1034a5e07972dc0440af3d91da86c45f81750b6c324e9bcf", size = 1324907, upload-time = "2025-10-02T00:19:57.961Z" }, 92 | { url = "https://files.pythonhosted.org/packages/e0/5d/f984d6008fa0dcf64624eed4334c88cdae31b48d0546a17017beea6f6978/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:247a8f29e4fecdf7ff894dd3b5759a21c5336b5e3c21ba2ee31a03b52b73a98c", size = 1243097, upload-time = "2025-10-02T00:19:59.37Z" }, 93 | { url = "https://files.pythonhosted.org/packages/14/dc/c07f02d3e5f307540f884cb9ae1c2b17849ebcbf112f81663abe8ca04511/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:6a464e605113b09d2f235fc6d7df8425831bbe40078fe6755b30058b8a904694", size = 1181197, upload-time = "2025-10-02T00:20:00.893Z" }, 94 | { url = "https://files.pythonhosted.org/packages/1a/59/6cf634b199a4e71cb11cc8157d3c8c0baea1d8c89b2bea3bf83a482ac742/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d355134c9735f3eb3724f3985551203976c823909aec118f616b8da096ffd9b5", size = 1356466, upload-time = "2025-10-02T00:20:02.497Z" }, 95 | { url = "https://files.pythonhosted.org/packages/1d/f1/ae443709da9396396545c1ecfc30fd2f69629a65e894341a72fa286f0c26/pyjson5-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c3353d214db15d6b05d941cdb2fc2e3d1c94650e5baecc6986424f20ebe76d1", size = 1211084, upload-time = "2025-10-02T00:20:03.99Z" }, 96 | { url = "https://files.pythonhosted.org/packages/28/a7/291e4ac2890dd94f773aa7fe606ffb7b5424ad5c21d888feccb0b0fbf76b/pyjson5-2.0.0-cp312-cp312-win32.whl", hash = "sha256:9f164c973f0d6b79ed3c92a4bb5506b04c810dcf84dc48b543d968ec0acfbfc8", size = 115425, upload-time = "2025-10-02T00:20:40.058Z" }, 97 | { url = "https://files.pythonhosted.org/packages/af/cb/cf69e6e080149b8993d553c683d364e714c6646f70f55b7c135efe942366/pyjson5-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:296cb2e2c6f64dc61397bd48f04569f1532cd9062d8ebca29ed02644b298e4fc", size = 135552, upload-time = "2025-10-02T00:20:41.392Z" }, 98 | { url = "https://files.pythonhosted.org/packages/3c/f7/b7784d5dd52a34f23efd4118bf856877a8f15bb2a53c43c192e4dee7d10f/pyjson5-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:b36fa4a4b6f632bbc2afc4caaa16e7f585cd2345de85a439e6ce734f915b8018", size = 116874, upload-time = "2025-10-02T00:20:42.379Z" }, 99 | { url = "https://files.pythonhosted.org/packages/74/f0/a0273fa863a96fb450336f5c8f3126cd1fefe17bd60451fd66dc58d0ab6c/pyjson5-2.0.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:6840b70981cb838e025a9f952004c6b59655c91076067abf01317fc10681cd7b", size = 299171, upload-time = "2025-10-02T00:20:43.467Z" }, 100 | { url = "https://files.pythonhosted.org/packages/e0/8c/402811e522cbed81f414056c1683c129127034a9f567fa707200c3c67cf7/pyjson5-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dd89ea40f33d1d835493ab0fc3b7b4d7c0c40254e0ddeefde08e0e9d98aebbde", size = 158725, upload-time = "2025-10-02T00:20:44.537Z" }, 101 | { url = "https://files.pythonhosted.org/packages/2f/00/f2392fe52b50aadf5037381a52f9eda0081be6c429d9d85b47f387ecda38/pyjson5-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dc47fe45e5c20137ac10e8f2d27985d97e67fa71410819a576fa21f181b8e94b", size = 150027, upload-time = "2025-10-02T00:20:45.54Z" }, 102 | { url = "https://files.pythonhosted.org/packages/36/5c/e3f18bb7059e4e4992b76bf2e9d8594615361313df2fb78b4c08d441a8a3/pyjson5-2.0.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:eb4e885db6fe2421735b913f43028578a30dbf9f4c86673649b52bbee91231a9", size = 187241, upload-time = "2025-10-02T00:20:46.869Z" }, 103 | { url = "https://files.pythonhosted.org/packages/ae/96/1d9cf5bf5ea863d61ab977f6e9842c8519ff430dbceb58580e06deb1dd4a/pyjson5-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4b56f404b77f6b6d4a53b74c4d3f989d33b33ec451d7b178dad43d2fb81204dc", size = 168678, upload-time = "2025-10-02T00:20:47.871Z" }, 104 | { url = "https://files.pythonhosted.org/packages/f5/f4/d0704fef397d0d28d1fc16f4577883331d46b6a2f2eb59c4cc1a364b19f9/pyjson5-2.0.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:20db35f29815572130ec8d539c2465c1e4e7c7677298d6f79216bda611577709", size = 169324, upload-time = "2025-10-02T00:20:48.829Z" }, 105 | { url = "https://files.pythonhosted.org/packages/df/8c/84eeafe750d04016aedb24cb02959e65a42ef09de675d0dca96013baf199/pyjson5-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:445a21f0a6333f352251e7cb5a8f471ce44e7d74892558bd256e0bb889c1961e", size = 184377, upload-time = "2025-10-02T00:20:50.41Z" }, 106 | { url = "https://files.pythonhosted.org/packages/9a/80/119b2b01ae625d06ab1d6d5b021f4988fea28cf0ce8921b83ee6f944a1ab/pyjson5-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:1bbabb12147f85850ba3b6a5813a3e9cc417ac9d0a66d57af42dd714f563b51e", size = 186931, upload-time = "2025-10-02T00:20:51.642Z" }, 107 | { url = "https://files.pythonhosted.org/packages/d8/d3/82f366ccadbe8a250e1b810ffa4a33006f66ec287e382632765b63758835/pyjson5-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:49f490d68bebfccb1aa01b612beef3abffa720c4069d82d74af8b55cf15cd214", size = 180127, upload-time = "2025-10-02T00:20:52.99Z" }, 108 | { url = "https://files.pythonhosted.org/packages/65/e2/8b96a72e8ab2e92c3748feafcec79f3e6219bf5289e5b053da7fe7fcb3f3/pyjson5-2.0.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:06cd493d607d94e841b6a8452f33bb45f55430ff33c992b8c4b671f8bebd2a14", size = 175413, upload-time = "2025-10-02T00:20:54.552Z" }, 109 | { url = "https://files.pythonhosted.org/packages/f8/9d/ea8542d9184616bedc3c7d8d8ac32d7e82fa4e347da08744b81cbffe00e3/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:9eea8981d20bf6c37939c013c51ea1e7c9252429b01002a51afce59081b9ae0f", size = 1150022, upload-time = "2025-10-02T00:20:55.861Z" }, 110 | { url = "https://files.pythonhosted.org/packages/6d/af/8b8060bb9609bf4ad0bfc6fb9f52373aada55c93880c9597e41aecc2d266/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:863a0688a090e8c0add0d769ddf51e2cd48edd1d585f34272e7b4f095593175b", size = 1011750, upload-time = "2025-10-02T00:20:57.505Z" }, 111 | { url = "https://files.pythonhosted.org/packages/14/3a/9e49bbecc03ebc21c0b45a4f51e74c87c5250822e6bcffb8f8bcf9e800fd/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:a4a0e0835d7a5c7b18c3333dd01940ee2d160560e50851803cfaab27cc298df3", size = 1324079, upload-time = "2025-10-02T00:20:58.882Z" }, 112 | { url = "https://files.pythonhosted.org/packages/2f/94/951c1f531a5369d8859e42a5ac60c7dacf4d8585bb25f37ca7bdd46b9cb1/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:42f3d404367f7365325be1f1460c515d40022d41bece841d47cf00e616967308", size = 1243622, upload-time = "2025-10-02T00:21:00.452Z" }, 113 | { url = "https://files.pythonhosted.org/packages/99/0b/edb91338101501f1ec18f003e2a8da7650409537f446c7db96d302c7870d/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:3765c07dc1cd5b954a3e793c73c5725bac5431b83f7c807d695d73bbf78ae431", size = 1182052, upload-time = "2025-10-02T00:21:02.139Z" }, 114 | { url = "https://files.pythonhosted.org/packages/64/f2/54e28fd04aa27375ec4baa447fd58a894cf3cfd20c6a0dad160ee8ec115c/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:51d33381fc268989d6ba3b6ff44e45b634ee490fc658704d04eca59ed9f8b53d", size = 1357131, upload-time = "2025-10-02T00:21:03.643Z" }, 115 | { url = "https://files.pythonhosted.org/packages/ac/1a/80b50d0fae42cf58e1a37f5b87543c445bb1781ffcc69c94cc73ed397d67/pyjson5-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9f42e70d01668ccff505de17a9358fd09b26f9de037dbc8f1476215f217d3dc1", size = 1212220, upload-time = "2025-10-02T00:21:05.044Z" }, 116 | { url = "https://files.pythonhosted.org/packages/39/fc/44fb44d5b915fc1c871aea2947d87b4cfd77c9f6673ffdaf4e41b7365a46/pyjson5-2.0.0-cp313-cp313-win32.whl", hash = "sha256:62e02fd3a4aa7bc48d9ad04dbd22076d4c33c8161df2f72cdbd8588b8634cb5d", size = 115225, upload-time = "2025-10-02T00:21:06.277Z" }, 117 | { url = "https://files.pythonhosted.org/packages/e9/60/d28dcdc482ed36196ee7523f47b1869f92a998777d46c80cf84ec1c8c962/pyjson5-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:5318cd5e7d130fb2532c0d295a5c914ee1ab629bc0c57b1ef625bddb272442c4", size = 135384, upload-time = "2025-10-02T00:21:07.284Z" }, 118 | { url = "https://files.pythonhosted.org/packages/79/3e/14be4a4efa651dab867057d81b4d56b1c9d5328418ca0b1d08d5e953e8d7/pyjson5-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:b274a6c6affca4a3210359bf486940ee08dbc9875f896ab19a14e344d9bbf322", size = 116783, upload-time = "2025-10-02T00:21:08.713Z" }, 119 | { url = "https://files.pythonhosted.org/packages/79/25/4a81e6d5611b38806e8f87a5b1cf4cbac21b9781c1cbba02c8e43ebd9664/pyjson5-2.0.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:6ae6b65bc5a45e853b462d840fc32be1df4dab8dbd48b1ff3078b8dac2df2f09", size = 301159, upload-time = "2025-10-02T00:21:09.745Z" }, 120 | { url = "https://files.pythonhosted.org/packages/a6/f4/8c948e8a8b1a518fe87a114df1d58ab5f80b55b6601b64f8649438293bfd/pyjson5-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6b24990927f723c2fff183ec7e14507f8ae3ce22743ac312aa9bf1327f9153dd", size = 159730, upload-time = "2025-10-02T00:21:11.946Z" }, 121 | { url = "https://files.pythonhosted.org/packages/39/1b/9cd7acea4c0e5a4ed44a79b99fc7e3a50b69639ea9f926efc35d660bef04/pyjson5-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a84949318c52844ced26622a733ca54215ccfa9ee87eb38f1c92ee1ed5994827", size = 151029, upload-time = "2025-10-02T00:21:12.953Z" }, 122 | { url = "https://files.pythonhosted.org/packages/c4/ff/136636d1ab42f98c55011d2b25a45b3f1107bef10248506d6bf549c8eabd/pyjson5-2.0.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:10fa949fd41e8583170e2b8404c026d8e088d370428b87270a3a8df5a09ffac5", size = 187718, upload-time = "2025-10-02T00:21:14.225Z" }, 123 | { url = "https://files.pythonhosted.org/packages/e0/97/e104682432b02f1458de22478d2b62caa607426e8284bec4680a3537cadd/pyjson5-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ccbc7a0cf1d9b8c0851b84601650ce9772e526a1a444633be6827aa162c20b54", size = 171291, upload-time = "2025-10-02T00:21:15.322Z" }, 124 | { url = "https://files.pythonhosted.org/packages/a2/91/bf4eacd990f93f8b5afe717f915ed248595261fcfb47e7718e17c55f5069/pyjson5-2.0.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:4e193346ab7c49605be4ec240c81d91014a276a163d5bba67eb53e64f425cecf", size = 168555, upload-time = "2025-10-02T00:21:16.519Z" }, 125 | { url = "https://files.pythonhosted.org/packages/24/70/fc2147cade7bd91c4d3726a200ae9556bcb45e294d8c57a904f15da16eea/pyjson5-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:25e9b32e21d4928201e2c410bafd196b0a4f0034761378821e99fc80c21ed0e3", size = 185817, upload-time = "2025-10-02T00:21:17.628Z" }, 126 | { url = "https://files.pythonhosted.org/packages/01/48/a8c396f25b53880bd06beb11ea8f63a42a6b8f9b82d42cc0cf6b0df8ca9f/pyjson5-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:63b0300e5ea302c107e518ef185c6f4ab8af49a5d4a52ed93e3e287fa8a6c69f", size = 188903, upload-time = "2025-10-02T00:21:19.058Z" }, 127 | { url = "https://files.pythonhosted.org/packages/7c/a3/8ffe10a49652bfd769348c6eca577463c2b3938baab5e62f3896fc5da0b7/pyjson5-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:72f5b5832d2c3055be492cf9853ce7fe57b57cc5e664f1327f10211cbd1114ef", size = 180252, upload-time = "2025-10-02T00:21:20.174Z" }, 128 | { url = "https://files.pythonhosted.org/packages/7f/f0/801b0523f679a9bd5356210be9a9b074fc14e0e969f2ed1f789cf6af3c45/pyjson5-2.0.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:da790aeb2dd88be1c94ea95b5ff4915614109e9e025df7f0936dadc01ae21e0b", size = 175965, upload-time = "2025-10-02T00:21:21.252Z" }, 129 | { url = "https://files.pythonhosted.org/packages/ea/04/ab703bccebc02c31056a525b7f06c473f141dc5bf96fe314893911a7b9ad/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ee211f71e3d0e7550c09b407dc75d01bbe6d5ed2ac7ee6aa54f870ebe17541aa", size = 1151968, upload-time = "2025-10-02T00:21:22.982Z" }, 130 | { url = "https://files.pythonhosted.org/packages/70/18/5c665a34ef6123d4c4f70173e30f533bbcf36ca76e3fa7c03b8400b2e34c/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:bf8e84ac6d58380b5fda77985f7acea5afe45bd45e24e77aca0a6912d25222fc", size = 1009858, upload-time = "2025-10-02T00:21:24.305Z" }, 131 | { url = "https://files.pythonhosted.org/packages/f1/bb/7641ee31fedbe337f5c7ed505b8491a96a94fdcc1567b0b1b2b3633ec755/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f0dd8b38187d0c2e741d40b9b348328172d0c894a90457f53b22e0f470b19009", size = 1324909, upload-time = "2025-10-02T00:21:25.874Z" }, 132 | { url = "https://files.pythonhosted.org/packages/aa/7f/4cd19d65074d85ad583ff0517e3771af8dd3e87a40d6c25bdb81d38ff0b4/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:4ac06acc8ffa5686abad2220dbbef89f99694f1f6ddb70e4ec5455bf9fd91176", size = 1245254, upload-time = "2025-10-02T00:21:27.762Z" }, 133 | { url = "https://files.pythonhosted.org/packages/54/26/0b96502136c4e74fa508e5a129119bd2df235dfd165acb0d74043e7fe6f0/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:34d2700a9472817c043a18d711ee8fd7bb6270dbd4013473d9aac51cef6a7d77", size = 1182526, upload-time = "2025-10-02T00:21:29.433Z" }, 134 | { url = "https://files.pythonhosted.org/packages/4c/34/e704bb86cd56092771589a08d1705d1e1310bdb955a752b26f483f7cd7c9/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:daf0e3ecf4f7888735050e1e4dc6f25f2f523706cf42de5c3f665042311db9dc", size = 1359472, upload-time = "2025-10-02T00:21:31.4Z" }, 135 | { url = "https://files.pythonhosted.org/packages/0d/fe/d9b6e1a1e4e4d08b3f9b022e92b93abf7baab5c959296faf10aa89cf17b2/pyjson5-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:93580c6dcfb3f4f189c2a8477d9bf262cbc31878cd809c118ddc6b1bb8d6f645", size = 1212271, upload-time = "2025-10-02T00:21:32.796Z" }, 136 | { url = "https://files.pythonhosted.org/packages/0b/0d/c4de90f7b1aecbc24bacc2ea4582e344043e8587c18596649950e877f5aa/pyjson5-2.0.0-cp314-cp314-win32.whl", hash = "sha256:dc53188059c2a73c8ddd0d17eaf970210a0ba48805e2178dfc8e71c063668d80", size = 118268, upload-time = "2025-10-02T00:22:01.555Z" }, 137 | { url = "https://files.pythonhosted.org/packages/52/8c/1bb60288c4d480a0b51e376a17d6c4d932dc8420989d1db440e3b284aad5/pyjson5-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:36ab5b8fcf1585623d12519f55e3efddbcbba6a0072e7168b4a3f48e3d4c64bb", size = 137772, upload-time = "2025-10-02T00:22:02.577Z" }, 138 | { url = "https://files.pythonhosted.org/packages/53/ea/c5e9e5a44b194851347698b5065df642d42852641d32da0c71626f60f3fc/pyjson5-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:371a8ee3d8c5f128f8024c5afc776b661043c2b2672de83a22ed6a4a289522f9", size = 121372, upload-time = "2025-10-02T00:22:03.666Z" }, 139 | { url = "https://files.pythonhosted.org/packages/05/13/1391b985d3cded0038816d07a5d68e9f525a2b304a258e890bb5a4e2c64a/pyjson5-2.0.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:111d4f3b384a41eae225bce1709c745c1aeafd51214bcd850469c5c34167856c", size = 322542, upload-time = "2025-10-02T00:21:33.993Z" }, 140 | { url = "https://files.pythonhosted.org/packages/24/c9/391def485564be4700e8baaa9a67292ed64a316050f625b84ef43358fbcc/pyjson5-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:15bc0bc456d2b101c469f57d0301a9624be682302d9ded569d5976c2c3b1130e", size = 169901, upload-time = "2025-10-02T00:21:35.081Z" }, 141 | { url = "https://files.pythonhosted.org/packages/d7/9c/2612e236a40eac86fba453dc9db1c334b4fb77ac5d1630498b0e3a0fd8d3/pyjson5-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:151ea53ec2ce1c014c58ee755d3113af80dc44cb8ca1008eabb829cd1001ea7b", size = 161759, upload-time = "2025-10-02T00:21:36.543Z" }, 142 | { url = "https://files.pythonhosted.org/packages/42/6f/f62b823d2e52ee7ddb25761b4bc8286c08199f6d42ddd1f01e8cb48a55a0/pyjson5-2.0.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:92fb2ae9e367fc585f93573222bfa2512c6fe85703658f96adbebd8459b16d0c", size = 184972, upload-time = "2025-10-02T00:21:37.646Z" }, 143 | { url = "https://files.pythonhosted.org/packages/02/72/2bca65d3ad6f19386fd0e350f66c7153c09173ca9a4742d4108d07e73f78/pyjson5-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a59fcaf3927277a385f17863077d474f7451b1471ddcf6acdd28c76950d4c868", size = 172446, upload-time = "2025-10-02T00:21:38.723Z" }, 144 | { url = "https://files.pythonhosted.org/packages/48/ec/752cf626a6caa69bf63fea4a7a47c9c57130578de502198105c3e2c5a55f/pyjson5-2.0.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:10cc1d0afd26479b2643ad3a67211e98fa72aa66030bbb695bb03d34cea2f801", size = 165790, upload-time = "2025-10-02T00:21:39.752Z" }, 145 | { url = "https://files.pythonhosted.org/packages/80/a6/1b41a3f87e899d7b1c48e5fb45d1d306c478708806286f113a0495c13261/pyjson5-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c69f3b28b669e26b11766a200b7d0d8bbfbd9a48735e39b9675e8fb8d6a99744", size = 188500, upload-time = "2025-10-02T00:21:40.789Z" }, 146 | { url = "https://files.pythonhosted.org/packages/c1/da/c9769cff5ce6b1c7e4b7e169fa1191bb2b6562849069ca11f79be6ed98d1/pyjson5-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:05d08aeb21bf547e1de4749d22b5638405aca12ba866b762d25d84575d327327", size = 193060, upload-time = "2025-10-02T00:21:41.885Z" }, 147 | { url = "https://files.pythonhosted.org/packages/31/ef/a97738263b05d91189df4e081d2331389ec95f662d26242f678b53b7d9d7/pyjson5-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:321e107c7df19d281e858bcfdbb39282b8cc1163a1e8c142b9d91af1e1db8573", size = 181832, upload-time = "2025-10-02T00:21:42.959Z" }, 148 | { url = "https://files.pythonhosted.org/packages/f0/15/2170f05792bddace7136100c30bdf73ec54fbed7ae86eb17f42e882238ec/pyjson5-2.0.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:66dceb6b83990bf81accbbc1a56897f1bb302b7da063d5eb2d756f26c4e98389", size = 178943, upload-time = "2025-10-02T00:21:44.041Z" }, 149 | { url = "https://files.pythonhosted.org/packages/0f/e6/a7f40e1bfa312f1987577c583b4dc1008e05f016585f0858d527e7d6e48d/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2de1242c168735ac589c2ca5708f95bd3d47c50f59464042316b56d77d807cae", size = 1153787, upload-time = "2025-10-02T00:21:45.727Z" }, 150 | { url = "https://files.pythonhosted.org/packages/cc/e3/4efcc86258a63c5c8af79fd8fe06e0ff98cebcc56facf473dba3318455a3/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:505dd929b620886c4bcf2ba19ca842dc5606ed1ad1fe5003cc09fbd2d910b0ef", size = 1014990, upload-time = "2025-10-02T00:21:47.134Z" }, 151 | { url = "https://files.pythonhosted.org/packages/e5/15/e7f1bc7aeb2c9f008a83c3e9129b4b16e1e27b2ae463efe05cfc8320ea68/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:48fb751c641fd03b5f002dc47a040aca9eec0a8a9bc11bc77e86dc40a6c3f10e", size = 1322761, upload-time = "2025-10-02T00:21:48.727Z" }, 152 | { url = "https://files.pythonhosted.org/packages/37/30/d937dfcb8386841571f7eda2b78b716ece4d62a10ce9a71f9dc8e02269fe/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:d67186c0a70308da9752202e8dcc6fcf63991d8a2aa4cfa463a587a3cbb6416c", size = 1247709, upload-time = "2025-10-02T00:21:50.485Z" }, 153 | { url = "https://files.pythonhosted.org/packages/6a/d6/ca54b0953f45bd89317f5069c8cb096df33c391ae2166259c273981c4884/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:0a9c0901313c8cf36f6f72cfc76b3ef335723fd240c869bc80a8711567573252", size = 1185323, upload-time = "2025-10-02T00:21:52.27Z" }, 154 | { url = "https://files.pythonhosted.org/packages/46/eb/eaa0c7eef752ea2afb192ff3f15cb79fa5229ab22cf84c0b941a0671364f/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:918175822878b4a48949af6fa236ccb2189b6548df14077b97246b61baff2ba7", size = 1360604, upload-time = "2025-10-02T00:21:53.819Z" }, 155 | { url = "https://files.pythonhosted.org/packages/5f/ca/192931f334270fa941977a9beb2590d40fe460711d932b825c3882f100de/pyjson5-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:7a09dac1228517792d8941718194ee5e4aa55ed604e0616938e55d75aedcb0c1", size = 1214048, upload-time = "2025-10-02T00:21:55.338Z" }, 156 | { url = "https://files.pythonhosted.org/packages/c2/61/63bd6351bd88e7158380eabf182beb377b53c4812175db3cde82fb2ad16e/pyjson5-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:caeee4168841a4d061f0e33cd162ae45fedbe9be9ed3dbd839d76d7791858dcf", size = 138873, upload-time = "2025-10-02T00:21:56.903Z" }, 157 | { url = "https://files.pythonhosted.org/packages/f6/ee/f856f8e18336a96ad7a7561dc482f776fa3c236ca278820f1ad4d7e04bba/pyjson5-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:7121183c7be324bdb6e824fc047ac29ad676025506e3cdbad6def5c4af9247d4", size = 168332, upload-time = "2025-10-02T00:21:58.038Z" }, 158 | { url = "https://files.pythonhosted.org/packages/62/9d/17ac8aacb439c79a912a57ee105bb060c6c10d40eab587928215e2022e5e/pyjson5-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f5e151599913b0c6e3bc3e176951f48039457e8a4b14f59c1ffffb8580ab58ea", size = 127386, upload-time = "2025-10-02T00:22:00.217Z" }, 159 | ] 160 | 161 | [[package]] 162 | name = "pymarkdownlnt" 163 | version = "0.9.33" 164 | source = { registry = "https://pypi.org/simple" } 165 | dependencies = [ 166 | { name = "application-properties" }, 167 | { name = "columnar" }, 168 | { name = "typing-extensions" }, 169 | ] 170 | sdist = { url = "https://files.pythonhosted.org/packages/30/15/cb76156751bafceebba839aa3f679940dda4fadee20b8864a4d36a9b1644/pymarkdownlnt-0.9.33.tar.gz", hash = "sha256:4486eb34fed9b66d2e4e91c5b5159b5242b816a7847585aa2a94afc58cc5583d", size = 422332, upload-time = "2025-10-24T03:17:15.291Z" } 171 | wheels = [ 172 | { url = "https://files.pythonhosted.org/packages/9c/b1/04c96cbbf8a209ff4059560c2c5c3e4be23926ce397699f09e4551510703/pymarkdownlnt-0.9.33-py3-none-any.whl", hash = "sha256:c5341a6f2539d087f76c88cda2dfc0c39e7632ebae915ea9399a083030951f35", size = 505133, upload-time = "2025-10-24T03:17:14.05Z" }, 173 | ] 174 | 175 | [[package]] 176 | name = "pyyaml" 177 | version = "6.0.3" 178 | source = { registry = "https://pypi.org/simple" } 179 | sdist = { url = "https://files.pythonhosted.org/packages/05/8e/961c0007c59b8dd7729d542c61a4d537767a59645b82a0b521206e1e25c2/pyyaml-6.0.3.tar.gz", hash = "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", size = 130960, upload-time = "2025-09-25T21:33:16.546Z" } 180 | wheels = [ 181 | { url = "https://files.pythonhosted.org/packages/f4/a0/39350dd17dd6d6c6507025c0e53aef67a9293a6d37d3511f23ea510d5800/pyyaml-6.0.3-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", size = 184227, upload-time = "2025-09-25T21:31:46.04Z" }, 182 | { url = "https://files.pythonhosted.org/packages/05/14/52d505b5c59ce73244f59c7a50ecf47093ce4765f116cdb98286a71eeca2/pyyaml-6.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", size = 174019, upload-time = "2025-09-25T21:31:47.706Z" }, 183 | { url = "https://files.pythonhosted.org/packages/43/f7/0e6a5ae5599c838c696adb4e6330a59f463265bfa1e116cfd1fbb0abaaae/pyyaml-6.0.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", size = 740646, upload-time = "2025-09-25T21:31:49.21Z" }, 184 | { url = "https://files.pythonhosted.org/packages/2f/3a/61b9db1d28f00f8fd0ae760459a5c4bf1b941baf714e207b6eb0657d2578/pyyaml-6.0.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", size = 840793, upload-time = "2025-09-25T21:31:50.735Z" }, 185 | { url = "https://files.pythonhosted.org/packages/7a/1e/7acc4f0e74c4b3d9531e24739e0ab832a5edf40e64fbae1a9c01941cabd7/pyyaml-6.0.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", size = 770293, upload-time = "2025-09-25T21:31:51.828Z" }, 186 | { url = "https://files.pythonhosted.org/packages/8b/ef/abd085f06853af0cd59fa5f913d61a8eab65d7639ff2a658d18a25d6a89d/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", size = 732872, upload-time = "2025-09-25T21:31:53.282Z" }, 187 | { url = "https://files.pythonhosted.org/packages/1f/15/2bc9c8faf6450a8b3c9fc5448ed869c599c0a74ba2669772b1f3a0040180/pyyaml-6.0.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", size = 758828, upload-time = "2025-09-25T21:31:54.807Z" }, 188 | { url = "https://files.pythonhosted.org/packages/a3/00/531e92e88c00f4333ce359e50c19b8d1de9fe8d581b1534e35ccfbc5f393/pyyaml-6.0.3-cp310-cp310-win32.whl", hash = "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", size = 142415, upload-time = "2025-09-25T21:31:55.885Z" }, 189 | { url = "https://files.pythonhosted.org/packages/2a/fa/926c003379b19fca39dd4634818b00dec6c62d87faf628d1394e137354d4/pyyaml-6.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", size = 158561, upload-time = "2025-09-25T21:31:57.406Z" }, 190 | { url = "https://files.pythonhosted.org/packages/6d/16/a95b6757765b7b031c9374925bb718d55e0a9ba8a1b6a12d25962ea44347/pyyaml-6.0.3-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", size = 185826, upload-time = "2025-09-25T21:31:58.655Z" }, 191 | { url = "https://files.pythonhosted.org/packages/16/19/13de8e4377ed53079ee996e1ab0a9c33ec2faf808a4647b7b4c0d46dd239/pyyaml-6.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", size = 175577, upload-time = "2025-09-25T21:32:00.088Z" }, 192 | { url = "https://files.pythonhosted.org/packages/0c/62/d2eb46264d4b157dae1275b573017abec435397aa59cbcdab6fc978a8af4/pyyaml-6.0.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", size = 775556, upload-time = "2025-09-25T21:32:01.31Z" }, 193 | { url = "https://files.pythonhosted.org/packages/10/cb/16c3f2cf3266edd25aaa00d6c4350381c8b012ed6f5276675b9eba8d9ff4/pyyaml-6.0.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", size = 882114, upload-time = "2025-09-25T21:32:03.376Z" }, 194 | { url = "https://files.pythonhosted.org/packages/71/60/917329f640924b18ff085ab889a11c763e0b573da888e8404ff486657602/pyyaml-6.0.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", size = 806638, upload-time = "2025-09-25T21:32:04.553Z" }, 195 | { url = "https://files.pythonhosted.org/packages/dd/6f/529b0f316a9fd167281a6c3826b5583e6192dba792dd55e3203d3f8e655a/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", size = 767463, upload-time = "2025-09-25T21:32:06.152Z" }, 196 | { url = "https://files.pythonhosted.org/packages/f2/6a/b627b4e0c1dd03718543519ffb2f1deea4a1e6d42fbab8021936a4d22589/pyyaml-6.0.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", size = 794986, upload-time = "2025-09-25T21:32:07.367Z" }, 197 | { url = "https://files.pythonhosted.org/packages/45/91/47a6e1c42d9ee337c4839208f30d9f09caa9f720ec7582917b264defc875/pyyaml-6.0.3-cp311-cp311-win32.whl", hash = "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", size = 142543, upload-time = "2025-09-25T21:32:08.95Z" }, 198 | { url = "https://files.pythonhosted.org/packages/da/e3/ea007450a105ae919a72393cb06f122f288ef60bba2dc64b26e2646fa315/pyyaml-6.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", size = 158763, upload-time = "2025-09-25T21:32:09.96Z" }, 199 | { url = "https://files.pythonhosted.org/packages/d1/33/422b98d2195232ca1826284a76852ad5a86fe23e31b009c9886b2d0fb8b2/pyyaml-6.0.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", size = 182063, upload-time = "2025-09-25T21:32:11.445Z" }, 200 | { url = "https://files.pythonhosted.org/packages/89/a0/6cf41a19a1f2f3feab0e9c0b74134aa2ce6849093d5517a0c550fe37a648/pyyaml-6.0.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0", size = 173973, upload-time = "2025-09-25T21:32:12.492Z" }, 201 | { url = "https://files.pythonhosted.org/packages/ed/23/7a778b6bd0b9a8039df8b1b1d80e2e2ad78aa04171592c8a5c43a56a6af4/pyyaml-6.0.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", size = 775116, upload-time = "2025-09-25T21:32:13.652Z" }, 202 | { url = "https://files.pythonhosted.org/packages/65/30/d7353c338e12baef4ecc1b09e877c1970bd3382789c159b4f89d6a70dc09/pyyaml-6.0.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", size = 844011, upload-time = "2025-09-25T21:32:15.21Z" }, 203 | { url = "https://files.pythonhosted.org/packages/8b/9d/b3589d3877982d4f2329302ef98a8026e7f4443c765c46cfecc8858c6b4b/pyyaml-6.0.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", size = 807870, upload-time = "2025-09-25T21:32:16.431Z" }, 204 | { url = "https://files.pythonhosted.org/packages/05/c0/b3be26a015601b822b97d9149ff8cb5ead58c66f981e04fedf4e762f4bd4/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", size = 761089, upload-time = "2025-09-25T21:32:17.56Z" }, 205 | { url = "https://files.pythonhosted.org/packages/be/8e/98435a21d1d4b46590d5459a22d88128103f8da4c2d4cb8f14f2a96504e1/pyyaml-6.0.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", size = 790181, upload-time = "2025-09-25T21:32:18.834Z" }, 206 | { url = "https://files.pythonhosted.org/packages/74/93/7baea19427dcfbe1e5a372d81473250b379f04b1bd3c4c5ff825e2327202/pyyaml-6.0.3-cp312-cp312-win32.whl", hash = "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", size = 137658, upload-time = "2025-09-25T21:32:20.209Z" }, 207 | { url = "https://files.pythonhosted.org/packages/86/bf/899e81e4cce32febab4fb42bb97dcdf66bc135272882d1987881a4b519e9/pyyaml-6.0.3-cp312-cp312-win_amd64.whl", hash = "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", size = 154003, upload-time = "2025-09-25T21:32:21.167Z" }, 208 | { url = "https://files.pythonhosted.org/packages/1a/08/67bd04656199bbb51dbed1439b7f27601dfb576fb864099c7ef0c3e55531/pyyaml-6.0.3-cp312-cp312-win_arm64.whl", hash = "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", size = 140344, upload-time = "2025-09-25T21:32:22.617Z" }, 209 | { url = "https://files.pythonhosted.org/packages/d1/11/0fd08f8192109f7169db964b5707a2f1e8b745d4e239b784a5a1dd80d1db/pyyaml-6.0.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", size = 181669, upload-time = "2025-09-25T21:32:23.673Z" }, 210 | { url = "https://files.pythonhosted.org/packages/b1/16/95309993f1d3748cd644e02e38b75d50cbc0d9561d21f390a76242ce073f/pyyaml-6.0.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", size = 173252, upload-time = "2025-09-25T21:32:25.149Z" }, 211 | { url = "https://files.pythonhosted.org/packages/50/31/b20f376d3f810b9b2371e72ef5adb33879b25edb7a6d072cb7ca0c486398/pyyaml-6.0.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", size = 767081, upload-time = "2025-09-25T21:32:26.575Z" }, 212 | { url = "https://files.pythonhosted.org/packages/49/1e/a55ca81e949270d5d4432fbbd19dfea5321eda7c41a849d443dc92fd1ff7/pyyaml-6.0.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", size = 841159, upload-time = "2025-09-25T21:32:27.727Z" }, 213 | { url = "https://files.pythonhosted.org/packages/74/27/e5b8f34d02d9995b80abcef563ea1f8b56d20134d8f4e5e81733b1feceb2/pyyaml-6.0.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", size = 801626, upload-time = "2025-09-25T21:32:28.878Z" }, 214 | { url = "https://files.pythonhosted.org/packages/f9/11/ba845c23988798f40e52ba45f34849aa8a1f2d4af4b798588010792ebad6/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", size = 753613, upload-time = "2025-09-25T21:32:30.178Z" }, 215 | { url = "https://files.pythonhosted.org/packages/3d/e0/7966e1a7bfc0a45bf0a7fb6b98ea03fc9b8d84fa7f2229e9659680b69ee3/pyyaml-6.0.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", size = 794115, upload-time = "2025-09-25T21:32:31.353Z" }, 216 | { url = "https://files.pythonhosted.org/packages/de/94/980b50a6531b3019e45ddeada0626d45fa85cbe22300844a7983285bed3b/pyyaml-6.0.3-cp313-cp313-win32.whl", hash = "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", size = 137427, upload-time = "2025-09-25T21:32:32.58Z" }, 217 | { url = "https://files.pythonhosted.org/packages/97/c9/39d5b874e8b28845e4ec2202b5da735d0199dbe5b8fb85f91398814a9a46/pyyaml-6.0.3-cp313-cp313-win_amd64.whl", hash = "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", size = 154090, upload-time = "2025-09-25T21:32:33.659Z" }, 218 | { url = "https://files.pythonhosted.org/packages/73/e8/2bdf3ca2090f68bb3d75b44da7bbc71843b19c9f2b9cb9b0f4ab7a5a4329/pyyaml-6.0.3-cp313-cp313-win_arm64.whl", hash = "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", size = 140246, upload-time = "2025-09-25T21:32:34.663Z" }, 219 | { url = "https://files.pythonhosted.org/packages/9d/8c/f4bd7f6465179953d3ac9bc44ac1a8a3e6122cf8ada906b4f96c60172d43/pyyaml-6.0.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", size = 181814, upload-time = "2025-09-25T21:32:35.712Z" }, 220 | { url = "https://files.pythonhosted.org/packages/bd/9c/4d95bb87eb2063d20db7b60faa3840c1b18025517ae857371c4dd55a6b3a/pyyaml-6.0.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", size = 173809, upload-time = "2025-09-25T21:32:36.789Z" }, 221 | { url = "https://files.pythonhosted.org/packages/92/b5/47e807c2623074914e29dabd16cbbdd4bf5e9b2db9f8090fa64411fc5382/pyyaml-6.0.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", size = 766454, upload-time = "2025-09-25T21:32:37.966Z" }, 222 | { url = "https://files.pythonhosted.org/packages/02/9e/e5e9b168be58564121efb3de6859c452fccde0ab093d8438905899a3a483/pyyaml-6.0.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", size = 836355, upload-time = "2025-09-25T21:32:39.178Z" }, 223 | { url = "https://files.pythonhosted.org/packages/88/f9/16491d7ed2a919954993e48aa941b200f38040928474c9e85ea9e64222c3/pyyaml-6.0.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", size = 794175, upload-time = "2025-09-25T21:32:40.865Z" }, 224 | { url = "https://files.pythonhosted.org/packages/dd/3f/5989debef34dc6397317802b527dbbafb2b4760878a53d4166579111411e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", size = 755228, upload-time = "2025-09-25T21:32:42.084Z" }, 225 | { url = "https://files.pythonhosted.org/packages/d7/ce/af88a49043cd2e265be63d083fc75b27b6ed062f5f9fd6cdc223ad62f03e/pyyaml-6.0.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", size = 789194, upload-time = "2025-09-25T21:32:43.362Z" }, 226 | { url = "https://files.pythonhosted.org/packages/23/20/bb6982b26a40bb43951265ba29d4c246ef0ff59c9fdcdf0ed04e0687de4d/pyyaml-6.0.3-cp314-cp314-win_amd64.whl", hash = "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", size = 156429, upload-time = "2025-09-25T21:32:57.844Z" }, 227 | { url = "https://files.pythonhosted.org/packages/f4/f4/a4541072bb9422c8a883ab55255f918fa378ecf083f5b85e87fc2b4eda1b/pyyaml-6.0.3-cp314-cp314-win_arm64.whl", hash = "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", size = 143912, upload-time = "2025-09-25T21:32:59.247Z" }, 228 | { url = "https://files.pythonhosted.org/packages/7c/f9/07dd09ae774e4616edf6cda684ee78f97777bdd15847253637a6f052a62f/pyyaml-6.0.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", size = 189108, upload-time = "2025-09-25T21:32:44.377Z" }, 229 | { url = "https://files.pythonhosted.org/packages/4e/78/8d08c9fb7ce09ad8c38ad533c1191cf27f7ae1effe5bb9400a46d9437fcf/pyyaml-6.0.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", size = 183641, upload-time = "2025-09-25T21:32:45.407Z" }, 230 | { url = "https://files.pythonhosted.org/packages/7b/5b/3babb19104a46945cf816d047db2788bcaf8c94527a805610b0289a01c6b/pyyaml-6.0.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", size = 831901, upload-time = "2025-09-25T21:32:48.83Z" }, 231 | { url = "https://files.pythonhosted.org/packages/8b/cc/dff0684d8dc44da4d22a13f35f073d558c268780ce3c6ba1b87055bb0b87/pyyaml-6.0.3-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", size = 861132, upload-time = "2025-09-25T21:32:50.149Z" }, 232 | { url = "https://files.pythonhosted.org/packages/b1/5e/f77dc6b9036943e285ba76b49e118d9ea929885becb0a29ba8a7c75e29fe/pyyaml-6.0.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", size = 839261, upload-time = "2025-09-25T21:32:51.808Z" }, 233 | { url = "https://files.pythonhosted.org/packages/ce/88/a9db1376aa2a228197c58b37302f284b5617f56a5d959fd1763fb1675ce6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", size = 805272, upload-time = "2025-09-25T21:32:52.941Z" }, 234 | { url = "https://files.pythonhosted.org/packages/da/92/1446574745d74df0c92e6aa4a7b0b3130706a4142b2d1a5869f2eaa423c6/pyyaml-6.0.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", size = 829923, upload-time = "2025-09-25T21:32:54.537Z" }, 235 | { url = "https://files.pythonhosted.org/packages/f0/7a/1c7270340330e575b92f397352af856a8c06f230aa3e76f86b39d01b416a/pyyaml-6.0.3-cp314-cp314t-win_amd64.whl", hash = "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", size = 174062, upload-time = "2025-09-25T21:32:55.767Z" }, 236 | { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, 237 | ] 238 | 239 | [[package]] 240 | name = "run-google-java-format" 241 | version = "0.1.0" 242 | source = { virtual = "." } 243 | 244 | [package.dev-dependencies] 245 | dev = [ 246 | { name = "pymarkdownlnt" }, 247 | { name = "ty" }, 248 | ] 249 | 250 | [package.metadata] 251 | 252 | [package.metadata.requires-dev] 253 | dev = [ 254 | { name = "pymarkdownlnt", specifier = ">=0.9.33" }, 255 | { name = "ty", specifier = ">=0.0.1a31" }, 256 | ] 257 | 258 | [[package]] 259 | name = "tomli" 260 | version = "2.3.0" 261 | source = { registry = "https://pypi.org/simple" } 262 | sdist = { url = "https://files.pythonhosted.org/packages/52/ed/3f73f72945444548f33eba9a87fc7a6e969915e7b1acc8260b30e1f76a2f/tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549", size = 17392, upload-time = "2025-10-08T22:01:47.119Z" } 263 | wheels = [ 264 | { url = "https://files.pythonhosted.org/packages/b3/2e/299f62b401438d5fe1624119c723f5d877acc86a4c2492da405626665f12/tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45", size = 153236, upload-time = "2025-10-08T22:01:00.137Z" }, 265 | { url = "https://files.pythonhosted.org/packages/86/7f/d8fffe6a7aefdb61bced88fcb5e280cfd71e08939da5894161bd71bea022/tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba", size = 148084, upload-time = "2025-10-08T22:01:01.63Z" }, 266 | { url = "https://files.pythonhosted.org/packages/47/5c/24935fb6a2ee63e86d80e4d3b58b222dafaf438c416752c8b58537c8b89a/tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf", size = 234832, upload-time = "2025-10-08T22:01:02.543Z" }, 267 | { url = "https://files.pythonhosted.org/packages/89/da/75dfd804fc11e6612846758a23f13271b76d577e299592b4371a4ca4cd09/tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441", size = 242052, upload-time = "2025-10-08T22:01:03.836Z" }, 268 | { url = "https://files.pythonhosted.org/packages/70/8c/f48ac899f7b3ca7eb13af73bacbc93aec37f9c954df3c08ad96991c8c373/tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845", size = 239555, upload-time = "2025-10-08T22:01:04.834Z" }, 269 | { url = "https://files.pythonhosted.org/packages/ba/28/72f8afd73f1d0e7829bfc093f4cb98ce0a40ffc0cc997009ee1ed94ba705/tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c", size = 245128, upload-time = "2025-10-08T22:01:05.84Z" }, 270 | { url = "https://files.pythonhosted.org/packages/b6/eb/a7679c8ac85208706d27436e8d421dfa39d4c914dcf5fa8083a9305f58d9/tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456", size = 96445, upload-time = "2025-10-08T22:01:06.896Z" }, 271 | { url = "https://files.pythonhosted.org/packages/0a/fe/3d3420c4cb1ad9cb462fb52967080575f15898da97e21cb6f1361d505383/tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be", size = 107165, upload-time = "2025-10-08T22:01:08.107Z" }, 272 | { url = "https://files.pythonhosted.org/packages/ff/b7/40f36368fcabc518bb11c8f06379a0fd631985046c038aca08c6d6a43c6e/tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac", size = 154891, upload-time = "2025-10-08T22:01:09.082Z" }, 273 | { url = "https://files.pythonhosted.org/packages/f9/3f/d9dd692199e3b3aab2e4e4dd948abd0f790d9ded8cd10cbaae276a898434/tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22", size = 148796, upload-time = "2025-10-08T22:01:10.266Z" }, 274 | { url = "https://files.pythonhosted.org/packages/60/83/59bff4996c2cf9f9387a0f5a3394629c7efa5ef16142076a23a90f1955fa/tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f", size = 242121, upload-time = "2025-10-08T22:01:11.332Z" }, 275 | { url = "https://files.pythonhosted.org/packages/45/e5/7c5119ff39de8693d6baab6c0b6dcb556d192c165596e9fc231ea1052041/tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52", size = 250070, upload-time = "2025-10-08T22:01:12.498Z" }, 276 | { url = "https://files.pythonhosted.org/packages/45/12/ad5126d3a278f27e6701abde51d342aa78d06e27ce2bb596a01f7709a5a2/tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8", size = 245859, upload-time = "2025-10-08T22:01:13.551Z" }, 277 | { url = "https://files.pythonhosted.org/packages/fb/a1/4d6865da6a71c603cfe6ad0e6556c73c76548557a8d658f9e3b142df245f/tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6", size = 250296, upload-time = "2025-10-08T22:01:14.614Z" }, 278 | { url = "https://files.pythonhosted.org/packages/a0/b7/a7a7042715d55c9ba6e8b196d65d2cb662578b4d8cd17d882d45322b0d78/tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876", size = 97124, upload-time = "2025-10-08T22:01:15.629Z" }, 279 | { url = "https://files.pythonhosted.org/packages/06/1e/f22f100db15a68b520664eb3328fb0ae4e90530887928558112c8d1f4515/tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878", size = 107698, upload-time = "2025-10-08T22:01:16.51Z" }, 280 | { url = "https://files.pythonhosted.org/packages/89/48/06ee6eabe4fdd9ecd48bf488f4ac783844fd777f547b8d1b61c11939974e/tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b", size = 154819, upload-time = "2025-10-08T22:01:17.964Z" }, 281 | { url = "https://files.pythonhosted.org/packages/f1/01/88793757d54d8937015c75dcdfb673c65471945f6be98e6a0410fba167ed/tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae", size = 148766, upload-time = "2025-10-08T22:01:18.959Z" }, 282 | { url = "https://files.pythonhosted.org/packages/42/17/5e2c956f0144b812e7e107f94f1cc54af734eb17b5191c0bbfb72de5e93e/tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b", size = 240771, upload-time = "2025-10-08T22:01:20.106Z" }, 283 | { url = "https://files.pythonhosted.org/packages/d5/f4/0fbd014909748706c01d16824eadb0307115f9562a15cbb012cd9b3512c5/tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf", size = 248586, upload-time = "2025-10-08T22:01:21.164Z" }, 284 | { url = "https://files.pythonhosted.org/packages/30/77/fed85e114bde5e81ecf9bc5da0cc69f2914b38f4708c80ae67d0c10180c5/tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f", size = 244792, upload-time = "2025-10-08T22:01:22.417Z" }, 285 | { url = "https://files.pythonhosted.org/packages/55/92/afed3d497f7c186dc71e6ee6d4fcb0acfa5f7d0a1a2878f8beae379ae0cc/tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05", size = 248909, upload-time = "2025-10-08T22:01:23.859Z" }, 286 | { url = "https://files.pythonhosted.org/packages/f8/84/ef50c51b5a9472e7265ce1ffc7f24cd4023d289e109f669bdb1553f6a7c2/tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606", size = 96946, upload-time = "2025-10-08T22:01:24.893Z" }, 287 | { url = "https://files.pythonhosted.org/packages/b2/b7/718cd1da0884f281f95ccfa3a6cc572d30053cba64603f79d431d3c9b61b/tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999", size = 107705, upload-time = "2025-10-08T22:01:26.153Z" }, 288 | { url = "https://files.pythonhosted.org/packages/19/94/aeafa14a52e16163008060506fcb6aa1949d13548d13752171a755c65611/tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e", size = 154244, upload-time = "2025-10-08T22:01:27.06Z" }, 289 | { url = "https://files.pythonhosted.org/packages/db/e4/1e58409aa78eefa47ccd19779fc6f36787edbe7d4cd330eeeedb33a4515b/tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3", size = 148637, upload-time = "2025-10-08T22:01:28.059Z" }, 290 | { url = "https://files.pythonhosted.org/packages/26/b6/d1eccb62f665e44359226811064596dd6a366ea1f985839c566cd61525ae/tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc", size = 241925, upload-time = "2025-10-08T22:01:29.066Z" }, 291 | { url = "https://files.pythonhosted.org/packages/70/91/7cdab9a03e6d3d2bb11beae108da5bdc1c34bdeb06e21163482544ddcc90/tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0", size = 249045, upload-time = "2025-10-08T22:01:31.98Z" }, 292 | { url = "https://files.pythonhosted.org/packages/15/1b/8c26874ed1f6e4f1fcfeb868db8a794cbe9f227299402db58cfcc858766c/tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879", size = 245835, upload-time = "2025-10-08T22:01:32.989Z" }, 293 | { url = "https://files.pythonhosted.org/packages/fd/42/8e3c6a9a4b1a1360c1a2a39f0b972cef2cc9ebd56025168c4137192a9321/tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005", size = 253109, upload-time = "2025-10-08T22:01:34.052Z" }, 294 | { url = "https://files.pythonhosted.org/packages/22/0c/b4da635000a71b5f80130937eeac12e686eefb376b8dee113b4a582bba42/tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463", size = 97930, upload-time = "2025-10-08T22:01:35.082Z" }, 295 | { url = "https://files.pythonhosted.org/packages/b9/74/cb1abc870a418ae99cd5c9547d6bce30701a954e0e721821df483ef7223c/tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8", size = 107964, upload-time = "2025-10-08T22:01:36.057Z" }, 296 | { url = "https://files.pythonhosted.org/packages/54/78/5c46fff6432a712af9f792944f4fcd7067d8823157949f4e40c56b8b3c83/tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77", size = 163065, upload-time = "2025-10-08T22:01:37.27Z" }, 297 | { url = "https://files.pythonhosted.org/packages/39/67/f85d9bd23182f45eca8939cd2bc7050e1f90c41f4a2ecbbd5963a1d1c486/tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf", size = 159088, upload-time = "2025-10-08T22:01:38.235Z" }, 298 | { url = "https://files.pythonhosted.org/packages/26/5a/4b546a0405b9cc0659b399f12b6adb750757baf04250b148d3c5059fc4eb/tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530", size = 268193, upload-time = "2025-10-08T22:01:39.712Z" }, 299 | { url = "https://files.pythonhosted.org/packages/42/4f/2c12a72ae22cf7b59a7fe75b3465b7aba40ea9145d026ba41cb382075b0e/tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b", size = 275488, upload-time = "2025-10-08T22:01:40.773Z" }, 300 | { url = "https://files.pythonhosted.org/packages/92/04/a038d65dbe160c3aa5a624e93ad98111090f6804027d474ba9c37c8ae186/tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67", size = 272669, upload-time = "2025-10-08T22:01:41.824Z" }, 301 | { url = "https://files.pythonhosted.org/packages/be/2f/8b7c60a9d1612a7cbc39ffcca4f21a73bf368a80fc25bccf8253e2563267/tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f", size = 279709, upload-time = "2025-10-08T22:01:43.177Z" }, 302 | { url = "https://files.pythonhosted.org/packages/7e/46/cc36c679f09f27ded940281c38607716c86cf8ba4a518d524e349c8b4874/tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0", size = 107563, upload-time = "2025-10-08T22:01:44.233Z" }, 303 | { url = "https://files.pythonhosted.org/packages/84/ff/426ca8683cf7b753614480484f6437f568fd2fda2edbdf57a2d3d8b27a0b/tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba", size = 119756, upload-time = "2025-10-08T22:01:45.234Z" }, 304 | { url = "https://files.pythonhosted.org/packages/77/b8/0135fadc89e73be292b473cb820b4f5a08197779206b33191e801feeae40/tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b", size = 14408, upload-time = "2025-10-08T22:01:46.04Z" }, 305 | ] 306 | 307 | [[package]] 308 | name = "toolz" 309 | version = "1.1.0" 310 | source = { registry = "https://pypi.org/simple" } 311 | sdist = { url = "https://files.pythonhosted.org/packages/11/d6/114b492226588d6ff54579d95847662fc69196bdeec318eb45393b24c192/toolz-1.1.0.tar.gz", hash = "sha256:27a5c770d068c110d9ed9323f24f1543e83b2f300a687b7891c1a6d56b697b5b", size = 52613, upload-time = "2025-10-17T04:03:21.661Z" } 312 | wheels = [ 313 | { url = "https://files.pythonhosted.org/packages/fb/12/5911ae3eeec47800503a238d971e51722ccea5feb8569b735184d5fcdbc0/toolz-1.1.0-py3-none-any.whl", hash = "sha256:15ccc861ac51c53696de0a5d6d4607f99c210739caf987b5d2054f3efed429d8", size = 58093, upload-time = "2025-10-17T04:03:20.435Z" }, 314 | ] 315 | 316 | [[package]] 317 | name = "ty" 318 | version = "0.0.1a31" 319 | source = { registry = "https://pypi.org/simple" } 320 | sdist = { url = "https://files.pythonhosted.org/packages/30/78/daa1e70377b8127e06db63063b7dd9694cb2bb611b4e3c2182b9ec5a02a1/ty-0.0.1a31.tar.gz", hash = "sha256:b878b04af63b1e716436897838ca6a107a672539155b6fc2051268cd85da9cd6", size = 4656004, upload-time = "2025-12-04T09:01:47.147Z" } 321 | wheels = [ 322 | { url = "https://files.pythonhosted.org/packages/08/4c/1e91d6b22dee1435db1cdf55e54ec601497dba650684517b1cd5b4345e80/ty-0.0.1a31-py3-none-linux_armv6l.whl", hash = "sha256:662b9a3a3497da12416789e21fda9eb4e1ac66c5233867d89953916099ee44f5", size = 9620261, upload-time = "2025-12-04T09:01:35.001Z" }, 323 | { url = "https://files.pythonhosted.org/packages/94/8f/eb6ac56cc03a00d3258c3362c4fb5a58152d03e9fa207db0465e2dc717e2/ty-0.0.1a31-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:da05f73df587ff1362d487681370db47541123c005a0d1a60a5a048039e309cc", size = 9411370, upload-time = "2025-12-04T09:01:23.903Z" }, 324 | { url = "https://files.pythonhosted.org/packages/d6/72/2cdbef5bd7ee7a58e71e67e845ae3f99dca695d0bca7561a3294fb8d723e/ty-0.0.1a31-py3-none-macosx_11_0_arm64.whl", hash = "sha256:74032bf207ce1eddc042f26aa9b6e0713373cf2c502174a53a41f9c469f02adb", size = 8925400, upload-time = "2025-12-04T09:01:59.074Z" }, 325 | { url = "https://files.pythonhosted.org/packages/f4/4d/a10c3f2e8969e9e1efe3179d2c961236413c9765c9f95e84e8f515fb9b02/ty-0.0.1a31-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cd383fd54872df15816a7853a8c824400c85f850916bad2052564bad8462f4f2", size = 9201615, upload-time = "2025-12-04T09:01:21.085Z" }, 326 | { url = "https://files.pythonhosted.org/packages/47/e5/bd26f0fc432459718b72a0bb41bd222fd1fad81c1d5f645a7eba94e14be6/ty-0.0.1a31-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c6defaf175bce7c91cea9a168a1c30bb523269ed174941cd31f8edc2d77f8ec7", size = 9401110, upload-time = "2025-12-04T09:01:32.241Z" }, 327 | { url = "https://files.pythonhosted.org/packages/ca/63/cbb3419f74ce38c0a2affbc269d4d27ec032cfbc3b011a8db5815c89f540/ty-0.0.1a31-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2d41f7e68f05517177ef82d89bfe0bf8e787a6b72ad396c1e44a16ef353b95e2", size = 9779837, upload-time = "2025-12-04T09:01:37.55Z" }, 328 | { url = "https://files.pythonhosted.org/packages/69/fb/1d99243a0e005fe8d53671d4a25d5ddcf345a12fb3c683726bd597e42f23/ty-0.0.1a31-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:22f2298a0de1a8af24f50e498023770b05ea4fc0ccebb2c53deb40ff73dc76fc", size = 10444412, upload-time = "2025-12-04T09:01:56.888Z" }, 329 | { url = "https://files.pythonhosted.org/packages/65/7f/95242feb774356b7a93beb5278cd8c8bbb6a8b12d94977ff954929ed257e/ty-0.0.1a31-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:38669b9aa53bd87160a2ee8447a3bf8d91dd14b7462f8aa98f1d2740b609589a", size = 10171070, upload-time = "2025-12-04T09:01:44.917Z" }, 330 | { url = "https://files.pythonhosted.org/packages/78/fa/4d8adeb9ff7fd32efcb9ebb05d5f61cd9ad4b4030390c76cd771fb38ac33/ty-0.0.1a31-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5fbc75e8e848929155b7ba0e9a222b2561222a1135bb492a9c5b9ad945c80b18", size = 10188190, upload-time = "2025-12-04T09:01:42.577Z" }, 331 | { url = "https://files.pythonhosted.org/packages/f6/40/295903716cc2e4fdb88d8cf8b974f0936e6c021f35d5a7f78b769c746bcc/ty-0.0.1a31-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915c0639dfb73f5f19cd69bbe89036ef18b8066ba88ce38d3e3cc0f39b32f99a", size = 9713419, upload-time = "2025-12-04T09:01:26.633Z" }, 332 | { url = "https://files.pythonhosted.org/packages/f0/93/b622782ce78f0cbacf167c617b41f45e76de02e3d5d5898fc78ad7a47de7/ty-0.0.1a31-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:28d23f4e58e9b08fc8966ad8dac754b4cd5ccafed711e2a32a62f3d2cb6f44cb", size = 9170660, upload-time = "2025-12-04T09:02:01.556Z" }, 333 | { url = "https://files.pythonhosted.org/packages/d9/5d/2a04dfd412c87d1da220260a5cf8444d36fa356d1f993ee1db5ad820df93/ty-0.0.1a31-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:cb2ebbc8065f4dd09e4b82f492becc55cad39068e842f82bfa1c9f7b9864b034", size = 9443773, upload-time = "2025-12-04T09:01:39.958Z" }, 334 | { url = "https://files.pythonhosted.org/packages/1f/5e/18c0123b8dcd6a7e7f4a35d3eed127c6c0140377f5986df6bd01c9df5eb1/ty-0.0.1a31-py3-none-musllinux_1_2_i686.whl", hash = "sha256:966984a8a0e4f99d133e9b73bc778d4861b58467bdb85950805d67ff90e73e3e", size = 9532255, upload-time = "2025-12-04T09:01:29.243Z" }, 335 | { url = "https://files.pythonhosted.org/packages/8a/c0/2570e4f891f33c3f9160f052d3759e9c7a3dee29bac5b93ad1f29ed42526/ty-0.0.1a31-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bc4fe23fddaa78c0b11637a1eff152b95988960e5d240d282b41f827d13b28f0", size = 9837753, upload-time = "2025-12-04T09:02:04.361Z" }, 336 | { url = "https://files.pythonhosted.org/packages/58/ad/6a231c11b95d3aa3f54824edfb7ab13ae13eea405bbcc6c80090551bd1b2/ty-0.0.1a31-py3-none-win32.whl", hash = "sha256:f82f4e051c40033ca9f10cffafc346fd86ea6541e786c2b1fcffa08c661efbaa", size = 9011568, upload-time = "2025-12-04T09:01:54.033Z" }, 337 | { url = "https://files.pythonhosted.org/packages/f7/8b/c07438de84e3e9cbecedd2e8895dc25ca1b110847dd95b5e9f50124eb8d5/ty-0.0.1a31-py3-none-win_amd64.whl", hash = "sha256:12fae6138c4cbd143fe4b5c616056535353a2d0821062d8750132d3ea022fa8f", size = 9880831, upload-time = "2025-12-04T09:01:18.284Z" }, 338 | { url = "https://files.pythonhosted.org/packages/a3/9c/ad589282e76e185eb54c3ce212182f7a28547ed20a5a08b51f9684dc2849/ty-0.0.1a31-py3-none-win_arm64.whl", hash = "sha256:4cc339de4dd4b8dd7167cfd1f826a25e303b3dec27da74596a0ce3ed83bcd293", size = 9380327, upload-time = "2025-12-04T09:01:49.651Z" }, 339 | ] 340 | 341 | [[package]] 342 | name = "typing-extensions" 343 | version = "4.15.0" 344 | source = { registry = "https://pypi.org/simple" } 345 | 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" } 346 | wheels = [ 347 | { 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" }, 348 | ] 349 | 350 | [[package]] 351 | name = "wcwidth" 352 | version = "0.2.14" 353 | source = { registry = "https://pypi.org/simple" } 354 | sdist = { url = "https://files.pythonhosted.org/packages/24/30/6b0809f4510673dc723187aeaf24c7f5459922d01e2f794277a3dfb90345/wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605", size = 102293, upload-time = "2025-09-22T16:29:53.023Z" } 355 | wheels = [ 356 | { url = "https://files.pythonhosted.org/packages/af/b5/123f13c975e9f27ab9c0770f514345bd406d0e8d3b7a0723af9d43f710af/wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1", size = 37286, upload-time = "2025-09-22T16:29:51.641Z" }, 357 | ] 358 | --------------------------------------------------------------------------------