diff --git a/.gitignore b/.gitignore index ec31f9d..37e509b 100644 --- a/.gitignore +++ b/.gitignore @@ -21,6 +21,7 @@ notebooks/*.cataclysm # we don't want completions regardless of name datafiles/plunkylib/completions/** +datafiles/chatsnack/completions/** # not code generations (not yet anyway) datafiles/cataclysm/code*/** diff --git a/README.md b/README.md index 68e72e5..9ba908c 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ cataclysm init ``` ### Configure API keys -Our demise is powered by OpenAI GPT4, so you'll need an API key from them. +Our demise is powered by OpenAI through chatsnack, so you'll need an API key. Use `init` or copy `env.template.cataclysm` to `.env` in your working/app directory and add your API keys there: ``` @@ -81,13 +81,13 @@ If you fear a `cataclysm`, your impending doom can be generated and previewed vi ``` ### **Chosen Doom** (Frozen Mode) -If you've chosen your own `doom`, you can impending doom can be generated and previewed via `doom.impending`. +If you've chosen your own `doom`, cached doom can be executed via `doom.chosen` without generating fresh code. ```python >>> from cataclysm import doom ->>> dump_unexecuted_code_str = doom.impending.say_stuff("YOU ARE DOOMED") ->>> print(dump_unexecuted_code_str) -[... code dump ...] +>>> result = doom.chosen.say_stuff("YOU ARE DOOMED") +>>> print(result) +[... cached result ...] ``` ## Useful Resources and Examples @@ -120,11 +120,11 @@ If you've chosen your own `doom`, you can impending doom can be generated and p ### What forces are at work to bring about `cataclysm`? -> The devastation is powered by OpenAI's ChatGPT API for the `gpt-4` large language model (LLM). It also works with `gpt-3.5-turbo`, but GPT4+ is highly recommended. The API is called via `plunkylib` (a yaml-friendly layer not totally unlike `langchain`), so you need an OpenAI API key. Include your own API key in your `.env` file, using `.env.template` as a reference. +> The devastation is powered by OpenAI's API through `chatsnack`, so you need an OpenAI API key. Include your own API key in your `.env` file, using `.env.template` as a reference. -### Can I experiment with a weaker `cataclysm` using `gpt-3.5-turbo`? +### Can I experiment with a weaker `cataclysm` using a cheaper model? -> To do so, edit `datafiles/plunkylib/petitions/CataclysmQuery.yml` to reference `CataclysmLLMParams_3-5` instead of `CataclysmLLMParams`. Your doom will be less impressive, but faster and less expensive. +> To do so, edit `datafiles/chatsnack/CataclysmQuery.yml` and set the `params.model` value to a faster or less expensive model. Your doom will be less impressive, but faster and less expensive. ### What if I don't have an OpenAI account or API key? @@ -160,7 +160,7 @@ If you've chosen your own `doom`, you can impending doom can be generated and p ### What prompts are you using? Can I change the prompts used? -> The prompts are in `default_files/datafiles/plunkylib/prompts/`. These will be changing a lot in the early days of the `cataclysm`, but you are free to experiment on your own. All I ask is that you consider sharing your coolest findings back to the project. +> The prompt is in `datafiles/chatsnack/CataclysmQuery.yml` after `cataclysm init`, with the packaged default in `cataclysm/default_files/datafiles/chatsnack/`. These will be changing a lot in the early days of the `cataclysm`, but you are free to experiment on your own. All I ask is that you consider sharing your coolest findings back to the project. ### Can you help my company use generative AI for our software development? diff --git a/cataclysm/__init__.py b/cataclysm/__init__.py index 859ccbe..58f5385 100644 --- a/cataclysm/__init__.py +++ b/cataclysm/__init__.py @@ -1,7 +1,8 @@ from loguru import logger import logging import os -from plunkylib import PLUNKYLIB_BASE_DIR + +CHATSNACK_BASE_DIR = os.getenv("CHATSNACK_BASE_DIR", "./datafiles/chatsnack").rstrip("/\\") # if there's no "CATACLYSM_BASE_DIR" env variable, set it to './datafiles/cataclysm' # this is the default directory for all cataclysm datafiles @@ -24,8 +25,8 @@ # Add the file sink to Loguru's sinks logger.add(**file_sink) -# disable debug logging for the plunkylib module -logger.disable("plunkylib") +# disable debug logging for the chatsnack module +logger.disable("chatsnack") # disable warning logging for the datafiles module logger.disable("datafiles") @@ -33,6 +34,8 @@ def initialize_datafiles(base_dir = "."): + chatsnack_base_dir = os.getenv("CHATSNACK_BASE_DIR", "./datafiles/chatsnack").rstrip("/\\") + # Replace this with the name of your package def get_top_level_package_name(): return __name__.split('.')[0] @@ -41,19 +44,15 @@ def get_top_level_package_name(): print("package_name: " + package_name) minimum_file_suffixes = [ - f"datafiles/plunkylib/petition/CataclysmQuery.yml", - f"datafiles/plunkylib/prompts/CataclysmPrompt.yml", - f"datafiles/plunkylib/params/CataclysmLLMParams.yml", - f"datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml", - f".env.template.cataclysm" + f"datafiles/chatsnack/CataclysmQuery.yml", + f"env.template.cataclysm" ] from pkg_resources import resource_filename import shutil def copy_files_to_destination(package_name, file_suffixes, destination): for file_suffix in file_suffixes: - # replace 'datafiles/plunkylib' in the suffix with PLUNKYLIB_BASE_DIR - dest_file_suffix = file_suffix.replace("datafiles/plunkylib", PLUNKYLIB_BASE_DIR) + dest_file_suffix = file_suffix.replace("datafiles/chatsnack", chatsnack_base_dir) dest_filename = os.path.join(destination, dest_file_suffix) if not os.path.exists(dest_filename): print("Copying default datafiles to " + dest_filename) @@ -66,7 +65,9 @@ def copy_files_to_destination(package_name, file_suffixes, destination): print("destination_file: " + destination_file) # Create any necessary directories in the destination path - os.makedirs(os.path.dirname(destination_file), exist_ok=True) + destination_dir = os.path.dirname(destination_file) + if destination_dir: + os.makedirs(destination_dir, exist_ok=True) # Copy the file shutil.copy2(source_file, destination_file) diff --git a/cataclysm/__main__.py b/cataclysm/__main__.py index 84bf99a..0e74541 100644 --- a/cataclysm/__main__.py +++ b/cataclysm/__main__.py @@ -1,7 +1,8 @@ from loguru import logger import logging import os -from plunkylib import PLUNKYLIB_BASE_DIR + +CHATSNACK_BASE_DIR = os.getenv("CHATSNACK_BASE_DIR", "./datafiles/chatsnack").rstrip("/\\") # if there's no "CATACLYSM_BASE_DIR" env variable, set it to './datafiles/cataclysm' # this is the default directory for all cataclysm datafiles @@ -24,8 +25,8 @@ # Add the file sink to Loguru's sinks logger.add(**file_sink) -# disable debug logging for the plunkylib module -logger.disable("plunkylib") +# disable debug logging for the chatsnack module +logger.disable("chatsnack") # disable warning logging for the datafiles module logger.disable("datafiles") @@ -34,6 +35,8 @@ def initialize_datafiles(base_dir = "."): print("cataclysm - initializing datafiles in directory: " + base_dir) + chatsnack_base_dir = os.getenv("CHATSNACK_BASE_DIR", "./datafiles/chatsnack").rstrip("/\\") + # Replace this with the name of your package def get_top_level_package_name(): return __name__.split('.')[0] @@ -41,10 +44,7 @@ def get_top_level_package_name(): package_name = get_top_level_package_name() minimum_file_suffixes = [ - f"datafiles/plunkylib/petition/CataclysmQuery.yml", - f"datafiles/plunkylib/prompts/CataclysmPrompt.yml", - f"datafiles/plunkylib/params/CataclysmLLMParams.yml", - f"datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml", + f"datafiles/chatsnack/CataclysmQuery.yml", f"env.template.cataclysm" ] @@ -52,8 +52,7 @@ def get_top_level_package_name(): import shutil def copy_files_to_destination(package_name, file_suffixes, destination): for file_suffix in file_suffixes: - # replace 'datafiles/plunkylib' in the suffix with PLUNKYLIB_BASE_DIR - dest_file_suffix = file_suffix.replace("datafiles/plunkylib", PLUNKYLIB_BASE_DIR) + dest_file_suffix = file_suffix.replace("datafiles/chatsnack", chatsnack_base_dir) dest_filename = os.path.join(destination, dest_file_suffix) if not os.path.exists(dest_filename): print(" Copying default file to " + dest_filename) @@ -66,7 +65,9 @@ def copy_files_to_destination(package_name, file_suffixes, destination): print(" destination_file: " + destination_file) # Create any necessary directories in the destination path - os.makedirs(os.path.dirname(destination_file), exist_ok=True) + destination_dir = os.path.dirname(destination_file) + if destination_dir: + os.makedirs(destination_dir, exist_ok=True) # Copy the file shutil.copy2(source_file, destination_file) @@ -109,4 +110,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/cataclysm/chatsnack_adapter.py b/cataclysm/chatsnack_adapter.py new file mode 100644 index 0000000..e6927b3 --- /dev/null +++ b/cataclysm/chatsnack_adapter.py @@ -0,0 +1,328 @@ +import ast +import os +from dataclasses import dataclass +from pathlib import Path +from typing import Any, Optional, Sequence + +from ruamel.yaml import YAML + + +CHAT_NAME = "CataclysmQuery" +CODE_START = "#|~~\n" +CODE_END = "#~~|\n" +PLACEHOLDER_FRAGMENTS = ( + "...", + "code here", + "exec block here", + "todo", +) + +Chat = None +ChatParams = None + + +@dataclass +class SubmittedCodeCapture: + code: Optional[str] = None + + +def _yaml_load(path: Path) -> dict: + yaml = YAML() + with path.open("r", encoding="utf-8") as file_obj: + loaded = yaml.load(file_obj) + return loaded or {} + + +def _base_dir(env_name: str, default: str) -> Path: + configured = os.getenv(env_name, default).rstrip("/\\") + return Path(configured) + + +def _chatsnack_base_dir() -> Path: + return _base_dir("CHATSNACK_BASE_DIR", "./datafiles/chatsnack") + + +def _legacy_plunkylib_base_dir() -> Path: + return _base_dir("PLUNKYLIB_BASE_DIR", "./datafiles/plunkylib") + + +def _scalar(value: Any) -> str: + if value is None: + return "" + return str(value).strip() + + +def _get_chat_classes(chat_cls=None, params_cls=None): + global Chat, ChatParams + if chat_cls is None: + if Chat is None: + from chatsnack import Chat as _Chat + + Chat = _Chat + chat_cls = Chat + if params_cls is None: + if ChatParams is None: + from chatsnack import ChatParams as _ChatParams + + ChatParams = _ChatParams + params_cls = ChatParams + return chat_cls, params_cls + + +def _coerce_chat_params(params_data: Optional[dict], params_cls): + if not params_data: + return None + + params = dict(params_data) + engine = params.pop("engine", None) + if engine and "model" not in params: + params["model"] = _scalar(engine) + + fields = getattr(params_cls, "__dataclass_fields__", None) + if fields: + params = {key: value for key, value in params.items() if key in fields} + return params_cls(**params) + + +def _load_primary_chat_data() -> Optional[dict]: + path = _chatsnack_base_dir() / f"{CHAT_NAME}.yml" + if not path.exists(): + return None + return _yaml_load(path) + + +def _legacy_petition_path() -> Path: + return _legacy_plunkylib_base_dir() / "petition" / f"{CHAT_NAME}.yml" + + +def _missing_chat_configuration_error() -> FileNotFoundError: + primary_path = _chatsnack_base_dir() / f"{CHAT_NAME}.yml" + legacy_path = _legacy_petition_path() + return FileNotFoundError( + "Could not find Cataclysm chat configuration. " + f"Expected chatsnack prompt at {primary_path}. " + "Run `cataclysm init` or set CHATSNACK_BASE_DIR to a directory " + f"containing {CHAT_NAME}.yml. " + f"Legacy plunkylib fallback was also absent at {legacy_path}." + ) + + +def _load_legacy_chat_data() -> dict: + base_dir = _legacy_plunkylib_base_dir() + petition = _yaml_load(_legacy_petition_path()) + prompt_name = _scalar(petition.get("chatprompt_name")) or "CataclysmPrompt" + params_name = _scalar(petition.get("params_name")) or "CataclysmLLMParams" + + prompt_data = _yaml_load(base_dir / "prompts" / f"{prompt_name}.yml") + params_data = _yaml_load(base_dir / "params" / f"{params_name}.yml") + params_data.setdefault("runtime", "chat_completions") + + return { + "params": params_data, + "messages": prompt_data.get("messages", []), + } + + +def _build_chat( + data: dict, + utensils: Optional[Sequence[Any]], + chat_cls, + params_cls, + auto_execute: Optional[bool] = None, + auto_feed: Optional[bool] = None, + tool_choice: Optional[Any] = None, +): + params = _coerce_chat_params(data.get("params"), params_cls) + kwargs = { + "name": CHAT_NAME, + "messages": data.get("messages", []), + } + if params is not None: + kwargs["params"] = params + if utensils: + kwargs["utensils"] = list(utensils) + if auto_execute is not None: + kwargs["auto_execute"] = auto_execute + if auto_feed is not None: + kwargs["auto_feed"] = auto_feed + if tool_choice is not None: + kwargs["tool_choice"] = tool_choice + return chat_cls(**kwargs) + + +def load_cataclysm_chat( + utensils: Optional[Sequence[Any]] = None, + chat_cls=None, + params_cls=None, + auto_execute: Optional[bool] = None, + auto_feed: Optional[bool] = None, + tool_choice: Optional[Any] = None, +): + chat_cls, params_cls = _get_chat_classes(chat_cls=chat_cls, params_cls=params_cls) + data = _load_primary_chat_data() + if data is None: + if not _legacy_petition_path().exists(): + raise _missing_chat_configuration_error() + data = _load_legacy_chat_data() + return _build_chat( + data, + utensils=utensils, + chat_cls=chat_cls, + params_cls=params_cls, + auto_execute=auto_execute, + auto_feed=auto_feed, + tool_choice=tool_choice, + ) + + +def extract_code_from_response(response_text: str) -> str: + if CODE_START not in response_text: + raise ValueError("Cataclysm response did not include the #|~~ code marker.") + + code = response_text.split(CODE_START, 1)[1] + if CODE_END in code: + code = code.split(CODE_END, 1)[0] + elif CODE_END.strip() in code: + code = code.split(CODE_END.strip(), 1)[0] + return code + + +def _target_includes_exec_return_value(target) -> bool: + if isinstance(target, ast.Name): + return target.id == "_exec_return_values" + if isinstance(target, (ast.Tuple, ast.List)): + return any(_target_includes_exec_return_value(item) for item in target.elts) + return False + + +def validate_generated_code(code: str) -> str: + normalized = code.strip().lower() + if not normalized: + raise ValueError("Cataclysm response produced an empty code body.") + if any(fragment in normalized for fragment in PLACEHOLDER_FRAGMENTS): + raise ValueError("Cataclysm response produced placeholder code.") + + try: + tree = ast.parse(code) + except SyntaxError as exc: + raise ValueError(f"Cataclysm response produced invalid Python: {exc.msg}.") from exc + + if not tree.body: + raise ValueError("Cataclysm response produced no executable Python statements.") + + assigns_return_value = False + raises_error = False + for node in ast.walk(tree): + if isinstance(node, ast.Assign): + assigns_return_value = any(_target_includes_exec_return_value(target) for target in node.targets) + elif isinstance(node, (ast.AnnAssign, ast.AugAssign)): + assigns_return_value = _target_includes_exec_return_value(node.target) + elif isinstance(node, ast.Raise): + raises_error = True + if assigns_return_value or raises_error: + break + + if not assigns_return_value and not raises_error: + raise ValueError("Cataclysm response did not assign _exec_return_values or raise an error.") + return code + + +def _strip_markers_or_fences(code: str) -> str: + stripped = code.strip() + if CODE_START in stripped: + stripped = extract_code_from_response(stripped).strip() + if stripped.startswith("```"): + lines = stripped.splitlines() + if lines and lines[0].startswith("```"): + lines = lines[1:] + if lines and lines[-1].strip() == "```": + lines = lines[:-1] + stripped = "\n".join(lines).strip() + return stripped + "\n" + + +def _validate_code_submission(code: str) -> str: + return validate_generated_code(_strip_markers_or_fences(code)) + + +def _build_submit_exec_body_utensils(capture: SubmittedCodeCapture, extra_utensils: Optional[Sequence[Any]]): + from chatsnack import utensil + + cataclysm_tools = utensil.group( + "cataclysm", + "Submit complete exec-ready Python bodies for Cataclysm to validate and cache.", + ) + + @cataclysm_tools + def submit_exec_body(code: str) -> str: + """Submit the complete exec-ready Python body for Cataclysm to cache.""" + capture.code = _validate_code_submission(code) + return "accepted" + + return [cataclysm_tools, *(extra_utensils or [])] + + +def _text_from_chat_result(result) -> Optional[str]: + if isinstance(result, str): + return result + + response = getattr(result, "response", None) + if isinstance(response, str) and response: + return response + + last = getattr(result, "last", None) + if isinstance(last, str): + return last + if isinstance(last, dict): + for key in ("content", "text"): + value = last.get(key) + if isinstance(value, str): + return value + return None + + +def _submit_exec_body_tool_choice(chat) -> dict: + if type(getattr(chat, "runtime", None)).__name__ == "ChatCompletionsAdapter": + return {"type": "function", "function": {"name": "submit_exec_body"}} + return {"type": "function", "name": "submit_exec_body"} + + +def _force_submit_exec_body_tool(chat) -> None: + choice = _submit_exec_body_tool_choice(chat) + try: + chat.tool_choice = choice + return + except Exception: + pass + + if getattr(chat, "params", None) is not None: + chat.params.tool_choice = choice + + +def generate_code_with_chatsnack( + formatted_info: str, + utensils: Optional[Sequence[Any]] = None, + chat_cls=None, + params_cls=None, +) -> str: + capture = SubmittedCodeCapture() + chat = load_cataclysm_chat( + utensils=_build_submit_exec_body_utensils(capture, utensils), + chat_cls=chat_cls, + params_cls=params_cls, + auto_execute=True, + auto_feed=False, + ) + _force_submit_exec_body_tool(chat) + + if hasattr(chat, "chat"): + result = chat.chat(arg1=formatted_info) + if capture.code is not None: + return capture.code + + response_text = _text_from_chat_result(result) + if response_text: + return _validate_code_submission(response_text) + + response_text = chat.ask(arg1=formatted_info) + return _validate_code_submission(response_text) diff --git a/cataclysm/default_files/datafiles/chatsnack/CataclysmQuery.yml b/cataclysm/default_files/datafiles/chatsnack/CataclysmQuery.yml new file mode 100644 index 0000000..333310a --- /dev/null +++ b/cataclysm/default_files/datafiles/chatsnack/CataclysmQuery.yml @@ -0,0 +1,64 @@ +params: + model: gpt-5-chat-latest + runtime: responses + responses: + max_output_tokens: 1200 +messages: + - system: | + You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Briefly explain the relevant constraints before creating the ideal source code. + - user: | + You are helping with a 'MagicMethod' class that generates code for a function using: + 1. Caller's suggested function name + 2. All arguments passed (in arg_in and kwargs_in) + 3. Stack trace info to provide useful context for what the app is intended to do + 4. Installed modules (code cannot use modules that are not installed) + 5. Source lines from the call stack + 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. + + Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for the function named in the "Function:" line of formatted_info (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. + + The value assigned to _exec_return_values must be the concrete value the original function call should return, with the type implied by the function name, arguments, and calling source lines. Do not return diagnostic dictionaries, wrappers, metadata, explanations, formulas, or multi-field result objects unless the function name or caller explicitly asks for that shape. For calculations, return the numeric result directly. + + If the submit_exec_body utensil is available, call submit_exec_body with the complete exec-ready Python body in its code argument, with no prose, markers, or code fences in that argument. After calling the utensil, stop. + + For plain-text fallback responses, write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. The marked block must contain complete executable Python, never placeholder text such as "...", "code here", or "(Our exec block here)". + + Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. + + After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the requested function's logic. + + Quote the developer's original calling signature source line in the first comment within the code. + + Solve to replace PUZZLEME in the following code: + + class MagicMethods: + def generate_code(self, formatted_info, args_in, kwargs_in): + _exec_return_values = None + # TODO: Figure out what PUZZLEME should be from the formatted_info + return exec(PUZZLEME) + def __getattr__(self, method_name): + def magic_method_manager(*args_in, **kwargs_in): + calling_function_name = method_name + inputs_info = [] + for i, arg_value in enumerate(args_in): + inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') + for arg_name, arg_value in kwargs_in.items(): + inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') + modules_info = get_installed_modules_info() + stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) + formatted_info = f"Function: {{calling_function_name}}\n" + formatted_info += "Arguments:\n" + formatted_info += "\n".join(inputs_info) + "\n" + formatted_info += f"Call Stack:\n{{stack_info}}\n" + formatted_info += "Source Code: Not available in this case\n" + formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" + + return self.generate_code(formatted_info, args, kwargs) + + return magic_method_manager + + doom = MagicMethods() + x = doom.<>(<>) + + --- Current data for 'formatted_info': --- + {arg1} diff --git a/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams.yml b/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams.yml deleted file mode 100644 index bb54c58..0000000 --- a/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-4-0314 -max_tokens: 1200 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml b/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml deleted file mode 100644 index e2a398e..0000000 --- a/cataclysm/default_files/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-3.5-turbo -max_tokens: 600 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/cataclysm/default_files/datafiles/plunkylib/petition/CataclysmQuery.yml b/cataclysm/default_files/datafiles/plunkylib/petition/CataclysmQuery.yml deleted file mode 100644 index e5b9e10..0000000 --- a/cataclysm/default_files/datafiles/plunkylib/petition/CataclysmQuery.yml +++ /dev/null @@ -1,4 +0,0 @@ -"params_name": |- - CataclysmLLMParams -"chatprompt_name": |- - CataclysmPrompt diff --git a/cataclysm/default_files/datafiles/plunkylib/prompts/CataclysmPrompt.yml b/cataclysm/default_files/datafiles/plunkylib/prompts/CataclysmPrompt.yml deleted file mode 100644 index ecb60de..0000000 --- a/cataclysm/default_files/datafiles/plunkylib/prompts/CataclysmPrompt.yml +++ /dev/null @@ -1,55 +0,0 @@ -messages: - - system: | - You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Always explain your complete thinking process before creating the ideal source code. - - user: | - You are helping with a 'MagicMethod' class that generates code for a function using: - 1. Caller's suggested function name - 2. All arguments passed (in arg_in and kwargs_in) - 3. Stack trace info to provide useful context for what the app is intended to do - 4. Installed modules (code cannot use modules that are not installed) - 5. Source lines from the call stack - 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. - - Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for <<>> (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. - - Write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. - - Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. - - After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the logic of <>. - - Quote the developer's original calling signature source line in the first comment within the code. - - Solve to replace PUZZLEME in the following code: - - class MagicMethods: - def generate_code(self, formatted_info, args_in, kwargs_in): - _exec_return_values = None - # TODO: Figure out what PUZZLEME should be from the formatted_info - return exec(PUZZLEME) - def __getattr__(self, method_name): - def magic_method_manager(*args_in, **kwargs_in): - calling_function_name = method_name - inputs_info = [] - for i, arg_value in enumerate(args_in): - inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') - for arg_name, arg_value in kwargs_in.items(): - inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') - modules_info = get_installed_modules_info() - stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) - formatted_info = f"Function: {{calling_function_name}}\n" - formatted_info += "Arguments:\n" - formatted_info += "\n".join(inputs_info) + "\n" - formatted_info += f"Call Stack:\n{{stack_info}}\n" - formatted_info += "Source Code: Not available in this case\n" - formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" - - return self.generate_code(formatted_info, args, kwargs) - - return magic_method_manager - - doom = MagicMethods() - x = doom.<>(<>) - - --- Current data for 'formatted_info': --- - {arg1} diff --git a/cataclysm/default_files/env.template.cataclysm b/cataclysm/default_files/env.template.cataclysm index 4ab17cf..e79589e 100644 --- a/cataclysm/default_files/env.template.cataclysm +++ b/cataclysm/default_files/env.template.cataclysm @@ -1,5 +1,4 @@ -PLUNKYLIB_LOGS_DIR = "./logs/plunkylib" -PLUNKYLIB_BASE_DIR = "./datafiles/plunkylib" +CHATSNACK_BASE_DIR = "./datafiles/chatsnack" CATACLYSM_BASE_DIR = "./datafiles/cataclysm" -OPENAI_API_KEY = "ADD_YOUR_OPENAI_KEY" \ No newline at end of file +OPENAI_API_KEY = "ADD_YOUR_OPENAI_KEY" diff --git a/cataclysm/doomed.py b/cataclysm/doomed.py index 7c3b731..3b7b3c4 100644 --- a/cataclysm/doomed.py +++ b/cataclysm/doomed.py @@ -1,17 +1,18 @@ -import asyncio import builtins -import datafiles -import hashlib import inspect import linecache -import os import pkg_resources -import sys import traceback import types -from typing import Optional -from plunkylib import * +from typing import Dict, Optional + +from datafiles import datafile import loguru + +from .chatsnack_adapter import ( + generate_code_with_chatsnack, +) + logger = loguru.logger @@ -21,14 +22,20 @@ class Function: signatures: Dict[str, str] class CataclysmCreator: - def __init__(self, autoexecute: bool = True, autogenerate: bool = True): + def __init__( + self, + autoexecute: bool = True, + autogenerate: bool = True, + _utensils: Optional[list] = None, + ): self._autoexecute_ = autoexecute self._autogenerate_ = autogenerate + self._utensils_ = _utensils if self._autoexecute_ and self._autogenerate_: # create a text-only version for the squeamish - self.impending = CataclysmCreator(autoexecute=False, autogenerate=True) + self.impending = CataclysmCreator(autoexecute=False, autogenerate=True, _utensils=_utensils) # create a version without more autogeneration for those who chose their fate - self.chosen = CataclysmCreator(autoexecute=True, autogenerate=False) + self.chosen = CataclysmCreator(autoexecute=True, autogenerate=False, _utensils=_utensils) def __getattr__(self, method_name): """For any missing attribute, return our magic function to spread programmer dread.""" @@ -142,17 +149,20 @@ def _save_conjured_code(self, funcname, signature, code): func_obj.datafile.save() def _generate_fresh_code(self, formatted_info): - """Generate fresh code using OpenAI given formatted_info to use in the prompt.""" - # use plunkylib for the query - ai_query = Petition.objects.get("CataclysmQuery") - ai_query.load_all() - args = {} - args['arg1'] = formatted_info - # we're not an async function, so we can't use await, so we can have asyncio run the function for us - completion_result, adj_prompt_text = asyncio.run(petition_completion2(petition=ai_query, additional=args, content_filter_check=False)) - # take the resulting text and get the code after #|~~ - fresh_code = completion_result.text.split("#|~~\n")[1] - return fresh_code + """Generate fresh code using chatsnack given formatted_info to use in the prompt.""" + response_text = generate_code_with_chatsnack( + formatted_info, + utensils=self._utensils_, + ) + return response_text + + def _retry_invalid_generated_code(self, formatted_info, error): + retry_info = formatted_info + retry_info += "\n\nThe previous generated code was rejected before execution.\n" + retry_info += f"Validation error: {error}\n" + retry_info += "Generate a complete exec-ready Python body between the required markers. " + retry_info += "The body must either assign _exec_return_values or intentionally raise an error." + return self._generate_fresh_code(retry_info) def _conjure_code(self, funcname, signature, formatted_info, retry=False): """ @@ -175,7 +185,12 @@ def _conjure_code(self, funcname, signature, formatted_info, retry=False): return doomed_code # generate fresh code - fresh_code = self._generate_fresh_code(formatted_info) + try: + fresh_code = self._generate_fresh_code(formatted_info) + except ValueError as error: + if retry: + raise + fresh_code = self._retry_invalid_generated_code(formatted_info, error) # log the code str, but each line will be prefixed by an extra # loginfo = f"Doomed code:\n{'## '.join(fresh_code.splitlines(True))}" diff --git a/datafiles/chatsnack/CataclysmQuery.yml b/datafiles/chatsnack/CataclysmQuery.yml new file mode 100644 index 0000000..333310a --- /dev/null +++ b/datafiles/chatsnack/CataclysmQuery.yml @@ -0,0 +1,64 @@ +params: + model: gpt-5-chat-latest + runtime: responses + responses: + max_output_tokens: 1200 +messages: + - system: | + You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Briefly explain the relevant constraints before creating the ideal source code. + - user: | + You are helping with a 'MagicMethod' class that generates code for a function using: + 1. Caller's suggested function name + 2. All arguments passed (in arg_in and kwargs_in) + 3. Stack trace info to provide useful context for what the app is intended to do + 4. Installed modules (code cannot use modules that are not installed) + 5. Source lines from the call stack + 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. + + Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for the function named in the "Function:" line of formatted_info (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. + + The value assigned to _exec_return_values must be the concrete value the original function call should return, with the type implied by the function name, arguments, and calling source lines. Do not return diagnostic dictionaries, wrappers, metadata, explanations, formulas, or multi-field result objects unless the function name or caller explicitly asks for that shape. For calculations, return the numeric result directly. + + If the submit_exec_body utensil is available, call submit_exec_body with the complete exec-ready Python body in its code argument, with no prose, markers, or code fences in that argument. After calling the utensil, stop. + + For plain-text fallback responses, write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. The marked block must contain complete executable Python, never placeholder text such as "...", "code here", or "(Our exec block here)". + + Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. + + After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the requested function's logic. + + Quote the developer's original calling signature source line in the first comment within the code. + + Solve to replace PUZZLEME in the following code: + + class MagicMethods: + def generate_code(self, formatted_info, args_in, kwargs_in): + _exec_return_values = None + # TODO: Figure out what PUZZLEME should be from the formatted_info + return exec(PUZZLEME) + def __getattr__(self, method_name): + def magic_method_manager(*args_in, **kwargs_in): + calling_function_name = method_name + inputs_info = [] + for i, arg_value in enumerate(args_in): + inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') + for arg_name, arg_value in kwargs_in.items(): + inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') + modules_info = get_installed_modules_info() + stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) + formatted_info = f"Function: {{calling_function_name}}\n" + formatted_info += "Arguments:\n" + formatted_info += "\n".join(inputs_info) + "\n" + formatted_info += f"Call Stack:\n{{stack_info}}\n" + formatted_info += "Source Code: Not available in this case\n" + formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" + + return self.generate_code(formatted_info, args, kwargs) + + return magic_method_manager + + doom = MagicMethods() + x = doom.<>(<>) + + --- Current data for 'formatted_info': --- + {arg1} diff --git a/examples/hangman/datafiles/chatsnack/CataclysmQuery.yml b/examples/hangman/datafiles/chatsnack/CataclysmQuery.yml new file mode 100644 index 0000000..333310a --- /dev/null +++ b/examples/hangman/datafiles/chatsnack/CataclysmQuery.yml @@ -0,0 +1,64 @@ +params: + model: gpt-5-chat-latest + runtime: responses + responses: + max_output_tokens: 1200 +messages: + - system: | + You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Briefly explain the relevant constraints before creating the ideal source code. + - user: | + You are helping with a 'MagicMethod' class that generates code for a function using: + 1. Caller's suggested function name + 2. All arguments passed (in arg_in and kwargs_in) + 3. Stack trace info to provide useful context for what the app is intended to do + 4. Installed modules (code cannot use modules that are not installed) + 5. Source lines from the call stack + 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. + + Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for the function named in the "Function:" line of formatted_info (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. + + The value assigned to _exec_return_values must be the concrete value the original function call should return, with the type implied by the function name, arguments, and calling source lines. Do not return diagnostic dictionaries, wrappers, metadata, explanations, formulas, or multi-field result objects unless the function name or caller explicitly asks for that shape. For calculations, return the numeric result directly. + + If the submit_exec_body utensil is available, call submit_exec_body with the complete exec-ready Python body in its code argument, with no prose, markers, or code fences in that argument. After calling the utensil, stop. + + For plain-text fallback responses, write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. The marked block must contain complete executable Python, never placeholder text such as "...", "code here", or "(Our exec block here)". + + Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. + + After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the requested function's logic. + + Quote the developer's original calling signature source line in the first comment within the code. + + Solve to replace PUZZLEME in the following code: + + class MagicMethods: + def generate_code(self, formatted_info, args_in, kwargs_in): + _exec_return_values = None + # TODO: Figure out what PUZZLEME should be from the formatted_info + return exec(PUZZLEME) + def __getattr__(self, method_name): + def magic_method_manager(*args_in, **kwargs_in): + calling_function_name = method_name + inputs_info = [] + for i, arg_value in enumerate(args_in): + inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') + for arg_name, arg_value in kwargs_in.items(): + inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') + modules_info = get_installed_modules_info() + stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) + formatted_info = f"Function: {{calling_function_name}}\n" + formatted_info += "Arguments:\n" + formatted_info += "\n".join(inputs_info) + "\n" + formatted_info += f"Call Stack:\n{{stack_info}}\n" + formatted_info += "Source Code: Not available in this case\n" + formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" + + return self.generate_code(formatted_info, args, kwargs) + + return magic_method_manager + + doom = MagicMethods() + x = doom.<>(<>) + + --- Current data for 'formatted_info': --- + {arg1} diff --git a/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams.yml b/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams.yml deleted file mode 100644 index bb54c58..0000000 --- a/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-4-0314 -max_tokens: 1200 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml b/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml deleted file mode 100644 index e2a398e..0000000 --- a/examples/hangman/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-3.5-turbo -max_tokens: 600 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/examples/hangman/datafiles/plunkylib/petition/CataclysmQuery.yml b/examples/hangman/datafiles/plunkylib/petition/CataclysmQuery.yml deleted file mode 100644 index e5b9e10..0000000 --- a/examples/hangman/datafiles/plunkylib/petition/CataclysmQuery.yml +++ /dev/null @@ -1,4 +0,0 @@ -"params_name": |- - CataclysmLLMParams -"chatprompt_name": |- - CataclysmPrompt diff --git a/examples/hangman/datafiles/plunkylib/prompts/CataclysmPrompt.yml b/examples/hangman/datafiles/plunkylib/prompts/CataclysmPrompt.yml deleted file mode 100644 index ecb60de..0000000 --- a/examples/hangman/datafiles/plunkylib/prompts/CataclysmPrompt.yml +++ /dev/null @@ -1,55 +0,0 @@ -messages: - - system: | - You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Always explain your complete thinking process before creating the ideal source code. - - user: | - You are helping with a 'MagicMethod' class that generates code for a function using: - 1. Caller's suggested function name - 2. All arguments passed (in arg_in and kwargs_in) - 3. Stack trace info to provide useful context for what the app is intended to do - 4. Installed modules (code cannot use modules that are not installed) - 5. Source lines from the call stack - 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. - - Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for <<>> (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. - - Write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. - - Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. - - After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the logic of <>. - - Quote the developer's original calling signature source line in the first comment within the code. - - Solve to replace PUZZLEME in the following code: - - class MagicMethods: - def generate_code(self, formatted_info, args_in, kwargs_in): - _exec_return_values = None - # TODO: Figure out what PUZZLEME should be from the formatted_info - return exec(PUZZLEME) - def __getattr__(self, method_name): - def magic_method_manager(*args_in, **kwargs_in): - calling_function_name = method_name - inputs_info = [] - for i, arg_value in enumerate(args_in): - inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') - for arg_name, arg_value in kwargs_in.items(): - inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') - modules_info = get_installed_modules_info() - stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) - formatted_info = f"Function: {{calling_function_name}}\n" - formatted_info += "Arguments:\n" - formatted_info += "\n".join(inputs_info) + "\n" - formatted_info += f"Call Stack:\n{{stack_info}}\n" - formatted_info += "Source Code: Not available in this case\n" - formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" - - return self.generate_code(formatted_info, args, kwargs) - - return magic_method_manager - - doom = MagicMethods() - x = doom.<>(<>) - - --- Current data for 'formatted_info': --- - {arg1} diff --git a/examples/image_resizer/datafiles/chatsnack/CataclysmQuery.yml b/examples/image_resizer/datafiles/chatsnack/CataclysmQuery.yml new file mode 100644 index 0000000..333310a --- /dev/null +++ b/examples/image_resizer/datafiles/chatsnack/CataclysmQuery.yml @@ -0,0 +1,64 @@ +params: + model: gpt-5-chat-latest + runtime: responses + responses: + max_output_tokens: 1200 +messages: + - system: | + You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Briefly explain the relevant constraints before creating the ideal source code. + - user: | + You are helping with a 'MagicMethod' class that generates code for a function using: + 1. Caller's suggested function name + 2. All arguments passed (in arg_in and kwargs_in) + 3. Stack trace info to provide useful context for what the app is intended to do + 4. Installed modules (code cannot use modules that are not installed) + 5. Source lines from the call stack + 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. + + Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for the function named in the "Function:" line of formatted_info (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. + + The value assigned to _exec_return_values must be the concrete value the original function call should return, with the type implied by the function name, arguments, and calling source lines. Do not return diagnostic dictionaries, wrappers, metadata, explanations, formulas, or multi-field result objects unless the function name or caller explicitly asks for that shape. For calculations, return the numeric result directly. + + If the submit_exec_body utensil is available, call submit_exec_body with the complete exec-ready Python body in its code argument, with no prose, markers, or code fences in that argument. After calling the utensil, stop. + + For plain-text fallback responses, write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. The marked block must contain complete executable Python, never placeholder text such as "...", "code here", or "(Our exec block here)". + + Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. + + After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the requested function's logic. + + Quote the developer's original calling signature source line in the first comment within the code. + + Solve to replace PUZZLEME in the following code: + + class MagicMethods: + def generate_code(self, formatted_info, args_in, kwargs_in): + _exec_return_values = None + # TODO: Figure out what PUZZLEME should be from the formatted_info + return exec(PUZZLEME) + def __getattr__(self, method_name): + def magic_method_manager(*args_in, **kwargs_in): + calling_function_name = method_name + inputs_info = [] + for i, arg_value in enumerate(args_in): + inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') + for arg_name, arg_value in kwargs_in.items(): + inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') + modules_info = get_installed_modules_info() + stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) + formatted_info = f"Function: {{calling_function_name}}\n" + formatted_info += "Arguments:\n" + formatted_info += "\n".join(inputs_info) + "\n" + formatted_info += f"Call Stack:\n{{stack_info}}\n" + formatted_info += "Source Code: Not available in this case\n" + formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" + + return self.generate_code(formatted_info, args, kwargs) + + return magic_method_manager + + doom = MagicMethods() + x = doom.<>(<>) + + --- Current data for 'formatted_info': --- + {arg1} diff --git a/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams.yml b/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams.yml deleted file mode 100644 index bb54c58..0000000 --- a/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-4-0314 -max_tokens: 1200 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml b/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml deleted file mode 100644 index e2a398e..0000000 --- a/examples/image_resizer/datafiles/plunkylib/params/CataclysmLLMParams_3-5.yml +++ /dev/null @@ -1,9 +0,0 @@ -engine: gpt-3.5-turbo -max_tokens: 600 -stop: - - "\n\n\n\n" - - "#~~|\n" -temperature: 0.0 -top_p: 1.0 -frequency_penalty: 0.0 -presence_penalty: 0.0 \ No newline at end of file diff --git a/examples/image_resizer/datafiles/plunkylib/petition/CataclysmQuery.yml b/examples/image_resizer/datafiles/plunkylib/petition/CataclysmQuery.yml deleted file mode 100644 index e5b9e10..0000000 --- a/examples/image_resizer/datafiles/plunkylib/petition/CataclysmQuery.yml +++ /dev/null @@ -1,4 +0,0 @@ -"params_name": |- - CataclysmLLMParams -"chatprompt_name": |- - CataclysmPrompt diff --git a/examples/image_resizer/datafiles/plunkylib/prompts/CataclysmPrompt.yml b/examples/image_resizer/datafiles/plunkylib/prompts/CataclysmPrompt.yml deleted file mode 100644 index ecb60de..0000000 --- a/examples/image_resizer/datafiles/plunkylib/prompts/CataclysmPrompt.yml +++ /dev/null @@ -1,55 +0,0 @@ -messages: - - system: | - You are a world-class Python code generator with vast expertise in open source code. You write excellent, robust code. Always explain your complete thinking process before creating the ideal source code. - - user: | - You are helping with a 'MagicMethod' class that generates code for a function using: - 1. Caller's suggested function name - 2. All arguments passed (in arg_in and kwargs_in) - 3. Stack trace info to provide useful context for what the app is intended to do - 4. Installed modules (code cannot use modules that are not installed) - 5. Source lines from the call stack - 6. Generated code can only use modules from "Installed Modules" and must always 'import' every dependency in the function body. - - Use the following context info, write a detailed Python script that perfectly satisfies the inferred requirements for <<>> (and be sure it is generally useful for common use cases). Code must be formatted to be run within exec() as a string and it must provide an appropriate return value to the caller. The code will have access to args_in and the kwargs_in dictionary, which you must use in the code as needed. - - Write only the exec-ready **body** of the script (importing any modules you need in the body), and remember to put the expected return value in _exec_return_values. Put the comment "#|~~" at the beginning of the code and "#~~|" at the end of the code to be exec'd to make it clear. - - Before writing any code, analyze whether I/O is truly required, explain what makes you think it is. If the caller doesn't need I/O, then it must behave in a read-only manner for files or resources. - - After that, discuss the best ways to approach the problem, mention common uses cases we must support, and then explain 1-3 important corner cases to consider (and how to handle them properly) before solving for the logic of <>. - - Quote the developer's original calling signature source line in the first comment within the code. - - Solve to replace PUZZLEME in the following code: - - class MagicMethods: - def generate_code(self, formatted_info, args_in, kwargs_in): - _exec_return_values = None - # TODO: Figure out what PUZZLEME should be from the formatted_info - return exec(PUZZLEME) - def __getattr__(self, method_name): - def magic_method_manager(*args_in, **kwargs_in): - calling_function_name = method_name - inputs_info = [] - for i, arg_value in enumerate(args_in): - inputs_info.append(f'args_in[{{i}}]-> {{type(arg_value).__name__}} = {{arg_value}}') - for arg_name, arg_value in kwargs_in.items(): - inputs_info.append(f'kwargs_in["{{arg_name}}"]-> {{type(arg_value).__name__}} = {{arg_value}}') - modules_info = get_installed_modules_info() - stack_info = self.tracelines(lines_before=2, lines_after=1, stack_depth=5, stack_skip_recent=1) - formatted_info = f"Function: {{calling_function_name}}\n" - formatted_info += "Arguments:\n" - formatted_info += "\n".join(inputs_info) + "\n" - formatted_info += f"Call Stack:\n{{stack_info}}\n" - formatted_info += "Source Code: Not available in this case\n" - formatted_info += "Installed Modules:\n" + "|".join(modules_info) + "\n" - - return self.generate_code(formatted_info, args, kwargs) - - return magic_method_manager - - doom = MagicMethods() - x = doom.<>(<>) - - --- Current data for 'formatted_info': --- - {arg1} diff --git a/poetry.lock b/poetry.lock index 54f9175..7a578b9 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,423 +1,386 @@ -# This file is automatically @generated by Poetry and should not be changed by hand. +# This file is automatically @generated by Poetry 1.4.1 and should not be changed by hand. [[package]] -name = "aiohttp" -version = "3.8.4" -description = "Async http client/server framework (asyncio)" +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5ce45967538fb747370308d3145aa68a074bdecb4f3a300869590f725ced69c1"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b744c33b6f14ca26b7544e8d8aadff6b765a80ad6164fb1a430bbadd593dfb1a"}, - {file = "aiohttp-3.8.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a45865451439eb320784918617ba54b7a377e3501fb70402ab84d38c2cd891b"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a86d42d7cba1cec432d47ab13b6637bee393a10f664c425ea7b305d1301ca1a3"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ee3c36df21b5714d49fc4580247947aa64bcbe2939d1b77b4c8dcb8f6c9faecc"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:176a64b24c0935869d5bbc4c96e82f89f643bcdf08ec947701b9dbb3c956b7dd"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c844fd628851c0bc309f3c801b3a3d58ce430b2ce5b359cd918a5a76d0b20cb5"}, - {file = "aiohttp-3.8.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5393fb786a9e23e4799fec788e7e735de18052f83682ce2dfcabaf1c00c2c08e"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e4b09863aae0dc965c3ef36500d891a3ff495a2ea9ae9171e4519963c12ceefd"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:adfbc22e87365a6e564c804c58fc44ff7727deea782d175c33602737b7feadb6"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:147ae376f14b55f4f3c2b118b95be50a369b89b38a971e80a17c3fd623f280c9"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:eafb3e874816ebe2a92f5e155f17260034c8c341dad1df25672fb710627c6949"}, - {file = "aiohttp-3.8.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6cc15d58053c76eacac5fa9152d7d84b8d67b3fde92709195cb984cfb3475ea"}, - {file = "aiohttp-3.8.4-cp310-cp310-win32.whl", hash = "sha256:59f029a5f6e2d679296db7bee982bb3d20c088e52a2977e3175faf31d6fb75d1"}, - {file = "aiohttp-3.8.4-cp310-cp310-win_amd64.whl", hash = "sha256:fe7ba4a51f33ab275515f66b0a236bcde4fb5561498fe8f898d4e549b2e4509f"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3d8ef1a630519a26d6760bc695842579cb09e373c5f227a21b67dc3eb16cfea4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b3f2e06a512e94722886c0827bee9807c86a9f698fac6b3aee841fab49bbfb4"}, - {file = "aiohttp-3.8.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a80464982d41b1fbfe3154e440ba4904b71c1a53e9cd584098cd41efdb188ef"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b631e26df63e52f7cce0cce6507b7a7f1bc9b0c501fcde69742130b32e8782f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3f43255086fe25e36fd5ed8f2ee47477408a73ef00e804cb2b5cba4bf2ac7f5e"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4d347a172f866cd1d93126d9b239fcbe682acb39b48ee0873c73c933dd23bd0f"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a3fec6a4cb5551721cdd70473eb009d90935b4063acc5f40905d40ecfea23e05"}, - {file = "aiohttp-3.8.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:80a37fe8f7c1e6ce8f2d9c411676e4bc633a8462844e38f46156d07a7d401654"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d1e6a862b76f34395a985b3cd39a0d949ca80a70b6ebdea37d3ab39ceea6698a"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:cd468460eefef601ece4428d3cf4562459157c0f6523db89365202c31b6daebb"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:618c901dd3aad4ace71dfa0f5e82e88b46ef57e3239fc7027773cb6d4ed53531"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:652b1bff4f15f6287550b4670546a2947f2a4575b6c6dff7760eafb22eacbf0b"}, - {file = "aiohttp-3.8.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80575ba9377c5171407a06d0196b2310b679dc752d02a1fcaa2bc20b235dbf24"}, - {file = "aiohttp-3.8.4-cp311-cp311-win32.whl", hash = "sha256:bbcf1a76cf6f6dacf2c7f4d2ebd411438c275faa1dc0c68e46eb84eebd05dd7d"}, - {file = "aiohttp-3.8.4-cp311-cp311-win_amd64.whl", hash = "sha256:6e74dd54f7239fcffe07913ff8b964e28b712f09846e20de78676ce2a3dc0bfc"}, - {file = "aiohttp-3.8.4-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:880e15bb6dad90549b43f796b391cfffd7af373f4646784795e20d92606b7a51"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb96fa6b56bb536c42d6a4a87dfca570ff8e52de2d63cabebfd6fb67049c34b6"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a6cadebe132e90cefa77e45f2d2f1a4b2ce5c6b1bfc1656c1ddafcfe4ba8131"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f352b62b45dff37b55ddd7b9c0c8672c4dd2eb9c0f9c11d395075a84e2c40f75"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ab43061a0c81198d88f39aaf90dae9a7744620978f7ef3e3708339b8ed2ef01"}, - {file = "aiohttp-3.8.4-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9cb1565a7ad52e096a6988e2ee0397f72fe056dadf75d17fa6b5aebaea05622"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:1b3ea7edd2d24538959c1c1abf97c744d879d4e541d38305f9bd7d9b10c9ec41"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:7c7837fe8037e96b6dd5cfcf47263c1620a9d332a87ec06a6ca4564e56bd0f36"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:3b90467ebc3d9fa5b0f9b6489dfb2c304a1db7b9946fa92aa76a831b9d587e99"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:cab9401de3ea52b4b4c6971db5fb5c999bd4260898af972bf23de1c6b5dd9d71"}, - {file = "aiohttp-3.8.4-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:d1f9282c5f2b5e241034a009779e7b2a1aa045f667ff521e7948ea9b56e0c5ff"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win32.whl", hash = "sha256:5e14f25765a578a0a634d5f0cd1e2c3f53964553a00347998dfdf96b8137f777"}, - {file = "aiohttp-3.8.4-cp36-cp36m-win_amd64.whl", hash = "sha256:4c745b109057e7e5f1848c689ee4fb3a016c8d4d92da52b312f8a509f83aa05e"}, - {file = "aiohttp-3.8.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:aede4df4eeb926c8fa70de46c340a1bc2c6079e1c40ccf7b0eae1313ffd33519"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddaae3f3d32fc2cb4c53fab020b69a05c8ab1f02e0e59665c6f7a0d3a5be54f"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4eb3b82ca349cf6fadcdc7abcc8b3a50ab74a62e9113ab7a8ebc268aad35bb9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9bcb89336efa095ea21b30f9e686763f2be4478f1b0a616969551982c4ee4c3b"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c08e8ed6fa3d477e501ec9db169bfac8140e830aa372d77e4a43084d8dd91ab"}, - {file = "aiohttp-3.8.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c6cd05ea06daca6ad6a4ca3ba7fe7dc5b5de063ff4daec6170ec0f9979f6c332"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b7a00a9ed8d6e725b55ef98b1b35c88013245f35f68b1b12c5cd4100dddac333"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:de04b491d0e5007ee1b63a309956eaed959a49f5bb4e84b26c8f5d49de140fa9"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:40653609b3bf50611356e6b6554e3a331f6879fa7116f3959b20e3528783e699"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dbf3a08a06b3f433013c143ebd72c15cac33d2914b8ea4bea7ac2c23578815d6"}, - {file = "aiohttp-3.8.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854f422ac44af92bfe172d8e73229c270dc09b96535e8a548f99c84f82dde241"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win32.whl", hash = "sha256:aeb29c84bb53a84b1a81c6c09d24cf33bb8432cc5c39979021cc0f98c1292a1a"}, - {file = "aiohttp-3.8.4-cp37-cp37m-win_amd64.whl", hash = "sha256:db3fc6120bce9f446d13b1b834ea5b15341ca9ff3f335e4a951a6ead31105480"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:fabb87dd8850ef0f7fe2b366d44b77d7e6fa2ea87861ab3844da99291e81e60f"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91f6d540163f90bbaef9387e65f18f73ffd7c79f5225ac3d3f61df7b0d01ad15"}, - {file = "aiohttp-3.8.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d265f09a75a79a788237d7f9054f929ced2e69eb0bb79de3798c468d8a90f945"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3d89efa095ca7d442a6d0cbc755f9e08190ba40069b235c9886a8763b03785da"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4dac314662f4e2aa5009977b652d9b8db7121b46c38f2073bfeed9f4049732cd"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fe11310ae1e4cd560035598c3f29d86cef39a83d244c7466f95c27ae04850f10"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ddb2a2026c3f6a68c3998a6c47ab6795e4127315d2e35a09997da21865757f8"}, - {file = "aiohttp-3.8.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e75b89ac3bd27d2d043b234aa7b734c38ba1b0e43f07787130a0ecac1e12228a"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6e601588f2b502c93c30cd5a45bfc665faaf37bbe835b7cfd461753068232074"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a5d794d1ae64e7753e405ba58e08fcfa73e3fad93ef9b7e31112ef3c9a0efb52"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:a1f4689c9a1462f3df0a1f7e797791cd6b124ddbee2b570d34e7f38ade0e2c71"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:3032dcb1c35bc330134a5b8a5d4f68c1a87252dfc6e1262c65a7e30e62298275"}, - {file = "aiohttp-3.8.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8189c56eb0ddbb95bfadb8f60ea1b22fcfa659396ea36f6adcc521213cd7b44d"}, - {file = "aiohttp-3.8.4-cp38-cp38-win32.whl", hash = "sha256:33587f26dcee66efb2fff3c177547bd0449ab7edf1b73a7f5dea1e38609a0c54"}, - {file = "aiohttp-3.8.4-cp38-cp38-win_amd64.whl", hash = "sha256:e595432ac259af2d4630008bf638873d69346372d38255774c0e286951e8b79f"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:5a7bdf9e57126dc345b683c3632e8ba317c31d2a41acd5800c10640387d193ed"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:22f6eab15b6db242499a16de87939a342f5a950ad0abaf1532038e2ce7d31567"}, - {file = "aiohttp-3.8.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7235604476a76ef249bd64cb8274ed24ccf6995c4a8b51a237005ee7a57e8643"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9eb976ffdd79d0e893869cfe179a8f60f152d42cb64622fca418cd9b18dc2a"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:92c0cea74a2a81c4c76b62ea1cac163ecb20fb3ba3a75c909b9fa71b4ad493cf"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:493f5bc2f8307286b7799c6d899d388bbaa7dfa6c4caf4f97ef7521b9cb13719"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0a63f03189a6fa7c900226e3ef5ba4d3bd047e18f445e69adbd65af433add5a2"}, - {file = "aiohttp-3.8.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:10c8cefcff98fd9168cdd86c4da8b84baaa90bf2da2269c6161984e6737bf23e"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bca5f24726e2919de94f047739d0a4fc01372801a3672708260546aa2601bf57"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:03baa76b730e4e15a45f81dfe29a8d910314143414e528737f8589ec60cf7391"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8c29c77cc57e40f84acef9bfb904373a4e89a4e8b74e71aa8075c021ec9078c2"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:03543dcf98a6619254b409be2d22b51f21ec66272be4ebda7b04e6412e4b2e14"}, - {file = "aiohttp-3.8.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:17b79c2963db82086229012cff93ea55196ed31f6493bb1ccd2c62f1724324e4"}, - {file = "aiohttp-3.8.4-cp39-cp39-win32.whl", hash = "sha256:34ce9f93a4a68d1272d26030655dd1b58ff727b3ed2a33d80ec433561b03d67a"}, - {file = "aiohttp-3.8.4-cp39-cp39-win_amd64.whl", hash = "sha256:41a86a69bb63bb2fc3dc9ad5ea9f10f1c9c8e282b471931be0268ddd09430b04"}, - {file = "aiohttp-3.8.4.tar.gz", hash = "sha256:bf2e1a9162c1e441bf805a1fd166e249d574ca04e03b34f97e2928769e91ab5c"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] -[package.dependencies] -aiosignal = ">=1.1.2" -async-timeout = ">=4.0.0a3,<5.0" -attrs = ">=17.3.0" -charset-normalizer = ">=2.0,<4.0" -frozenlist = ">=1.1.1" -multidict = ">=4.5,<7.0" -yarl = ">=1.0,<2.0" - -[package.extras] -speedups = ["Brotli", "aiodns", "cchardet"] - [[package]] -name = "aiosignal" -version = "1.3.1" -description = "aiosignal: a list of registered asynchronous callbacks" +name = "anyio" +version = "4.14.0" +description = "High-level concurrency and networking framework on top of asyncio or Trio" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" files = [ - {file = "aiosignal-1.3.1-py3-none-any.whl", hash = "sha256:f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17"}, - {file = "aiosignal-1.3.1.tar.gz", hash = "sha256:54cd96e15e1649b75d6c87526a6ff0b6c1b0dd3459f43d9ca11d48c339b68cfc"}, + {file = "anyio-4.14.0-py3-none-any.whl", hash = "sha256:dd9b7a2a9799ed6552fde617b2c5df02b7fdd7d88392fc48101e51bae46164d9"}, + {file = "anyio-4.14.0.tar.gz", hash = "sha256:b47c1f9ccf73e67021df785332508f99379c68fa7d0684e8e3492cb1d4b23f89"}, ] [package.dependencies] -frozenlist = ">=1.1.0" +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} + +[package.extras] +trio = ["trio (>=0.32.0)"] [[package]] -name = "async-timeout" -version = "4.0.2" -description = "Timeout context manager for asyncio programs" +name = "cached-property" +version = "2.0.1" +description = "A decorator for caching properties in classes." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, - {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, + {file = "cached_property-2.0.1-py3-none-any.whl", hash = "sha256:f617d70ab1100b7bcf6e42228f9ddcb78c676ffa167278d9f730d1c2fba69ccb"}, + {file = "cached_property-2.0.1.tar.gz", hash = "sha256:484d617105e3ee0e4f1f58725e72a8ef9e93deee462222dbd51cd91230897641"}, ] [[package]] -name = "attrs" -version = "22.2.0" -description = "Classes Without Boilerplate" +name = "certifi" +version = "2026.6.17" +description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" files = [ - {file = "attrs-22.2.0-py3-none-any.whl", hash = "sha256:29e95c7f6778868dbd49170f98f8818f78f3dc5e0e37c0b1f474e3561b240836"}, - {file = "attrs-22.2.0.tar.gz", hash = "sha256:c9227bfc2f01993c03f68db37d1d15c9690188323c067c641f1a35ca58185f99"}, + {file = "certifi-2026.6.17-py3-none-any.whl", hash = "sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db"}, + {file = "certifi-2026.6.17.tar.gz", hash = "sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432"}, ] +[[package]] +name = "chatsnack" +version = "0.5.0" +description = "chatsnack is the easiest Python library for rapid development with OpenAI's ChatGPT API. It provides an intuitive interface for creating and managing chat-based prompts and responses, making it convenient to build complex, interactive conversations with AI." +category = "main" +optional = false +python-versions = "^3.10" +files = [] +develop = false + +[package.dependencies] +datafiles = "^2.0" +loguru = "^0.6.0" +nest-asyncio = "^1.5.6" +openai = ">=2.29.0" +python-dotenv = "^1.0.0" +websockets = ">=13.0" + [package.extras] -cov = ["attrs[tests]", "coverage-enable-subprocess", "coverage[toml] (>=5.3)"] -dev = ["attrs[docs,tests]"] -docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope.interface"] -tests = ["attrs[tests-no-zope]", "zope.interface"] -tests-no-zope = ["cloudpickle", "cloudpickle", "hypothesis", "hypothesis", "mypy (>=0.971,<0.990)", "mypy (>=0.971,<0.990)", "pympler", "pympler", "pytest (>=4.3.0)", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-mypy-plugins", "pytest-xdist[psutil]", "pytest-xdist[psutil]"] +examples = ["Flask (>=2.1,<3.0)", "questionary (>=1.10.0,<2.0.0)", "rich (>=13.3.2,<14.0.0)"] +flask = ["Flask (>=2.1,<3.0)"] +questionary = ["questionary (>=1.10.0,<2.0.0)"] +rich = ["rich (>=13.3.2,<14.0.0)"] + +[package.source] +type = "git" +url = "https://github.com/Mattie/chatsnack.git" +reference = "630ea4b5ce76b163833ad7c0b8d03072ec95d5a6" +resolved_reference = "630ea4b5ce76b163833ad7c0b8d03072ec95d5a6" [[package]] -name = "cached-property" -version = "1.5.2" -description = "A decorator for caching properties in classes." +name = "classproperties" +version = "0.2.0" +description = "property for class methods" category = "main" optional = false python-versions = "*" files = [ - {file = "cached-property-1.5.2.tar.gz", hash = "sha256:9fa5755838eecbb2d234c3aa390bd80fbd3ac6b6869109bfc1b499f7bd89a130"}, - {file = "cached_property-1.5.2-py2.py3-none-any.whl", hash = "sha256:df4f613cf7ad9a588cc381aaf4a512d26265ecebd5eb9e1ba12f1319eb85a6a0"}, + {file = "classproperties-0.2.0.tar.gz", hash = "sha256:a77e96a666898ecd697dd7f331d9ab1e38383c1edef809d953bb5f8a3ea67c2a"}, ] [[package]] -name = "certifi" -version = "2022.12.7" -description = "Python package for providing Mozilla's CA Bundle." +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." category = "main" optional = false -python-versions = ">=3.6" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "certifi-2022.12.7-py3-none-any.whl", hash = "sha256:4ad3232f5e926d6718ec31cfc1fcadfde020920e278684144551c91769c7bc18"}, - {file = "certifi-2022.12.7.tar.gz", hash = "sha256:35824b4c3a97115964b408844d64aa14db1cc518f6562e8d7261699d1350a9e3"}, -] - -[[package]] -name = "charset-normalizer" -version = "3.1.0" -description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." -category = "main" -optional = false -python-versions = ">=3.7.0" -files = [ - {file = "charset-normalizer-3.1.0.tar.gz", hash = "sha256:34e0a2f9c370eb95597aae63bf85eb5e96826d81e3dcf88b8886012906f509b5"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e0ac8959c929593fee38da1c2b64ee9778733cdf03c482c9ff1d508b6b593b2b"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d7fc3fca01da18fbabe4625d64bb612b533533ed10045a2ac3dd194bfa656b60"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:04eefcee095f58eaabe6dc3cc2262f3bcd776d2c67005880894f447b3f2cb9c1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20064ead0717cf9a73a6d1e779b23d149b53daf971169289ed2ed43a71e8d3b0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1435ae15108b1cb6fffbcea2af3d468683b7afed0169ad718451f8db5d1aff6f"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c84132a54c750fda57729d1e2599bb598f5fa0344085dbde5003ba429a4798c0"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f2568b4189dda1c567339b48cba4ac7384accb9c2a7ed655cd86b04055c795"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11d3bcb7be35e7b1bba2c23beedac81ee893ac9871d0ba79effc7fc01167db6c"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:891cf9b48776b5c61c700b55a598621fdb7b1e301a550365571e9624f270c203"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5f008525e02908b20e04707a4f704cd286d94718f48bb33edddc7d7b584dddc1"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:b06f0d3bf045158d2fb8837c5785fe9ff9b8c93358be64461a1089f5da983137"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:49919f8400b5e49e961f320c735388ee686a62327e773fa5b3ce6721f7e785ce"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:22908891a380d50738e1f978667536f6c6b526a2064156203d418f4856d6e86a"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win32.whl", hash = "sha256:12d1a39aa6b8c6f6248bb54550efcc1c38ce0d8096a146638fd4738e42284448"}, - {file = "charset_normalizer-3.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:65ed923f84a6844de5fd29726b888e58c62820e0769b76565480e1fdc3d062f8"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9a3267620866c9d17b959a84dd0bd2d45719b817245e49371ead79ed4f710d19"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6734e606355834f13445b6adc38b53c0fd45f1a56a9ba06c2058f86893ae8017"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f8303414c7b03f794347ad062c0516cee0e15f7a612abd0ce1e25caf6ceb47df"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:aaf53a6cebad0eae578f062c7d462155eada9c172bd8c4d250b8c1d8eb7f916a"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3dc5b6a8ecfdc5748a7e429782598e4f17ef378e3e272eeb1340ea57c9109f41"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e1b25e3ad6c909f398df8921780d6a3d120d8c09466720226fc621605b6f92b1"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ca564606d2caafb0abe6d1b5311c2649e8071eb241b2d64e75a0d0065107e62"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b82fab78e0b1329e183a65260581de4375f619167478dddab510c6c6fb04d9b6"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:bd7163182133c0c7701b25e604cf1611c0d87712e56e88e7ee5d72deab3e76b5"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:11d117e6c63e8f495412d37e7dc2e2fff09c34b2d09dbe2bee3c6229577818be"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:cf6511efa4801b9b38dc5546d7547d5b5c6ef4b081c60b23e4d941d0eba9cbeb"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:abc1185d79f47c0a7aaf7e2412a0eb2c03b724581139193d2d82b3ad8cbb00ac"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cb7b2ab0188829593b9de646545175547a70d9a6e2b63bf2cd87a0a391599324"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win32.whl", hash = "sha256:c36bcbc0d5174a80d6cccf43a0ecaca44e81d25be4b7f90f0ed7bcfbb5a00909"}, - {file = "charset_normalizer-3.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:cca4def576f47a09a943666b8f829606bcb17e2bc2d5911a46c8f8da45f56755"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0c95f12b74681e9ae127728f7e5409cbbef9cd914d5896ef238cc779b8152373"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fca62a8301b605b954ad2e9c3666f9d97f63872aa4efcae5492baca2056b74ab"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0aa6cd53ab9a31d397f8303f92c42f534693528fafbdb997c82bae6e477ad9"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c3af8e0f07399d3176b179f2e2634c3ce9c1301379a6b8c9c9aeecd481da494f"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a5fc78f9e3f501a1614a98f7c54d3969f3ad9bba8ba3d9b438c3bc5d047dd28"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:628c985afb2c7d27a4800bfb609e03985aaecb42f955049957814e0491d4006d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:74db0052d985cf37fa111828d0dd230776ac99c740e1a758ad99094be4f1803d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:1e8fcdd8f672a1c4fc8d0bd3a2b576b152d2a349782d1eb0f6b8e52e9954731d"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:04afa6387e2b282cf78ff3dbce20f0cc071c12dc8f685bd40960cc68644cfea6"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:dd5653e67b149503c68c4018bf07e42eeed6b4e956b24c00ccdf93ac79cdff84"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:d2686f91611f9e17f4548dbf050e75b079bbc2a82be565832bc8ea9047b61c8c"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win32.whl", hash = "sha256:4155b51ae05ed47199dc5b2a4e62abccb274cee6b01da5b895099b61b1982974"}, - {file = "charset_normalizer-3.1.0-cp37-cp37m-win_amd64.whl", hash = "sha256:322102cdf1ab682ecc7d9b1c5eed4ec59657a65e1c146a0da342b78f4112db23"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:e633940f28c1e913615fd624fcdd72fdba807bf53ea6925d6a588e84e1151531"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3a06f32c9634a8705f4ca9946d667609f52cf130d5548881401f1eb2c39b1e2c"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7381c66e0561c5757ffe616af869b916c8b4e42b367ab29fedc98481d1e74e14"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3573d376454d956553c356df45bb824262c397c6e26ce43e8203c4c540ee0acb"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e89df2958e5159b811af9ff0f92614dabf4ff617c03a4c1c6ff53bf1c399e0e1"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78cacd03e79d009d95635e7d6ff12c21eb89b894c354bd2b2ed0b4763373693b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de5695a6f1d8340b12a5d6d4484290ee74d61e467c39ff03b39e30df62cf83a0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1c60b9c202d00052183c9be85e5eaf18a4ada0a47d188a83c8f5c5b23252f649"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:f645caaf0008bacf349875a974220f1f1da349c5dbe7c4ec93048cdc785a3326"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ea9f9c6034ea2d93d9147818f17c2a0860d41b71c38b9ce4d55f21b6f9165a11"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:80d1543d58bd3d6c271b66abf454d437a438dff01c3e62fdbcd68f2a11310d4b"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:73dc03a6a7e30b7edc5b01b601e53e7fc924b04e1835e8e407c12c037e81adbd"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6f5c2e7bc8a4bf7c426599765b1bd33217ec84023033672c1e9a8b35eaeaaaf8"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win32.whl", hash = "sha256:12a2b561af122e3d94cdb97fe6fb2bb2b82cef0cdca131646fdb940a1eda04f0"}, - {file = "charset_normalizer-3.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:3160a0fd9754aab7d47f95a6b63ab355388d890163eb03b2d2b87ab0a30cfa59"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:38e812a197bf8e71a59fe55b757a84c1f946d0ac114acafaafaf21667a7e169e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6baf0baf0d5d265fa7944feb9f7451cc316bfe30e8df1a61b1bb08577c554f31"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8f25e17ab3039b05f762b0a55ae0b3632b2e073d9c8fc88e89aca31a6198e88f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3747443b6a904001473370d7810aa19c3a180ccd52a7157aacc264a5ac79265e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b116502087ce8a6b7a5f1814568ccbd0e9f6cfd99948aa59b0e241dc57cf739f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d16fd5252f883eb074ca55cb622bc0bee49b979ae4e8639fff6ca3ff44f9f854"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fa558996782fc226b529fdd2ed7866c2c6ec91cee82735c98a197fae39f706"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6f6c7a8a57e9405cad7485f4c9d3172ae486cfef1344b5ddd8e5239582d7355e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ac3775e3311661d4adace3697a52ac0bab17edd166087d493b52d4f4f553f9f0"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:10c93628d7497c81686e8e5e557aafa78f230cd9e77dd0c40032ef90c18f2230"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:6f4f4668e1831850ebcc2fd0b1cd11721947b6dc7c00bf1c6bd3c929ae14f2c7"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:0be65ccf618c1e7ac9b849c315cc2e8a8751d9cfdaa43027d4f6624bd587ab7e"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:53d0a3fa5f8af98a1e261de6a3943ca631c526635eb5817a87a59d9a57ebf48f"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win32.whl", hash = "sha256:a04f86f41a8916fe45ac5024ec477f41f886b3c435da2d4e3d2709b22ab02af1"}, - {file = "charset_normalizer-3.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:830d2948a5ec37c386d3170c483063798d7879037492540f10a475e3fd6f244b"}, - {file = "charset_normalizer-3.1.0-py3-none-any.whl", hash = "sha256:3d9098b479e78c85080c98e1e35ff40b4a31d8953102bb0fd7d1b6f8a2111a3d"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] [[package]] -name = "classproperties" -version = "0.2.0" -description = "property for class methods" +name = "datafiles" +version = "2.5" +description = "File-based ORM for dataclasses." category = "main" optional = false -python-versions = "*" +python-versions = "<4.0,>=3.10" files = [ - {file = "classproperties-0.2.0.tar.gz", hash = "sha256:a77e96a666898ecd697dd7f331d9ab1e38383c1edef809d953bb5f8a3ea67c2a"}, + {file = "datafiles-2.5-py3-none-any.whl", hash = "sha256:3c4b50339b698ef7096f7244233e80c5686838f0dcd4c77bfe7e0e52ddea75de"}, + {file = "datafiles-2.5.tar.gz", hash = "sha256:432498336b57aaa9e3427f3c2cf0c558b980a01d825661da9df61076b3b84f8e"}, +] + +[package.dependencies] +cached_property = ">=1.5,<3.0" +classproperties = ">=0.2,<0.3" +json-five = ">=1.1.2,<2.0.0" +minilog = ">=2.3,<3.0" +parse = ">=1.12,<2.0" +"ruamel.yaml" = ">=0.18.10,<0.20.0" +tomlkit = ">=0.10.1,<0.15.0" + +[[package]] +name = "distro" +version = "1.9.0" +description = "Distro - an OS platform information API" +category = "main" +optional = false +python-versions = ">=3.6" +files = [ + {file = "distro-1.9.0-py3-none-any.whl", hash = "sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2"}, + {file = "distro-1.9.0.tar.gz", hash = "sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"}, ] [[package]] -name = "click" -version = "8.1.3" -description = "Composable command line interface toolkit" +name = "exceptiongroup" +version = "1.3.1" +description = "Backport of PEP 654 (exception groups)" category = "main" optional = false python-versions = ">=3.7" files = [ - {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, - {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, + {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"}, + {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"}, ] [package.dependencies] -colorama = {version = "*", markers = "platform_system == \"Windows\""} +typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""} + +[package.extras] +test = ["pytest (>=6)"] [[package]] -name = "colorama" -version = "0.4.6" -description = "Cross-platform colored terminal text." +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" category = "main" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +python-versions = ">=3.8" files = [ - {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, - {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, ] [[package]] -name = "datafiles" -version = "2.1" -description = "File-based ORM for dataclasses." +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." category = "main" optional = false -python-versions = ">=3.8,<4.0" +python-versions = ">=3.8" files = [ - {file = "datafiles-2.1-py3-none-any.whl", hash = "sha256:31de48c187436bef9062efffc17fa9a42cd4fb8929d86f334413950f9e17d052"}, - {file = "datafiles-2.1.tar.gz", hash = "sha256:70728378e9313702b055c6cdeade385a170ea26a008d299f61ec360080c245a5"}, + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, ] [package.dependencies] -cached_property = ">=1.5,<2.0" -classproperties = ">=0.2,<0.3" -minilog = ">=2.1,<3.0" -parse = ">=1.12,<2.0" -"ruamel.yaml" = ">=0.17.21,<0.18.0" -tomlkit = ">=0.10.1,<0.11.0" +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] +trio = ["trio (>=0.22.0,<1.0)"] [[package]] -name = "frozenlist" -version = "1.3.3" -description = "A list-like structure which implements collections.abc.MutableSequence" +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff8bf625fe85e119553b5383ba0fb6aa3d0ec2ae980295aaefa552374926b3f4"}, - {file = "frozenlist-1.3.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dfbac4c2dfcc082fcf8d942d1e49b6aa0766c19d3358bd86e2000bf0fa4a9cf0"}, - {file = "frozenlist-1.3.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b1c63e8d377d039ac769cd0926558bb7068a1f7abb0f003e3717ee003ad85530"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7fdfc24dcfce5b48109867c13b4cb15e4660e7bd7661741a391f821f23dfdca7"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c926450857408e42f0bbc295e84395722ce74bae69a3b2aa2a65fe22cb14b99"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1841e200fdafc3d51f974d9d377c079a0694a8f06de2e67b48150328d66d5483"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f470c92737afa7d4c3aacc001e335062d582053d4dbe73cda126f2d7031068dd"}, - {file = "frozenlist-1.3.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:783263a4eaad7c49983fe4b2e7b53fa9770c136c270d2d4bbb6d2192bf4d9caf"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:924620eef691990dfb56dc4709f280f40baee568c794b5c1885800c3ecc69816"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae4dc05c465a08a866b7a1baf360747078b362e6a6dbeb0c57f234db0ef88ae0"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:bed331fe18f58d844d39ceb398b77d6ac0b010d571cba8267c2e7165806b00ce"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:02c9ac843e3390826a265e331105efeab489ffaf4dd86384595ee8ce6d35ae7f"}, - {file = "frozenlist-1.3.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9545a33965d0d377b0bc823dcabf26980e77f1b6a7caa368a365a9497fb09420"}, - {file = "frozenlist-1.3.3-cp310-cp310-win32.whl", hash = "sha256:d5cd3ab21acbdb414bb6c31958d7b06b85eeb40f66463c264a9b343a4e238642"}, - {file = "frozenlist-1.3.3-cp310-cp310-win_amd64.whl", hash = "sha256:b756072364347cb6aa5b60f9bc18e94b2f79632de3b0190253ad770c5df17db1"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b4395e2f8d83fbe0c627b2b696acce67868793d7d9750e90e39592b3626691b7"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:14143ae966a6229350021384870458e4777d1eae4c28d1a7aa47f24d030e6678"}, - {file = "frozenlist-1.3.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5d8860749e813a6f65bad8285a0520607c9500caa23fea6ee407e63debcdbef6"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23d16d9f477bb55b6154654e0e74557040575d9d19fe78a161bd33d7d76808e8"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb82dbba47a8318e75f679690190c10a5e1f447fbf9df41cbc4c3afd726d88cb"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9309869032abb23d196cb4e4db574232abe8b8be1339026f489eeb34a4acfd91"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a97b4fe50b5890d36300820abd305694cb865ddb7885049587a5678215782a6b"}, - {file = "frozenlist-1.3.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c188512b43542b1e91cadc3c6c915a82a5eb95929134faf7fd109f14f9892ce4"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:303e04d422e9b911a09ad499b0368dc551e8c3cd15293c99160c7f1f07b59a48"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:0771aed7f596c7d73444c847a1c16288937ef988dc04fb9f7be4b2aa91db609d"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:66080ec69883597e4d026f2f71a231a1ee9887835902dbe6b6467d5a89216cf6"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:41fe21dc74ad3a779c3d73a2786bdf622ea81234bdd4faf90b8b03cad0c2c0b4"}, - {file = "frozenlist-1.3.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f20380df709d91525e4bee04746ba612a4df0972c1b8f8e1e8af997e678c7b81"}, - {file = "frozenlist-1.3.3-cp311-cp311-win32.whl", hash = "sha256:f30f1928162e189091cf4d9da2eac617bfe78ef907a761614ff577ef4edfb3c8"}, - {file = "frozenlist-1.3.3-cp311-cp311-win_amd64.whl", hash = "sha256:a6394d7dadd3cfe3f4b3b186e54d5d8504d44f2d58dcc89d693698e8b7132b32"}, - {file = "frozenlist-1.3.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8df3de3a9ab8325f94f646609a66cbeeede263910c5c0de0101079ad541af332"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0693c609e9742c66ba4870bcee1ad5ff35462d5ffec18710b4ac89337ff16e27"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd4210baef299717db0a600d7a3cac81d46ef0e007f88c9335db79f8979c0d3d"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:394c9c242113bfb4b9aa36e2b80a05ffa163a30691c7b5a29eba82e937895d5e"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6327eb8e419f7d9c38f333cde41b9ae348bec26d840927332f17e887a8dcb70d"}, - {file = "frozenlist-1.3.3-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e24900aa13212e75e5b366cb9065e78bbf3893d4baab6052d1aca10d46d944c"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:3843f84a6c465a36559161e6c59dce2f2ac10943040c2fd021cfb70d58c4ad56"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:84610c1502b2461255b4c9b7d5e9c48052601a8957cd0aea6ec7a7a1e1fb9420"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:c21b9aa40e08e4f63a2f92ff3748e6b6c84d717d033c7b3438dd3123ee18f70e"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:efce6ae830831ab6a22b9b4091d411698145cb9b8fc869e1397ccf4b4b6455cb"}, - {file = "frozenlist-1.3.3-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:40de71985e9042ca00b7953c4f41eabc3dc514a2d1ff534027f091bc74416401"}, - {file = "frozenlist-1.3.3-cp37-cp37m-win32.whl", hash = "sha256:180c00c66bde6146a860cbb81b54ee0df350d2daf13ca85b275123bbf85de18a"}, - {file = "frozenlist-1.3.3-cp37-cp37m-win_amd64.whl", hash = "sha256:9bbbcedd75acdfecf2159663b87f1bb5cfc80e7cd99f7ddd9d66eb98b14a8411"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:034a5c08d36649591be1cbb10e09da9f531034acfe29275fc5454a3b101ce41a"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba64dc2b3b7b158c6660d49cdb1d872d1d0bf4e42043ad8d5006099479a194e5"}, - {file = "frozenlist-1.3.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:47df36a9fe24054b950bbc2db630d508cca3aa27ed0566c0baf661225e52c18e"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:008a054b75d77c995ea26629ab3a0c0d7281341f2fa7e1e85fa6153ae29ae99c"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:841ea19b43d438a80b4de62ac6ab21cfe6827bb8a9dc62b896acc88eaf9cecba"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e235688f42b36be2b6b06fc37ac2126a73b75fb8d6bc66dd632aa35286238703"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ca713d4af15bae6e5d79b15c10c8522859a9a89d3b361a50b817c98c2fb402a2"}, - {file = "frozenlist-1.3.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ac5995f2b408017b0be26d4a1d7c61bce106ff3d9e3324374d66b5964325448"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4ae8135b11652b08a8baf07631d3ebfe65a4c87909dbef5fa0cdde440444ee4"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4ea42116ceb6bb16dbb7d526e242cb6747b08b7710d9782aa3d6732bd8d27649"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:810860bb4bdce7557bc0febb84bbd88198b9dbc2022d8eebe5b3590b2ad6c842"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ee78feb9d293c323b59a6f2dd441b63339a30edf35abcb51187d2fc26e696d13"}, - {file = "frozenlist-1.3.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0af2e7c87d35b38732e810befb9d797a99279cbb85374d42ea61c1e9d23094b3"}, - {file = "frozenlist-1.3.3-cp38-cp38-win32.whl", hash = "sha256:899c5e1928eec13fd6f6d8dc51be23f0d09c5281e40d9cf4273d188d9feeaf9b"}, - {file = "frozenlist-1.3.3-cp38-cp38-win_amd64.whl", hash = "sha256:7f44e24fa70f6fbc74aeec3e971f60a14dde85da364aa87f15d1be94ae75aeef"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:2b07ae0c1edaa0a36339ec6cce700f51b14a3fc6545fdd32930d2c83917332cf"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ebb86518203e12e96af765ee89034a1dbb0c3c65052d1b0c19bbbd6af8a145e1"}, - {file = "frozenlist-1.3.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:5cf820485f1b4c91e0417ea0afd41ce5cf5965011b3c22c400f6d144296ccbc0"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c11e43016b9024240212d2a65043b70ed8dfd3b52678a1271972702d990ac6d"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8fa3c6e3305aa1146b59a09b32b2e04074945ffcfb2f0931836d103a2c38f936"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:352bd4c8c72d508778cf05ab491f6ef36149f4d0cb3c56b1b4302852255d05d5"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:65a5e4d3aa679610ac6e3569e865425b23b372277f89b5ef06cf2cdaf1ebf22b"}, - {file = "frozenlist-1.3.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e2c1185858d7e10ff045c496bbf90ae752c28b365fef2c09cf0fa309291669"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f163d2fd041c630fed01bc48d28c3ed4a3b003c00acd396900e11ee5316b56bb"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:05cdb16d09a0832eedf770cb7bd1fe57d8cf4eaf5aced29c4e41e3f20b30a784"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:8bae29d60768bfa8fb92244b74502b18fae55a80eac13c88eb0b496d4268fd2d"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:eedab4c310c0299961ac285591acd53dc6723a1ebd90a57207c71f6e0c2153ab"}, - {file = "frozenlist-1.3.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3bbdf44855ed8f0fbcd102ef05ec3012d6a4fd7c7562403f76ce6a52aeffb2b1"}, - {file = "frozenlist-1.3.3-cp39-cp39-win32.whl", hash = "sha256:efa568b885bca461f7c7b9e032655c0c143d305bf01c30caf6db2854a4532b38"}, - {file = "frozenlist-1.3.3-cp39-cp39-win_amd64.whl", hash = "sha256:cfe33efc9cb900a4c46f91a5ceba26d6df370ffddd9ca386eb1d4f0ad97b9ea9"}, - {file = "frozenlist-1.3.3.tar.gz", hash = "sha256:58bcc55721e8a90b88332d6cd441261ebb22342e238296bb330968952fbb3a6a"}, + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, ] +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = ">=1.0.0,<2.0.0" +idna = "*" + +[package.extras] +brotli = ["brotli", "brotlicffi"] +cli = ["click (>=8.0.0,<9.0.0)", "pygments (>=2.0.0,<3.0.0)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (>=1.0.0,<2.0.0)"] +zstd = ["zstandard (>=0.18.0)"] + [[package]] name = "idna" -version = "3.4" +version = "3.18" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.9" files = [ - {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, - {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, + {file = "idna-3.18-py3-none-any.whl", hash = "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2"}, + {file = "idna-3.18.tar.gz", hash = "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848"}, ] +[package.extras] +all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.3.0" +description = "brain-dead simple config-ini parsing" +category = "dev" +optional = false +python-versions = ">=3.10" +files = [ + {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"}, + {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"}, +] + +[[package]] +name = "jiter" +version = "0.15.0" +description = "Fast iterable JSON parser." +category = "main" +optional = false +python-versions = ">=3.9" +files = [ + {file = "jiter-0.15.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:edebcf7d1f601199084bb6e844d7dc67e03e04f6ac786b0332d616635c4ff7a4"}, + {file = "jiter-0.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9f924585cdacf631cd382b657966847bb537bf9ed0a6f9b991da5f05a631480f"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abbf258599526ad0326fe51e252e24f2bd6f24f1852681b4b78feda3808f1d18"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7c468136b8bd6bb18c8786e4236a1fa27362f24cb23450ba0cb204ab379b8e6f"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:05906b93d72f03339e6bb7cf8dc10ebda64a0266126eed6beba79e20abcf5fd4"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:30ce785d2adb8e32c3f7741442370a74834ec4c01f3c48f0750227a0b4ef27d6"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fd73e3da91a0a722d67165e849ce2cdc10de0e0d48738c142be8c6c5f310f4c"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:ceb8fc27d38793f9c97149be8302720c5b22e5c195a37bf2c45dc36c4600a512"}, + {file = "jiter-0.15.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d726e3ceeb337191324b49de298142f27c3ad10886341555d1d5315b5f252c6a"}, + {file = "jiter-0.15.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:2c8aea7781d2a372227871de4e1a1332aa96f5a89fd76c5e835dafdbad102887"}, + {file = "jiter-0.15.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cf4bd113a69c0a740e27cb962ce10630c36d2b8f59d759a651b955ee9d18a823"}, + {file = "jiter-0.15.0-cp310-cp310-win32.whl", hash = "sha256:d92a5cd21fdb083931d546c207aa29633787c5dc5b02daab2d32b843f88a2c53"}, + {file = "jiter-0.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:e58585a58209d72691ce2d62a9147445f5a87beb0bde97fde284c96ae392a3d1"}, + {file = "jiter-0.15.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0f862193b8696249d22ec433e85fd2ab0ad9596bc3e45e6c0bc55e8aeba97be2"}, + {file = "jiter-0.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1303d4d68a9b051ea90502402063ecf3807da00ad2affa19ca1ae3b90b3c5f67"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:392b8ab019e5502d08aff85c6272209c24bc2cbe706ea82a56368f524236614a"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:773b6eb282ce11ee19f05f6b2d4404fa308e5bbd353b0b80a0262caad6db2cd7"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d2c0c44d569ce0f2850f5c926f8caeb5f245fbc84475aeb36efccc2103e6dbd"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:032396229564bca02440396bd327710719f724f5e7b7e9f7a8eb3faa4a2c2281"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3d37768fce7f88dd2a8c6091f2325dea27d30d30d5c6e7a1c0f0af77723b708"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:2c9cb907439d20bd0c7d7565ca01ee52234203208433749bae5b516907526928"}, + {file = "jiter-0.15.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9100ddbec09741cc66feb0fc6773f8bdbd0e3c345689368f260082ff85dcc0cd"}, + {file = "jiter-0.15.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ae1b0d82ac2d987f9ea512b1c9adfcc71a28de3dea3a6039b54d76cffda9901e"}, + {file = "jiter-0.15.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:8020c99ec13a7db2b6f96cbe82ef4721c88b426a4892f27478044af0284615ef"}, + {file = "jiter-0.15.0-cp311-cp311-win32.whl", hash = "sha256:42bfb257930800cf43e7c62c832402c704ab60797c992faf88d20e903eac8f32"}, + {file = "jiter-0.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:860a74063284a2ae9bfedd694f299cc2c68e2696c5f3d440cc9d18bb81b9dd04"}, + {file = "jiter-0.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:37a10c377ce3a4a85f4a67f28b7afe093154cde77eaf248a72e856aa08b4d865"}, + {file = "jiter-0.15.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0e90a1c315a0226ec822d973817967f9223b7701546c8c2a7913e7ab0926294d"}, + {file = "jiter-0.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8c9004af7c8d67cce7f1aae1026fb55607f4aa600710d08ede3a3ce4aeefe7e0"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c210f8b35dc6f30aafd4b4365ca89b9d1189f21ab49b8e68fa6322a847aef138"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5f30bae8bc1c2d613e28e5af3e8cceb09b742f1c8a8a5f839fb67afaffc03b61"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c60e71b6d10cfc284c9bf36bd885e8d44c46f688ce50aa91b5edd90181dea687"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ab068bce62a45aa3e7367eceaffb5dde60b7eb853be8dece45132e3d0ff4879"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa248c9eb220197d363f688818dac2fd4b2f0cd7d843ca7105d652034823427d"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:2a77aadd57cac1682e4401a72724d2796d89a4ba129b1a5812aa94ee480826eb"}, + {file = "jiter-0.15.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2ae901f3a55bfafdde31d289590fa25e3245735a2b1e8c7cc15871710a002871"}, + {file = "jiter-0.15.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:f0b271b462769543716f92d3a4f90527df6ef5ed05ee95ec4137f513e21e1b77"}, + {file = "jiter-0.15.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:2fb6a5d26af81fc0f00f9360a891e05cf755e149bba391c4d563adc54812973d"}, + {file = "jiter-0.15.0-cp312-cp312-win32.whl", hash = "sha256:c2f6bb8b5216ab9e7873bc08b5d7bef2b8abbb578a3069bf1cd14a45d71d771d"}, + {file = "jiter-0.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:40b2c7e92c44a84d748d21706c68dc6ff8161d80b59c99d774721a0d2317d7c7"}, + {file = "jiter-0.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:cc0bc345cf2df9d1c00ac443f50d543c1ccfa8b0422cb85b1ab70d681c0b255b"}, + {file = "jiter-0.15.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1c11465f97e2abf45a014b83b730222f8f1c5335e802c7055a67d50de6f1f4e3"}, + {file = "jiter-0.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e7b1776f0797956c509e123d0952d10d293a9492dea9f288ab9570ec01d1a5"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:351a341c2105aa430b7047e30f1bf7975f6313b00165d3fc07be2edaf741f279"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4ab395feec8d249ec4044e228e98a7033f043426a265df439dc3698823f0a4e4"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a2a438005b6f22d0273413484d6094d7c2c5d10ec1b3a3bf128e0d1d3ba53258"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f18f85e4218d1b40f000f42a92239a7a61a902cd42c65e6c360dbd17dcb20894"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d1aa62e277fc1cbd80e6deacae6f4d983b41b3d7728e0645c5d741a6149bba45"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:6550fa135c7deb8ead6af49ed7ff648532ea8334a1447fe34a36315ef79c5c29"}, + {file = "jiter-0.15.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:066f8f33f18b2419cd8213b2436fa7fbc9c499f315971cfa3ce1f9820c001b1b"}, + {file = "jiter-0.15.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:75e8a04e91432dde9f1838373cf93d23726c79d3e908d319acf0e796f85592e7"}, + {file = "jiter-0.15.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:a97261f1fccb8e50ecd2890a96e46efdc3f57c80a197324c6777827231eca712"}, + {file = "jiter-0.15.0-cp313-cp313-win32.whl", hash = "sha256:c77496cb10bd7549690fbbab3e5ec05857b83e49276f4a9423a766ddd2afcd4c"}, + {file = "jiter-0.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:b15741f501469009ae0ae90b7147958a664a7dede40aa7ff174a8a4645f546d0"}, + {file = "jiter-0.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:5d6a60072b44c3c2b797a7ddcbcbbf2b34ea3cfd4721580fbfd2a09d9d9b84ba"}, + {file = "jiter-0.15.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ef1fd24d9413f6209e00d3d5a453e67acfe004a25cc6c8e8484faed4311ab9e8"}, + {file = "jiter-0.15.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:144f8e72cb53dab146347b91cceac01f5481237f2b93b4a339a1ee8f8878b67c"}, + {file = "jiter-0.15.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553fcac2ef2cb990877f9fc0833b8b629a3e6a5670b6b5fd58219b41a653ddc4"}, + {file = "jiter-0.15.0-cp313-cp313t-win_amd64.whl", hash = "sha256:774f93f65031856bf14ad9f59bdcab8b8cad501e5ceabd51ba3525f76937a25b"}, + {file = "jiter-0.15.0-cp313-cp313t-win_arm64.whl", hash = "sha256:f1e1754960f38ec40613a07e5e372df67acb3b890fb383b6fb3de3e49ddbf3c7"}, + {file = "jiter-0.15.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:ac0d9ddea4350974be7a221fc25895f251a8fee748c889bdced2141c0fec1a49"}, + {file = "jiter-0.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:01a8222cf05ab1128e239421156c207949808acaaea2bdfd33130ae666786e86"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:182226cbc930c9fab81bc2e41a4da672f89539906dadb05e75670ac07b94f71f"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:71683c38c825452999b5717fcae07ea708e8c93003e808be4319c1b02e3d176e"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30f2218e6a9e5c18bc10fe6d41ac189c442c88eacf11bad9f28ef95a9bef00e6"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5157de9f76eb4bc5ea74a1219366a25f945ad305641d74e04f59c54087091aa9"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90c5db5527c221249a876160663ab891ace358c17f7b9c93ec1478b7f0550e5c"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:3e4540b8e74e4268811ac05db226a6a128ff572e7e0ce3f1163b693cadb184cd"}, + {file = "jiter-0.15.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:62ebd14e47e9aed9df4472afcb2663668ce4d74891cd54f86bf6e44029d6dc89"}, + {file = "jiter-0.15.0-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:0be6f5ad41a809f303f416d17cec92a7a725902fb9b4f3de3d19362ac0ef8554"}, + {file = "jiter-0.15.0-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:813dfbb17d65328bf86e5f0905dd277ba2265d3ca20556e86c0c7035b7182e5a"}, + {file = "jiter-0.15.0-cp314-cp314-win32.whl", hash = "sha256:50e51156192722a9c58db112837d3f8ef96fb3c5ecc14e95f409134b08b158ec"}, + {file = "jiter-0.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:30ce1a5d16b5641dc935d50ef775af6a0871e3d14ab05d6fc54dff371b78e558"}, + {file = "jiter-0.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:510c8b3c17a0ed9ac69850c0438dada3c9b82d9c4d589fcb62002a5a9cf3a866"}, + {file = "jiter-0.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7553333dd0930c104a5a0db8df72bf7219fe663d731383b576bb6ed6351c984d"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f2143ab06181d2b029eedcb6af3cebe95f11bbac62441781860f98ee9330a6a6"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6eac374c5c975709b69c10f09afd199df74150172156ad10c8d4fd785b7da995"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b3b3b775e33d3bfaec9899edc526ae97b0da0bf9d071a46124ba419149a414f8"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eda3071db3346334beae1360b46da4606da57bf3528c167b3c38533afaf9f2c5"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6694a173ecabc12eb60efbc0b474464ead1951ff65cd8b1e72100715c64512b"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:a254e10b593624d230c365b6d616b22ca0ad65e63a16e6631c2b3466022e6ba8"}, + {file = "jiter-0.15.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d8d2955167274e15d79a7a020afdd9b39c990eb80b2d89fca695d92dcfdd38ec"}, + {file = "jiter-0.15.0-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:acf4ee4d1fc55917239fe72972fb292dd773055d05eb040d36f4326e02cc2c0e"}, + {file = "jiter-0.15.0-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:e7196e56f1cd69af1dbb07dff02dcfb260a50b45a82d409d92a06fedb32473b5"}, + {file = "jiter-0.15.0-cp314-cp314t-win32.whl", hash = "sha256:7f6163c0f10b055245f814dcc59f4818da60dfe72f3e72ab89fc24b6bd5e9c52"}, + {file = "jiter-0.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:980c256edb05b78a111b99c4de3b1d32e31634b867fd1fc2cf726e7b7bba9854"}, + {file = "jiter-0.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:66b1880df2d01e206e8339769d1c7c1753bcb653efd6289e203f6f24ebada0c0"}, + {file = "jiter-0.15.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:04b400bbf8c9efb03d9bdd976475c919c1d85593b04b9fff7ae234065daf87ae"}, + {file = "jiter-0.15.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:25ffbe229aa8cd98c28879d8aa1a6e34ae77992ab984a65fba800859dab16269"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5607e6013ed7e6b0ec9661e467b7ffde0aa7ab36833a04850f26fcf88ed4845b"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:50164d7610c00e7cd913a873fce30b6beeebf4b37e53983e33f22de4c900f6b8"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ab596fa3837e91e7e6a31b5f639988bfc6a35d1f915ac3932d946062219d588f"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d72d8af5c1013656a8870c866660627d1a75bc185814ee022c8533caa1de88ae"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c84c1b7be454b0c16f8499b4ebfbfd82ea5cca6527cceefcbbc06a7557b5ed2e"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:d636d5095155afd364247f65070fab7beda13498d7ff4de331046e704ab9657f"}, + {file = "jiter-0.15.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7d3d6683288c11cbab50e865f2e2f13950179aa45410e30b2cfbd3fb7b0177bf"}, + {file = "jiter-0.15.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7ce8902f939970048b233087082e7bb829db29375811c7ad50687b8624c6fd08"}, + {file = "jiter-0.15.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4363818355dbc70ae1a8e9eaba9de350d93ede4ff6992b8f8eb8cbb6e5122d42"}, + {file = "jiter-0.15.0-cp39-cp39-win32.whl", hash = "sha256:8f7e9bc0f1135039b22ee6eab588d42df1ce55842b30740a352885eb267bd941"}, + {file = "jiter-0.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:1c15024a3d892223b18f597c86d59387249dc396590844ce6b9f6131d1093bae"}, + {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:411fa4dfa5a7ae3d11491027ffb9beadec3996010a986862db70d91abba1c750"}, + {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:2b0074e2f56eb2dacca1689760fd2852a068f85a0547a157b82cb4cafeb6768b"}, + {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:913d02d29c9606643418d9ccfc3b72492ab25a6bf7889934e09a3490f8d3438b"}, + {file = "jiter-0.15.0-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b15d3ec9b0449c40e85319bdb4caa8b77ab526e74f5532ed94bec15e2f66822c"}, + {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:631f13a3d04e97d4e083993b10f4b99530e3a10d953e2eb5e196b7dc7f812ce0"}, + {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:b6c0ffae686c39bf3737be60793783267628783ea42545632c10b291105aee45"}, + {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d54fb5b31dea401a41af3f8a7d2512e9b6a6a005491e6166c7e4ffab9639a9c"}, + {file = "jiter-0.15.0-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54d5d6090cdc1b7c9e780dfb04949a990adb1e301a2fc0bbcee7de4638d33f9a"}, + {file = "jiter-0.15.0.tar.gz", hash = "sha256:4251acc80e2b7c9b7b8823456ea0fceeb0734dac2df7636d3c711b38476b5a76"}, +] + +[[package]] +name = "json-five" +version = "1.1.2" +description = "A JSON5 parser that, among other features, supports round-trip preservation of comments" +category = "main" +optional = false +python-versions = ">=3.8.0" +files = [ + {file = "json_five-1.1.2-py3-none-any.whl", hash = "sha256:b10608e6af9730b9e1c1a099e71f86acb905991f830957a6b25f53bd4826fe8f"}, + {file = "json_five-1.1.2.tar.gz", hash = "sha256:1c5b1bae6039bc44632d009b32338d4b59ab765c596d96577b52cc3dadc936e2"}, +] + +[package.dependencies] +regex = "*" +sly = ">=0.5" + [[package]] name = "loguru" version = "0.6.0" @@ -439,443 +402,675 @@ dev = ["Sphinx (>=4.1.1)", "black (>=19.10b0)", "colorama (>=0.3.4)", "docutils [[package]] name = "minilog" -version = "2.1" +version = "2.3.1" description = "Minimalistic wrapper for Python logging." category = "main" optional = false -python-versions = ">=3.7,<4.0" -files = [ - {file = "minilog-2.1-py3-none-any.whl", hash = "sha256:0c48879cc9e72f0127aa2c36b522dc6fa10fa8532956197436b491d31617d5d5"}, - {file = "minilog-2.1.tar.gz", hash = "sha256:2048a8d381b36ef5f146fb9a657e627729411f8e2ed0047e2c1286cf8e3e58d7"}, -] - -[[package]] -name = "multidict" -version = "6.0.4" -description = "multidict implementation" -category = "main" -optional = false -python-versions = ">=3.7" +python-versions = "<4.0,>=3.8" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "minilog-2.3.1-py3-none-any.whl", hash = "sha256:1a679fefe6140ce1d59c3246adc991f9eb480169e5a6c54d2be9023ee459dc30"}, + {file = "minilog-2.3.1.tar.gz", hash = "sha256:4b602572c3bcdd2d8f00d879f635c0de9e632d5d0307e131c91074be8acf444e"}, ] [[package]] name = "nest-asyncio" -version = "1.5.6" +version = "1.6.0" description = "Patch asyncio to allow nested event loops" category = "main" optional = false python-versions = ">=3.5" files = [ - {file = "nest_asyncio-1.5.6-py3-none-any.whl", hash = "sha256:b9a953fb40dceaa587d109609098db21900182b16440652454a146cffb06e8b8"}, - {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, ] [[package]] name = "openai" -version = "0.27.2" -description = "Python client library for the OpenAI API" +version = "2.43.0" +description = "The official Python library for the openai API" category = "main" optional = false -python-versions = ">=3.7.1" +python-versions = ">=3.9" files = [ - {file = "openai-0.27.2-py3-none-any.whl", hash = "sha256:6df674cf257e9e0504f1fd191c333d3f6a2442b13218d0eccf06230eb24d320e"}, - {file = "openai-0.27.2.tar.gz", hash = "sha256:5869fdfa34b0ec66c39afa22f4a0fb83a135dff81f6505f52834c6ab3113f762"}, + {file = "openai-2.43.0-py3-none-any.whl", hash = "sha256:65a670b54fadf2268c9e1330133373c963eb779ee969e5cbad419ec2c21dce97"}, + {file = "openai-2.43.0.tar.gz", hash = "sha256:e74d238200a26868977002190fb6631613480a93dfe0c9c982e77021ed60a017"}, ] [package.dependencies] -aiohttp = "*" -requests = ">=2.20" -tqdm = "*" +anyio = ">=3.5.0,<5" +distro = ">=1.7.0,<2" +httpx = ">=0.23.0,<1" +jiter = ">=0.10.0,<1" +pydantic = ">=1.9.0,<3" +sniffio = "*" +tqdm = ">4" +typing-extensions = ">=4.14,<5" [package.extras] -datalib = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] -dev = ["black (>=21.6b0,<22.0)", "pytest (>=6.0.0,<7.0.0)", "pytest-asyncio", "pytest-mock"] -embeddings = ["matplotlib", "numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "plotly", "scikit-learn (>=1.0.2)", "scipy", "tenacity (>=8.0.1)"] -wandb = ["numpy", "openpyxl (>=3.0.7)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)", "wandb"] +aiohttp = ["aiohttp", "httpx-aiohttp (>=0.1.9)"] +datalib = ["numpy (>=1)", "pandas (>=1.2.3)", "pandas-stubs (>=1.1.0.11)"] +realtime = ["websockets (>=13,<16)"] +voice-helpers = ["numpy (>=2.0.2)", "sounddevice (>=0.5.1)"] + +[[package]] +name = "packaging" +version = "26.2" +description = "Core utilities for Python packages" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"}, + {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"}, +] [[package]] name = "parse" -version = "1.19.0" +version = "1.22.1" description = "parse() is the opposite of format()" category = "main" optional = false python-versions = "*" files = [ - {file = "parse-1.19.0.tar.gz", hash = "sha256:9ff82852bcb65d139813e2a5197627a94966245c897796760a3a2a8eb66f020b"}, + {file = "parse-1.22.1-py2.py3-none-any.whl", hash = "sha256:20f0925a46f06602485ac90d751764d0697fd8455aaa97489ba8953a4b66de32"}, + {file = "parse-1.22.1.tar.gz", hash = "sha256:d3a4740ec3da338e2b258b2d69741b731eadfddca59e24a14bc4ee5fce38c911"}, ] [[package]] -name = "plunkylib" -version = "0.1.5" -description = "plunkylib - Python LLM User Navigation Kit via YAML" +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +category = "dev" +optional = false +python-versions = ">=3.9" +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "pydantic" +version = "2.13.4" +description = "Data validation using Python type hints" category = "main" optional = false -python-versions = ">=3.10,<4.0" +python-versions = ">=3.9" files = [ - {file = "plunkylib-0.1.5-py3-none-any.whl", hash = "sha256:b76639b0238fd8359cd0911dec31ae5f0ca6165cb2799a93d5effd92cffacba0"}, - {file = "plunkylib-0.1.5.tar.gz", hash = "sha256:cae76049a05540a20824edee7bf08a940e29eb81701ee71719f38c91a9b31211"}, + {file = "pydantic-2.13.4-py3-none-any.whl", hash = "sha256:45a282cde31d808236fd7ea9d919b128653c8b38b393d1c4ab335c62924d9aba"}, + {file = "pydantic-2.13.4.tar.gz", hash = "sha256:c40756b57adaa8b1efeeced5c196f3f3b7c435f90e84ea7f443901bec8099ef6"}, ] [package.dependencies] -datafiles = ">=2.0,<3.0" -loguru = ">=0.6.0,<0.7.0" -nest-asyncio = ">=1.5.6,<2.0.0" -openai = ">=0.27.2,<0.28.0" -python-dotenv = ">=1.0.0,<2.0.0" -typer = ">=0.7.0,<0.8.0" +annotated-types = ">=0.6.0" +pydantic-core = "2.46.4" +typing-extensions = ">=4.14.1" +typing-inspection = ">=0.4.2" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata"] [[package]] -name = "python-dotenv" -version = "1.0.0" -description = "Read key-value pairs from a .env file and set them as environment variables" +name = "pydantic-core" +version = "2.46.4" +description = "Core functionality for Pydantic validation and serialization" category = "main" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +files = [ + {file = "pydantic_core-2.46.4-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a396dcc17e5a0b164dbe026896245a4fa9ff402edca1dff0be3d53a517f74de4"}, + {file = "pydantic_core-2.46.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:da4b951fe36dc7c3a1ccb4e3cd1747c3542b8c9ceede8fc86cae054e764485f5"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bb63e0198ca18aad131c089b9204c23079c3afa95487e561f4c522d519e55aba"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f47286a97f0bc9b8859519809077b91b2cefe4ae47fcbf5e466a009c1c5d742b"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:905a0ed8ea6f2d61c1738835f99b699348d7857379083e5fc497fa0c967a407c"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea793e075b70290d89d8142074262885d3f7da19634845135751bd6344f73b50"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:395aebd9183f9d112f569aeb5b2214d1a10a33bec8456447f7fbdfa51d38d4cd"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:b078afbc25f3a1436c7a1d2cd3e322497ee99615ba97c563566fdf46aff1ee01"}, + {file = "pydantic_core-2.46.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f747929cf940cddb5b3668a390056ddd5ba2e5010615ea2dcf4f9c4f3ab8791d"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:daa27d92c36f24388fe3ad306b174781c747627f134452e4f128ea00ce1fe8c4"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:19e51f073cd3df251856a8a4189fbdf1de4012c3ebacfb1884f94f1eb406079f"}, + {file = "pydantic_core-2.46.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1747f85cee84c26985853c6f3d9bd3e75da5212912443fa111c113b9c246f39"}, + {file = "pydantic_core-2.46.4-cp310-cp310-win32.whl", hash = "sha256:2f84c03c8607173d16b5a854ec68a2f9079ae03237a54fb506d13af47e1d018d"}, + {file = "pydantic_core-2.46.4-cp310-cp310-win_amd64.whl", hash = "sha256:8358a950c8909158e3df31538a7e4edc2d7265a7c54b47f0864d9e5bae9dcebf"}, + {file = "pydantic_core-2.46.4-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:0e96592440881c74a213e5ad528e2b24d3d4f940de2766bed9010ab1d9e51594"}, + {file = "pydantic_core-2.46.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e0d65b8c354be7fb5f720c3caa8bc940bc2d20ce749c8e06135f07f8ed95dd7c"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bfb192b3f4b9e8a89b6277b6ce787564f62cfd272055f6e685726b111dc7826"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9037063db01f09b09e237c282b6792bd4da634b5402c4e7f0c61effed7701a04"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fc010ab034c8c7452522748bf937df58020d256ccae0874463d1f4d01758af8e"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8c5dac79fa1614d1e06ca695109c6105923bd9c7d1d6c918d4e637b7e6b32fd3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9fa868638bf362d3d138ea55829cefb3d5f4b0d7f142234382a15e2485dbec4"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:17299feefe090f2caa5b8e37222bb5f663e4935a8bfa6931d4102e5df1a9f398"}, + {file = "pydantic_core-2.46.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4c63ebc82684aa89d9a3bcbd13d515b3be44250dc68dd3bd81526c1cb31286c3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aaa2a54443eff1950ba5ddc6b6ccda0d9c84a364276a62f969bdf2a390650848"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:18e5ceec2ab67e6d5f1a9085e5a24c9c4e2ac4545730bfe668680bca05e555f3"}, + {file = "pydantic_core-2.46.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a0f62d0a58f4e7da165457e995725421e0064f2255d8eccebc49f41bbc23b109"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win32.whl", hash = "sha256:041bde0a48fd37cf71cab1c9d56d3e8625a3793fef1f7dd232b3ff37e978ecda"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win_amd64.whl", hash = "sha256:6f2eeda33a839975441c86a4119e1383c50b47faf0cbb5176985565c6bb02c33"}, + {file = "pydantic_core-2.46.4-cp311-cp311-win_arm64.whl", hash = "sha256:14f4c5d6db102bd796a627bbb3a17b4cf4574b9ae861d8b7c9a9661c6dd3362d"}, + {file = "pydantic_core-2.46.4-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:3245406455a5d98187ec35530fd772b1d799b26667980872c8d4614991e2c4a2"}, + {file = "pydantic_core-2.46.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:962ccbab7b642487b1d8b7df90ef677e03134cf1fd8880bf698649b22a69371f"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8233f2947cf85404441fd7e0085f53b10c93e0ee78611099b5c7237e36aacbf7"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:3a233125ac121aa3ffba9a2b59edfc4a985a76092dc8279586ab4b71390875e7"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5b712b53160b79a5850310b912a5ef8e57e56947c8ad690c227f5c9d7e561712"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9401557acd873c3a7f3eb9383edef8ac4968f9510e340f4808d427e75667e7b4"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:926c9541b14b12b1681dca8a0b75feb510b06c6341b70a8e500c2fdcff837cce"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:56cb4851bcaf3d117eddcef4fe66afd750a50274b0da8e22be256d10e5611987"}, + {file = "pydantic_core-2.46.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c68fcd102d71ea85c5b2dfac3f4f8476eff42a9e078fd5faefff6d145063536b"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b2f69dec1725e79a012d920df1707de5caf7ed5e08f3be4435e25803efc47458"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:8d0820e8192167f80d88d64038e609c31452eeca865b4e1d9950a27a4609b00b"}, + {file = "pydantic_core-2.46.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fbdb89b3e1c94a30cc5edfce477c6e6a5dc4d8f84665b455c27582f211a1c72c"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win32.whl", hash = "sha256:9aa768456404a8bf48a4406685ac2bec8e72b62c69313734fa3b73cf33b3a894"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win_amd64.whl", hash = "sha256:e9c26f834c65f5752f3f06cb08cb86a913ceb7274d0db6e267808a708b46bc89"}, + {file = "pydantic_core-2.46.4-cp312-cp312-win_arm64.whl", hash = "sha256:4fc73cb559bdb54b1134a706a2802a4cddd27a0633f5abb7e53056268751ac6a"}, + {file = "pydantic_core-2.46.4-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:5d5902252db0d3cedf8d4a1bc68f70eeb430f7e4c7104c8c476753519b423008"}, + {file = "pydantic_core-2.46.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:c94f0688e7b8d0a67abf40e57a7eaaecd17cc9586706a31b76c031f63df052b4"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f027324c56cd5406ca49c124b0db10e56c69064fec039acc571c29020cc87c76"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e739fee756ba1010f8bcccb534252e85a35fe45ae92c295a06059ce58b74ccd3"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9d56801be94b86a9da183e5f3766e6310752b99ff647e38b09a9500d88e46e76"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2412e734dcb48da14d4e4006b82b46b74f2518b8a26ee7e58c6844a6cd6d03c4"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9551187363ffc0de2a00b2e47c25aeaeb1020b69b668762966df15fc5659dd5a"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:0186750b482eefa11d7f435892b09c5c606193ef3375bcf94aa00ae6bfb66262"}, + {file = "pydantic_core-2.46.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:5855698a4856556d86e8e6cd8434bc3ac0314ee8e12089ae0e143f64c6256e4e"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:cbaf13819775b7f769bf4a1f066cb6df7a28d4480081a589828ef190226881cd"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:633147d34cf4550417f12e2b1a0383973bdf5cdfde212cb09e9a581cf10820be"}, + {file = "pydantic_core-2.46.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:82cf5301172168103724d49a1444d3378cb20cdee30b116a1bd6031236298a5d"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win32.whl", hash = "sha256:9fa8ae11da9e2b3126c6426f147e0fba88d96d65921799bb30c6abd1cb2c97fb"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win_amd64.whl", hash = "sha256:6b3ace8194b0e5204818c92802dcdca7fc6d88aabbb799d7c795540d9cd6d292"}, + {file = "pydantic_core-2.46.4-cp313-cp313-win_arm64.whl", hash = "sha256:184c081504d17f1c1066e430e117142b2c77d9448a97f7b65c6ac9fd9aee238d"}, + {file = "pydantic_core-2.46.4-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:428e04521a40150c85216fc8b85e8d39fece235a9cf5e383761238c7fa9b96fb"}, + {file = "pydantic_core-2.46.4-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:23ace664830ee0bfe014a0c7bc248b1f7f25ed7ad103852c317624a1083af462"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce5c1d2a8b27468f433ca974829c44060b8097eedc39933e3c206a90ee49c4a9"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:7283d57845ecf5a163403eb0702dfc220cc4fbdd18919cb5ccea4f95ee1cdab4"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8daafc69c93ee8a0204506a3b6b30f586ef54028f52aeeeb5c4cfc5184fd5914"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd2213145bcc2ba85884d0ac63d222fece9209678f77b9b4d76f054c561adb28"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7a5f930472650a82629163023e630d160863fce524c616f4e5186e5de9d9a49b"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:c1b3f518abeca3aa13c712fd202306e145abf59a18b094a6bafb2d2bbf59192c"}, + {file = "pydantic_core-2.46.4-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1a7dd0b3ee80d90150e3495a3a13ac34dbcbfd4f012996a6a1d8900e91b5c0fb"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_aarch64.whl", hash = "sha256:3fb702cd90b0446a3a1c5e470bfa0dd23c0233b676a9099ddcc964fa6ca13898"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_armv7l.whl", hash = "sha256:b8458003118a712e66286df6a707db01c52c0f52f7db8e4a38f0da1d3b94fc4e"}, + {file = "pydantic_core-2.46.4-cp314-cp314-musllinux_1_1_x86_64.whl", hash = "sha256:372429a130e469c9cd698925ce5fc50940b7a1336b0d82038e63d5bbc4edc519"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win32.whl", hash = "sha256:85bb3611ff1802f3ee7fdd7dbff26b56f343fb432d57a4728fdd49b6ef35e2f4"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win_amd64.whl", hash = "sha256:811ff8e9c313ab425368bcbb36e5c4ebd7108c2bbf4e4089cfbb0b01eff63fac"}, + {file = "pydantic_core-2.46.4-cp314-cp314-win_arm64.whl", hash = "sha256:bfec22eab3c8cc2ceec0248aec886624116dc079afa027ecc8ad4a7e62010f8a"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:af8244b2bef6aaad6d92cda81372de7f8c8d36c9f0c3ea36e827c60e7d9467a0"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:5a4330cdbc57162e4b3aa303f588ba752257694c9c9be3e7ebb11b4aca659b5d"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:29c61fc04a3d840155ff08e475a04809278972fe6aef51e2720554e96367e34b"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c50f2528cf200c5eed56faf3f4e22fcd5f38c157a8b78576e6ba3168ec35f000"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0cbe8b01f948de4286c74cdd6c667aceb38f5c1e26f0693b3983d9d74887c65e"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:617d7e2ca7dcb8c5cf6bcb8c59b8832c94b36196bbf1cbd1bfb56ed341905edd"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7027560ee92211647d0d34e3f7cd6f50da56399d26a9c8ad0da286d3869a53f3"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:f99626688942fb746e545232e7726926f3be91b5975f8b55327665fafda991c7"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc3e9034a63de20e15e8ade85358bc6efc614008cab72898b4b4952bea0509ff"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_aarch64.whl", hash = "sha256:97e7cf2be5c77b7d1a9713a05605d49460d02c6078d38d8bef3cbe323c548424"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_armv7l.whl", hash = "sha256:3bf92c5d0e00fefaab325a4d27828fe6b6e2a21848686b5b60d2d9eeb09d76c6"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-musllinux_1_1_x86_64.whl", hash = "sha256:3ecbc122d18468d06ca279dc26a8c2e2d5acb10943bb35e36ae92096dc3b5565"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win32.whl", hash = "sha256:e846ae7835bf0703ae43f534ab79a867146dadd59dc9ca5c8b53d5c8f7c9ef02"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win_amd64.whl", hash = "sha256:2108ba5c1c1eca18030634489dc544844144ee36357f2f9f780b93e7ddbb44b5"}, + {file = "pydantic_core-2.46.4-cp314-cp314t-win_arm64.whl", hash = "sha256:4fcbe087dbc2068af7eda3aa87634eba216dbda64d1ae73c8684b621d33f6596"}, + {file = "pydantic_core-2.46.4-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:fd8b3d9fd264be37976686c7f65cd52a83f5e84f4bfd2adf9c1d469676bbb6ae"}, + {file = "pydantic_core-2.46.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9f444c499b3eefd3a92e348059471ea0c3a6e303d9c1cec09fa748fd9f895201"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3447661d99f75a3683a4cf5c87da72f2161964611864dbbeac7fbb118bb4bfc0"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8b9bab013d1c7a79d3501ff86d0bc9c31bf587db4551677b96bec07df78c6b15"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d995260fdf4e1db774581b4900e0f832abe3c7c84996726bbc161b19c8f29e76"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f13a646d65d09fbf1bc6b3a9635d30095c8e7e5cc419ff35ecc563c5fd04cd49"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:432c179df7874eeb73307aad2df0755e1ae0efa61ff0ea89b93e194411ae3928"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:e68b7a074f65a2fd746c52a7ce6142ab7006074ac269ace0c25cd8ba171f8066"}, + {file = "pydantic_core-2.46.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4a05d69cba51d852c5c3e92758653245a50c0b646ced0cf05bd793ed592839d6"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:228ee9bae8bef5b1e97ec58302f80357c37199e0d0a99174e138d28e6957b9d9"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:10e17cbb10a330363733efc4d7c4d0dd827ac0909b8f6a6542298fed1ea62f29"}, + {file = "pydantic_core-2.46.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:91a06d2e259ecfbd8c901d70c3c507900458498142b3026a296b7de4d1322cc9"}, + {file = "pydantic_core-2.46.4-cp39-cp39-win32.whl", hash = "sha256:d80ee3d731373b24cebbc10d689ca4ee1875caf0d5703a245db18efd4dd37fc1"}, + {file = "pydantic_core-2.46.4-cp39-cp39-win_amd64.whl", hash = "sha256:3be77f45df024d789a672ae34f8b06fb346c4f9f46ea714956660ea4862e89ac"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_10_12_x86_64.whl", hash = "sha256:14d4edf427bdcf950a8a02d7cb44a08614388dd6e1bdcbf4f67504fa7887da9c"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-macosx_11_0_arm64.whl", hash = "sha256:0ce40cd7b21210e99342afafbd4d0f76d784eb5b1d60f3bdc566be4983c6c73b"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90884113d8b48f760e9587002789ddd741e76ab9f89518cd1e43b1f1a52ec44b"}, + {file = "pydantic_core-2.46.4-graalpy311-graalpy242_311_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:66ce7632c22d837c95301830e111ad0128a32b8207533b60896a96c4915192ea"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_10_12_x86_64.whl", hash = "sha256:1d8ba486450b14f3b1d63bc521d410ec7565e52f887b9fb671791886436a42f7"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-macosx_11_0_arm64.whl", hash = "sha256:3009f12e4e90b7f88b4f9adb1b0c4a3d58fe7820f3238c190047209d148026df"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad785e92e6dc634c21555edc8bd6b64957ab844541bcb96a1366c202951ae526"}, + {file = "pydantic_core-2.46.4-graalpy312-graalpy250_312_native-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00c603d540afdd6b80eb39f078f33ebd46211f02f33e34a32d9f053bba711de0"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:0c563b08bca408dc7f65f700633d8442fffb2421fc47b8101377e9fd65051ff0"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:db06ffe51636ffe9ca531fe9023dd64bdd794be8754cb5df57c5498ae5b518a7"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:133878133d271ade3d41d1bfb2a45ec38dbdbda40bc065921c6b04e4630127e2"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9bc519fbf2b7578398853d815009ae5e4d4603d12f4e3f91da8c06852d3da3e9"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c7a7bd4e39e8e4c12c39cd480356842b6a8a06e41b23a55a5e3e191718838ddf"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:d396ec2b979760aaf3218e76c24e65bd0aca24983298653b3a9d7a45f9e47b30"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:86e1a4418c6cd97d60c95c71164158eaf7324fae7b0923264016baa993eba6fc"}, + {file = "pydantic_core-2.46.4-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:d51026d73fcfd93610abc7b27789c26b313920fcfb20e27462d74a7f8b06e983"}, + {file = "pydantic_core-2.46.4.tar.gz", hash = "sha256:62f875393d7f270851f20523dd2e29f082bcc82292d66db2b64ea71f64b6e1c1"}, +] + +[package.dependencies] +typing-extensions = ">=4.14.1" + +[[package]] +name = "pygments" +version = "2.20.0" +description = "Pygments is a syntax highlighting package written in Python." +category = "dev" +optional = false +python-versions = ">=3.9" files = [ - {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, - {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, + {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"}, + {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"}, ] [package.extras] -cli = ["click (>=5.0)"] +windows-terminal = ["colorama (>=0.4.6)"] [[package]] -name = "requests" -version = "2.31.0" -description = "Python HTTP for Humans." -category = "main" +name = "pytest" +version = "9.1.1" +description = "pytest: simple powerful testing with Python" +category = "dev" optional = false -python-versions = ">=3.7" +python-versions = ">=3.10" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"}, + {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"}, ] [package.dependencies] -certifi = ">=2017.4.17" -charset-normalizer = ">=2,<4" -idna = ">=2.5,<4" -urllib3 = ">=1.21.1,<3" +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} +iniconfig = ">=1.0.1" +packaging = ">=22" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -socks = ["PySocks (>=1.5.6,!=1.5.7)"] -use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "python-dotenv" +version = "1.2.2" +description = "Read key-value pairs from a .env file and set them as environment variables" +category = "main" +optional = false +python-versions = ">=3.10" +files = [ + {file = "python_dotenv-1.2.2-py3-none-any.whl", hash = "sha256:1d8214789a24de455a8b8bd8ae6fe3c6b69a5e3d64aa8a8e5d68e694bbcb285a"}, + {file = "python_dotenv-1.2.2.tar.gz", hash = "sha256:2c371a91fbd7ba082c2c1dc1f8bf89ca22564a087c2c287cd9b662adde799cf3"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "regex" +version = "2026.5.9" +description = "Alternative regular expression module, to replace re." +category = "main" +optional = false +python-versions = ">=3.10" +files = [ + {file = "regex-2026.5.9-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a9e1328e17c84c1a5d22ec9f785ecef4a967fab9a42b6a8dc3bcbebd0a0c9e44"}, + {file = "regex-2026.5.9-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bfe1ce50cbfb569d74e1e4337da6468961f31dbea55fd85aa5de59c0947a805a"}, + {file = "regex-2026.5.9-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:15ee42209947f4ca045412eae98416317238163618ace2a8e54f99586a466733"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4bb445ff3f725f59df8f6014edb547ee928ec7023a774f6a39a3f953038cbb2"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:446ddd671e43ab535810c4b21cff7104945c701d4a14d1e6d1cd6f4e445a8bea"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:7b92817338591505f282cf3864c145244b1edcf5381d237038df955001091538"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d6b8a143aca6c39b446ea8092cde25cc8fe9304d4f5fecfbc1a9dbb0282703c2"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0f03aa6898aaaac4592479821df16e68e8d0e29e903e65d8f2dfb2f19028a989"}, + {file = "regex-2026.5.9-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ed457d8e98ae812ed7732bef7bf78de78e834eae0372a74e23ca90ef21d910f9"}, + {file = "regex-2026.5.9-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:71b61c5bfe1c806332defc42ad6c780b3c55f661986d7f40283a3a88274b4c00"}, + {file = "regex-2026.5.9-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:3b1e39888c5e0c7d92cea4fc777396c4a90363b05de75d02eb459a4752200808"}, + {file = "regex-2026.5.9-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:6ba42b2e7e7f46cf68cc6a5ca36fa07959f9bbd9c6bdcc47b6ee76549a590248"}, + {file = "regex-2026.5.9-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:c010eb8caca74bdb40c07498d7ece26b4428fd3f04aa8a72c9ac6f79e8faaac6"}, + {file = "regex-2026.5.9-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:a6a563446a41adc451393dc6b8e6ad87979efaee3c8738690a8d1b08ebead1b4"}, + {file = "regex-2026.5.9-cp310-cp310-win32.whl", hash = "sha256:954cc214c04663ee6d266fc61739cad83054683048de65c5bd1d640ad28098ac"}, + {file = "regex-2026.5.9-cp310-cp310-win_amd64.whl", hash = "sha256:b310768746dd314ea6e2ff4cc89ef215426813396ff4e94ee8e6f7096c8b6e03"}, + {file = "regex-2026.5.9-cp310-cp310-win_arm64.whl", hash = "sha256:19c16ceb4a267a8789e25733e583983eeab9f0f8664e66b0bd1c5d21f14c2d4b"}, + {file = "regex-2026.5.9-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ccf5249114cc3e772ecdd88a98a86eca0fd74c61ce32a94743758c083fc05d48"}, + {file = "regex-2026.5.9-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46f1326ca6e65b0879d23ca302c0f2415aad42ff0309b9c818e7949fe19a41d8"}, + {file = "regex-2026.5.9-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ef31cbfe458e21c6122ba8150ff060e0c7789ed0d26eb423f25472584920b555"}, + {file = "regex-2026.5.9-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:992604d02e6d9c6d786c24a706a71ecffe1020fc1ef264044474cd81fa2c3919"}, + {file = "regex-2026.5.9-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c9411dd64ca95477225734a93dfc8583b51916b8d5942f99d6cac21e09965451"}, + {file = "regex-2026.5.9-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3dd4a3ff360dfb836fecdb93a4598f9d6e2ac81e3e397125145c6221bf58cf4c"}, + {file = "regex-2026.5.9-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2a661a7d270a61f7cf460caee8b9fa2d5ef9e5c681234bcb9e0fe14f488e7dfc"}, + {file = "regex-2026.5.9-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f079e50a0d3cc3cd5091fa9ff45869a2e6b2cd35895731edafb0327901a8d86d"}, + {file = "regex-2026.5.9-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:4ebe8f0b5ec5a5024dc4a4c59f444c4e9afc5f2abdbb8962065b75d27fb971f9"}, + {file = "regex-2026.5.9-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:97cf3bc1b7d7d2306772ec07366c80d9df00ff79e79cea32898883a646d2fae2"}, + {file = "regex-2026.5.9-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:0f9eede6a5cbdc02d4978090186390936e1776a7d1359b21e41014c609880bcf"}, + {file = "regex-2026.5.9-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:01f0f5f55f4b64dacec85dc116d3c05fd23ad3ff037bbc73a2085775953c2611"}, + {file = "regex-2026.5.9-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1268eddd8486dc561d08eee1156e40aa3a8fe10f4bdec8fa653b455fcbffd12c"}, + {file = "regex-2026.5.9-cp311-cp311-win32.whl", hash = "sha256:8676474c07469d6f33dd1085ca2cd45f65785f32518f2b20e36d9953ca07f994"}, + {file = "regex-2026.5.9-cp311-cp311-win_amd64.whl", hash = "sha256:246de9d60aa3f8538b519834dd95cbf276ea263d6a7bd5a3666dc3fa0230505b"}, + {file = "regex-2026.5.9-cp311-cp311-win_arm64.whl", hash = "sha256:d726ca3f0d76969bf1e8e477d160d3d666bbf999f6860bd314889e5345782046"}, + {file = "regex-2026.5.9-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:57eeeb05db7979413dec5438f2db21d7ecbba787cde7a711df1a6f6df672aa06"}, + {file = "regex-2026.5.9-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:398c521292f4c7fb807001dcd54694d3a1fcafc179a36ad9cc56f98df85930b6"}, + {file = "regex-2026.5.9-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f7a7c26137296beba7784de6eba69c6a93a63ccebc385e4962fe67e267a91225"}, + {file = "regex-2026.5.9-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6441cc660d76107934a09c22167200839a0e89604a6297f78a974e66e931d2c0"}, + {file = "regex-2026.5.9-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:91328f1c23d47595ca3ef0a7557fa129c5a23404b775c770697d2f35b33e0107"}, + {file = "regex-2026.5.9-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:93a7860539414dddaefba2b40f8771765ae17949d4c7182b876ce429e11a8309"}, + {file = "regex-2026.5.9-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dd2810d22146b6d838acc5ec15602cb6b47920aa4e33015df3868eedfd20bab8"}, + {file = "regex-2026.5.9-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:daff2bdbaf1d23e52fdff7c0b7bc2048b68f978df6a4d107ac981f94caef2e66"}, + {file = "regex-2026.5.9-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4eeb011098fcb77af513dcef521a3dbecbf8849b1e38940759d293b7a93f5026"}, + {file = "regex-2026.5.9-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:ea9c8ecfa1b73c73b626534d6626e5340d429630943672b8480724f44e84b962"}, + {file = "regex-2026.5.9-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cd2846168eb9ee3c513902bc8225409cb1caab31d04728b145171fa1625d9621"}, + {file = "regex-2026.5.9-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:39617fb0cde9c0e6306dc70e3bfc096f3da793219879f7ae7aa341a69fbdcf6d"}, + {file = "regex-2026.5.9-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fd03c4f0e33280d15cae17159b899245d6b7c53d21def19b263b39655061f5ce"}, + {file = "regex-2026.5.9-cp312-cp312-win32.whl", hash = "sha256:164eba9b755ea6f244b0d881196fbc1fac09714e9782c9e2732b813142033c8e"}, + {file = "regex-2026.5.9-cp312-cp312-win_amd64.whl", hash = "sha256:86f40a5d6444db30a125c9c9177e6b25dad981cbc37451fd838f145e6edac92e"}, + {file = "regex-2026.5.9-cp312-cp312-win_arm64.whl", hash = "sha256:96f5f58b54a063d7ea9dca08e1cf57bfe10499c4d579ee672da284f57f5f0070"}, + {file = "regex-2026.5.9-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:d626b84406444b165fc0ba981604edea39f0588ff1f92baa23fe50799ea9afdb"}, + {file = "regex-2026.5.9-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d7bdc0ab8f3dd7e1b4f9ab88634e13374669db86bb3c72e8292f07ae313f539f"}, + {file = "regex-2026.5.9-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a8820737949116ffff55fe18f9fc644530063ba6ebfcb8314239416e78f1347c"}, + {file = "regex-2026.5.9-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa0fbdbac82cb3e4450d0ccde7d7a35607f4cb2dd9fba4b8b69bfaf8c9fa6aed"}, + {file = "regex-2026.5.9-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:57e8915c7986aa33d25e4d3629cef711cd2863f2961b10409f0c04cb8b7d9020"}, + {file = "regex-2026.5.9-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:508f56a89ba9cb26e4168cbc37dbd60a28d82430a9e18ad1d25fe0883c314ca2"}, + {file = "regex-2026.5.9-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b6d189041f15691cfa2b6c4290448ec221244d225b3f5fe9e7771b34ffcdf6e2"}, + {file = "regex-2026.5.9-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e82db382b44d0111b22601c509c89f64434816c9e0eef9d1989cda8cc6ff1c04"}, + {file = "regex-2026.5.9-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2acfb48634f64996b57f90f39afa692ff362162722581921fe92239a59960f3c"}, + {file = "regex-2026.5.9-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:d29eebfc9525db68cad3c97eedd7f754fa265aa5cd0cf4f863b2421e1b48fc9f"}, + {file = "regex-2026.5.9-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:debb893095e944091c16e641a6e33c1b0f4cb61ab945ec5afbf53ce7068834d8"}, + {file = "regex-2026.5.9-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:d659eee77986549c9ea45b861c7567e44d6287c3dc9a4565478853f7b9fe2ff6"}, + {file = "regex-2026.5.9-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2efa205e6d98b24d1f3ab395c11aa15cdf10935bca283d0285e0499c284fba21"}, + {file = "regex-2026.5.9-cp313-cp313-win32.whl", hash = "sha256:f3844f134e834076677dd369976e9f5068679fcb8e50102fdf6b7ac96a3ec127"}, + {file = "regex-2026.5.9-cp313-cp313-win_amd64.whl", hash = "sha256:3527bb4942d2c14552155406cdedd906567456821848aed1cb4933a391bf5eca"}, + {file = "regex-2026.5.9-cp313-cp313-win_arm64.whl", hash = "sha256:56a33f191f17d8c417f99945ebdc1e691d3af9605d86ec68c7e54a57e3e17af6"}, + {file = "regex-2026.5.9-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:01f28d868834624c934b8d2e0aa1c8341337e37831f4a012f18a5afcba4cbaf3"}, + {file = "regex-2026.5.9-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:48036f6374aaa79eb3b754ec29c61d1c6b1606749d705a13f8854fa2539671f6"}, + {file = "regex-2026.5.9-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b96350aa424e79d4fd6b567b344dcbe2b2d6bfc48dfe7717587e1fa6d43da6ff"}, + {file = "regex-2026.5.9-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8f3af7a4903c5c04a11a196a5aa75cdd7dd3f8508132f9fb3259d9f5908e3b88"}, + {file = "regex-2026.5.9-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7e87577720152d2caae19fe2baaf1f8d5ca12091e9e229f03915c37d1e4b9178"}, + {file = "regex-2026.5.9-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c8b9b9d294cfea3cd19c718ade7cc93492b2c4991abd9a68d0b3477ae6d8e100"}, + {file = "regex-2026.5.9-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:728d8bfd28a8845c8b6bc5dc7ce010453d206396786c0765c2740cb65f37791e"}, + {file = "regex-2026.5.9-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7e30b874d341fac767d7df5a0870540541c2c054b80cfaac116e8d367a8a7ff2"}, + {file = "regex-2026.5.9-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fd190e88a895a8901325fad284a3f74ea52b1da8525b76cc811fa9b1edf0ce2b"}, + {file = "regex-2026.5.9-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:8e76e8161ad00694cfce6767d5dea860c6391ac5b83e5c3a39661e696f11fc7e"}, + {file = "regex-2026.5.9-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:ddda5340e6c01a293027dd46232fa79eaff1b48058ce7a98f572b6445b088041"}, + {file = "regex-2026.5.9-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:205109e96b3cf5adf8f4cd62bedde9487feb282b9497a3535451e5a24cd706a0"}, + {file = "regex-2026.5.9-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:dfbe4579b9f08036aa7d101d1835437a20783574ac66327e6b29b4018a138081"}, + {file = "regex-2026.5.9-cp313-cp313t-win32.whl", hash = "sha256:ed2c9e8068b614c574d8d30e543d617cf5379b0535d46f97ef00e904745a08b5"}, + {file = "regex-2026.5.9-cp313-cp313t-win_amd64.whl", hash = "sha256:b46b0f094dc1d3b90356c85a0bd2c9bafc4a6a190b9d6f8ddd5a033b6e088ed4"}, + {file = "regex-2026.5.9-cp313-cp313t-win_arm64.whl", hash = "sha256:872acc074bd29ffc9913ecdfedf6ea77502312ca44a4aa0d3779089c6069d8de"}, + {file = "regex-2026.5.9-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:1bd7587a2948b4085195d5a3374eaf4a425dc3e55784c038175355ecf3bbbf8a"}, + {file = "regex-2026.5.9-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:dea2e88e1cce4522496cce630e11e67b98b7076620bc4336c3f674bc21a375f4"}, + {file = "regex-2026.5.9-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2099f7e7ff7b6aa3192312650a56e91cc091e49d50b04e4f6f8b6e28b3b27f1c"}, + {file = "regex-2026.5.9-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ecd353045824e4477562a2ac718c25799cdaaa41f7aa925a806a8a3e6848a5b9"}, + {file = "regex-2026.5.9-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:65c8c8c37377794bd5b2f3ebe51919042bf17aec802e23c833d89782ed0c78af"}, + {file = "regex-2026.5.9-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:5b73ab8afcf66c622db143d1c6fda4e58e4d537ee4f125229ad47b1ab80f34c0"}, + {file = "regex-2026.5.9-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0de5cf193997384ed2ca6f1cd4f78055b255d93d82d5a8cd6ba0d11c10b167e4"}, + {file = "regex-2026.5.9-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:d641a8c9a61618047796d572a39a79b26167b0411d2c3031937b2fe2d081e2cf"}, + {file = "regex-2026.5.9-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:24b2355ef5cc9aa5b8f07d17704face1c166fdcc2290fa7bd6e6c925655a8346"}, + {file = "regex-2026.5.9-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:a24852d3c29ad9e47593593d8a247c44ccc3d0548ef12c822d6ed0810affe676"}, + {file = "regex-2026.5.9-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:916714069da19329ef7de197dcbc77bb3104145c7c2c864dbfbe318f46b88b14"}, + {file = "regex-2026.5.9-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:fa411799ca8da32a8d38d020a88faa5b6f91657d284761352940ecf9f7c3bbdd"}, + {file = "regex-2026.5.9-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:1e6da47d679b7010ef27556b6e0f99771b744936db1792a10ceac6547ae1503e"}, + {file = "regex-2026.5.9-cp314-cp314-win32.whl", hash = "sha256:98bd73080e8756255137e1bd3f3f00295bbc5aa383c0e0f973920e9134d7c4ad"}, + {file = "regex-2026.5.9-cp314-cp314-win_amd64.whl", hash = "sha256:ff8d372ac2acdc048d1c19916f27ee61bc5722728458ba6ca5052f2c72d51763"}, + {file = "regex-2026.5.9-cp314-cp314-win_arm64.whl", hash = "sha256:e1d93bf647916292e8edcec150c07ddf3dc50179ccaf770c04a7f9e452155372"}, + {file = "regex-2026.5.9-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:83d0ee4a57d1c87cb549e195ec300b8f0ec3a82eba66d835e4e2ed8634fe4499"}, + {file = "regex-2026.5.9-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:d3d7eb5c9a7f6df82ed3cfac9beb93882a5cbcb5b8b157b56cb2b3b276574ac1"}, + {file = "regex-2026.5.9-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:075160bf16658e16d35233300b8453aac25de4cbea808d22348b6979668e924d"}, + {file = "regex-2026.5.9-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:45375819235558a4ff1c4971dc32881f022613abdb180128f5cb4768c1765a1c"}, + {file = "regex-2026.5.9-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:ead4b163ac30a29574510cd4b3e2e985ac5290c05fc7095557d6a5f403fc31b5"}, + {file = "regex-2026.5.9-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8c6e4218fbdfbcd4f6c19efca40930d24a621bf4b48cb76bc6640543bd28ef20"}, + {file = "regex-2026.5.9-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6351571c8a42b505eb555c0dc47d740d0fb66977dc142919eea6f4325b7c56a0"}, + {file = "regex-2026.5.9-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:002205cafd2a9e78c6290c7d1df277bf3277b3b7a30e0b4bb0dac2e2e3f7cb2d"}, + {file = "regex-2026.5.9-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8abd33fef90b2a9efac5557d6033ca82d1195ed3a15fea5af15ba7b463c6a63b"}, + {file = "regex-2026.5.9-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:31037c82eccb44b7ea2e9e221d7c01429430e989a1f4b91ea5a855f6017b509a"}, + {file = "regex-2026.5.9-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:5604dfd046dc37eca90250fc3be938b076c8059fa772ac0ed6f499b0f0fb0415"}, + {file = "regex-2026.5.9-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:0e1b1b4e496afbb24f4a62aba855ee4f88f25578927697b340702e48c9ee6bc2"}, + {file = "regex-2026.5.9-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:be3372b9df6ddecff6486d37e19095a7b4973137caf5512407a89f4455361f41"}, + {file = "regex-2026.5.9-cp314-cp314t-win32.whl", hash = "sha256:3ddd90103f9e5c471c49c7852ecc1fe27c7e45eb99e977aefe7caa4e779f4f58"}, + {file = "regex-2026.5.9-cp314-cp314t-win_amd64.whl", hash = "sha256:ca518ed29c46eecba6010b15f1b9a479314d2de409536e71b6a13aa04e3b8a77"}, + {file = "regex-2026.5.9-cp314-cp314t-win_arm64.whl", hash = "sha256:5e41809d2683fcde7d5a8c87a6567ba1fb1ce0de9f31bff578de00a4b2d76daa"}, + {file = "regex-2026.5.9.tar.gz", hash = "sha256:a8234aa23ec39894bfe4a3f1b85616a7032481964a13ac6fc9f10de4f6fca270"}, +] [[package]] name = "ruamel-yaml" -version = "0.17.21" +version = "0.19.1" description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order" category = "main" optional = false -python-versions = ">=3" +python-versions = ">=3.9" files = [ - {file = "ruamel.yaml-0.17.21-py3-none-any.whl", hash = "sha256:742b35d3d665023981bd6d16b3d24248ce5df75fdb4e2924e93a05c1f8b61ca7"}, - {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, + {file = "ruamel_yaml-0.19.1-py3-none-any.whl", hash = "sha256:27592957fedf6e0b62f281e96effd28043345e0e66001f97683aa9a40c667c93"}, + {file = "ruamel_yaml-0.19.1.tar.gz", hash = "sha256:53eb66cd27849eff968ebf8f0bf61f46cdac2da1d1f3576dd4ccee9b25c31993"}, ] -[package.dependencies] -"ruamel.yaml.clib" = {version = ">=0.2.6", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.11\""} - [package.extras] -docs = ["ryd"] +docs = ["mercurial (>5.7)", "ryd"] jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] +libyaml = ["ruamel.yaml.clibz (>=0.3.7)"] +oldlibyaml = ["ruamel.yaml.clib"] [[package]] -name = "ruamel-yaml-clib" -version = "0.2.7" -description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" +name = "sly" +version = "0.5" +description = "\"SLY - Sly Lex Yacc\"" category = "main" optional = false -python-versions = ">=3.5" +python-versions = "*" files = [ - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, - {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:41d0f1fa4c6830176eef5b276af04c89320ea616655d01327d5ce65e50575c94"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win32.whl", hash = "sha256:f6d3d39611ac2e4f62c3128a9eed45f19a6608670c5a2f4f07f24e8de3441d38"}, - {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-win_amd64.whl", hash = "sha256:da538167284de58a52109a9b89b8f6a53ff8437dd6dc26d33b57bf6699153122"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, - {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, - {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, - {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, - {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, - {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, + {file = "sly-0.5-py3-none-any.whl", hash = "sha256:20485483259eec7f6ba85ff4d2e96a4e50c6621902667fc2695cc8bc2a3e5133"}, + {file = "sly-0.5.tar.gz", hash = "sha256:251d42015e8507158aec2164f06035df4a82b0314ce6450f457d7125e7649024"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +category = "main" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "tomli" +version = "2.4.1" +description = "A lil' TOML parser" +category = "dev" +optional = false +python-versions = ">=3.8" +files = [ + {file = "tomli-2.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30"}, + {file = "tomli-2.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076"}, + {file = "tomli-2.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c"}, + {file = "tomli-2.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc"}, + {file = "tomli-2.4.1-cp311-cp311-win32.whl", hash = "sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049"}, + {file = "tomli-2.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e"}, + {file = "tomli-2.4.1-cp311-cp311-win_arm64.whl", hash = "sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a"}, + {file = "tomli-2.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9"}, + {file = "tomli-2.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585"}, + {file = "tomli-2.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1"}, + {file = "tomli-2.4.1-cp312-cp312-win32.whl", hash = "sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917"}, + {file = "tomli-2.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9"}, + {file = "tomli-2.4.1-cp312-cp312-win_arm64.whl", hash = "sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54"}, + {file = "tomli-2.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897"}, + {file = "tomli-2.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d"}, + {file = "tomli-2.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5"}, + {file = "tomli-2.4.1-cp313-cp313-win32.whl", hash = "sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd"}, + {file = "tomli-2.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36"}, + {file = "tomli-2.4.1-cp313-cp313-win_arm64.whl", hash = "sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf"}, + {file = "tomli-2.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662"}, + {file = "tomli-2.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15"}, + {file = "tomli-2.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba"}, + {file = "tomli-2.4.1-cp314-cp314-win32.whl", hash = "sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6"}, + {file = "tomli-2.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7"}, + {file = "tomli-2.4.1-cp314-cp314-win_arm64.whl", hash = "sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4"}, + {file = "tomli-2.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d"}, + {file = "tomli-2.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c"}, + {file = "tomli-2.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f"}, + {file = "tomli-2.4.1-cp314-cp314t-win32.whl", hash = "sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8"}, + {file = "tomli-2.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26"}, + {file = "tomli-2.4.1-cp314-cp314t-win_arm64.whl", hash = "sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396"}, + {file = "tomli-2.4.1-py3-none-any.whl", hash = "sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe"}, + {file = "tomli-2.4.1.tar.gz", hash = "sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f"}, ] [[package]] name = "tomlkit" -version = "0.10.2" +version = "0.14.0" description = "Style preserving TOML library" category = "main" optional = false -python-versions = ">=3.6,<4.0" +python-versions = ">=3.9" files = [ - {file = "tomlkit-0.10.2-py3-none-any.whl", hash = "sha256:905cf92c2111ef80d355708f47ac24ad1b6fc2adc5107455940088c9bbecaedb"}, - {file = "tomlkit-0.10.2.tar.gz", hash = "sha256:30d54c0b914e595f3d10a87888599eab5321a2a69abc773bbefff51599b72db6"}, + {file = "tomlkit-0.14.0-py3-none-any.whl", hash = "sha256:592064ed85b40fa213469f81ac584f67a4f2992509a7c3ea2d632208623a3680"}, + {file = "tomlkit-0.14.0.tar.gz", hash = "sha256:cf00efca415dbd57575befb1f6634c4f42d2d87dbba376128adb42c121b87064"}, ] [[package]] name = "tqdm" -version = "4.65.0" +version = "4.68.3" description = "Fast, Extensible Progress Meter" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tqdm-4.65.0-py3-none-any.whl", hash = "sha256:c4f53a17fe37e132815abceec022631be8ffe1b9381c2e6e30aa70edc99e9671"}, - {file = "tqdm-4.65.0.tar.gz", hash = "sha256:1871fb68a86b8fb3b59ca4cdd3dcccbc7e6d613eeed31f4c332531977b89beb5"}, + {file = "tqdm-4.68.3-py3-none-any.whl", hash = "sha256:39832cc2def2789a6f29df83f172db7416cea70052c0907a57801c5f2fdccb03"}, + {file = "tqdm-4.68.3.tar.gz", hash = "sha256:00dfa48452b6b6cfae3dd9885636c23d3422d1ec97c66d96818cbd5e0821d482"}, ] [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} [package.extras] -dev = ["py-make (>=0.1.0)", "twine", "wheel"] +discord = ["envwrap", "requests"] notebook = ["ipywidgets (>=6)"] -slack = ["slack-sdk"] -telegram = ["requests"] +slack = ["envwrap", "slack-sdk"] +telegram = ["envwrap", "requests"] [[package]] -name = "typer" -version = "0.7.0" -description = "Typer, build great CLIs. Easy to code. Based on Python type hints." +name = "typing-extensions" +version = "4.15.0" +description = "Backported and Experimental Type Hints for Python 3.9+" category = "main" optional = false -python-versions = ">=3.6" +python-versions = ">=3.9" files = [ - {file = "typer-0.7.0-py3-none-any.whl", hash = "sha256:b5e704f4e48ec263de1c0b3a2387cd405a13767d2f907f44c1a08cbad96f606d"}, - {file = "typer-0.7.0.tar.gz", hash = "sha256:ff797846578a9f2a201b53442aedeb543319466870fbe1c701eab66dd7681165"}, + {file = "typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548"}, + {file = "typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466"}, ] -[package.dependencies] -click = ">=7.1.1,<9.0.0" - -[package.extras] -all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] -dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"] -doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"] -test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<13.0.0)", "shellingham (>=1.3.0,<2.0.0)"] - [[package]] -name = "urllib3" -version = "1.26.15" -description = "HTTP library with thread-safe connection pooling, file post, and more." +name = "typing-inspection" +version = "0.4.2" +description = "Runtime typing introspection tools" category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = ">=3.9" files = [ - {file = "urllib3-1.26.15-py2.py3-none-any.whl", hash = "sha256:aa751d169e23c7479ce47a0cb0da579e3ede798f994f5816a74e4f4500dcea42"}, - {file = "urllib3-1.26.15.tar.gz", hash = "sha256:8a388717b9476f934a21484e8c8e61875ab60644d29b9b39e11e4b9dc1c6b305"}, + {file = "typing_inspection-0.4.2-py3-none-any.whl", hash = "sha256:4ed1cacbdc298c220f1bd249ed5287caa16f34d44ef4e9c3d0cbad5b521545e7"}, + {file = "typing_inspection-0.4.2.tar.gz", hash = "sha256:ba561c48a67c5958007083d386c3295464928b01faa735ab8547c5692e87f464"}, ] -[package.extras] -brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] -socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] +[package.dependencies] +typing-extensions = ">=4.12.0" [[package]] -name = "win32-setctime" -version = "1.1.0" -description = "A small Python utility to set file creation time on Windows" +name = "websockets" +version = "16.0" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" category = "main" optional = false -python-versions = ">=3.5" +python-versions = ">=3.10" files = [ - {file = "win32_setctime-1.1.0-py3-none-any.whl", hash = "sha256:231db239e959c2fe7eb1d7dc129f11172354f98361c4fa2d6d2d7e278baa8aad"}, - {file = "win32_setctime-1.1.0.tar.gz", hash = "sha256:15cf5750465118d6929ae4de4eb46e8edae9a5634350c01ba582df868e932cb2"}, + {file = "websockets-16.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a"}, + {file = "websockets-16.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0"}, + {file = "websockets-16.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957"}, + {file = "websockets-16.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72"}, + {file = "websockets-16.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde"}, + {file = "websockets-16.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3"}, + {file = "websockets-16.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3"}, + {file = "websockets-16.0-cp310-cp310-win32.whl", hash = "sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9"}, + {file = "websockets-16.0-cp310-cp310-win_amd64.whl", hash = "sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35"}, + {file = "websockets-16.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8"}, + {file = "websockets-16.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad"}, + {file = "websockets-16.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d"}, + {file = "websockets-16.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe"}, + {file = "websockets-16.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b"}, + {file = "websockets-16.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5"}, + {file = "websockets-16.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64"}, + {file = "websockets-16.0-cp311-cp311-win32.whl", hash = "sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6"}, + {file = "websockets-16.0-cp311-cp311-win_amd64.whl", hash = "sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac"}, + {file = "websockets-16.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00"}, + {file = "websockets-16.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79"}, + {file = "websockets-16.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39"}, + {file = "websockets-16.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c"}, + {file = "websockets-16.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f"}, + {file = "websockets-16.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1"}, + {file = "websockets-16.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2"}, + {file = "websockets-16.0-cp312-cp312-win32.whl", hash = "sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89"}, + {file = "websockets-16.0-cp312-cp312-win_amd64.whl", hash = "sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea"}, + {file = "websockets-16.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9"}, + {file = "websockets-16.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230"}, + {file = "websockets-16.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c"}, + {file = "websockets-16.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5"}, + {file = "websockets-16.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82"}, + {file = "websockets-16.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8"}, + {file = "websockets-16.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f"}, + {file = "websockets-16.0-cp313-cp313-win32.whl", hash = "sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a"}, + {file = "websockets-16.0-cp313-cp313-win_amd64.whl", hash = "sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156"}, + {file = "websockets-16.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0"}, + {file = "websockets-16.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904"}, + {file = "websockets-16.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4"}, + {file = "websockets-16.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e"}, + {file = "websockets-16.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4"}, + {file = "websockets-16.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1"}, + {file = "websockets-16.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3"}, + {file = "websockets-16.0-cp314-cp314-win32.whl", hash = "sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8"}, + {file = "websockets-16.0-cp314-cp314-win_amd64.whl", hash = "sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d"}, + {file = "websockets-16.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244"}, + {file = "websockets-16.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e"}, + {file = "websockets-16.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641"}, + {file = "websockets-16.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8"}, + {file = "websockets-16.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e"}, + {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944"}, + {file = "websockets-16.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206"}, + {file = "websockets-16.0-cp314-cp314t-win32.whl", hash = "sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6"}, + {file = "websockets-16.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd"}, + {file = "websockets-16.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d"}, + {file = "websockets-16.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03"}, + {file = "websockets-16.0-pp311-pypy311_pp73-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da"}, + {file = "websockets-16.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c"}, + {file = "websockets-16.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767"}, + {file = "websockets-16.0-py3-none-any.whl", hash = "sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec"}, + {file = "websockets-16.0.tar.gz", hash = "sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5"}, ] -[package.extras] -dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] - [[package]] -name = "yarl" -version = "1.8.2" -description = "Yet another URL library" +name = "win32-setctime" +version = "1.2.0" +description = "A small Python utility to set file creation time on Windows" category = "main" optional = false -python-versions = ">=3.7" +python-versions = ">=3.5" files = [ - {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:bb81f753c815f6b8e2ddd2eef3c855cf7da193b82396ac013c661aaa6cc6b0a5"}, - {file = "yarl-1.8.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:47d49ac96156f0928f002e2424299b2c91d9db73e08c4cd6742923a086f1c863"}, - {file = "yarl-1.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3fc056e35fa6fba63248d93ff6e672c096f95f7836938241ebc8260e062832fe"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:58a3c13d1c3005dbbac5c9f0d3210b60220a65a999b1833aa46bd6677c69b08e"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:10b08293cda921157f1e7c2790999d903b3fd28cd5c208cf8826b3b508026996"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:de986979bbd87272fe557e0a8fcb66fd40ae2ddfe28a8b1ce4eae22681728fef"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c4fcfa71e2c6a3cb568cf81aadc12768b9995323186a10827beccf5fa23d4f8"}, - {file = "yarl-1.8.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae4d7ff1049f36accde9e1ef7301912a751e5bae0a9d142459646114c70ecba6"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:bf071f797aec5b96abfc735ab97da9fd8f8768b43ce2abd85356a3127909d146"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:74dece2bfc60f0f70907c34b857ee98f2c6dd0f75185db133770cd67300d505f"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:df60a94d332158b444301c7f569659c926168e4d4aad2cfbf4bce0e8fb8be826"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:63243b21c6e28ec2375f932a10ce7eda65139b5b854c0f6b82ed945ba526bff3"}, - {file = "yarl-1.8.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:cfa2bbca929aa742b5084fd4663dd4b87c191c844326fcb21c3afd2d11497f80"}, - {file = "yarl-1.8.2-cp310-cp310-win32.whl", hash = "sha256:b05df9ea7496df11b710081bd90ecc3a3db6adb4fee36f6a411e7bc91a18aa42"}, - {file = "yarl-1.8.2-cp310-cp310-win_amd64.whl", hash = "sha256:24ad1d10c9db1953291f56b5fe76203977f1ed05f82d09ec97acb623a7976574"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a1fca9588f360036242f379bfea2b8b44cae2721859b1c56d033adfd5893634"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f37db05c6051eff17bc832914fe46869f8849de5b92dc4a3466cd63095d23dfd"}, - {file = "yarl-1.8.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:77e913b846a6b9c5f767b14dc1e759e5aff05502fe73079f6f4176359d832581"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0978f29222e649c351b173da2b9b4665ad1feb8d1daa9d971eb90df08702668a"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:388a45dc77198b2460eac0aca1efd6a7c09e976ee768b0d5109173e521a19daf"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2305517e332a862ef75be8fad3606ea10108662bc6fe08509d5ca99503ac2aee"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42430ff511571940d51e75cf42f1e4dbdded477e71c1b7a17f4da76c1da8ea76"}, - {file = "yarl-1.8.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3150078118f62371375e1e69b13b48288e44f6691c1069340081c3fd12c94d5b"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:c15163b6125db87c8f53c98baa5e785782078fbd2dbeaa04c6141935eb6dab7a"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4d04acba75c72e6eb90745447d69f84e6c9056390f7a9724605ca9c56b4afcc6"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e7fd20d6576c10306dea2d6a5765f46f0ac5d6f53436217913e952d19237efc4"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:75c16b2a900b3536dfc7014905a128a2bea8fb01f9ee26d2d7d8db0a08e7cb2c"}, - {file = "yarl-1.8.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d88056a04860a98341a0cf53e950e3ac9f4e51d1b6f61a53b0609df342cc8b2"}, - {file = "yarl-1.8.2-cp311-cp311-win32.whl", hash = "sha256:fb742dcdd5eec9f26b61224c23baea46c9055cf16f62475e11b9b15dfd5c117b"}, - {file = "yarl-1.8.2-cp311-cp311-win_amd64.whl", hash = "sha256:8c46d3d89902c393a1d1e243ac847e0442d0196bbd81aecc94fcebbc2fd5857c"}, - {file = "yarl-1.8.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ceff9722e0df2e0a9e8a79c610842004fa54e5b309fe6d218e47cd52f791d7ef"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3f6b4aca43b602ba0f1459de647af954769919c4714706be36af670a5f44c9c1"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1684a9bd9077e922300ecd48003ddae7a7474e0412bea38d4631443a91d61077"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ebb78745273e51b9832ef90c0898501006670d6e059f2cdb0e999494eb1450c2"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3adeef150d528ded2a8e734ebf9ae2e658f4c49bf413f5f157a470e17a4a2e89"}, - {file = "yarl-1.8.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57a7c87927a468e5a1dc60c17caf9597161d66457a34273ab1760219953f7f4c"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:efff27bd8cbe1f9bd127e7894942ccc20c857aa8b5a0327874f30201e5ce83d0"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:a783cd344113cb88c5ff7ca32f1f16532a6f2142185147822187913eb989f739"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:705227dccbe96ab02c7cb2c43e1228e2826e7ead880bb19ec94ef279e9555b5b"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:34c09b43bd538bf6c4b891ecce94b6fa4f1f10663a8d4ca589a079a5018f6ed7"}, - {file = "yarl-1.8.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:a48f4f7fea9a51098b02209d90297ac324241bf37ff6be6d2b0149ab2bd51b37"}, - {file = "yarl-1.8.2-cp37-cp37m-win32.whl", hash = "sha256:0414fd91ce0b763d4eadb4456795b307a71524dbacd015c657bb2a39db2eab89"}, - {file = "yarl-1.8.2-cp37-cp37m-win_amd64.whl", hash = "sha256:d881d152ae0007809c2c02e22aa534e702f12071e6b285e90945aa3c376463c5"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5df5e3d04101c1e5c3b1d69710b0574171cc02fddc4b23d1b2813e75f35a30b1"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7a66c506ec67eb3159eea5096acd05f5e788ceec7b96087d30c7d2865a243918"}, - {file = "yarl-1.8.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2b4fa2606adf392051d990c3b3877d768771adc3faf2e117b9de7eb977741229"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e21fb44e1eff06dd6ef971d4bdc611807d6bd3691223d9c01a18cec3677939e"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:93202666046d9edadfe9f2e7bf5e0782ea0d497b6d63da322e541665d65a044e"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fc77086ce244453e074e445104f0ecb27530d6fd3a46698e33f6c38951d5a0f1"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64dd68a92cab699a233641f5929a40f02a4ede8c009068ca8aa1fe87b8c20ae3"}, - {file = "yarl-1.8.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1b372aad2b5f81db66ee7ec085cbad72c4da660d994e8e590c997e9b01e44901"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e6f3515aafe0209dd17fb9bdd3b4e892963370b3de781f53e1746a521fb39fc0"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:dfef7350ee369197106805e193d420b75467b6cceac646ea5ed3049fcc950a05"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:728be34f70a190566d20aa13dc1f01dc44b6aa74580e10a3fb159691bc76909d"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:ff205b58dc2929191f68162633d5e10e8044398d7a45265f90a0f1d51f85f72c"}, - {file = "yarl-1.8.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:baf211dcad448a87a0d9047dc8282d7de59473ade7d7fdf22150b1d23859f946"}, - {file = "yarl-1.8.2-cp38-cp38-win32.whl", hash = "sha256:272b4f1599f1b621bf2aabe4e5b54f39a933971f4e7c9aa311d6d7dc06965165"}, - {file = "yarl-1.8.2-cp38-cp38-win_amd64.whl", hash = "sha256:326dd1d3caf910cd26a26ccbfb84c03b608ba32499b5d6eeb09252c920bcbe4f"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:f8ca8ad414c85bbc50f49c0a106f951613dfa5f948ab69c10ce9b128d368baf8"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:418857f837347e8aaef682679f41e36c24250097f9e2f315d39bae3a99a34cbf"}, - {file = "yarl-1.8.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ae0eec05ab49e91a78700761777f284c2df119376e391db42c38ab46fd662b77"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:009a028127e0a1755c38b03244c0bea9d5565630db9c4cf9572496e947137a87"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3edac5d74bb3209c418805bda77f973117836e1de7c000e9755e572c1f7850d0"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da65c3f263729e47351261351b8679c6429151ef9649bba08ef2528ff2c423b2"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ef8fb25e52663a1c85d608f6dd72e19bd390e2ecaf29c17fb08f730226e3a08"}, - {file = "yarl-1.8.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcd7bb1e5c45274af9a1dd7494d3c52b2be5e6bd8d7e49c612705fd45420b12d"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44ceac0450e648de86da8e42674f9b7077d763ea80c8ceb9d1c3e41f0f0a9951"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:97209cc91189b48e7cfe777237c04af8e7cc51eb369004e061809bcdf4e55220"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:48dd18adcf98ea9cd721a25313aef49d70d413a999d7d89df44f469edfb38a06"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e59399dda559688461762800d7fb34d9e8a6a7444fd76ec33220a926c8be1516"}, - {file = "yarl-1.8.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:d617c241c8c3ad5c4e78a08429fa49e4b04bedfc507b34b4d8dceb83b4af3588"}, - {file = "yarl-1.8.2-cp39-cp39-win32.whl", hash = "sha256:cb6d48d80a41f68de41212f3dfd1a9d9898d7841c8f7ce6696cf2fd9cb57ef83"}, - {file = "yarl-1.8.2-cp39-cp39-win_amd64.whl", hash = "sha256:6604711362f2dbf7160df21c416f81fac0de6dbcf0b5445a2ef25478ecc4c778"}, - {file = "yarl-1.8.2.tar.gz", hash = "sha256:49d43402c6e3013ad0978602bf6bf5328535c48d192304b91b97a3c6790b1562"}, + {file = "win32_setctime-1.2.0-py3-none-any.whl", hash = "sha256:95d644c4e708aba81dc3704a116d8cbc974d70b3bdb8be1d150e36be6e9d1390"}, + {file = "win32_setctime-1.2.0.tar.gz", hash = "sha256:ae1fdf948f5640aae05c511ade119313fb6a30d7eabe25fef9764dca5873c4c0"}, ] -[package.dependencies] -idna = ">=2.0" -multidict = ">=4.0" +[package.extras] +dev = ["black (>=19.3b0)", "pytest (>=4.6.2)"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "7a56ac60a6f7bd62246c2b3be3ef53d80cc8ee4fc4785d7fa5abcf0b2298199c" +content-hash = "671b8c7eedbe5f9b589b3352706f384cd268f959449626fdaca2aaad0be79639" diff --git a/pyproject.toml b/pyproject.toml index 93b27af..e25e895 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,19 +5,29 @@ description = "The Last Library" authors = ["Mattie Casper"] license = "MIT" readme = "README.md" -include = ["default_files/**"] +include = ["cataclysm/default_files/**"] exclude = ["examples/**", "tests/**"] [tool.poetry.dependencies] python = "^3.10" -plunkylib = "^0.1.4" +chatsnack = { git = "https://github.com/Mattie/chatsnack.git", rev = "630ea4b5ce76b163833ad7c0b8d03072ec95d5a6" } loguru = "^0.6.0" -openai = "^0.27.2" datafiles = "^2.1" +"ruamel.yaml" = ">=0.18.10,<0.20.0" [tool.poetry.scripts] cataclysm = "cataclysm.__main__:main" +[tool.poetry.group.dev.dependencies] +pytest = "^9.0" + +[tool.pytest.ini_options] +markers = [ + "live: requires OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + "notebooks: notebook-derived tests", + "notebooks_live: live notebook cells that require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", +] + [build-system] requires = ["poetry-core"] build-backend = "poetry.core.masonry.api" diff --git a/tests/notebook_support.py b/tests/notebook_support.py new file mode 100644 index 0000000..b68782d --- /dev/null +++ b/tests/notebook_support.py @@ -0,0 +1,766 @@ +from __future__ import annotations + +import ast +import builtins +import json +import linecache +import math +import os +import re +import shlex +import shutil +import subprocess +import sys +import uuid +from contextlib import contextmanager +from dataclasses import dataclass, field +from pathlib import Path +from typing import Any + +import pytest + + +REPO_ROOT = Path(__file__).resolve().parents[1] +NOTEBOOKS_DIR = REPO_ROOT / "notebooks" +INPUT_TAG = "input" +SKIP_TEST_TAG = "skip_test" +ALLOWED_EXECUTION_TAGS = {INPUT_TAG, SKIP_TEST_TAG} +LEGACY_EXECUTION_TAGS = {"test", "live", "manual"} +LIVE_ENV_VALUES = {"1", "true", "yes"} +LIVE_CELL_SKIP_REASON = ( + "Notebook live cells require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1." +) + +_SHELL_LINE_RE = re.compile(r"^(?P\s*)!(?P.*)$") +_PYCAT_LINE_RE = re.compile(r"^(?P\s*)%pycat\s+(?P.+?)\s*$") +_TIMEIT_LINE_RE = re.compile(r"^(?P\s*)%timeit\s+(?P.+?)\s*$") + + +def live_notebook_cells_enabled() -> bool: + run_live = os.environ.get("CATACLYSM_RUN_LIVE_TESTS", "").lower() in LIVE_ENV_VALUES + return bool(os.environ.get("OPENAI_API_KEY")) and run_live + + +@dataclass(frozen=True) +class NotebookCell: + notebook_path: Path + notebook_name: str + notebook_cell_index: int + code_cell_ordinal: int + tags: tuple[str, ...] + source: str + original_source: str + defined_names: frozenset[str] = field(default_factory=frozenset) + dependency_map: dict[str, int] = field(default_factory=dict) + parse_error: str | None = None + + @property + def pytest_id(self) -> str: + return f"{self.notebook_name}::cell_{self.notebook_cell_index}" + + @property + def synthetic_filename(self) -> str: + return f"{self.notebook_path}::cell_{self.notebook_cell_index}" + + @property + def execution_tags(self) -> tuple[str, ...]: + known = ALLOWED_EXECUTION_TAGS | LEGACY_EXECUTION_TAGS + return tuple(tag for tag in self.tags if tag in known) + + @property + def legacy_execution_tags(self) -> tuple[str, ...]: + return tuple(tag for tag in self.tags if tag in LEGACY_EXECUTION_TAGS) + + @property + def skip_for_input(self) -> bool: + return INPUT_TAG in self.tags + + @property + def skip_for_test(self) -> bool: + return SKIP_TEST_TAG in self.tags + + +@dataclass(frozen=True) +class NotebookDocument: + path: Path + cells: tuple[NotebookCell, ...] + + @property + def name(self) -> str: + return self.path.name + + def cell_for_index(self, notebook_cell_index: int) -> NotebookCell: + for cell in self.cells: + if cell.notebook_cell_index == notebook_cell_index: + return cell + raise KeyError(f"{self.path.name} has no code cell {notebook_cell_index}") + + def prior_defining_cell(self, name: str, before_index: int) -> NotebookCell | None: + for cell in reversed(self.cells): + if cell.notebook_cell_index >= before_index: + continue + if name in cell.defined_names: + return cell + return None + + +@dataclass(frozen=True) +class CellExecutionRecord: + status: str + reason: str | None = None + + +class _TopLevelNameAnalyzer(ast.NodeVisitor): + def __init__(self) -> None: + self.defined_names: set[str] = set() + self.loaded_names: set[str] = set() + + def visit_FunctionDef(self, node: ast.FunctionDef) -> None: + self.defined_names.add(node.name) + self._visit_function_signature(node) + + def visit_AsyncFunctionDef(self, node: ast.AsyncFunctionDef) -> None: + self.defined_names.add(node.name) + self._visit_function_signature(node) + + def visit_ClassDef(self, node: ast.ClassDef) -> None: + self.defined_names.add(node.name) + for decorator in node.decorator_list: + self.visit(decorator) + for base in node.bases: + self.visit(base) + for keyword in node.keywords: + self.visit(keyword.value) + + def visit_Lambda(self, node: ast.Lambda) -> None: + self._visit_arguments(node.args) + + def visit_Import(self, node: ast.Import) -> None: + for alias in node.names: + self.defined_names.add(alias.asname or alias.name.split(".")[0]) + + def visit_ImportFrom(self, node: ast.ImportFrom) -> None: + for alias in node.names: + self.defined_names.add(alias.asname or alias.name) + + def visit_Name(self, node: ast.Name) -> None: + if isinstance(node.ctx, ast.Store): + self.defined_names.add(node.id) + elif isinstance(node.ctx, ast.Load): + self.loaded_names.add(node.id) + + def _visit_function_signature( + self, + node: ast.FunctionDef | ast.AsyncFunctionDef, + ) -> None: + for decorator in node.decorator_list: + self.visit(decorator) + self._visit_arguments(node.args) + if node.returns is not None: + self.visit(node.returns) + + def _visit_arguments(self, args: ast.arguments) -> None: + for arg in list(args.posonlyargs) + list(args.args) + list(args.kwonlyargs): + if arg.annotation is not None: + self.visit(arg.annotation) + if args.vararg and args.vararg.annotation is not None: + self.visit(args.vararg.annotation) + if args.kwarg and args.kwarg.annotation is not None: + self.visit(args.kwarg.annotation) + for default in list(args.defaults) + [d for d in args.kw_defaults if d is not None]: + self.visit(default) + + +def load_notebook_documents() -> tuple[NotebookDocument, ...]: + documents: list[NotebookDocument] = [] + for path in sorted(NOTEBOOKS_DIR.glob("*.ipynb")): + data = json.loads(path.read_text(encoding="utf-8")) + cells: list[NotebookCell] = [] + prior_name_sources: dict[str, int] = {} + code_cell_ordinal = 0 + for notebook_cell_index, raw_cell in enumerate(data.get("cells", []), start=1): + if raw_cell.get("cell_type") != "code": + continue + code_cell_ordinal += 1 + metadata = raw_cell.get("metadata", {}) + tags = tuple(metadata.get("tags", [])) + original_source = "".join(raw_cell.get("source", [])) + source = _transform_notebook_source(original_source) + defined_names, loaded_names, parse_error = _analyze_cell_source(source) + dependency_map = { + name: prior_name_sources[name] + for name in loaded_names + if name in prior_name_sources + } + cell = NotebookCell( + notebook_path=path, + notebook_name=path.name, + notebook_cell_index=notebook_cell_index, + code_cell_ordinal=code_cell_ordinal, + tags=tags, + source=source, + original_source=original_source, + defined_names=defined_names, + dependency_map=dependency_map, + parse_error=parse_error, + ) + cells.append(cell) + for name in defined_names: + prior_name_sources[name] = notebook_cell_index + documents.append(NotebookDocument(path=path, cells=tuple(cells))) + return tuple(documents) + + +def iter_notebook_cells() -> tuple[NotebookCell, ...]: + cells: list[NotebookCell] = [] + for document in load_notebook_documents(): + cells.extend(document.cells) + return tuple(cells) + + +def notebook_test_params() -> list[pytest.ParameterSet]: + params: list[pytest.ParameterSet] = [] + for cell in iter_notebook_cells(): + marks = [] + if not cell.skip_for_input and not cell.skip_for_test: + marks.extend([pytest.mark.live, pytest.mark.notebooks_live]) + params.append(pytest.param(cell, id=cell.pytest_id, marks=marks)) + return params + + +class NotebookRunner: + def __init__(self, notebook: NotebookDocument, workspace_root: Path) -> None: + self.notebook = notebook + workspace_root.mkdir(parents=True, exist_ok=True) + self.workdir = _make_unique_directory(workspace_root, _slugify(notebook.path.stem)) + self.env = _notebook_env(self.workdir) + self.globals: dict[str, Any] = { + "__builtins__": builtins.__dict__, + "__name__": "__notebook__", + "__package__": None, + "__file__": str(notebook.path), + "__notebook_shell__": self._run_shell_cell, + "__notebook_pycat__": self._run_pycat, + "__notebook_timeit__": self._run_timeit, + } + self.execution_ledger: dict[int, CellExecutionRecord] = {} + self._ensure_repo_root_on_path() + self._seed_notebook_assets() + + def ensure_cell(self, notebook_cell_index: int) -> None: + __tracebackhide__ = True + target_cell = self.notebook.cell_for_index(notebook_cell_index) + target_record = self.execution_ledger.get(notebook_cell_index) + if target_record is not None: + self._finalize_target(target_cell, target_record) + return + + for cell in self.notebook.cells: + if cell.notebook_cell_index > notebook_cell_index: + break + if cell.notebook_cell_index in self.execution_ledger: + continue + + blocking_reason = self._blocking_reason(cell) + if blocking_reason is not None: + self.execution_ledger[cell.notebook_cell_index] = CellExecutionRecord( + status="skipped", + reason=blocking_reason, + ) + continue + + try: + self._execute_cell(cell) + except pytest.skip.Exception as exc: + self.execution_ledger[cell.notebook_cell_index] = CellExecutionRecord( + status="skipped", + reason=str(exc), + ) + continue + except Exception as exc: + reason = f"{type(exc).__name__}: {exc}" + self.execution_ledger[cell.notebook_cell_index] = CellExecutionRecord( + status="failed", + reason=reason, + ) + if cell.notebook_cell_index == notebook_cell_index: + raise + + target_record = self.execution_ledger[notebook_cell_index] + self._finalize_target(target_cell, target_record) + + def _ensure_repo_root_on_path(self) -> None: + repo_root = str(REPO_ROOT) + if repo_root not in sys.path: + sys.path.insert(0, repo_root) + + def _seed_notebook_assets(self) -> None: + notebook_dir = self.notebook.path.parent + for sibling in notebook_dir.iterdir(): + if sibling == self.notebook.path: + continue + destination = self.workdir / sibling.name + if sibling.is_dir(): + shutil.copytree(sibling, destination, dirs_exist_ok=True) + elif sibling.is_file() and sibling.suffix != ".ipynb": + shutil.copy2(sibling, destination) + + def _execute_cell(self, cell: NotebookCell) -> None: + __tracebackhide__ = True + if cell.parse_error is not None: + raise SyntaxError(cell.parse_error) + + _register_cell_source_in_linecache(cell) + code = compile(cell.source, cell.synthetic_filename, "exec") + self.globals["__file__"] = cell.synthetic_filename + with _temporary_env(self.env), _temporary_cwd(self.workdir): + try: + exec(code, self.globals, self.globals) + _assert_notebook_cell_state(cell, self.globals) + except NameError as exc: + missing_name = _missing_name_from_error(exc) + if missing_name: + blocking_reason = self._missing_name_blocking_reason( + missing_name, + cell, + ) + if blocking_reason is not None: + raise pytest.skip.Exception(blocking_reason) + _add_notebook_cell_exception_note(exc, cell, self.workdir) + raise + except BaseException as exc: + if isinstance(exc, pytest.skip.Exception): + raise + _add_notebook_cell_exception_note(exc, cell, self.workdir) + raise + self.execution_ledger[cell.notebook_cell_index] = CellExecutionRecord(status="completed") + + def _run_shell_cell(self, command: str) -> None: + __tracebackhide__ = True + parsed = shlex.split(command, posix=False) + normalized = [part.lower() for part in parsed] + if normalized[:3] == ["pip", "install", "cataclysm"]: + __import__("cataclysm") + return + if normalized[:2] == ["cataclysm", "init"]: + from cataclysm import initialize_datafiles + + initialize_datafiles(str(self.workdir)) + return + + result = subprocess.run( + command, + cwd=self.workdir, + env=self.env, + shell=True, + text=True, + capture_output=True, + check=False, + ) + if result.returncode == 0: + if result.stdout: + sys.stdout.write(result.stdout) + if result.stderr: + sys.stderr.write(result.stderr) + return + + if result.stdout: + sys.stdout.write(result.stdout) + if result.stderr: + sys.stderr.write(result.stderr) + exc = subprocess.CalledProcessError( + result.returncode, + result.args, + output=result.stdout, + stderr=result.stderr, + ) + _add_shell_command_exception_note(exc, command=command, cwd=self.workdir) + raise exc + + def _run_pycat(self, target_path: str) -> None: + __tracebackhide__ = True + path = (self.workdir / target_path).resolve() + if not _is_relative_to(path, self.workdir.resolve()): + raise ValueError(f"%pycat target escapes notebook workdir: {target_path}") + print(path.read_text(encoding="utf-8")) + + def _run_timeit(self, command: str) -> None: + __tracebackhide__ = True + expression = _strip_timeit_options(command) + exec(expression, self.globals, self.globals) + + def _blocking_reason(self, cell: NotebookCell) -> str | None: + failed_prerequisite = self._first_prior_status(cell, "failed") + if failed_prerequisite is not None: + return ( + f"Blocked by failing prerequisite cell " + f"{failed_prerequisite.notebook_cell_index}: " + f"{self.execution_ledger[failed_prerequisite.notebook_cell_index].reason}" + ) + + if cell.skip_for_test: + return "Notebook cell is tagged skip_test." + + if cell.skip_for_input: + return "Notebook cell is tagged input." + + if not live_notebook_cells_enabled(): + return LIVE_CELL_SKIP_REASON + + for name, dependency_cell_index in cell.dependency_map.items(): + dependency_record = self.execution_ledger.get(dependency_cell_index) + if dependency_record is None or dependency_record.status == "completed": + continue + dependency_cell = self.notebook.cell_for_index(dependency_cell_index) + return ( + f"Blocked by prerequisite cell {dependency_cell.notebook_cell_index} " + f"for '{name}': {dependency_record.reason}" + ) + return None + + def _finalize_target(self, cell: NotebookCell, record: CellExecutionRecord) -> None: + if record.status == "completed": + return + if record.status == "skipped": + raise pytest.skip.Exception(record.reason or "Notebook cell skipped.") + raise RuntimeError( + f"{cell.pytest_id} previously failed during replay: {record.reason}" + ) + + def _first_prior_status( + self, + cell: NotebookCell, + status: str, + ) -> NotebookCell | None: + for prior_cell in self.notebook.cells: + if prior_cell.notebook_cell_index >= cell.notebook_cell_index: + break + prior = self.execution_ledger.get( + prior_cell.notebook_cell_index, + CellExecutionRecord("pending"), + ) + if prior.status == status: + return prior_cell + return None + + def _missing_name_blocking_reason(self, missing_name: str, cell: NotebookCell) -> str | None: + dependency_cell = self.notebook.prior_defining_cell( + missing_name, + before_index=cell.notebook_cell_index, + ) + if dependency_cell is None: + return None + dependency_record = self.execution_ledger.get(dependency_cell.notebook_cell_index) + if dependency_record is None or dependency_record.status == "completed": + return None + return ( + f"Blocked by prerequisite cell {dependency_cell.notebook_cell_index} " + f"for '{missing_name}': {dependency_record.reason}" + ) + + +def _analyze_cell_source(source: str) -> tuple[frozenset[str], set[str], str | None]: + try: + tree = ast.parse(source) + except SyntaxError as exc: + return frozenset(), set(), exc.msg + + analyzer = _TopLevelNameAnalyzer() + analyzer.visit(tree) + return frozenset(analyzer.defined_names), set(analyzer.loaded_names), None + + +def _transform_notebook_source(source: str) -> str: + transformed_lines: list[str] = [] + for line in source.splitlines(keepends=True): + shell_match = _SHELL_LINE_RE.match(line) + if shell_match is not None: + indent = shell_match.group("indent") + command = shell_match.group("command").rstrip("\r\n") + newline = "\n" if line.endswith("\n") else "" + transformed_lines.append(f"{indent}__notebook_shell__({command!r}){newline}") + continue + + pycat_match = _PYCAT_LINE_RE.match(line) + if pycat_match is not None: + indent = pycat_match.group("indent") + target_path = pycat_match.group("path").strip() + newline = "\n" if line.endswith("\n") else "" + transformed_lines.append(f"{indent}__notebook_pycat__({target_path!r}){newline}") + continue + + timeit_match = _TIMEIT_LINE_RE.match(line) + if timeit_match is not None: + indent = timeit_match.group("indent") + command = timeit_match.group("command").rstrip("\r\n") + newline = "\n" if line.endswith("\n") else "" + transformed_lines.append(f"{indent}__notebook_timeit__({command!r}){newline}") + continue + + transformed_lines.append(line) + return "".join(transformed_lines) + + +def _strip_timeit_options(command: str) -> str: + parts = shlex.split(command, posix=False) + index = 0 + while index < len(parts): + part = parts[index] + if part in {"-n", "-r"} and index + 1 < len(parts): + index += 2 + continue + if part.startswith("-"): + index += 1 + continue + break + expression = " ".join(parts[index:]).strip() + if not expression: + raise ValueError(f"Could not find expression in %timeit command: {command}") + return expression + + +def _notebook_env(workdir: Path) -> dict[str, str]: + env = os.environ.copy() + pythonpath = str(REPO_ROOT) + if env.get("PYTHONPATH"): + pythonpath += os.pathsep + env["PYTHONPATH"] + env.update( + { + "PYTHONPATH": pythonpath, + "CHATSNACK_BASE_DIR": str(workdir / "datafiles" / "chatsnack"), + "CATACLYSM_BASE_DIR": str(workdir / "datafiles" / "cataclysm"), + "CATACLYSM_LOGS_DIR": str(workdir / "logs"), + } + ) + return env + + +@contextmanager +def _temporary_cwd(path: Path): + original = Path.cwd() + os.chdir(path) + try: + yield + finally: + os.chdir(original) + + +@contextmanager +def _temporary_env(env: dict[str, str]): + old_values: dict[str, str | None] = {} + for key, value in env.items(): + old_values[key] = os.environ.get(key) + os.environ[key] = value + try: + yield + finally: + for key, old_value in old_values.items(): + if old_value is None: + os.environ.pop(key, None) + else: + os.environ[key] = old_value + + +def _missing_name_from_error(exc: NameError) -> str | None: + match = re.search(r"name '([^']+)' is not defined", str(exc)) + if match: + return match.group(1) + return None + + +def _slugify(value: str) -> str: + slug = re.sub(r"[^a-zA-Z0-9]+", "-", value).strip("-").lower() + return f"notebook-{slug or 'run'}-" + + +def _make_unique_directory(parent: Path, prefix: str) -> Path: + for _ in range(20): + candidate = parent / f"{prefix}{uuid.uuid4().hex[:8]}" + try: + candidate.mkdir(parents=True, exist_ok=False) + return candidate + except FileExistsError: + continue + raise RuntimeError(f"Could not create a unique directory under {parent}") + + +def _register_cell_source_in_linecache(cell: NotebookCell) -> None: + linecache.cache[cell.synthetic_filename] = ( + len(cell.original_source), + None, + cell.original_source.splitlines(keepends=True), + cell.synthetic_filename, + ) + + +def _add_notebook_cell_exception_note( + exc: BaseException, + cell: NotebookCell, + workdir: Path, +) -> None: + note = ( + "Notebook cell context:\n" + f"notebook: {cell.notebook_name}\n" + f"cell: {cell.notebook_cell_index}\n" + f"workdir: {workdir}\n" + "cell source:\n" + f"{cell.original_source.rstrip()}" + ) + _add_exception_note_once(exc, note) + + +def _add_shell_command_exception_note( + exc: BaseException, + *, + command: str, + cwd: Path, +) -> None: + note = ( + "Notebook shell command failed:\n" + f"command: {command}\n" + f"exit code: {getattr(exc, 'returncode', 'unknown')}\n" + f"cwd: {cwd}" + ) + _add_exception_note_once(exc, note) + + +def _add_exception_note_once(exc: BaseException, note: str) -> None: + notes = getattr(exc, "__notes__", ()) + if note in notes: + return + if hasattr(exc, "add_note"): + exc.add_note(note) + else: + exc.__notes__ = (*notes, note) + + +def _is_relative_to(path: Path, parent: Path) -> bool: + try: + path.relative_to(parent) + return True + except ValueError: + return False + + +def _assert_notebook_cell_state(cell: NotebookCell, globals_dict: dict[str, Any]) -> None: + if cell.notebook_name != "GettingStartedWithTheEnd-cataclysm.ipynb": + return + + expectations = { + 9: _assert_first_shortest_path, + 11: _assert_second_shortest_path, + 21: _assert_impending_code, + 24: _assert_celsius_conversion, + 28: _assert_first_three_digit_prime, + 30: _assert_palindrome_result, + 33: _assert_person_class_example, + 34: _assert_compound_interest_example, + } + assertion = expectations.get(cell.notebook_cell_index) + if assertion is not None: + assertion(globals_dict) + + +def _assert_first_shortest_path(globals_dict: dict[str, Any]) -> None: + _assert_shortest_path(globals_dict, "shortest_path", "A", "D") + + +def _assert_second_shortest_path(globals_dict: dict[str, Any]) -> None: + _assert_shortest_path(globals_dict, "shortest_path2", "D", "A") + + +def _assert_shortest_path( + globals_dict: dict[str, Any], + variable_name: str, + start: str, + end: str, +) -> None: + graph = globals_dict["graph"] + path = _coerce_path(globals_dict[variable_name]) + assert path[0] == start + assert path[-1] == end + assert _path_cost(graph, path) == _dijkstra_cost(graph, start, end) + + +def _coerce_path(value: Any) -> list[str]: + if isinstance(value, dict): + for key in ("path", "shortest_path", "nodes"): + if key in value: + return _coerce_path(value[key]) + if isinstance(value, tuple): + for item in value: + if isinstance(item, (list, tuple, str)): + path = _coerce_path(item) + if path: + return path + if isinstance(value, str): + return re.findall(r"\b[A-Z]\b", value) + if isinstance(value, (list, tuple)): + return [str(item) for item in value] + raise AssertionError(f"Could not interpret shortest path value: {value!r}") + + +def _path_cost(graph: dict[str, dict[str, int]], path: list[str]) -> int: + total = 0 + for left, right in zip(path, path[1:]): + total += graph[left][right] + return total + + +def _dijkstra_cost(graph: dict[str, dict[str, int]], start: str, end: str) -> int: + unvisited = set(graph) + distances = {node: math.inf for node in graph} + distances[start] = 0 + while unvisited: + current = min(unvisited, key=lambda node: distances[node]) + unvisited.remove(current) + if current == end: + return int(distances[current]) + for neighbor, cost in graph[current].items(): + if neighbor in unvisited: + distances[neighbor] = min(distances[neighbor], distances[current] + cost) + raise AssertionError(f"No path from {start} to {end}") + + +def _assert_impending_code(globals_dict: dict[str, Any]) -> None: + src = globals_dict["_doomed_code_str"] + assert isinstance(src, str) + assert "_exec_return_values" in src + + +def _assert_celsius_conversion(globals_dict: dict[str, Any]) -> None: + assert globals_dict["newlist"] == [32, 77, 212] + + +def _assert_first_three_digit_prime(globals_dict: dict[str, Any]) -> None: + assert globals_dict["uhoh"] == 101 + + +def _assert_palindrome_result(globals_dict: dict[str, Any]) -> None: + assert globals_dict["is_palindrome"] is True + + +def _assert_person_class_example(globals_dict: dict[str, Any]) -> None: + person1 = globals_dict["person1"] + person2 = globals_dict["person2"] + assert person1.get_full_name() == "John Doe" + assert person1.is_adult() is True + assert person2.get_full_name() == "Jane Doe" + assert person2.is_adult() is False + + +def _assert_compound_interest_example(globals_dict: dict[str, Any]) -> None: + future_value = float(globals_dict["future_value"]) + total_interest = float(globals_dict["total_interest"]) + effective_interest_rate = float(globals_dict["effective_interest_rate"]) + + expected_future_value = 300000 * (1 + 0.045 / 12) ** (12 * 5) + expected_effective_interest_rate = (1 + 0.045 / 12) ** 12 - 1 + assert math.isclose(future_value, expected_future_value, rel_tol=1e-4, abs_tol=1) + assert math.isclose(total_interest, future_value - 300000, rel_tol=1e-4, abs_tol=1) + assert math.isclose( + effective_interest_rate, + expected_effective_interest_rate, + rel_tol=1e-4, + abs_tol=0.001, + ) diff --git a/tests/test_chatsnack_adapter.py b/tests/test_chatsnack_adapter.py new file mode 100644 index 0000000..98aada1 --- /dev/null +++ b/tests/test_chatsnack_adapter.py @@ -0,0 +1,288 @@ +from dataclasses import dataclass + +import pytest + +from cataclysm import chatsnack_adapter + + +@dataclass +class FakeParams: + model: str = None + max_tokens: int = None + runtime: str = None + responses: dict = None + stop: list = None + temperature: float = None + top_p: float = None + frequency_penalty: float = None + presence_penalty: float = None + auto_execute: bool = None + auto_feed: bool = None + + +class FakeChat: + instances = [] + response_text = "analysis\n#|~~\n_exec_return_values = 42\n#~~|\n" + + def __init__(self, **kwargs): + self.kwargs = kwargs + self.params = kwargs.get("params") + self.messages = kwargs.get("messages") + self.utensils = kwargs.get("utensils") + self.asked_with = None + self.instances.append(self) + + def ask(self, **kwargs): + self.asked_with = kwargs + return self.response_text + + +class ToolCallingFakeChat(FakeChat): + def chat(self, **kwargs): + self.chatted_with = kwargs + for utensil_item in self.utensils: + if hasattr(utensil_item, "utensils"): + for utensil_function in utensil_item.utensils: + if utensil_function.name == "submit_exec_body": + utensil_function(code="_exec_return_values = 99\n") + return self + + +def _write_primary_chat(base_dir): + base_dir.mkdir(parents=True) + (base_dir / "CataclysmQuery.yml").write_text( + """ +params: + model: test-model + runtime: responses + responses: + max_output_tokens: 123 +messages: + - system: Primary prompt + - user: "{arg1}" +""".lstrip(), + encoding="utf-8", + ) + + +def _write_legacy_chat(base_dir): + (base_dir / "petition").mkdir(parents=True) + (base_dir / "prompts").mkdir() + (base_dir / "params").mkdir() + (base_dir / "petition" / "CataclysmQuery.yml").write_text( + """ +params_name: CataclysmLLMParams +chatprompt_name: CataclysmPrompt +""".lstrip(), + encoding="utf-8", + ) + (base_dir / "prompts" / "CataclysmPrompt.yml").write_text( + """ +messages: + - system: Legacy prompt + - user: "{arg1}" +""".lstrip(), + encoding="utf-8", + ) + (base_dir / "params" / "CataclysmLLMParams.yml").write_text( + """ +engine: gpt-4-0314 +max_tokens: 1200 +temperature: 0.0 +""".lstrip(), + encoding="utf-8", + ) + + +def test_generate_code_falls_back_to_marker_text(monkeypatch, tmp_path): + FakeChat.instances = [] + chat_dir = tmp_path / "chatsnack" + _write_primary_chat(chat_dir) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + code = chatsnack_adapter.generate_code_with_chatsnack( + "formatted context", + chat_cls=FakeChat, + params_cls=FakeParams, + ) + + assert code == "_exec_return_values = 42\n" + assert FakeChat.instances[-1].asked_with == {"arg1": "formatted context"} + + +def test_generate_code_uses_submit_exec_body_utensil(monkeypatch, tmp_path): + ToolCallingFakeChat.instances = [] + chat_dir = tmp_path / "chatsnack" + _write_primary_chat(chat_dir) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + code = chatsnack_adapter.generate_code_with_chatsnack( + "formatted context", + utensils=["internal-tool"], + chat_cls=ToolCallingFakeChat, + params_cls=FakeParams, + ) + chat = ToolCallingFakeChat.instances[-1] + + assert code == "_exec_return_values = 99\n" + assert chat.chatted_with == {"arg1": "formatted context"} + assert chat.kwargs["auto_execute"] is True + assert chat.kwargs["auto_feed"] is False + assert chat.tool_choice == {"type": "function", "name": "submit_exec_body"} + assert len(chat.utensils) == 2 + assert getattr(chat.utensils[0], "name") == "cataclysm" + assert chat.utensils[1] == "internal-tool" + + +def test_extract_code_from_response_removes_markers(): + response = "analysis first\n#|~~\n_exec_return_values = 1\n#~~|\nignored" + + assert chatsnack_adapter.extract_code_from_response(response) == "_exec_return_values = 1\n" + + +def test_extract_code_from_response_requires_start_marker(): + with pytest.raises(ValueError, match="code marker"): + chatsnack_adapter.extract_code_from_response("_exec_return_values = 1") + + +def test_validate_generated_code_rejects_placeholder_body(): + with pytest.raises(ValueError, match="placeholder"): + chatsnack_adapter.validate_generated_code("# code here\n") + + +def test_validate_generated_code_rejects_body_without_return_assignment_or_raise(): + with pytest.raises(ValueError, match="_exec_return_values"): + chatsnack_adapter.validate_generated_code("result = 12\n") + + +def test_validate_generated_code_accepts_exec_return_assignment(): + code = "_exec_return_values = args_in[0] + args_in[1]\n" + + assert chatsnack_adapter.validate_generated_code(code) == code + + +def test_primary_chatsnack_yaml_loads(monkeypatch, tmp_path): + chat_dir = tmp_path / "chatsnack" + _write_primary_chat(chat_dir) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + chat = chatsnack_adapter.load_cataclysm_chat(chat_cls=FakeChat, params_cls=FakeParams) + + assert chat.params.model == "test-model" + assert chat.params.runtime == "responses" + assert chat.params.responses == {"max_output_tokens": 123} + assert chat.messages[0]["system"] == "Primary prompt" + + +def test_primary_yaml_builds_real_chatsnack_chat(monkeypatch, tmp_path): + chat_dir = tmp_path / "chatsnack" + _write_primary_chat(chat_dir) + monkeypatch.chdir(tmp_path) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + capture = chatsnack_adapter.SubmittedCodeCapture() + utensils = chatsnack_adapter._build_submit_exec_body_utensils(capture, None) + chat = chatsnack_adapter.load_cataclysm_chat( + utensils=utensils, + auto_execute=True, + auto_feed=False, + ) + + assert chat.model == "test-model" + assert chat.messages[1]["user"] == "{arg1}" + + +def test_primary_yaml_uses_responses_compatible_request_shape(monkeypatch, tmp_path): + chat_dir = tmp_path / "chatsnack" + _write_primary_chat(chat_dir) + monkeypatch.chdir(tmp_path) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + capture = chatsnack_adapter.SubmittedCodeCapture() + utensils = chatsnack_adapter._build_submit_exec_body_utensils(capture, None) + chat = chatsnack_adapter.load_cataclysm_chat( + utensils=utensils, + auto_execute=True, + auto_feed=False, + ) + chatsnack_adapter._force_submit_exec_body_tool(chat) + kwargs = chat._build_completion_request_kwargs() + + assert type(chat.runtime).__name__ == "ResponsesAdapter" + assert kwargs["model"] == "test-model" + assert kwargs["max_output_tokens"] == 123 + assert kwargs["tool_choice"] == {"type": "function", "name": "submit_exec_body"} + assert "max_completion_tokens" not in kwargs + assert "stop" not in kwargs + assert "frequency_penalty" not in kwargs + assert "presence_penalty" not in kwargs + + +def test_legacy_plunkylib_yaml_fallback_maps_engine_to_model(monkeypatch, tmp_path): + chatsnack_dir = tmp_path / "missing-chatsnack" + legacy_dir = tmp_path / "plunkylib" + _write_legacy_chat(legacy_dir) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chatsnack_dir)) + monkeypatch.setenv("PLUNKYLIB_BASE_DIR", str(legacy_dir)) + + chat = chatsnack_adapter.load_cataclysm_chat(chat_cls=FakeChat, params_cls=FakeParams) + + assert chat.params.model == "gpt-4-0314" + assert chat.params.max_tokens == 1200 + assert chat.params.runtime == "chat_completions" + assert chat.messages[0]["system"] == "Legacy prompt" + + +def test_missing_primary_and_legacy_yaml_raises_actionable_error(monkeypatch, tmp_path): + chatsnack_dir = tmp_path / "missing-chatsnack" + legacy_dir = tmp_path / "missing-plunkylib" + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chatsnack_dir)) + monkeypatch.setenv("PLUNKYLIB_BASE_DIR", str(legacy_dir)) + + with pytest.raises(FileNotFoundError) as exc_info: + chatsnack_adapter.load_cataclysm_chat(chat_cls=FakeChat, params_cls=FakeParams) + + message = str(exc_info.value) + assert "Cataclysm chat configuration" in message + assert "cataclysm init" in message + assert "CHATSNACK_BASE_DIR" in message + assert str(chatsnack_dir / "CataclysmQuery.yml") in message + + +def test_legacy_fallback_uses_chat_completion_runtime(monkeypatch, tmp_path): + chatsnack_dir = tmp_path / "missing-chatsnack" + legacy_dir = tmp_path / "plunkylib" + _write_legacy_chat(legacy_dir) + monkeypatch.chdir(tmp_path) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chatsnack_dir)) + monkeypatch.setenv("PLUNKYLIB_BASE_DIR", str(legacy_dir)) + + capture = chatsnack_adapter.SubmittedCodeCapture() + utensils = chatsnack_adapter._build_submit_exec_body_utensils(capture, None) + chat = chatsnack_adapter.load_cataclysm_chat( + utensils=utensils, + auto_execute=True, + auto_feed=False, + ) + chatsnack_adapter._force_submit_exec_body_tool(chat) + kwargs = chat._build_completion_request_kwargs() + + assert type(chat.runtime).__name__ == "ChatCompletionsAdapter" + assert kwargs["model"] == "gpt-4-0314" + assert kwargs["max_completion_tokens"] == 1200 + assert kwargs["tool_choice"] == {"type": "function", "function": {"name": "submit_exec_body"}} + + +def test_internal_utensils_are_passed_to_chat(monkeypatch, tmp_path): + chat_dir = tmp_path / "chatsnack" + utensil = object() + _write_primary_chat(chat_dir) + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(chat_dir)) + + chat = chatsnack_adapter.load_cataclysm_chat( + utensils=[utensil], + chat_cls=FakeChat, + params_cls=FakeParams, + ) + + assert chat.utensils == [utensil] diff --git a/tests/test_docs_examples_offline.py b/tests/test_docs_examples_offline.py new file mode 100644 index 0000000..f338335 --- /dev/null +++ b/tests/test_docs_examples_offline.py @@ -0,0 +1,73 @@ +from pathlib import Path + +from tests.notebook_support import load_notebook_documents + + +REPO_ROOT = Path(__file__).resolve().parents[1] +README_PATH = REPO_ROOT / "README.md" + + +def _readme_section(readme: str, heading: str) -> str: + start = readme.index(heading) + next_heading = readme.find("\n### ", start + len(heading)) + if next_heading == -1: + return readme[start:] + return readme[start:next_heading] + + +def test_readme_keeps_core_usage_and_configuration_examples(): + readme = README_PATH.read_text(encoding="utf-8") + + expected_fragments = [ + "from cataclysm import consume", + "consume(globals())", + "from cataclysm import doom", + "doom.impending", + "doom.chosen", + "cataclysm init", + "OPENAI_API_KEY", + "datafiles/chatsnack/CataclysmQuery.yml", + ] + + missing = [fragment for fragment in expected_fragments if fragment not in readme] + assert missing == [] + + +def test_readme_chosen_doom_section_uses_chosen_api(): + readme = README_PATH.read_text(encoding="utf-8") + chosen_section = _readme_section(readme, "### **Chosen Doom**") + + assert "doom.chosen" in chosen_section + + +def test_notebook_examples_transform_into_valid_python(): + issues = [] + + for document in load_notebook_documents(): + for cell in document.cells: + if cell.parse_error is not None: + issues.append(f"{document.name} cell {cell.notebook_cell_index}: {cell.parse_error}") + continue + try: + compile(cell.source, cell.synthetic_filename, "exec") + except SyntaxError as exc: + issues.append(f"{document.name} cell {cell.notebook_cell_index}: {exc.msg}") + + assert issues == [] + + +def test_notebook_keeps_presented_cataclysm_entrypoints(): + joined_sources = "\n".join( + cell.original_source + for document in load_notebook_documents() + for cell in document.cells + ) + + expected_fragments = [ + "consume(globals())", + "doom.", + "doom.impending", + ] + + missing = [fragment for fragment in expected_fragments if fragment not in joined_sources] + assert missing == [] diff --git a/tests/test_doom_basics.py b/tests/test_doom_basics.py index a11160c..56c9838 100644 --- a/tests/test_doom_basics.py +++ b/tests/test_doom_basics.py @@ -1,6 +1,15 @@ import pytest +import os from cataclysm import doom +pytestmark = [ + pytest.mark.live, + pytest.mark.skipif( + os.getenv("CATACLYSM_RUN_LIVE_TESTS") != "1" or not os.getenv("OPENAI_API_KEY"), + reason="live doom tests require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + ), +] + # TODO Add a setup to clear the code cache def test_add_numbers(): @@ -62,4 +71,4 @@ def test_sum_of_squares(): result = doom.sum_of_squares([2, 2, 3]) assert result != 14 -# To run tests, execute the command `pytest .py` \ No newline at end of file +# To run tests, execute the command `pytest .py` diff --git a/tests/test_doom_callstack.py b/tests/test_doom_callstack.py index bbf885f..73c72aa 100644 --- a/tests/test_doom_callstack.py +++ b/tests/test_doom_callstack.py @@ -1,6 +1,15 @@ import pytest +import os from cataclysm import doom +pytestmark = [ + pytest.mark.live, + pytest.mark.skipif( + os.getenv("CATACLYSM_RUN_LIVE_TESTS") != "1" or not os.getenv("OPENAI_API_KEY"), + reason="live doom tests require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + ), +] + # TODO Add a setup to clear the code cache def level_19(x): """ We have docstrings in each of these to make things interesting""" diff --git a/tests/test_doom_impending_basics.py b/tests/test_doom_impending_basics.py index 122982d..4901aaa 100644 --- a/tests/test_doom_impending_basics.py +++ b/tests/test_doom_impending_basics.py @@ -1,6 +1,15 @@ import pytest +import os from cataclysm import doom +pytestmark = [ + pytest.mark.live, + pytest.mark.skipif( + os.getenv("CATACLYSM_RUN_LIVE_TESTS") != "1" or not os.getenv("OPENAI_API_KEY"), + reason="live doom tests require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + ), +] + # TODO Add a setup to clear the code cache # def _impending_exec_wrapper(*args_in, **kwargs_in): @@ -48,4 +57,4 @@ def test_impending_base(): -# To run tests, execute the command `pytest .py` \ No newline at end of file +# To run tests, execute the command `pytest .py` diff --git a/tests/test_doom_inspection.py b/tests/test_doom_inspection.py index db4576b..106d7c5 100644 --- a/tests/test_doom_inspection.py +++ b/tests/test_doom_inspection.py @@ -1,6 +1,15 @@ import pytest +import os from cataclysm import doom +pytestmark = [ + pytest.mark.live, + pytest.mark.skipif( + os.getenv("CATACLYSM_RUN_LIVE_TESTS") != "1" or not os.getenv("OPENAI_API_KEY"), + reason="live doom tests require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + ), +] + # TODO Add a setup to clear the code cache # NOTE: This test file is testing inspection of keyword args, comments and docstrings. diff --git a/tests/test_doom_offline.py b/tests/test_doom_offline.py new file mode 100644 index 0000000..9d21a72 --- /dev/null +++ b/tests/test_doom_offline.py @@ -0,0 +1,75 @@ +import subprocess +import sys + +from cataclysm import doomed + + +def test_generate_fresh_code_passes_formatted_info_and_utensils(monkeypatch): + calls = [] + + def fake_generate(formatted_info, utensils=None): + calls.append((formatted_info, utensils)) + return "_exec_return_values = 5\n" + + monkeypatch.setattr(doomed, "generate_code_with_chatsnack", fake_generate) + creator = doomed.CataclysmCreator(_utensils=["internal-tool"]) + + assert creator._generate_fresh_code("context") == "_exec_return_values = 5\n" + assert calls == [("context", ["internal-tool"])] + + +def test_retry_regenerates_and_saves_even_when_cached_code_exists(): + creator = doomed.CataclysmCreator(autoexecute=False, autogenerate=True) + saved = [] + + creator._lookup_old_code = lambda funcname, signature: "cached code" + creator._generate_fresh_code = lambda formatted_info: "fresh code" + creator._save_conjured_code = lambda funcname, signature, code: saved.append( + (funcname, signature, code) + ) + + code = creator._conjure_code("make_thing", "make_thing-0-0", "context", retry=True) + + assert code == "fresh code" + assert saved == [("make_thing", "make_thing-0-0", "fresh code")] + + +def test_invalid_generated_code_retries_before_saving(): + creator = doomed.CataclysmCreator(autoexecute=False, autogenerate=True) + calls = [] + saved = [] + + creator._lookup_old_code = lambda funcname, signature: None + + def fake_generate(formatted_info): + calls.append(formatted_info) + if len(calls) == 1: + raise ValueError("Cataclysm response produced placeholder code.") + return "_exec_return_values = 12\n" + + creator._generate_fresh_code = fake_generate + creator._save_conjured_code = lambda funcname, signature, code: saved.append( + (funcname, signature, code) + ) + + code = creator._conjure_code("add_numbers", "add_numbers-2-0-int-int", "context") + + assert code == "_exec_return_values = 12\n" + assert len(calls) == 2 + assert "Validation error" in calls[1] + assert saved == [("add_numbers", "add_numbers-2-0-int-int", "_exec_return_values = 12\n")] + + +def test_importing_cataclysm_does_not_import_plunkylib(): + result = subprocess.run( + [ + sys.executable, + "-c", + "import sys; import cataclysm; print('plunkylib' in sys.modules)", + ], + check=True, + capture_output=True, + text=True, + ) + + assert result.stdout.strip() == "False" diff --git a/tests/test_doom_retry.py b/tests/test_doom_retry.py index 4ea2cb0..7929188 100644 --- a/tests/test_doom_retry.py +++ b/tests/test_doom_retry.py @@ -1,6 +1,15 @@ import pytest +import os from cataclysm import doom +pytestmark = [ + pytest.mark.live, + pytest.mark.skipif( + os.getenv("CATACLYSM_RUN_LIVE_TESTS") != "1" or not os.getenv("OPENAI_API_KEY"), + reason="live doom tests require OPENAI_API_KEY and CATACLYSM_RUN_LIVE_TESTS=1", + ), +] + # TODO Add a setup to clear the code cache # TODO: We can get coverage of the retry method this way but can't be 100% sure it worked. @@ -18,4 +27,4 @@ def test_throw_ZeroDivisionError(): # we tell it to retry and not fail so technically it's a pass assert True -# To run tests, execute the command `pytest .py` \ No newline at end of file +# To run tests, execute the command `pytest .py` diff --git a/tests/test_init_files.py b/tests/test_init_files.py new file mode 100644 index 0000000..d423781 --- /dev/null +++ b/tests/test_init_files.py @@ -0,0 +1,58 @@ +from pathlib import Path + +import cataclysm +from cataclysm.__main__ import initialize_datafiles + + +def test_packaged_env_template_uses_chatsnack_configuration(): + env_template = Path(cataclysm.__path__[0]) / "default_files" / "env.template.cataclysm" + content = env_template.read_text(encoding="utf-8") + + assert "CHATSNACK_BASE_DIR" in content + assert "OPENAI_API_KEY" in content + assert "PLUNKYLIB_BASE_DIR" not in content + + +def test_packaged_defaults_include_chatsnack_prompt_and_no_plunkylib_assets(): + defaults_root = Path(cataclysm.__path__[0]) / "default_files" + default_files = { + path.relative_to(defaults_root).as_posix() + for path in defaults_root.rglob("*") + if path.is_file() + } + + assert "datafiles/chatsnack/CataclysmQuery.yml" in default_files + assert all("plunkylib" not in path.lower() for path in default_files) + + +def test_initialize_datafiles_copies_chatsnack_defaults(tmp_path): + initialize_datafiles(base_dir=str(tmp_path)) + + assert (tmp_path / "datafiles" / "chatsnack" / "CataclysmQuery.yml").exists() + assert (tmp_path / "env.template.cataclysm").exists() + assert not (tmp_path / "datafiles" / "plunkylib").exists() + + +def test_initialize_datafiles_reads_chatsnack_base_dir_at_call_time(monkeypatch, tmp_path): + custom_chatsnack_dir = tmp_path / "custom" / "chatsnack" + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(custom_chatsnack_dir)) + + initialize_datafiles(base_dir=str(tmp_path)) + + assert (custom_chatsnack_dir / "CataclysmQuery.yml").exists() + assert not (tmp_path / "datafiles" / "chatsnack" / "CataclysmQuery.yml").exists() + assert (tmp_path / "env.template.cataclysm").exists() + + +def test_package_initialize_datafiles_reads_chatsnack_base_dir_at_call_time( + monkeypatch, + tmp_path, +): + custom_chatsnack_dir = tmp_path / "package" / "chatsnack" + monkeypatch.setenv("CHATSNACK_BASE_DIR", str(custom_chatsnack_dir)) + + cataclysm.initialize_datafiles(base_dir=str(tmp_path)) + + assert (custom_chatsnack_dir / "CataclysmQuery.yml").exists() + assert not (tmp_path / "datafiles" / "chatsnack" / "CataclysmQuery.yml").exists() + assert (tmp_path / "env.template.cataclysm").exists() diff --git a/tests/test_notebook_metadata.py b/tests/test_notebook_metadata.py new file mode 100644 index 0000000..47fa673 --- /dev/null +++ b/tests/test_notebook_metadata.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import pytest + +from tests.notebook_support import INPUT_TAG, SKIP_TEST_TAG, load_notebook_documents + + +pytestmark = pytest.mark.notebooks + + +def test_notebook_code_cells_only_use_allowed_special_execution_tags(): + issues: list[str] = [] + execution_like_tags = {INPUT_TAG, SKIP_TEST_TAG, "test", "live", "manual"} + allowed_shapes = { + frozenset(), + frozenset({SKIP_TEST_TAG}), + frozenset({INPUT_TAG, SKIP_TEST_TAG}), + } + + for document in load_notebook_documents(): + for cell in document.cells: + found = tuple(tag for tag in cell.tags if tag in execution_like_tags) + found_shape = frozenset(found) + if found_shape not in allowed_shapes: + issues.append( + f"{document.name} cell {cell.notebook_cell_index} " + f"has invalid execution tags {list(found)}" + ) + if any(tag not in {INPUT_TAG, SKIP_TEST_TAG} for tag in found): + issues.append( + f"{document.name} cell {cell.notebook_cell_index} " + f"still uses legacy execution tags {found}" + ) + + assert not issues, "Notebook metadata issues:\n" + "\n".join(issues) diff --git a/tests/test_notebooks.py b/tests/test_notebooks.py new file mode 100644 index 0000000..22725ad --- /dev/null +++ b/tests/test_notebooks.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +import pytest + +from tests.notebook_support import ( + NotebookRunner, + load_notebook_documents, + notebook_test_params, +) + + +pytestmark = pytest.mark.notebooks + + +@pytest.fixture(scope="session") +def notebook_runners(tmp_path_factory) -> dict[str, NotebookRunner]: + workspace_root = tmp_path_factory.mktemp("cataclysm-notebook-runs") + runners: dict[str, NotebookRunner] = {} + try: + for document in load_notebook_documents(): + runners[str(document.path)] = NotebookRunner(document, workspace_root) + yield runners + finally: + _release_notebook_file_handles() + + +def _release_notebook_file_handles() -> None: + import logging + + logging.shutdown() + try: + from loguru import logger + except ImportError: + return + logger.remove() + + +@pytest.mark.parametrize("cell", notebook_test_params()) +def test_notebook_code_cell_executes(cell, notebook_runners): + __tracebackhide__ = True + runner = notebook_runners[str(cell.notebook_path)] + runner.ensure_cell(cell.notebook_cell_index) diff --git a/tests/test_public_api_offline.py b/tests/test_public_api_offline.py new file mode 100644 index 0000000..f956e0e --- /dev/null +++ b/tests/test_public_api_offline.py @@ -0,0 +1,174 @@ +import builtins + +import pytest + +from cataclysm import doomed +from cataclysm.total import consume + + +def _stabilize_creator(monkeypatch, creator): + monkeypatch.setattr(creator, "_get_installed_modules_info", lambda: ["testpkg (1.0)"]) + monkeypatch.setattr(creator, "_get_tracelines", lambda: ["test trace"]) + + +def test_consume_intercepts_missing_global_functions(monkeypatch): + calls = [] + + class FakeCataclysmCreator: + def __getattr__(self, name): + def generated(*args, **kwargs): + calls.append((name, args, kwargs)) + return "generated result" + + return generated + + monkeypatch.setattr(doomed, "CataclysmCreator", FakeCataclysmCreator) + namespace = {"__builtins__": builtins} + + consume(namespace) + exec("result = missing_function(2, label='x')", namespace, namespace) + + assert namespace["result"] == "generated result" + assert calls == [("missing_function", (2,), {"label": "x"})] + + +def test_creator_executes_generated_body_and_returns_exec_value(monkeypatch): + creator = doomed.CataclysmCreator() + _stabilize_creator(monkeypatch, creator) + saved = [] + + monkeypatch.setattr(creator, "_lookup_old_code", lambda funcname, signature: None) + monkeypatch.setattr( + creator, + "_save_conjured_code", + lambda funcname, signature, code: saved.append((funcname, signature, code)), + ) + monkeypatch.setattr( + creator, + "_generate_fresh_code", + lambda formatted_info: "_exec_return_values = args_in[0] + bonus\n", + ) + + assert creator.add_with_bonus(7, bonus=5) == 12 + assert saved[0][0] == "add_with_bonus" + assert saved[0][2] == "_exec_return_values = args_in[0] + bonus\n" + assert saved[0][1].startswith("add_with_bonus-1-1-int-") + assert saved[0][1].endswith("-bonus") + + +def test_impending_returns_generated_code_without_executing_it(monkeypatch): + creator = doomed.CataclysmCreator() + _stabilize_creator(monkeypatch, creator.impending) + generated_code = "raise AssertionError('impending should only preview')\n" + saved = [] + + monkeypatch.setattr(creator.impending, "_lookup_old_code", lambda funcname, signature: None) + monkeypatch.setattr( + creator.impending, + "_save_conjured_code", + lambda funcname, signature, code: saved.append((funcname, signature, code)), + ) + monkeypatch.setattr( + creator.impending, + "_generate_fresh_code", + lambda formatted_info: generated_code, + ) + + assert creator.impending.preview_possible_code(1) == generated_code + assert saved == [ + ( + "preview_possible_code", + "preview_possible_code-1-0-int", + generated_code, + ) + ] + + +def test_chosen_executes_cached_code_without_generation(monkeypatch): + creator = doomed.CataclysmCreator() + _stabilize_creator(monkeypatch, creator.chosen) + + monkeypatch.setattr( + creator.chosen, + "_lookup_old_code", + lambda funcname, signature: "_exec_return_values = args_in[0] * 2\n", + ) + monkeypatch.setattr( + creator.chosen, + "_generate_fresh_code", + lambda formatted_info: pytest.fail("chosen mode should use cached code"), + ) + + assert creator.chosen.double_cached_value(8) == 16 + + +def test_chosen_raises_name_error_when_cached_code_is_missing(monkeypatch): + creator = doomed.CataclysmCreator() + _stabilize_creator(monkeypatch, creator.chosen) + monkeypatch.setattr(creator.chosen, "_lookup_old_code", lambda funcname, signature: None) + + with pytest.raises(NameError, match="No code for function unknown_cached_function"): + creator.chosen.unknown_cached_function("x") + + +def test_cached_code_is_reused_without_fresh_generation(monkeypatch): + creator = doomed.CataclysmCreator(autoexecute=False, autogenerate=True) + _stabilize_creator(monkeypatch, creator) + + monkeypatch.setattr( + creator, + "_lookup_old_code", + lambda funcname, signature: "_exec_return_values = 'cached'\n", + ) + monkeypatch.setattr( + creator, + "_generate_fresh_code", + lambda formatted_info: pytest.fail("cached code should be reused"), + ) + monkeypatch.setattr( + creator, + "_save_conjured_code", + lambda funcname, signature, code: pytest.fail("cached code should not be saved again"), + ) + + assert creator.cached_answer("anything") == "_exec_return_values = 'cached'\n" + + +def test_runtime_execution_error_triggers_one_retry_with_context(monkeypatch): + creator = doomed.CataclysmCreator() + _stabilize_creator(monkeypatch, creator) + calls = [] + saved = [] + + monkeypatch.setattr(creator, "_lookup_old_code", lambda funcname, signature: None) + monkeypatch.setattr( + creator, + "_save_conjured_code", + lambda funcname, signature, code: saved.append((funcname, signature, code)), + ) + + def fake_generate(formatted_info): + calls.append(formatted_info) + if len(calls) == 1: + return "raise RuntimeError('bad generated code')\n" + return "_exec_return_values = 'fixed after retry'\n" + + monkeypatch.setattr(creator, "_generate_fresh_code", fake_generate) + + assert creator.flaky_generated_function() == "fixed after retry" + assert len(calls) == 2 + assert "Errored code:" in calls[1] + assert "raise RuntimeError('bad generated code')" in calls[1] + assert "RuntimeError: bad generated code" in calls[1] + assert saved == [ + ( + "flaky_generated_function", + "flaky_generated_function-0-0", + "raise RuntimeError('bad generated code')\n", + ), + ( + "flaky_generated_function", + "flaky_generated_function-0-0", + "_exec_return_values = 'fixed after retry'\n", + ), + ]