fix: 🐛Cleaned up python files and moved site bounding boxes to config

This commit is contained in:
2025-11-01 10:20:07 +00:00
parent f3d61b9370
commit 92ede3712e
5 changed files with 244 additions and 67 deletions
+85 -30
View File
@@ -2,29 +2,33 @@ from nimrod_3 import Nimrod
import os
from pathlib import Path
import re
import logging # TODO: Add logging
import logging
import yaml
"""
import nimrod
a = nimrod.Nimrod(open(
'200802252000_nimrod_ng_radar_rainrate_composite_1km_merged_UK_zip'))
a.query()
a.extract_asc(open('full_raster.asc', 'w'))
a.apply_bbox(279906, 285444, 283130, 290440)
a.query()
a.extract_asc(open('clipped_raster.asc', 'w'))
"""
logging.basicConfig(
level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s"
)
BOUNDING_BOX_INFO = {
"BRISCS": (607000, 608000, 217000, 218000),
"WINTSC": (499000, 500000, 416000, 417000),
}
in_top_folder = "./dat_files"
out_top_folder = "./asc_files"
IN_TOP_FOLDER = "./dat_files"
OUT_TOP_FOLDER = "./asc_files"
CONFIG_FILE = "config.yaml"
def get_datetime(file_name: str) -> str:
# Pattern to match YYYYMMDDHHMM format
"""
Extract datetime from a filename using regex pattern matching.
Args:
file_name (str): The name of the file to extract datetime from.
Returns:
str: The extracted datetime in YYYYMMDDHHMM format, or 'date_not_found' if no match.
"""
pattern = r"(\d{8})(\d{4})"
match = re.search(pattern, file_name)
if match:
@@ -35,37 +39,88 @@ def get_datetime(file_name: str) -> str:
return "date_not_found"
def load_config() -> dict:
"""
Load configuration from YAML file.
Returns:
dict: Configuration dictionary containing bounding box information.
Raises:
FileNotFoundError: If the config.yaml file is not found.
yaml.YAMLError: If there's an error parsing the YAML file.
"""
try:
with open(CONFIG_FILE, "r") as file:
config = yaml.safe_load(file)
return config.get("bounding_box_info", {})
except FileNotFoundError:
logging.error(
f"Config file {CONFIG_FILE} not found. Using default configuration."
)
return {}
except yaml.YAMLError as e:
logging.error(f"Error parsing YAML file: {e}")
return {}
def process_nimrod_files() -> None:
"""
Process all Nimrod files in the input directory, applying bounding box clipping
and exporting to ASC format.
This function reads all files from IN_TOP_FOLDER, applies the appropriate bounding
box for each area, and exports clipped raster data to OUT_TOP_FOLDER.
"""
# Load configuration
bounding_box_info = load_config()
# Use default if config is empty
if not bounding_box_info:
bounding_box_info = {
"BRISCS": (607000, 608000, 217000, 218000),
"WINTSC": (499000, 500000, 416000, 417000),
}
# read all file names in the folder
area_folders = os.listdir(in_top_folder)
area_folders = os.listdir(IN_TOP_FOLDER)
for area in area_folders:
bounding_box = BOUNDING_BOX_INFO.get(area, (0, 0, 0, 0))
print(area, bounding_box)
bounding_box = bounding_box_info.get(area, (0, 0, 0, 0))
logging.info(f"Processing area: {area}, bounding box: {bounding_box}")
xmin, xmax, ymin, ymax = bounding_box
os.makedirs(Path(out_top_folder, area), exist_ok=True)
for in_file in os.listdir(Path(in_top_folder, area)):
os.makedirs(Path(OUT_TOP_FOLDER, area), exist_ok=True)
for in_file in os.listdir(Path(IN_TOP_FOLDER, area)):
timestamp = get_datetime(in_file)
out_file_name = f"{timestamp}_{area}.asc"
out_file_path = Path(out_top_folder, area, out_file_name)
in_file_full = Path(in_top_folder, area, in_file)
#print(in_file_full)
out_file_path = Path(OUT_TOP_FOLDER, area, out_file_name)
in_file_full = Path(IN_TOP_FOLDER, area, in_file)
try:
image = Nimrod(open(in_file_full, 'rb'))
image = Nimrod(open(in_file_full, "rb"))
image.apply_bbox(xmin, xmax, ymin, ymax)
# image.query() # prints out file_details
with open(out_file_path, 'w') as outfile:
with open(out_file_path, "w") as outfile:
image.extract_asc(outfile)
logging.info(f"Successfully processed: {in_file_full}")
except Nimrod.HeaderReadError as e:
print(f'Failed to read file {in_file_full}, is it corrupt?')
print(e)
logging.error(f"Failed to read file {in_file_full}, is it corrupt?")
logging.error(e)
continue
except Nimrod.PayloadReadError as e:
print(f'Failed to load the raster data in {in_file_full}')
print(e)
logging.error(f"Failed to load the raster data in {in_file_full}")
logging.error(e)
continue
except Nimrod.BboxRangeError as e:
print(f'Bounding Box out of range. Given bounding box: {bounding_box}')
print(e)
logging.error(
f"Bounding Box out of range. Given bounding box: {bounding_box}"
)
logging.error(e)
# Skips the whole area as bounding box will be out of bounds for all files
break
if __name__ == "__main__":
process_nimrod_files()
+16
View File
@@ -0,0 +1,16 @@
bounding_box_info:
# SITE_NAME:
# - XMIN
# - XMAX
# - YMIN
# - YMAX
BRISCS:
- 607000
- 608000
- 217000
- 218000
WINTSC:
- 499000
- 500000
- 416000
- 417000
+75 -20
View File
@@ -67,17 +67,48 @@ import sys
import struct
import array
import argparse
from typing import IO
class Nimrod:
"""Reading, querying and processing of NIMROD format rainfall data files."""
"""
Reading, querying and processing of NIMROD format rainfall data files.
This class provides functionality to parse NIMROD format files, display
header information, and extract raster data to ESRI ASCII format files.
Attributes:
hdr_element (List): List of all header elements indexed by element number
nrows (int): Number of rows in the raster image
ncols (int): Number of columns in the raster image
n_data_specific_reals (int): Number of data-specific real header entries
n_data_specific_ints (int): Number of data-specific integer header entries
y_top (float): Top northing coordinate
y_pixel_size (float): Size of pixel in y-direction
x_left (float): Left easting coordinate
x_pixel_size (float): Size of pixel in x-direction
x_right (float): Right easting coordinate
y_bottom (float): Bottom northing coordinate
data (array.array): Raster data array
"""
class RecordLenError(Exception):
"""
Exception Type: NIMROD record length read from file not as expected.
Attributes:
message (str): Error message describing the problem
"""
def __init__(self, actual, expected, location):
def __init__(self, actual: int, expected: int, location: str) -> None:
"""
Initialize the RecordLenError with details about the error.
Args:
actual (int): Actual record length read from file
expected (int): Expected record length
location (str): Description of position in file where error occurred
"""
self.message = "Incorrect record length %d bytes (expected %d) at %s." % (
actual,
expected,
@@ -85,43 +116,57 @@ class Nimrod:
)
class HeaderReadError(Exception):
"""Exception Type: Read error whilst parsing NIMROD header elements."""
"""
Exception Type: Read error whilst parsing NIMROD header elements.
This exception is raised when there are issues reading the header data
from a NIMROD file.
"""
pass
class PayloadReadError(Exception):
"""Exception Type: Read error whilst parsing NIMROD raster data."""
"""
Exception Type: Read error whilst parsing NIMROD raster data.
This exception is raised when there are issues reading the raster data
payload from a NIMROD file.
"""
pass
class BboxRangeError(Exception):
"""
Exception Type: Bounding box specified out of range of raster image.
This exception is raised when a bounding box is specified that does not
intersect with the raster image data.
"""
pass
def __init__(self, infile):
def __init__(self, infile: IO[bytes]) -> None:
"""
Parse all header and data info from a NIMROD data file into this object.
(This method based on read_nimrod.py by Charles Kilburn Aug 2008)
Args:
infile: NIMROD file object opened for binary reading
infile (IO[bytes]): NIMROD file object opened for binary reading
Raises:
RecordLenError: NIMROD record length read from file not as expected
HeaderReadError: Read error whilst parsing NIMROD header elements
PayloadReadError: Read error whilst parsing NIMROD raster data
"""
def check_record_len(infile, expected, location):
def check_record_len(infile: IO[bytes], expected: int, location: str) -> None:
"""
Check record length in C struct is as expected.
Args:
infile: file to read from
expected: expected value of record length read
location: description of position in file (for reporting)
infile (IO[bytes]): file to read from
expected (int): expected value of record length read
location (str): description of position in file (for reporting)
Raises:
HeaderReadError: Read error whilst reading record length
RecordLenError: Unexpected NIMROD record length read from file
@@ -220,8 +265,14 @@ class Nimrod:
check_record_len(infile, array_size * 2, "data end")
infile.close()
def query(self):
"""Print complete NIMROD file header information."""
def query(self) -> None:
"""
Print complete NIMROD file header information.
This method displays all header information from the parsed NIMROD file
in a formatted manner including general headers, data-specific headers,
and character headers along with validity time and coordinate ranges.
"""
print("NIMROD file raw header fields listed by element number:")
print("General (Integer) header entries:")
@@ -273,7 +324,7 @@ class Nimrod:
)
print("Image size: %d rows x %d cols" % (self.nrows, self.ncols))
def apply_bbox(self, xmin, xmax, ymin, ymax):
def apply_bbox(self, xmin: float, xmax: float, ymin: float, ymax: float) -> None:
"""
Clip raster data to all pixels that intersect specified bounding box.
@@ -283,10 +334,11 @@ class Nimrod:
width of the raster edge will intersect with the pixel.
Args:
xmin: Most negative easting or longitude of bounding box
xmax: Most positive easting or longitude of bounding box
ymin: Most negative northing or latitude of bounding box
ymax: Most positive northing or latitude of bounding box
xmin (float): Most negative easting or longitude of bounding box
xmax (float): Most positive easting or longitude of bounding box
ymin (float): Most negative northing or latitude of bounding box
ymax (float): Most positive northing or latitude of bounding box
Raises:
BboxRangeError: Bounding box specified out of range of raster image
"""
@@ -337,12 +389,15 @@ class Nimrod:
self.hdr_element[34] = self.y_top
self.hdr_element[36] = self.x_left
def extract_asc(self, outfile):
def extract_asc(self, outfile: IO[str]) -> None:
"""
Write raster data to an ESRI ASCII (.asc) format file.
Args:
outfile: file object opened for writing text
outfile (IO[str]): file object opened for writing text
Raises:
ValueError: If x_pixel_size != y_pixel_size (non-square pixels)
"""
# As ESRI ASCII format only supports square pixels, warn if not so
+1
View File
@@ -5,5 +5,6 @@ description = "Add your description here"
readme = "README.md"
requires-python = ">=3.12"
dependencies = [
"pyyaml>=6.0.3",
"ruff>=0.14.3",
]
Generated
+51 -1
View File
@@ -7,11 +7,61 @@ name = "met-office"
version = "0.1.0"
source = { virtual = "." }
dependencies = [
{ name = "pyyaml" },
{ name = "ruff" },
]
[package.metadata]
requires-dist = [{ name = "ruff", specifier = ">=0.14.3" }]
requires-dist = [
{ name = "pyyaml", specifier = ">=6.0.3" },
{ name = "ruff", specifier = ">=0.14.3" },
]
[[package]]
name = "pyyaml"
version = "6.0.3"
source = { registry = "https://pypi.org/simple" }
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" }
wheels = [
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
{ 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" },
]
[[package]]
name = "ruff"