diff --git a/api/__init__.py b/api/__init__.py index f18b928..0c55854 100644 --- a/api/__init__.py +++ b/api/__init__.py @@ -1,7 +1,10 @@ from .info import * from .llm import ask from .graph import * +from .project import * from .entities import * +from .git_utils import * from .code_coverage import * +from .index import create_app from .analyzers.source_analyzer import * from .auto_complete import prefix_search diff --git a/api/analyzers/analyzer.py b/api/analyzers/analyzer.py index 9e458d5..0c2d8d5 100644 --- a/api/analyzers/analyzer.py +++ b/api/analyzers/analyzer.py @@ -1,28 +1,102 @@ -import io from pathlib import Path +from typing import Optional + +from tree_sitter import Language, Node, Parser, Point +from api.entities.entity import Entity +from api.entities.file import File from abc import ABC, abstractmethod +from multilspy import SyncLanguageServer class AbstractAnalyzer(ABC): + def __init__(self, language: Language) -> None: + self.language = language + self.parser = Parser(language) + + def find_parent(self, node: Node, parent_types: list) -> Node: + while node and node.type not in parent_types: + node = node.parent + return node + + def resolve(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[tuple[File, Node]]: + try: + return [(files[Path(location['absolutePath'])], files[Path(location['absolutePath'])].tree.root_node.descendant_for_point_range(Point(location['range']['start']['line'], location['range']['start']['character']), Point(location['range']['end']['line'], location['range']['end']['character']))) for location in lsp.request_definition(str(path), node.start_point.row, node.start_point.column) if location and Path(location['absolutePath']) in files] + except Exception as e: + return [] + + @abstractmethod + def get_entity_label(self, node: Node) -> str: + """ + Get the entity label from the node. + + Args: + node (Node): The node. + + Returns: + str: The entity label. + """ + pass + + @abstractmethod + def get_entity_name(self, node: Node) -> str: + """ + Get the entity name from the node. + + Args: + node (Node): The node. + + Returns: + str: The entity name. + """ + pass + + @abstractmethod + def get_entity_docstring(self, node: Node) -> Optional[str]: + """ + Get the entity docstring from the node. + + Args: + node (Node): The node. + + Returns: + Optional[str]: The entity docstring. + """ + pass + @abstractmethod - def first_pass(self, path: Path, f: io.TextIOWrapper) -> None: + def get_entity_types(self) -> list[str]: """ - Perform the first pass of analysis on the given file. + Get the top level entity types for the language. + + Returns: + list[str]: The list of top level entity types. + """ + + pass + + @abstractmethod + def add_symbols(self, entity: Entity) -> None: + """ + Add symbols to the entity. Args: - path (Path): The path to the file being processed. - f (io.TextIOWrapper): The file object. + entity (Entity): The entity to add symbols to. """ pass @abstractmethod - def second_pass(self, path: Path, f: io.TextIOWrapper) -> None: + def resolve_symbol(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, key: str, symbol: Node) -> Entity: """ - Perform a second pass analysis on the given source file. + Resolve a symbol to an entity. Args: + lsp (SyncLanguageServer): The language server. path (Path): The path to the file. - f (io.TextIOWrapper): The file handle of the file to be processed. + key (str): The symbol key. + symbol (Node): The symbol node. + + Returns: + Entity: The entity. """ pass diff --git a/api/analyzers/c/analyzer.py b/api/analyzers/c/analyzer.py index 09a5e26..918f0b6 100644 --- a/api/analyzers/c/analyzer.py +++ b/api/analyzers/c/analyzer.py @@ -1,478 +1,476 @@ -import io -import os -from ..utils import * -from pathlib import Path -from ...entities import * -from ...graph import Graph -from typing import Optional -from ..analyzer import AbstractAnalyzer +# import io +# import os +# from ..utils import * +# from pathlib import Path +# from ...entities import * +# from ...graph import Graph +# from typing import Optional +# from ..analyzer import AbstractAnalyzer -import tree_sitter_c as tsc -from tree_sitter import Language, Parser, Node +# import tree_sitter_c as tsc +# from tree_sitter import Language, Node -C_LANGUAGE = Language(tsc.language()) +# import logging +# logger = logging.getLogger('code_graph') -import logging -logger = logging.getLogger('code_graph') +# class CAnalyzer(AbstractAnalyzer): +# def __init__(self) -> None: +# super().__init__(Language(tsc.language())) -class CAnalyzer(AbstractAnalyzer): - def __init__(self) -> None: - self.parser = Parser(C_LANGUAGE) +# def process_pointer_declaration(self, node: Node) -> tuple[str, int]: +# """ +# Processes a pointer declaration node to determine the argument name and pointer count. - def process_pointer_declaration(self, node: Node) -> tuple[str, int]: - """ - Processes a pointer declaration node to determine the argument name and pointer count. +# Args: +# node (Node): The AST node representing a pointer declaration. - Args: - node (Node): The AST node representing a pointer declaration. +# Returns: +# Tuple[str, int]: A tuple containing the argument name and the pointer count. +# """ - Returns: - Tuple[str, int]: A tuple containing the argument name and the pointer count. - """ +# assert(node.type == 'pointer_declarator') + +# text = node.text.decode('utf-8') +# idx = max(text.rfind(' '), text.rfind('*')) + 1 +# name = text[idx:] +# t = text[:idx] + +# return (t, name) - assert(node.type == 'pointer_declarator') +# def process_parameter_declaration(self, node: Node) -> tuple[bool, str, int, str]: +# """ +# Processes a parameter declaration node to determine its properties. - text = node.text.decode('utf-8') - idx = max(text.rfind(' '), text.rfind('*')) + 1 - name = text[idx:] - t = text[:idx] +# Args: +# node (Node): The AST node representing a parameter declaration. + +# Returns: +# Tuple[bool, str, int, Optional[str]]: A tuple containing: +# - A boolean indicating if the parameter is const. +# - A string representing the argument type. +# - An integer representing the pointer count. +# - An optional string for the argument name (None if not found). +# """ + +# assert(node.type == 'parameter_declaration') + +# const = False +# pointer = 0 +# arg_name = '' +# arg_type = '' + +# for child in node.children: +# t = child.type + +# if t == 'type_qualifier': +# child = child.children[0] +# if child.type == 'const': +# const = True + +# elif t == 'type_identifier': +# arg_type = child.text.decode('utf-8') + +# elif t == 'identifier': +# arg_name = child.text.decode('utf-8') + +# elif t == 'primitive_type': +# arg_type = child.text.decode('utf-8') + +# elif t == 'pointer_declarator': +# pointer_arg_name, arg_name = self.process_pointer_declaration(child) +# arg_type += pointer_arg_name + +# elif t == 'sized_type_specifier': +# arg_type = child.text.decode('utf-8') + +# return (const, arg_type, pointer, arg_name) + +# def process_function_definition_node(self, node: Node, path: Path, +# source_code: str) -> Optional[Function]: +# """ +# Processes a function definition node to extract function details. + +# Args: +# node (Node): The AST node representing a function definition. +# path (Path): The file path where the function is defined. + +# Returns: +# Optional[Function]: A Function object containing details about the function, or None if the function name cannot be determined. +# """ + +# # Extract function name +# res = find_child_of_type(node, 'function_declarator') +# if res is None: +# return None - return (t, name) +# function_declarator = res[0] - def process_parameter_declaration(self, node: Node) -> tuple[bool, str, int, str]: - """ - Processes a parameter declaration node to determine its properties. +# res = find_child_of_type(function_declarator, 'identifier') +# if res is None: +# return None - Args: - node (Node): The AST node representing a parameter declaration. - - Returns: - Tuple[bool, str, int, Optional[str]]: A tuple containing: - - A boolean indicating if the parameter is const. - - A string representing the argument type. - - An integer representing the pointer count. - - An optional string for the argument name (None if not found). - """ - - assert(node.type == 'parameter_declaration') - - const = False - pointer = 0 - arg_name = '' - arg_type = '' - - for child in node.children: - t = child.type - - if t == 'type_qualifier': - child = child.children[0] - if child.type == 'const': - const = True - - elif t == 'type_identifier': - arg_type = child.text.decode('utf-8') - - elif t == 'identifier': - arg_name = child.text.decode('utf-8') - - elif t == 'primitive_type': - arg_type = child.text.decode('utf-8') - - elif t == 'pointer_declarator': - pointer_arg_name, arg_name = self.process_pointer_declaration(child) - arg_type += pointer_arg_name - - elif t == 'sized_type_specifier': - arg_type = child.text.decode('utf-8') - - return (const, arg_type, pointer, arg_name) - - def process_function_definition_node(self, node: Node, path: Path, - source_code: str) -> Optional[Function]: - """ - Processes a function definition node to extract function details. - - Args: - node (Node): The AST node representing a function definition. - path (Path): The file path where the function is defined. - - Returns: - Optional[Function]: A Function object containing details about the function, or None if the function name cannot be determined. - """ - - # Extract function name - res = find_child_of_type(node, 'function_declarator') - if res is None: - return None - - function_declarator = res[0] - - res = find_child_of_type(function_declarator, 'identifier') - if res is None: - return None - - identifier = res[0] - function_name = identifier.text.decode('utf-8') - logger.info(f"Function declaration: {function_name}") - - # Extract function return type - res = find_child_of_type(node, 'primitive_type') - ret_type = 'Unknown' - if res is not None: - ret_type = res[0] - ret_type = ret_type.text.decode('utf-8') - - # Extract function parameters - args = [] - res = find_child_of_type(function_declarator, 'parameter_list') - if res is not None: - parameters = res[0] - - # Extract arguments and their types - for child in parameters.children: - if child.type == 'parameter_declaration': - arg = self.process_parameter_declaration(child) - args.append(arg) - - # Extract function definition line numbers - start_line = node.start_point[0] - end_line = node.end_point[0] - - # Create Function object - docs = '' - src = source_code[node.start_byte:node.end_byte] - f = Function(str(path), function_name, docs, ret_type, src, start_line, end_line) - - # Add arguments to Function object - for arg in args: - const = arg[0] - t = arg[1] - pointer = arg[2] - name = arg[3] - - # Skip f(void) - if name is None and t == 'void': - continue - - type_str = 'const ' if const else '' - type_str += t - type_str += '*' * pointer - - f.add_argument(name, type_str) - - return f - - def process_function_definition(self, parent: File, node: Node, path: Path, - graph: Graph, source_code: str) -> None: - """ - Processes a function definition node and adds it to the graph. - - Args: - parent (File): The parent File object. - node (Node): The AST node representing the function definition. - path (Path): The file path where the function is defined. - graph (Graph): The Graph object to which the function entity will be added. - - Returns: - None - """ - - assert(node.type == 'function_definition') - - entity = self.process_function_definition_node(node, path, source_code) - if entity is not None: - # Add Function object to the graph - try: - graph.add_function(entity) - except Exception: - logger.error(f"Failed creating function: {entity}") - entity = None - - if entity is not None: - # Connect parent to entity - graph.connect_entities('DEFINES', parent.id, entity.id) - - def process_field_declaration(self, node: Node) -> Optional[tuple[str, str]]: - """ - Processes a field declaration node to extract field name and type. - - Args: - node (Node): The AST node representing a field declaration. - - Returns: - Optional[Tuple[str, str]]: A tuple containing the field name and type, or None if either could not be determined. - """ - - assert(node.type == 'field_declaration') - - const = False - field_name = None - field_type = '' - - for child in node.children: - if child.type == 'field_identifier': - field_name = child.text.decode('utf-8') - elif child.type == 'type_qualifier': - const = True - elif child.type == 'struct_specifier': - # TODO: handle nested structs - # TODO: handle union - pass - elif child.type == 'primitive_type': - field_type = child.text.decode('utf-8') - elif child.type == 'sized_type_specifier': - field_type = child.text.decode('utf-8') - elif child.type == 'pointer_declarator': - pointer_field_type, field_name = self.process_pointer_declaration(child) - field_type += pointer_field_type - elif child.type == 'array_declarator': - field_type += '[]' - field_name = child.children[0].text.decode('utf-8') - else: - continue - - if field_type is not None and const is True: - field_type = f'const {field_type}' - - if field_name is not None and field_type is not None: - return (field_name, field_type) - else: - return None - - def process_struct_specifier_node(self, node: Node, path: Path) -> Optional[Struct]: - """ - Processes a struct specifier node to extract struct fields. - - Args: - node (Node): The AST node representing the struct specifier. - path (Path): The file path where the struct is defined. - - Returns: - Optional[Struct]: A Struct object containing details about the struct, or None if the struct name or fields could not be determined. - """ - - # Do not process struct without a declaration_list - res = find_child_of_type(node, 'field_declaration_list') - if res is None: - return None - - field_declaration_list = res[0] - - # Extract struct name - res = find_child_of_type(node, 'type_identifier') - if res is None: - return None - - type_identifier = res[0] - struct_name = type_identifier.text.decode('utf-8') - - start_line = node.start_point[0] - end_line = node.end_point[0] - s = Struct(str(path), struct_name, '', start_line, end_line) - - # Collect struct fields - for child in field_declaration_list.children: - if child.type == 'field_declaration': - res = self.process_field_declaration(child) - if res is None: - return None - else: - field_name, field_type = res - s.add_field(field_name, field_type) - - return s - - def process_struct_specifier(self, parent: File, node: Node, path: Path, - graph: Graph) -> Node: - """ - Processes a struct specifier node to extract struct details and adds it to the graph. - - Args: - parent (File): The parent File object. - node (Node): The AST node representing the struct specifier. - path (Path): The file path where the struct is defined. - graph (Graph): The Graph object to which the struct entity will be added. - - Returns: - Optional[Node]: The processed AST node representing the struct specifier if successful, otherwise None. - - Raises: - AssertionError: If the provided node is not of type 'struct_specifier'. - """ - - assert(node.type == 'struct_specifier') - - entity = self.process_struct_specifier_node(node, path) - if entity is not None: - # Add Struct object to the graph - try: - graph.add_struct(entity) - except Exception: - logger.warning(f"Failed creating struct: {entity}") - entity = None - - if entity is not None: - # Connect parent to entity - graph.connect_entities('DEFINES', parent.id, entity.id) - - def first_pass(self, path: Path, f: io.TextIOWrapper, graph:Graph) -> None: - """ - Perform the first pass processing of a C source file or header file. - - Args: - path (Path): The path to the C source file or header file. - f (io.TextIOWrapper): The file object representing the opened C source file or header file. - graph (Graph): The Graph object where entities will be added. - - Returns: - None - - Raises: - None - - This function processes the specified C source file or header file to extract and add function definitions - and struct definitions to the provided graph object. - - - If the file path does not end with '.c' or '.h', it logs a debug message and skips processing. - - It creates a File entity representing the file and adds it to the graph. - - It parses the file content using a parser instance (`self.parser`). - - Function definitions and struct definitions are extracted using Tree-sitter queries. - - Each function definition is processed using `self.process_function_definition`. - - Each struct definition is processed using `self.process_struct_specifier`. - """ - - if path.suffix != '.c' and path.suffix != '.h': - logger.debug(f"Skipping none C file {path}") - return - - logger.info(f"Processing {path}") - - # Create file entity - file = File(os.path.dirname(path), path.name, path.suffix) - graph.add_file(file) - - # Parse file - source_code = f.read() - tree = self.parser.parse(source_code) - try: - source_code = source_code.decode('utf-8') - except Exception as e: - logger.error(f"Failed decoding source code: {e}") - source_code = '' - - # Process function definitions - query = C_LANGUAGE.query("(function_definition) @function") - captures = query.captures(tree.root_node) - # captures: {'function': - # [, - # - # ] - # } - - if 'function' in captures: - functions = captures['function'] - for node in functions: - self.process_function_definition(file, node, path, graph, source_code) - - # Process struct definitions - query = C_LANGUAGE.query("(struct_specifier) @struct") - captures = query.captures(tree.root_node) +# identifier = res[0] +# function_name = identifier.text.decode('utf-8') +# logger.info(f"Function declaration: {function_name}") + +# # Extract function return type +# res = find_child_of_type(node, 'primitive_type') +# ret_type = 'Unknown' +# if res is not None: +# ret_type = res[0] +# ret_type = ret_type.text.decode('utf-8') + +# # Extract function parameters +# args = [] +# res = find_child_of_type(function_declarator, 'parameter_list') +# if res is not None: +# parameters = res[0] + +# # Extract arguments and their types +# for child in parameters.children: +# if child.type == 'parameter_declaration': +# arg = self.process_parameter_declaration(child) +# args.append(arg) + +# # Extract function definition line numbers +# start_line = node.start_point[0] +# end_line = node.end_point[0] + +# # Create Function object +# docs = '' +# src = source_code[node.start_byte:node.end_byte] +# f = Function(str(path), function_name, docs, ret_type, src, start_line, end_line) + +# # Add arguments to Function object +# for arg in args: +# const = arg[0] +# t = arg[1] +# pointer = arg[2] +# name = arg[3] + +# # Skip f(void) +# if name is None and t == 'void': +# continue + +# type_str = 'const ' if const else '' +# type_str += t +# type_str += '*' * pointer + +# f.add_argument(name, type_str) + +# return f + +# def process_function_definition(self, parent: File, node: Node, path: Path, +# graph: Graph, source_code: str) -> None: +# """ +# Processes a function definition node and adds it to the graph. + +# Args: +# parent (File): The parent File object. +# node (Node): The AST node representing the function definition. +# path (Path): The file path where the function is defined. +# graph (Graph): The Graph object to which the function entity will be added. + +# Returns: +# None +# """ + +# assert(node.type == 'function_definition') + +# entity = self.process_function_definition_node(node, path, source_code) +# if entity is not None: +# # Add Function object to the graph +# try: +# graph.add_function(entity) +# except Exception: +# logger.error(f"Failed creating function: {entity}") +# entity = None + +# if entity is not None: +# # Connect parent to entity +# graph.connect_entities('DEFINES', parent.id, entity.id) + +# def process_field_declaration(self, node: Node) -> Optional[tuple[str, str]]: +# """ +# Processes a field declaration node to extract field name and type. + +# Args: +# node (Node): The AST node representing a field declaration. + +# Returns: +# Optional[Tuple[str, str]]: A tuple containing the field name and type, or None if either could not be determined. +# """ + +# assert(node.type == 'field_declaration') + +# const = False +# field_name = None +# field_type = '' + +# for child in node.children: +# if child.type == 'field_identifier': +# field_name = child.text.decode('utf-8') +# elif child.type == 'type_qualifier': +# const = True +# elif child.type == 'struct_specifier': +# # TODO: handle nested structs +# # TODO: handle union +# pass +# elif child.type == 'primitive_type': +# field_type = child.text.decode('utf-8') +# elif child.type == 'sized_type_specifier': +# field_type = child.text.decode('utf-8') +# elif child.type == 'pointer_declarator': +# pointer_field_type, field_name = self.process_pointer_declaration(child) +# field_type += pointer_field_type +# elif child.type == 'array_declarator': +# field_type += '[]' +# field_name = child.children[0].text.decode('utf-8') +# else: +# continue + +# if field_type is not None and const is True: +# field_type = f'const {field_type}' + +# if field_name is not None and field_type is not None: +# return (field_name, field_type) +# else: +# return None + +# def process_struct_specifier_node(self, node: Node, path: Path) -> Optional[Struct]: +# """ +# Processes a struct specifier node to extract struct fields. + +# Args: +# node (Node): The AST node representing the struct specifier. +# path (Path): The file path where the struct is defined. + +# Returns: +# Optional[Struct]: A Struct object containing details about the struct, or None if the struct name or fields could not be determined. +# """ + +# # Do not process struct without a declaration_list +# res = find_child_of_type(node, 'field_declaration_list') +# if res is None: +# return None + +# field_declaration_list = res[0] + +# # Extract struct name +# res = find_child_of_type(node, 'type_identifier') +# if res is None: +# return None + +# type_identifier = res[0] +# struct_name = type_identifier.text.decode('utf-8') + +# start_line = node.start_point[0] +# end_line = node.end_point[0] +# s = Struct(str(path), struct_name, '', start_line, end_line) + +# # Collect struct fields +# for child in field_declaration_list.children: +# if child.type == 'field_declaration': +# res = self.process_field_declaration(child) +# if res is None: +# return None +# else: +# field_name, field_type = res +# s.add_field(field_name, field_type) + +# return s + +# def process_struct_specifier(self, parent: File, node: Node, path: Path, +# graph: Graph) -> Node: +# """ +# Processes a struct specifier node to extract struct details and adds it to the graph. + +# Args: +# parent (File): The parent File object. +# node (Node): The AST node representing the struct specifier. +# path (Path): The file path where the struct is defined. +# graph (Graph): The Graph object to which the struct entity will be added. + +# Returns: +# Optional[Node]: The processed AST node representing the struct specifier if successful, otherwise None. + +# Raises: +# AssertionError: If the provided node is not of type 'struct_specifier'. +# """ + +# assert(node.type == 'struct_specifier') + +# entity = self.process_struct_specifier_node(node, path) +# if entity is not None: +# # Add Struct object to the graph +# try: +# graph.add_struct(entity) +# except Exception: +# logger.warning(f"Failed creating struct: {entity}") +# entity = None + +# if entity is not None: +# # Connect parent to entity +# graph.connect_entities('DEFINES', parent.id, entity.id) + +# def first_pass(self, path: Path, graph:Graph) -> None: +# """ +# Perform the first pass processing of a C source file or header file. + +# Args: +# path (Path): The path to the C source file or header file. +# f (io.TextIOWrapper): The file object representing the opened C source file or header file. +# graph (Graph): The Graph object where entities will be added. + +# Returns: +# None + +# Raises: +# None + +# This function processes the specified C source file or header file to extract and add function definitions +# and struct definitions to the provided graph object. + +# - If the file path does not end with '.c' or '.h', it logs a debug message and skips processing. +# - It creates a File entity representing the file and adds it to the graph. +# - It parses the file content using a parser instance (`self.parser`). +# - Function definitions and struct definitions are extracted using Tree-sitter queries. +# - Each function definition is processed using `self.process_function_definition`. +# - Each struct definition is processed using `self.process_struct_specifier`. +# """ + +# if path.suffix != '.c' and path.suffix != '.h': +# logger.debug(f"Skipping none C file {path}") +# return + +# logger.info(f"Processing {path}") + +# # Create file entity +# file = File(os.path.dirname(path), path.name, path.suffix) +# graph.add_file(file) + +# # Parse file +# source_code = path.read_bytes() +# tree = self.parser.parse(source_code) +# try: +# source_code = source_code.decode('utf-8') +# except Exception as e: +# logger.error(f"Failed decoding source code: {e}") +# source_code = '' + +# # Process function definitions +# query = self.language.query("(function_definition) @function") +# captures = query.captures(tree.root_node) +# # captures: {'function': +# # [, +# # +# # ] +# # } + +# if 'function' in captures: +# functions = captures['function'] +# for node in functions: +# self.process_function_definition(file, node, path, graph, source_code) + +# # Process struct definitions +# query = self.language.query("(struct_specifier) @struct") +# captures = query.captures(tree.root_node) - if 'struct' in captures: - structs = captures['struct'] - # captures: {'struct': - # [ - # - # ] - # } - for node in structs: - self.process_struct_specifier(file, node, path, graph) - - def second_pass(self, path: Path, f: io.TextIOWrapper, graph: Graph) -> None: - """ - Perform the second pass processing of a C source file or header file to establish function call relationships. - - Args: - path (Path): The path to the C source file or header file. - f (io.TextIOWrapper): The file object representing the opened C source file or header file. - graph (Graph): The Graph object containing entities (functions and files) to establish relationships. - - Returns: - None - - This function processes the specified C source file or header file to establish relationships between - functions based on function calls. It performs the following steps: - - - Checks if the file path ends with '.c' or '.h'. If not, logs a debug message and skips processing. - - Retrieves the file entity (`file`) from the graph based on the file path. - - Parses the content of the file using a parser instance (`self.parser`). If parsing fails, logs an error. - - Uses Tree-sitter queries (`query_function_def` and `query_call_exp`) to locate function definitions and - function invocations (calls) within the parsed AST (`tree.root_node`). - - Iterates over captured function definitions (`function_defs`) and their corresponding function calls - (`function_calls`). For each function call: - - Retrieves or creates a function entity (`callee_f`) in the graph. - - Connects the caller function (`caller_f`) to the callee function (`callee_f`) using a 'CALLS' edge in - the graph. - - Note: - - This function assumes that function calls to native functions (e.g., 'printf') will create missing - function entities (`Function` objects) and add them to the graph. - - Example usage: - ``` - second_pass(Path('/path/to/file.c'), open('/path/to/file.c', 'r'), graph) - ``` - """ - - if path.suffix != '.c' and path.suffix != '.h': - logger.debug(f"Skipping none C file {path}") - return - - logger.info(f"Processing {path}") - - # Get file entity - file = graph.get_file(os.path.dirname(path), path.name, path.suffix) - if file is None: - logger.error(f"File entity not found for: {path}") - return - - try: - # Parse file - content = f.read() - tree = self.parser.parse(content) - except Exception as e: - logger.error(f"Failed to process file {path}: {e}") - return - - # Locate function invocation - query_call_exp = C_LANGUAGE.query("(call_expression function: (identifier) @callee)") - - # Locate function definitions - query_function_def = C_LANGUAGE.query(""" - ( - function_definition - declarator: (function_declarator - declarator: (identifier) @function_name) - )""") - - function_defs = query_function_def.captures(tree.root_node) - for function_def in function_defs: - caller = function_def[0] - caller_name = caller.text.decode('utf-8') - caller_f = graph.get_function_by_name(caller_name) - assert(caller_f is not None) - - function_calls = query_call_exp.captures(caller.parent.parent) - for function_call in function_calls: - callee = function_call[0] - callee_name = callee.text.decode('utf-8') - callee_f = graph.get_function_by_name(callee_name) - - if callee_f is None: - # Create missing function - # Assuming this is a call to a native function e.g. 'printf' - callee_f = Function('/', callee_name, None, None, None, 0, 0) - graph.add_function(callee_f) - - # Connect the caller and callee in the graph - graph.connect_entities('CALLS', caller_f.id, callee_f.id) +# if 'struct' in captures: +# structs = captures['struct'] +# # captures: {'struct': +# # [ +# # +# # ] +# # } +# for node in structs: +# self.process_struct_specifier(file, node, path, graph) + +# def second_pass(self, path: Path, graph: Graph) -> None: +# """ +# Perform the second pass processing of a C source file or header file to establish function call relationships. + +# Args: +# path (Path): The path to the C source file or header file. +# f (io.TextIOWrapper): The file object representing the opened C source file or header file. +# graph (Graph): The Graph object containing entities (functions and files) to establish relationships. + +# Returns: +# None + +# This function processes the specified C source file or header file to establish relationships between +# functions based on function calls. It performs the following steps: + +# - Checks if the file path ends with '.c' or '.h'. If not, logs a debug message and skips processing. +# - Retrieves the file entity (`file`) from the graph based on the file path. +# - Parses the content of the file using a parser instance (`self.parser`). If parsing fails, logs an error. +# - Uses Tree-sitter queries (`query_function_def` and `query_call_exp`) to locate function definitions and +# function invocations (calls) within the parsed AST (`tree.root_node`). +# - Iterates over captured function definitions (`function_defs`) and their corresponding function calls +# (`function_calls`). For each function call: +# - Retrieves or creates a function entity (`callee_f`) in the graph. +# - Connects the caller function (`caller_f`) to the callee function (`callee_f`) using a 'CALLS' edge in +# the graph. + +# Note: +# - This function assumes that function calls to native functions (e.g., 'printf') will create missing +# function entities (`Function` objects) and add them to the graph. + +# Example usage: +# ``` +# second_pass(Path('/path/to/file.c'), open('/path/to/file.c', 'r'), graph) +# ``` +# """ + +# if path.suffix != '.c' and path.suffix != '.h': +# logger.debug(f"Skipping none C file {path}") +# return + +# logger.info(f"Processing {path}") + +# # Get file entity +# file = graph.get_file(os.path.dirname(path), path.name, path.suffix) +# if file is None: +# logger.error(f"File entity not found for: {path}") +# return + +# try: +# # Parse file +# content = path.read_bytes() +# tree = self.parser.parse(content) +# except Exception as e: +# logger.error(f"Failed to process file {path}: {e}") +# return + +# # Locate function invocation +# query_call_exp = self.language.query("(call_expression function: (identifier) @callee)") + +# # Locate function definitions +# query_function_def = self.language.query(""" +# ( +# function_definition +# declarator: (function_declarator +# declarator: (identifier) @function_name) +# )""") + +# function_defs = query_function_def.captures(tree.root_node) +# for function_def in function_defs: +# caller = function_def[0] +# caller_name = caller.text.decode('utf-8') +# caller_f = graph.get_function_by_name(caller_name) +# assert(caller_f is not None) + +# function_calls = query_call_exp.captures(caller.parent.parent) +# for function_call in function_calls: +# callee = function_call[0] +# callee_name = callee.text.decode('utf-8') +# callee_f = graph.get_function_by_name(callee_name) + +# if callee_f is None: +# # Create missing function +# # Assuming this is a call to a native function e.g. 'printf' +# callee_f = Function('/', callee_name, None, None, None, 0, 0) +# graph.add_function(callee_f) + +# # Connect the caller and callee in the graph +# graph.connect_entities('CALLS', caller_f.id, callee_f.id) diff --git a/api/analyzers/java/analyzer.py b/api/analyzers/java/analyzer.py new file mode 100644 index 0000000..29a88fe --- /dev/null +++ b/api/analyzers/java/analyzer.py @@ -0,0 +1,102 @@ +from pathlib import Path +from ...entities import * +from typing import Optional +from ..analyzer import AbstractAnalyzer + +from multilspy import SyncLanguageServer + +import tree_sitter_java as tsjava +from tree_sitter import Language, Node + +import logging +logger = logging.getLogger('code_graph') + +class JavaAnalyzer(AbstractAnalyzer): + def __init__(self) -> None: + super().__init__(Language(tsjava.language())) + + def get_entity_label(self, node: Node) -> str: + if node.type == 'class_declaration': + return "Class" + elif node.type == 'interface_declaration': + return "Interface" + elif node.type == 'enum_declaration': + return "Enum" + elif node.type == 'method_declaration': + return "Method" + elif node.type == 'constructor_declaration': + return "Constructor" + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_name(self, node: Node) -> str: + if node.type in ['class_declaration', 'interface_declaration', 'enum_declaration', 'method_declaration', 'constructor_declaration']: + return node.child_by_field_name('name').text.decode('utf-8') + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_docstring(self, node: Node) -> Optional[str]: + if node.type in ['class_declaration', 'interface_declaration', 'enum_declaration', 'method_declaration', 'constructor_declaration']: + if node.prev_sibling.type == "block_comment": + return node.prev_sibling.text.decode('utf-8') + return None + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_types(self) -> list[str]: + return ['class_declaration', 'interface_declaration', 'enum_declaration', 'method_declaration', 'constructor_declaration'] + + def add_symbols(self, entity: Entity) -> None: + if entity.node.type == 'class_declaration': + interfaces_query = self.language.query("(super_interfaces (type_list (type_identifier) @interface))") + interfaces_captures = interfaces_query.captures(entity.node) + if 'interface' in interfaces_captures: + for interface in interfaces_captures['interface']: + entity.add_symbol("implement_interface", interface) + base_class_query = self.language.query("(superclass (type_identifier) @base_class)") + base_class_captures = base_class_query.captures(entity.node) + if 'base_class' in base_class_captures: + base_class = base_class_captures['base_class'][0] + entity.add_symbol("base_class", base_class) + elif entity.node.type == 'interface_declaration': + query = self.language.query("(extends_interfaces (type_list (type_identifier) @type))?") + extends_captures = query.captures(entity.node) + if 'type' in extends_captures: + for interface in extends_captures['type']: + entity.add_symbol("extend_interface", interface) + elif entity.node.type in ['method_declaration', 'constructor_declaration']: + query = self.language.query("(method_invocation) @reference.call") + captures = query.captures(entity.node) + if 'reference.call' in captures: + for caller in captures['reference.call']: + entity.add_symbol("call", caller) + if entity.node.type == 'method_declaration': + query = self.language.query("(formal_parameters (formal_parameter type: (_) @parameter))") + captures = query.captures(entity.node) + if 'parameter' in captures: + for parameter in captures['parameter']: + entity.add_symbol("parameters", parameter) + entity.add_symbol("return_type", entity.node.child_by_field_name('type')) + + def resolve_type(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[Entity]: + res = [] + for file, resolved_node in self.resolve(files, lsp, path, node): + type_dec = self.find_parent(resolved_node, ['class_declaration', 'interface_declaration', 'enum_declaration']) + if type_dec in file.entities: + res.append(file.entities[type_dec]) + return res + + def resolve_method(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[Entity]: + res = [] + for file, resolved_node in self.resolve(files, lsp, path, node.child_by_field_name('name')): + method_dec = self.find_parent(resolved_node, ['method_declaration', 'constructor_declaration', 'class_declaration', 'interface_declaration', 'enum_declaration']) + if method_dec.type in ['class_declaration', 'interface_declaration', 'enum_declaration']: + continue + if method_dec in file.entities: + res.append(file.entities[method_dec]) + return res + + def resolve_symbol(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, key: str, symbol: Node) -> Entity: + if key in ["implement_interface", "base_class", "extend_interface", "parameters", "return_type"]: + return self.resolve_type(files, lsp, path, symbol) + elif key in ["call"]: + return self.resolve_method(files, lsp, path, symbol) + else: + raise ValueError(f"Unknown key {key}") diff --git a/api/analyzers/python/analyzer.py b/api/analyzers/python/analyzer.py index 5376139..51e590c 100644 --- a/api/analyzers/python/analyzer.py +++ b/api/analyzers/python/analyzer.py @@ -1,392 +1,88 @@ -import io -import os -from ..utils import * +from multilspy import SyncLanguageServer from pathlib import Path from ...entities import * -from ...graph import Graph -from typing import Union, Optional +from typing import Optional from ..analyzer import AbstractAnalyzer import tree_sitter_python as tspython -from tree_sitter import Language, Parser, Node - -PY_LANGUAGE = Language(tspython.language()) +from tree_sitter import Language, Node import logging logger = logging.getLogger('code_graph') class PythonAnalyzer(AbstractAnalyzer): def __init__(self) -> None: - self.parser = Parser(PY_LANGUAGE) - - def process_class_definition(self, node: Node, path: Path) -> tuple[Class, list[str]]: - """ - Processes a class definition node from the syntax tree and extracts relevant information. - - Args: - node (Node): The Tree-sitter node representing the class definition. - path (Path): The file path where the class is defined. - - Returns: - Class: An instance of the Class containing the extracted information. - - This function performs the following tasks: - 1. Extracts the class name from the node. - 2. Extracts the docstring if it exists. - 3. Extracts the list of inherited classes. - 4. Creates a Class object with the extracted information. - - Example: - Given a Tree-sitter node representing a class definition, this function will extract - the class name, docstring, and inherited classes, and create a corresponding Class - object, which will then be added to the graph. - - Note: - This function assumes that the Tree-sitter node structure follows a specific pattern - for class definitions in Python. - """ - - # Extract class name - class_name = node.child_by_field_name("name") - class_name = class_name.text.decode("utf8") - logger.info(f"Class declaration: {class_name}") - - # Extract docstring - docstring_node = None - body_node = node.child_by_field_name('body') - if body_node.child_count > 0 and body_node.child(0).type == 'expression_statement': - docstring_node = body_node.child(0).child(0) - - docstring = docstring_node.text.decode('utf-8') if docstring_node else None - logger.debug(f"Class docstring: {docstring}") - - # Extract inherited classes - inherited_classes_node = node.child_by_field_name('superclasses') - inherited_classes = [] - if inherited_classes_node: - for child in inherited_classes_node.children: - if child.type == 'identifier': - inherited_classes.append(child.text.decode('utf-8')) - logger.debug(f"Class inherited classes: {inherited_classes}") - - # Create Class object - c = Class(str(path), class_name, docstring, - node.start_point[0], node.end_point[0]) - - return (c, inherited_classes) - - def process_function_definition(self, node: Node, path: Path, source_code: str) -> Function: - """ - Processes a function definition node from the syntax tree and extracts relevant information. - - Args: - node (Node): The Tree-sitter node representing the function definition. - path (Path): The file path where the function is defined. - - Returns: - Function: An instance of the Function class containing the extracted information. - - This function performs the following tasks: - 1. Extracts the function name. - 2. Extracts the function body, parameters, return type, docstring, and line numbers. - 3. Creates a Function object with the extracted information and adds arguments. - - Example: - Given a Tree-sitter node representing a function definition, this function will extract - the function name, docstring, arguments with their types, return type, and source line - numbers. It then creates a Function object, adds the arguments, and finally adds the - Function object to the graph. - - Note: - This function assumes that the Tree-sitter node structure follows a specific pattern - for function definitions in Python. - """ - - # Extract function name - function_name = node.child_by_field_name('name').text.decode('utf-8') - logger.info(f"Function declaration: {function_name}") - - # Extract function body, parameters, return type - body = node.child_by_field_name('body') - parameters = node.child_by_field_name('parameters') - return_type = node.child_by_field_name('return_type') - - # Extract function definition line numbers - start_line = node.start_point[0] - end_line = node.end_point[0] - - # Extract docstring - docstring = None - if body and body.child_count > 0 and body.children[0].type == 'expression_statement': - first_child = body.children[0] - if first_child.child(0).type == 'string': - docstring = first_child.child(0).text.decode('utf-8') - - # Extract arguments and their types - args = [] - if parameters: - for param in parameters.children: - if param.type == 'identifier': - arg_name = param.text.decode('utf-8') - arg_type = None - if param.next_sibling and param.next_sibling.type == 'type': - arg_type = param.next_sibling.text.decode('utf-8') - elif param.type == 'typed_parameter': - arg_name_node = param.children[0] - arg_type_node = param.children[2].children[0] - - arg_name = arg_name_node.text.decode('utf-8') - arg_type = arg_type_node.text.decode('utf-8') - elif param.type == 'typed_default_parameter': - arg_name_node = param.children[0] - arg_type_node = param.children[2].children[0] - - arg_name = arg_name_node.text.decode('utf-8') - arg_type = arg_type_node.text.decode('utf-8') - - else: - logger.debug(f'Unknown function parameter node type: {param.type}') - continue - - args.append((arg_name, arg_type)) - - # Extract return type - ret_type = return_type.text.decode('utf-8') if return_type else None - - # Create Function object - src = source_code[node.start_byte:node.end_byte] - f = Function(str(path), function_name, docstring, ret_type, src, start_line, end_line) - - # Add arguments to Function object - for arg in args: - f.add_argument(arg[0], arg[1]) - - return f - - def first_pass_traverse(self, parent: Union[File,Class,Function], node: Node, - path: Path, graph: Graph, source_code: str) -> None: - """ - Recursively traverses a syntax tree node, processes class and function definitions, - and connects them in a graph representation. - - Args: - parent (Union[File, Class, Function]): The parent entity (File, Class, or Function) to connect to. - node (Node): The Tree-sitter node to process. - path (Path): The path of the file being analyzed. - - This method processes each node based on its type: - - If the node represents a class definition ('class_definition'), it invokes - 'process_class_definition' to extract class information and connects it to the parent entity. - - If the node represents a function definition ('function_definition'), it invokes - 'process_function_definition' to extract function information and connects it to the parent entity. - - Recursively visits child nodes to continue the traversal. - - Note: - The method assumes that the Tree-sitter node structure follows a specific pattern - for class and function definitions in Python. - - Example: - Given a Tree-sitter node representing a Python file's syntax tree, this method - recursively traverses each node, processes class and function definitions, - connects them in a graph representation, and updates the parent entity accordingly. - """ - - entity = None - - if node.type == "class_definition": - entity = self.process_class_definition(node, path)[0] - # Add Class object to the graph - graph.add_class(entity) - - elif node.type == "function_definition": - entity = self.process_function_definition(node, path, source_code) - # Add Function object to the graph - graph.add_function(entity) - - if entity is not None: - # Connect parent to entity and update parent - graph.connect_entities('DEFINES', parent.id, entity.id) - parent = entity - - # Recursivly visit child nodes - for child in node.children: - self.first_pass_traverse(parent, child, path, graph, source_code) - - def first_pass(self, path: Path, f: io.TextIOWrapper, graph:Graph) -> None: - """ - Perform the first pass of analysis on the given file. - - Args: - path (Path): The path to the file being processed. - f (io.TextIOWrapper): The file object. - """ - - if path.suffix != '.py': - logger.debug(f"Skipping none Python file {path}") - return - - logger.info(f"Python Processing {path}") - - # Create file entity - file = File(os.path.dirname(path), path.name, path.suffix) - graph.add_file(file) - - # Parse file - source_code = f.read() - tree = self.parser.parse(source_code) - try: - source_code = source_code.decode('utf-8') - except Exception as e: - logger.error(f"Failed decoding source code: {e}") - source_code = '' - - # Walk thought the AST - self.first_pass_traverse(file, tree.root_node, path, graph, source_code) - - def process_function_call(self, node) -> Optional[str]: - """ - Process a function call node to extract the callee's name. - - Args: - node (Node): The function call node in the AST. - - Returns: - Optional[str]: The name of the callee function or None if it cannot be determined. - """ - - # locate argument_list node - res = find_child_of_type(node, 'argument_list') - if res is None: - logger.warning("Failed to locate 'argument_list'") + super().__init__(Language(tspython.language())) + + def get_entity_label(self, node: Node) -> str: + if node.type == 'class_definition': + return "Class" + elif node.type == 'function_definition': + return "Function" + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_name(self, node: Node) -> str: + if node.type in ['class_definition', 'function_definition']: + return node.child_by_field_name('name').text.decode('utf-8') + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_docstring(self, node: Node) -> Optional[str]: + if node.type in ['class_definition', 'function_definition']: + body = node.child_by_field_name('body') + if body.child_count > 0 and body.children[0].type == 'expression_statement': + docstring_node = body.children[0].child(0) + return docstring_node.text.decode('utf-8') return None - - callee_name = None - argument_list, idx = res - sibling = node.children[idx-1] - - # Determine the type of the sibling node and extract the callee's name - if sibling.type == 'identifier': - callee_name = sibling.text.decode('utf-8') - elif sibling.type == 'attribute': - # call - # attribute (sibling) - # identifier - # . - # identifier - # argument_list - idx = len(sibling.children)-1 - callee_name = sibling.children[idx].text.decode('utf-8') + raise ValueError(f"Unknown entity type: {node.type}") + + def get_entity_types(self) -> list[str]: + return ['class_definition', 'function_definition'] + + def add_symbols(self, entity: Entity) -> None: + if entity.node.type == 'class_definition': + superclasses = entity.node.child_by_field_name("superclasses") + if superclasses: + base_classes_query = self.language.query("(argument_list (_) @base_class)") + base_classes_captures = base_classes_query.captures(superclasses) + if 'base_class' in base_classes_captures: + for base_class in base_classes_captures['base_class']: + entity.add_symbol("base_class", base_class) + elif entity.node.type == 'function_definition': + query = self.language.query("(call) @reference.call") + captures = query.captures(entity.node) + if 'reference.call' in captures: + for caller in captures['reference.call']: + entity.add_symbol("call", caller) + query = self.language.query("(typed_parameter type: (_) @parameter)") + captures = query.captures(entity.node) + if 'parameter' in captures: + for parameter in captures['parameter']: + entity.add_symbol("parameters", parameter) + return_type = entity.node.child_by_field_name('return_type') + if return_type: + entity.add_symbol("return_type", return_type) + + def resolve_type(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[Entity]: + res = [] + for file, resolved_node in self.resolve(files, lsp, path, node): + type_dec = self.find_parent(resolved_node, ['class_definition']) + res.append(file.entities[type_dec]) + return res + + def resolve_method(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, node: Node) -> list[Entity]: + res = [] + for file, resolved_node in self.resolve(files, lsp, path, node): + method_dec = self.find_parent(resolved_node, ['function_definition', 'class_definition']) + if not method_dec: + continue + if method_dec in file.entities: + res.append(file.entities[method_dec]) + return res + + def resolve_symbol(self, files: dict[Path, File], lsp: SyncLanguageServer, path: Path, key: str, symbol: Node) -> Entity: + if key in ["base_class", "parameters", "return_type"]: + return self.resolve_type(files, lsp, path, symbol) + elif key in ["call"]: + return self.resolve_method(files, lsp, path, symbol) else: - # Add support additional call constructs - logger.warning("Unknown function call pattern") - return None - - logger.debug(f"callee_name: {callee_name}") - return callee_name - - def process_call_node(self, caller: Union[Function, File], callee_name: str, - graph:Graph) -> None: - """ - Process a call node in the AST, connecting the caller to the callee in the graph. - - Args: - caller (Union[Function, File]): The caller entity in the graph. - callee_name (str): The name of the callee function or class. - """ - - # Attempt to find the callee as a function first - callee = graph.get_function_by_name(callee_name) - - # If the callee is not a function, check if it is a class - if callee is None: - callee = graph.get_class_by_name(callee_name) - - # If the callee is neither a function nor a class, create a new function entity - if callee is None: - # Create Function callee_name - # Assuming this is a call to either a native or imported Function - # Although this call might just be a Class instantiation. - logger.info(f"Creating missing Class/Function {callee_name}") - callee = Function('/', callee_name, None, None, None,0, 0) - graph.add_function(callee) - - # Connect the caller and callee in the graph - graph.connect_entities('CALLS', caller.id, callee.id) - - def process_inheritance(self, cls: Class, super_classes: list[str], - graph: Graph) -> None: - for super_class in super_classes: - logger.info(f"Class {cls.name} inherits {super_class}") - - # Try to get Class object from graph - _super_class = graph.get_class_by_name(super_class) - if _super_class is None: - # Missing super class, might be imported from external library - # Create missing class. - _super_class = Class('/', super_class, '', 0, 0) - graph.add_class(_super_class) - - # Connect class to its super class - graph.connect_entities('INHERITS', cls.id, _super_class.id) - - def second_pass_traverse(self, parent: Union[File, Class, Function], - node: Node, path: Path, graph: Graph, source_code: str) -> None: - """ - Traverse the AST nodes during the second pass and process each node accordingly. - - Args: - parent (Union[File, Class, Function]): The parent entity in the graph. - node (Node): The current AST node being processed. - path (Path): The path to the file being processed. - """ - - if node.type == "class_definition": - cls, super_classes = self.process_class_definition(node, path) - cls = graph.get_class_by_name(cls.name) - self.process_inheritance(cls, super_classes, graph) - parent = cls - - elif node.type == "function_definition": - # TODO: simply extract function name, no need to parse entire function - # see C analyzer - func = self.process_function_definition(node, path, source_code) - parent = graph.get_function_by_name(func.name) - elif node.type == "call": - callee = self.process_function_call(node) - if callee is not None: - self.process_call_node(parent, callee, graph) - - # Recursivly visit child nodes - for child in node.children: - self.second_pass_traverse(parent, child, path, graph, source_code) - - def second_pass(self, path: Path, f: io.TextIOWrapper, graph: Graph) -> None: - """ - Perform a second pass analysis on the given Python file. - - Args: - path (Path): The path to the file. - f (io.TextIOWrapper): The file handle of the file to be processed. - """ - - if path.suffix != '.py': - logger.debug(f"Skipping none Python file {path}") - return - - logger.info(f"Processing {path}") - - # Get file entity - file = graph.get_file(os.path.dirname(path), path.name, path.suffix) - if file is None: - logger.error(f"File entity not found for: {path}") - return - - try: - # Parse file - source_code = f.read() - tree = self.parser.parse(source_code) - - # Walk thought the AST - self.second_pass_traverse(file, tree.root_node, path, graph, source_code) - except Exception as e: - logger.error(f"Failed to process file {path}: {e}") + raise ValueError(f"Unknown key {key}") diff --git a/api/analyzers/source_analyzer.py b/api/analyzers/source_analyzer.py index c0fc786..9b8e703 100644 --- a/api/analyzers/source_analyzer.py +++ b/api/analyzers/source_analyzer.py @@ -1,31 +1,76 @@ -import os -import shutil -import concurrent.futures - +from contextlib import nullcontext from pathlib import Path -from typing import Optional, List +from typing import Optional + +from api.entities.entity import Entity +from api.entities.file import File from ..graph import Graph -from .c.analyzer import CAnalyzer +from .analyzer import AbstractAnalyzer +# from .c.analyzer import CAnalyzer +from .java.analyzer import JavaAnalyzer from .python.analyzer import PythonAnalyzer +from multilspy import SyncLanguageServer +from multilspy.multilspy_config import MultilspyConfig +from multilspy.multilspy_logger import MultilspyLogger + import logging # Configure logging logging.basicConfig(level=logging.DEBUG, format='%(filename)s - %(asctime)s - %(levelname)s - %(message)s') # List of available analyzers -analyzers = {'.c': CAnalyzer(), - '.h': CAnalyzer(), - '.py': PythonAnalyzer()} +analyzers: dict[str, AbstractAnalyzer] = { + # '.c': CAnalyzer(), + # '.h': CAnalyzer(), + '.py': PythonAnalyzer(), + '.java': JavaAnalyzer()} + +class NullLanguageServer: + def start_server(self): + return nullcontext() class SourceAnalyzer(): + def __init__(self) -> None: + self.files: dict[Path, File] = {} - def supported_types(self) -> List[str]: + def supported_types(self) -> list[str]: """ """ return list(analyzers.keys()) - - def first_pass(self, ignore: List[str], executor: concurrent.futures.Executor) -> None: + + def create_entity_hierarchy(self, entity: Entity, file: File, analyzer: AbstractAnalyzer, graph: Graph): + types = analyzer.get_entity_types() + stack = list(entity.node.children) + while stack: + node = stack.pop() + if node.type in types: + child = Entity(node) + child.id = graph.add_entity(analyzer.get_entity_label(node), analyzer.get_entity_name(node), analyzer.get_entity_docstring(node), str(file.path), node.start_point.row, node.end_point.row, {}) + analyzer.add_symbols(child) + file.add_entity(child) + entity.add_child(child) + graph.connect_entities("DEFINES", entity.id, child.id) + self.create_entity_hierarchy(child, file, analyzer, graph) + else: + stack.extend(node.children) + + def create_hierarchy(self, file: File, analyzer: AbstractAnalyzer, graph: Graph): + types = analyzer.get_entity_types() + stack = [file.tree.root_node] + while stack: + node = stack.pop() + if node.type in types: + entity = Entity(node) + entity.id = graph.add_entity(analyzer.get_entity_label(node), analyzer.get_entity_name(node), analyzer.get_entity_docstring(node), str(file.path), node.start_point.row, node.end_point.row, {}) + analyzer.add_symbols(entity) + file.add_entity(entity) + graph.connect_entities("DEFINES", file.id, entity.id) + self.create_entity_hierarchy(entity, file, analyzer, graph) + else: + stack.extend(node.children) + + def first_pass(self, path: Path, ignore: list[str], graph: Graph) -> None: """ Perform the first pass analysis on source files in the given directory tree. @@ -34,44 +79,34 @@ def first_pass(self, ignore: List[str], executor: concurrent.futures.Executor) - executor (concurrent.futures.Executor): The executor to run tasks concurrently. """ - tasks = [] - for dirpath, dirnames, filenames in os.walk("."): - - # skip current directory if it is within the ignore list - if dirpath in ignore: - # in-place clear dirnames to prevent os.walk from recursing into - # any of the nested directories - logging.info(f'ignoring directory: {dirpath}') - dirnames[:] = [] + for file_path in path.rglob('*.*'): + # Skip none supported files + if file_path.suffix not in analyzers: + logging.info(f"Skipping none supported file {file_path}") continue - logging.info(f'Processing directory: {dirpath}') - - # Process each file in the current directory - for filename in filenames: - file_path = Path(os.path.join(dirpath, filename)) + # Skip ignored files + if any([i in str(file_path) for i in ignore]): + logging.info(f"Skipping ignored file {file_path}") + continue - # Skip none supported files - ext = file_path.suffix - if ext not in analyzers: - logging.info(f"Skipping none supported file {file_path}") - continue + logging.info(f'Processing file: {file_path}') - logging.info(f'Processing file: {file_path}') + analyzer = analyzers[file_path.suffix] - def process_file(path: Path) -> None: - with open(path, 'rb') as f: - ext = path.suffix - analyzers[ext].first_pass(path, f, self.graph) + # Parse file + source_code = file_path.read_bytes() + tree = analyzer.parser.parse(source_code) - process_file(file_path) - #task = executor.submit(process_file, file_path) - #tasks.append(task) + # Create file entity + file = File(file_path, tree) + self.files[file_path] = file - # Wait for all tasks to complete - #concurrent.futures.wait(tasks) + # Walk thought the AST + graph.add_file(file) + self.create_hierarchy(file, analyzer, graph) - def second_pass(self, ignore: List[str], executor: concurrent.futures.Executor) -> None: + def second_pass(self, graph: Graph, path: Path) -> None: """ Recursively analyze the contents of a directory. @@ -81,61 +116,57 @@ def second_pass(self, ignore: List[str], executor: concurrent.futures.Executor) executor (concurrent.futures.Executor): The executor to run tasks concurrently. """ - tasks = [] - for dirpath, dirnames, filenames in os.walk("."): - - # skip current directory if it is within the ignore list - if dirpath in ignore: - # in-place clear dirnames to prevent os.walk from recursing into - # any of the nested directories - logging.info(f'ignoring directory: {dirpath}') - dirnames[:] = [] - continue - - logging.info(f'Processing directory: {dirpath}') - - # Process each file in the current directory - for filename in filenames: - file_path = Path(os.path.join(dirpath, filename)) - - # Skip none supported files - ext = file_path.suffix - if ext not in analyzers: - continue - + logger = MultilspyLogger() + logger.logger.setLevel(logging.ERROR) + lsps = {} + if any(path.rglob('*.java')): + config = MultilspyConfig.from_dict({"code_language": "java"}) + lsps[".java"] = SyncLanguageServer.create(config, logger, str(path)) + else: + lsps[".java"] = NullLanguageServer() + if any(path.rglob('*.py')): + config = MultilspyConfig.from_dict({"code_language": "python"}) + lsps[".py"] = SyncLanguageServer.create(config, logger, str(path)) + else: + lsps[".py"] = NullLanguageServer() + with lsps[".java"].start_server(), lsps[".py"].start_server(): + for file_path, file in self.files.items(): logging.info(f'Processing file: {file_path}') - - def process_file(path: Path) -> None: - with open(path, 'rb') as f: - ext = path.suffix - analyzers[ext].second_pass(path, f, self.graph) - - task = executor.submit(process_file, file_path) - tasks.append(task) - - # Wait for all tasks to complete - concurrent.futures.wait(tasks) - - def analyze_file(self, path: Path, graph: Graph) -> None: - ext = path.suffix - logging.info(f"analyze_file: path: {path}") + for _, entity in file.entities.items(): + entity.resolved_symbol(lambda key, symbol: analyzers[file_path.suffix].resolve_symbol(self.files, lsps[file_path.suffix], file_path, key, symbol)) + for key, symbols in entity.resolved_symbols.items(): + for symbol in symbols: + if key == "base_class": + graph.connect_entities("EXTENDS", entity.id, symbol.id) + elif key == "implement_interface": + graph.connect_entities("IMPLEMENTS", entity.id, symbol.id) + elif key == "extend_interface": + graph.connect_entities("EXTENDS", entity.id, symbol.id) + elif key == "call": + graph.connect_entities("CALLS", entity.id, symbol.id) + elif key == "return_type": + graph.connect_entities("RETURNS", entity.id, symbol.id) + elif key == "parameters": + graph.connect_entities("PARAMETERS", entity.id, symbol.id) + + def analyze_file(self, file_path: Path, path: Path, graph: Graph) -> None: + ext = file_path.suffix + logging.info(f"analyze_file: path: {file_path}") logging.info(f"analyze_file: ext: {ext}") if ext not in analyzers: return - with open(path, 'rb') as f: - analyzers[ext].first_pass(path, f, graph) - analyzers[ext].second_pass(path, f, graph) + self.first_pass(file_path, [], graph) + self.second_pass(graph, path) - def analyze_sources(self, ignore: List[str]) -> None: - with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor: - # First pass analysis of the source code - self.first_pass(ignore, executor) + def analyze_sources(self, path: Path, ignore: list[str], graph: Graph) -> None: + # First pass analysis of the source code + self.first_pass(path, ignore, graph) - # Second pass analysis of the source code - self.second_pass(ignore, executor) + # Second pass analysis of the source code + self.second_pass(graph, path) - def analyze_local_folder(self, path: str, g: Graph, ignore: Optional[List[str]] = []) -> None: + def analyze_local_folder(self, path: str, g: Graph, ignore: Optional[list[str]] = []) -> None: """ Analyze path. @@ -146,24 +177,15 @@ def analyze_local_folder(self, path: str, g: Graph, ignore: Optional[List[str]] logging.info(f"Analyzing local folder {path}") - # Save original working directory for later restore - original_dir = Path.cwd() - - # change working directory to path - os.chdir(path) - - # Initialize the graph and analyzer - self.graph = g - # Analyze source files - self.analyze_sources(ignore) + self.analyze_sources(Path(path), ignore, g) logging.info("Done analyzing path") - # Restore original working dir - os.chdir(original_dir) - - def analyze_local_repository(self, path: str, ignore: Optional[List[str]] = []) -> Graph: + def analyze_local_repository(self, path: str, ignore: Optional[list[str]] = None) -> Graph: + if ignore is None: + ignore = [] + # ... (rest of the function implementation) """ Analyze a local Git repository. diff --git a/api/analyzers/utils.py b/api/analyzers/utils.py deleted file mode 100644 index 24b5a31..0000000 --- a/api/analyzers/utils.py +++ /dev/null @@ -1,23 +0,0 @@ -from typing import Union -from tree_sitter import Node - -def print_node(node, indent=0): - """ - Recursively print a tree-sitter node and its children. - - Args: - node: The tree-sitter node to print. - indent: The current indentation level for pretty printing. - """ - indent_str = ' ' * indent - print(f"{indent_str}{node.type}") - - for child in node.children: - print_node(child, indent + 1) - -def find_child_of_type(node: Node, child_type: str) -> Union[tuple[Node, int], None]: - for idx, child in enumerate(node.children): - if child.type == child_type: - return (child, idx) - - return None diff --git a/api/entities/__init__.py b/api/entities/__init__.py index 58ef864..9b2e748 100644 --- a/api/entities/__init__.py +++ b/api/entities/__init__.py @@ -1,8 +1,5 @@ # __init__.py from .file import File -from .cls import Class -from .struct import Struct -from .function import Function -from .argument import Argument +from .entity import Entity from .entity_encoder import * diff --git a/api/entities/argument.py b/api/entities/argument.py deleted file mode 100644 index 25e5a6c..0000000 --- a/api/entities/argument.py +++ /dev/null @@ -1,33 +0,0 @@ -from typing import Optional - -class Argument: - def __init__(self, name: str, type_: Optional[str]) -> None: - """ - Initialize an Argument object. - - Args: - name (str): Name of the argument. - type_ (Optional[str], optional): Type of the argument. Defaults to None. - """ - - if type_ is None: - type_ = 'Unknown' - - self.name = name - self.type = type_ - - def __str__(self) -> str: - return f""" - name: {self.name} - type_: {self.type_}""" - - def __repr__(self) -> str: - return f""" - name: {self.name} - type: {self.type}""" - - def __eq__(self, other) -> bool: - if not isinstance(other, Argument): - return False - - return self.name == other.name and self.type == other.type diff --git a/api/entities/cls.py b/api/entities/cls.py deleted file mode 100644 index b64c393..0000000 --- a/api/entities/cls.py +++ /dev/null @@ -1,45 +0,0 @@ -from typing import Optional - -class Class(): - """ - Represents a class with a name and an optional docstring. - """ - - def __init__(self, path: str, name: str, doc: Optional[str], - src_start: int, src_end: int) -> None: - """ - Initializes a Class instance. - - Args: - path (str): The path under which the class is defined - name (str): The name of the class. - doc (Optional[str], optional): The docstring of the class. Defaults to None. - src_start (int): Start line of the class in the source code. - src_end (int): End line of the class in the source code. - """ - - self.path = path - self.name = name - self.doc = doc - self.src_start = src_start - self.src_end = src_end - - def __str__(self) -> str: - return f""" - id: {self.id if hasattr(self, 'id') else 'Unknown'} - path: {self.path} - name: {self.name} - doc: {self.doc} - src_start: {self. src_start} - src_end: {self.src_end}""" - - def __eq__(self, other): - if not isinstance(other, Class): - return False - - return (self.path == other.path and - self.name == other.name and - self.doc == other.doc and - self.src_start == other.src_start and - self.src_end == other.src_end) - diff --git a/api/entities/entity.py b/api/entities/entity.py new file mode 100644 index 0000000..e271693 --- /dev/null +++ b/api/entities/entity.py @@ -0,0 +1,31 @@ +from typing import Callable, Self +from tree_sitter import Node + + +class Entity: + def __init__(self, node: Node): + self.node = node + self.symbols: dict[str, list[Node]] = {} + self.resolved_symbols: dict[str, set[Self]] = {} + self.children: dict[Node, Self] = {} + + def add_symbol(self, key: str, symbol: Node): + if key not in self.symbols: + self.symbols[key] = [] + self.symbols[key].append(symbol) + + def add_resolved_symbol(self, key: str, symbol: Self): + if key not in self.resolved_symbols: + self.resolved_symbols[key] = set() + self.resolved_symbols[key].add(symbol) + + def add_child(self, child: Self): + child.parent = self + self.children[child.node] = child + + def resolved_symbol(self, f: Callable[[str, Node], list[Self]]): + for key, symbols in self.symbols.items(): + self.resolved_symbols[key] = set() + for symbol in symbols: + for resolved_symbol in f(key, symbol): + self.resolved_symbols[key].add(resolved_symbol) \ No newline at end of file diff --git a/api/entities/file.py b/api/entities/file.py index 884aa6b..c59e2b6 100644 --- a/api/entities/file.py +++ b/api/entities/file.py @@ -1,33 +1,37 @@ +from pathlib import Path +from tree_sitter import Node, Tree + +from api.entities.entity import Entity + + class File: """ Represents a file with basic properties like path, name, and extension. """ - def __init__(self, path: str, name: str, ext: str) -> None: + def __init__(self, path: Path, tree: Tree) -> None: """ Initialize a File object. Args: - path (str): The full path to the file. - name (str): The name of the file. - ext (str): The file extension. + path (Path): The full path to the file. + tree (Tree): The parsed AST of the file content. """ self.path = path - self.name = name - self.ext = ext + self.tree = tree + self.entities: dict[Node, Entity] = {} + + def add_entity(self, entity: Entity): + entity.parent = self + self.entities[entity.node] = entity def __str__(self) -> str: - return f""" - path: {self.path} - name: {self.name} - ext: {self.ext}""" + return f"path: {self.path}" def __eq__(self, other) -> bool: if not isinstance(other, File): return False - return (self.ext == other.ext and - self.path == other.path and - self.name == other.name) + return self.path == other.path diff --git a/api/entities/function.py b/api/entities/function.py deleted file mode 100644 index ee1c4d0..0000000 --- a/api/entities/function.py +++ /dev/null @@ -1,62 +0,0 @@ -from .argument import Argument -from typing import List, Optional - -class Function: - def __init__(self, path: str, name: str, doc: Optional[str], - ret_type: Optional[str], src: Optional[str], - src_start: int, src_end: int) -> None: - """ - Initialize a Function object. - - Args: - path (str): Path of the function definition. - name (str): Name of the function. - ret_type (Optional[str]): Return type of the function. - src_start (int): Start line of the function in the source code. - src_end (int): End line of the function in the source code. - """ - - self.path = path - self.name = name - self.doc = doc - self.ret_type = ret_type - self.src = src - self.src_start = src_start - self.src_end = src_end - - self.args: List[Argument] = [] - - def __str__(self) -> str: - return f""" - path: {self.path} - name: {self.name} - doc: {self.doc} - ret_type: {self.ret_type} - src: {self.src} - src_start: {self. src_start} - src_end: {self.src_end} - args: {self.args}""" - - def __eq__(self, other): - if not isinstance(other, Function): - return False - - return (self.doc == other.doc and - self.args == other.args and - self.path == other.path and - self.name == other.name and - self.ret_type == other.ret_type and - self.src_end == other.src_end and - self.src_start == other.src_start) - - def add_argument(self, name: str, t: Optional[str]) -> None: - """ - Add an argument to the function. - - Args: - name (str): Name of the argument. - type_ (str): Type of the argument. - """ - - self.args.append(Argument(name, t)) - diff --git a/api/entities/struct.py b/api/entities/struct.py deleted file mode 100644 index 1a51904..0000000 --- a/api/entities/struct.py +++ /dev/null @@ -1,60 +0,0 @@ -from typing import List, Optional - -class Struct(): - """ - Represents a struct with a name and an optional docstring. - """ - - def __init__(self, path: str, name: str, doc: Optional[str], - src_start: int, src_end: int) -> None: - """ - Initializes a Struct instance. - - Args: - path (str): The path under which the struct is defined - name (str): The name of the struct. - doc (Optional[str], optional): The docstring of the struct. Defaults to None. - src_start (int): Start line of the struct in the source code. - src_end (int): End line of the struct in the source code. - """ - - self.path = path - self.name = name - self.doc = doc - self.src_start = src_start - self.src_end = src_end - - self.fields: List[List[str, str]] = [] - - def __str__(self) -> str: - return f""" - id: {self.id if hasattr(self, 'id') else 'Unknown'} # type: ignore - path: {self.path} - name: {self.name} - doc: {self.doc} - src_start: {self. src_start} - src_end: {self.src_end} - fields: {self.fields}""" - - def __eq__(self, other): - if not isinstance(other, Struct): - return False - - return (self.path == other.path and - self.name == other.name and - self.doc == other.doc and - self.src_start == other.src_start and - self.src_end == other.src_end and - self.fields == other.fields) - - def add_field(self, name: str, t: str) -> None: - """ - Add a field to the struct. - - Args: - name (str): Name of the argument. - t (str): Type of the field. - """ - - self.fields.append([name, t]) - diff --git a/api/git_utils/__init__.py b/api/git_utils/__init__.py new file mode 100644 index 0000000..4fd3af9 --- /dev/null +++ b/api/git_utils/__init__.py @@ -0,0 +1 @@ +from .git_utils import * diff --git a/api/git_utils/git_graph.py b/api/git_utils/git_graph.py new file mode 100644 index 0000000..42df35a --- /dev/null +++ b/api/git_utils/git_graph.py @@ -0,0 +1,177 @@ +import os +import logging +from git import Commit +from falkordb import FalkorDB, Node +from typing import List, Optional + +# Configure logging +logging.basicConfig(level=logging.DEBUG, format='%(filename)s - %(asctime)s - %(levelname)s - %(message)s') + +class GitGraph(): + """ + Represents a git commit graph + nodes are commits where one commit leads to its parents and children + edges contains queries and parameters for transitioning the code-graph + from the current commit to parent / child + """ + + def __init__(self, name: str): + + self.db = FalkorDB(host=os.getenv('FALKORDB_HOST', 'localhost'), + port=os.getenv('FALKORDB_PORT', 6379), + username=os.getenv('FALKORDB_USERNAME', None), + password=os.getenv('FALKORDB_PASSWORD', None)) + + self.g = self.db.select_graph(name) + + # create indicies + # index commit hash + try: + self.g.create_node_range_index("Commit", "hash") + except Exception: + pass + + def _commit_from_node(self, node:Node) -> dict: + """ + Returns a dict representing a commit node + """ + + return {'hash': node.properties['hash'], + 'date': node.properties['date'], + 'author': node.properties['author'], + 'message': node.properties['message']} + + def add_commit(self, commit: Commit) -> None: + """ + Add a new commit to the graph + """ + date = commit.committed_date + author = commit.author.name + hexsha = commit.hexsha + message = commit.message + logging.info(f"Adding commit {hexsha}: {message}") + + q = "MERGE (c:Commit {hash: $hash, author: $author, message: $message, date: $date})" + params = {'hash': hexsha, 'author': author, 'message': message, 'date': date} + self.g.query(q, params) + + def list_commits(self) -> List[Node]: + """ + List all commits + """ + + q = "MATCH (c:Commit) RETURN c ORDER BY c.date" + result_set = self.g.query(q).result_set + + return [self._commit_from_node(row[0]) for row in result_set] + + def get_commits(self, hashes: List[str]) -> List[dict]: + logging.info(f"Searching for commits {hashes}") + + q = """MATCH (c:Commit) + WHERE c.hash IN $hashes + RETURN c""" + + params = {'hashes': hashes} + res = self.g.query(q, params).result_set + + commits = [] + for row in res: + commit = self._commit_from_node(row[0]) + commits.append(commit) + + logging.info(f"retrived commits: {commits}") + return commits + + def get_child_commit(self, parent) -> Optional[dict]: + q = """MATCH (c:Commit {hash: $parent})-[:CHILD]->(child: Commit) + RETURN child""" + + res = self.g.query(q, {'parent': parent}).result_set + + if len(res) > 0: + assert(len(res) == 1) + return self._commit_from_node(res[0][0]) + + return None + + def connect_commits(self, child: str, parent: str) -> None: + """ + connect commits via both PARENT and CHILD edges + """ + + logging.info(f"Connecting commits {child} -PARENT-> {parent}") + logging.info(f"Connecting commits {parent} -CHILD-> {child}") + + q = """MATCH (child :Commit {hash: $child_hash}), (parent :Commit {hash: $parent_hash}) + MERGE (child)-[:PARENT]->(parent) + MERGE (parent)-[:CHILD]->(child)""" + + params = {'child_hash': child, 'parent_hash': parent} + + self.g.query(q, params) + + + def set_parent_transition(self, child: str, parent: str, queries: [str], params: [str]) -> None: + """ + Sets the queries and parameters needed to transition the code-graph + from the child commit to the parent commit + """ + + q = """MATCH (child :Commit {hash: $child})-[e:PARENT]->(parent :Commit {hash: $parent}) + SET e.queries = $queries, e.params = $params""" + + _params = {'child': child, 'parent': parent, 'queries': queries, 'params': params} + + self.g.query(q, _params) + + + def set_child_transition(self, child: str, parent: str, queries: [str], params: [str]) -> None: + """ + Sets the queries and parameters needed to transition the code-graph + from the parent commit to the child commit + """ + + q = """MATCH (parent :Commit {hash: $parent})-[e:CHILD]->(child :Commit {hash: $child}) + SET e.queries = $queries, e.params = $params""" + + _params = {'child': child, 'parent': parent, 'queries': queries, 'params': params} + + self.g.query(q, _params) + + + def get_parent_transitions(self, child: str, parent: str) -> List[tuple[str: dict]]: + """ + Get queries and parameters transitioning from child commit to parent commit + """ + q = """MATCH path = (:Commit {hash: $child_hash})-[:PARENT*]->(:Commit {hash: $parent_hash}) + WITH path + LIMIT 1 + UNWIND relationships(path) AS e + WITH e + WHERE e.queries is not NULL + RETURN collect(e.queries), collect(e.params) + """ + + res = self.g.query(q, {'child_hash': child, 'parent_hash': parent}).result_set + + return (res[0][0], res[0][1]) + + + def get_child_transitions(self, child: str, parent: str) -> List[tuple[str: dict]]: + """ + Get queries and parameters transitioning from parent commit to child commit + """ + q = """MATCH path = (:Commit {hash: $parent_hash})-[:CHILD*]->(:Commit {hash: $child_hash}) + WITH path + LIMIT 1 + UNWIND relationships(path) AS e + WITH e + WHERE e.queries is not NULL + RETURN collect(e.queries), collect(e.params) + """ + + res = self.g.query(q, {'child_hash': child, 'parent_hash': parent}).result_set + + return (res[0][0], res[0][1]) + diff --git a/api/git_utils/git_utils.py b/api/git_utils/git_utils.py new file mode 100644 index 0000000..b50a880 --- /dev/null +++ b/api/git_utils/git_utils.py @@ -0,0 +1,378 @@ +import os +import json +import logging +from ..info import * +from git import Repo +from pathlib import Path +from ..graph import Graph +from .git_graph import GitGraph +from typing import List, Optional +from ..analyzers import SourceAnalyzer + +# Configure logging +logging.basicConfig(level=logging.DEBUG, format='%(filename)s - %(asctime)s - %(levelname)s - %(message)s') + +def GitRepoName(repo_name): + return "{" + repo_name + "}_git" + +def is_ignored(file_path: str, ignore_list: List[str]) -> bool: + """ + Checks if a file should be ignored based on the ignore list. + + Args: + file_path (str): The file path to check. + ignore_list (List[str]): List of patterns to ignore. + + Returns: + bool: True if the file should be ignored, False otherwise. + """ + + return any(file_path.startswith(ignore) for ignore in ignore_list) + +def classify_changes(diff, ignore_list: List[str]) -> tuple[list[Path], list[Path], list[Path]]: + """ + Classifies changes into added, deleted, and modified files. + + Args: + diff: The git diff object representing changes between two commits. + ignore_list (List[str]): List of file patterns to ignore. + + Returns: + (List[str], List[str], List[str]): A tuple of lists representing added, deleted, and modified files. + """ + + added, deleted, modified = [], [], [] + + for change in diff: + if change.new_file and not is_ignored(change.b_path, ignore_list): + logging.debug(f"new file: {change.b_path}") + added.append(Path(change.b_path)) + if change.deleted_file and not is_ignored(change.a_path, ignore_list): + logging.debug(f"deleted file: {change.a_path}") + deleted.append(Path(change.a_path)) + if change.change_type == 'M' and not is_ignored(change.a_path, ignore_list): + logging.debug(f"change file: {change.a_path}") + modified.append(Path(change.a_path)) + + return added, deleted, modified + +# build a graph capturing the git commit history +def build_commit_graph(path: str, repo_name: str, ignore_list: Optional[List[str]] = None) -> GitGraph: + """ + Builds a graph representation of the git commit history. + + Args: + path (str): Path to the git repository. + repo_name (str): Name of the repository. + ignore_list (List[str], optional): List of file patterns to ignore. + + Returns: + GitGraph: Graph object representing the commit history. + """ + + if ignore_list is None: + ignore_list = [] + + # Copy the graph into a temporary graph + logging.info(f"Cloning source graph {repo_name} -> {repo_name}_tmp") + # Will be deleted at the end of this function + g = Graph(repo_name).clone(repo_name + "_tmp") + g.enable_backlog() + + analyzer = SourceAnalyzer() + git_graph = GitGraph(GitRepoName(repo_name)) + supported_types = analyzer.supported_types() + + # Initialize with the current commit + # Save current git for later restoration + repo = Repo('.') + current_commit = repo.head.commit + current_commit_hexsha = current_commit.hexsha + + # Add commit to the git graph + git_graph.add_commit(current_commit) + + #-------------------------------------------------------------------------- + # Process git history going backwards + #-------------------------------------------------------------------------- + + logging.info("Computing transition queries moving backwards") + + child_commit = current_commit + while len(child_commit.parents) > 0: + parent_commit = child_commit.parents[0] + + # add commit to the git graph + git_graph.add_commit(parent_commit) + + # connect child parent commits relation + git_graph.connect_commits(child_commit.hexsha, parent_commit.hexsha) + + # Represents the changes going backward! + # e.g. which files need to be deleted when moving back one commit + # + # if we were to switch "direction" going forward + # delete events would become add event + # e.g. which files need to be added when moving forward from this commit + # to the next one + + # Process file changes in this commit + logging.info(f"""Computing diff between + child {child_commit.hexsha}: {child_commit.message} + and {parent_commit.hexsha}: {parent_commit.message}""") + + diff = child_commit.diff(parent_commit) + added, deleted, modified = classify_changes(diff, ignore_list) + + # Checkout prev commit + logging.info(f"Checking out commit: {parent_commit.hexsha}") + repo.git.checkout(parent_commit.hexsha) + + #----------------------------------------------------------------------- + # Apply changes going backwards + #----------------------------------------------------------------------- + + # apply deletions + # TODO: a bit of a waste, compute in previous loop + deleted_files = [] + for deleted_file_path in deleted: + _ext = os.path.splitext(deleted_file_path)[1] + if _ext in supported_types: + _path = os.path.dirname(deleted_file_path) + _name = os.path.basename(deleted_file_path) + deleted_files.append( + {'path': _path, 'name': _name, 'ext' : _ext}) + + # remove deleted files from the graph + if len(deleted_files) > 0: + logging.info(f"Removing deleted files: {deleted_files}") + g.delete_files(deleted_files) + + if len(added) > 0: + for new_file in added: + # New file been added + logging.info(f"Introducing a new source file: {new_file}") + analyzer.analyze_file(new_file, Path(path), g) + + queries, params = g.clear_backlog() + + # Save transition queries to the git graph + if len(queries) > 0: + assert(len(queries) == len(params)) + + # Covert parameters from dict to JSON formatted string + params = [json.dumps(p) for p in params] + + # Log transitions + logging.debug(f"""Save graph transition from + commit: {child_commit.hexsha} + to + commit: {parent_commit.hexsha} + Queries: {queries} + Parameters: {params} + """) + + git_graph.set_parent_transition(child_commit.hexsha, + parent_commit.hexsha, queries, params) + # advance to the next commit + child_commit = parent_commit + + #-------------------------------------------------------------------------- + # Process git history going forward + #-------------------------------------------------------------------------- + + logging.info("Computing transition queries moving forward") + parent_commit = child_commit + while parent_commit.hexsha != current_commit_hexsha: + child_commit = git_graph.get_child_commit(parent_commit.hexsha) + child_commit = repo.commit(child_commit['hash']) + + # Represents the changes going forward + # e.g. which files need to be deleted when moving forward one commit + + # Process file changes in this commit + logging.info(f"""Computing diff between + child {parent_commit.hexsha}: {parent_commit.message} + and {child_commit.hexsha}: {child_commit.message}""") + + diff = parent_commit.diff(child_commit) + added, deleted, modified = classify_changes(diff, ignore_list) + + # Checkout child commit + logging.info(f"Checking out commit: {child_commit.hexsha}") + repo.git.checkout(child_commit.hexsha) + + #----------------------------------------------------------------------- + # Apply changes going forward + #----------------------------------------------------------------------- + + # apply deletions + # TODO: a bit of a waste, compute in previous loop + deleted_files = [] + for deleted_file_path in deleted: + _ext = os.path.splitext(deleted_file_path)[1] + if _ext in supported_types: + _path = os.path.dirname(deleted_file_path) + _name = os.path.basename(deleted_file_path) + deleted_files.append( + {'path': _path, 'name': _name, 'ext' : _ext}) + + # remove deleted files from the graph + if len(deleted_files) > 0: + logging.info(f"Removing deleted files: {deleted_files}") + g.delete_files(deleted_files) + + if len(added) > 0: + for new_file in added: + # New file been added + logging.info(f"Introducing a new source file: {new_file}") + analyzer.analyze_file(new_file, Path(path), g) + + queries, params = g.clear_backlog() + + # Save transition queries to the git graph + if len(queries) > 0: + assert(len(queries) == len(params)) + + # Covert parameters from dict to JSON formatted string + params = [json.dumps(p) for p in params] + + # Log transitions + logging.debug(f"""Save graph transition from + commit: {parent_commit.hexsha} + to + commit: {child_commit.hexsha} + Queries: {queries} + Parameters: {params} + """) + + git_graph.set_child_transition(child_commit.hexsha, + parent_commit.hexsha, queries, params) + # advance to the child_commit + parent_commit = child_commit + + logging.debug("Done processing repository commit history") + + #-------------------------------------------------------------------------- + # Clean up + #-------------------------------------------------------------------------- + + # Delete temporaty graph + g.disable_backlog() + + logging.debug(f"Deleting temporary graph {repo_name + '_tmp'}") + g.delete() + + return git_graph + +def switch_commit(repo: str, to: str) -> dict[str, dict[str, list]]: + """ + Switches the state of a graph repository from its current commit to the given commit. + + This function handles switching between two git commits for a graph-based repository. + It identifies the changes (additions, deletions, modifications) in nodes and edges between + the current commit and the target commit and then applies the necessary transitions. + + Args: + repo (str): The name of the graph repository to switch commits. + to (str): The target commit hash to switch the graph to. + + Returns: + dict: A dictionary containing the changes made during the commit switch, organized by: + - 'deletions': { + 'nodes': List of node IDs deleted, + 'edges': List of edge IDs deleted + }, + - 'additions': { + 'nodes': List of new Node objects added, + 'edges': List of new Edge objects added + }, + - 'modifications': { + 'nodes': List of modified Node objects, + 'edges': List of modified Edge objects + } + """ + + # Validate input arguments + if not repo or not isinstance(repo, str): + raise ValueError("Invalid repository name") + + if not to or not isinstance(to, str): + raise ValueError("Invalid desired commit value") + + logging.info(f"Switching to commit: {to}") + + # Initialize return value to an empty change set + change_set = { + 'deletions': { + 'nodes': [], + 'edges': [] + }, + 'additions': { + 'nodes': [], + 'edges': [], + }, + 'modifications': { + 'nodes': [], + 'edges': [] + } + } + + # Initialize the graph and GitGraph objects + g = Graph(repo) + git_graph = GitGraph(GitRepoName(repo)) + + # Get the current commit hash of the graph + current_hash = get_repo_commit(repo) + logging.info(f"Current graph commit: {current_hash}") + + if current_hash == to: + logging.debug("Current commit: {current_hash} is the requested commit") + # No change remain at the current commit + return change_set + + # Find the path between the current commit and the desired commit + commits = git_graph.get_commits([current_hash, to]) + + # Ensure both current and target commits are present + if len(commits) != 2: + logging.error("Missing commits. Unable to proceed.") + raise ValueError("Commits not found") + + # Identify the current and new commits based on their hashes + current_commit, new_commit = (commits if commits[0]['hash'] == current_hash else reversed(commits)) + + # Determine the direction of the switch (forward or backward in the commit history) + child_commit = None + parent_commit = None + if current_commit['date'] > new_commit['date']: + child_commit = current_commit + parent_commit = new_commit + logging.info(f"Moving backward from {child_commit['hash']} to {parent_commit['hash']}") + # Get the transitions (queries and parameters) for moving backward + queries, params = git_graph.get_parent_transitions(child_commit['hash'], parent_commit['hash']) + else: + child_commit = new_commit + parent_commit = current_commit + logging.info(f"Moving forward from {parent_commit['hash']} to {child_commit['hash']}") + # Get the transitions (queries and parameters) for moving forward + queries, params = git_graph.get_child_transitions(child_commit['hash'], parent_commit['hash']) + + # Apply each transition query with its respective parameters + for q, p in zip(queries, params): + for _q, _p in zip(q, p): + _p = json.loads(_p) + logging.debug(f"Executing query: {_q} with params: {_p}") + + # Rerun the query with parameters on the graph + res = g.rerun_query(_q, _p) + if "DELETE" in _q: + deleted_nodes = res.result_set[0][0] + change_set['deletions']['nodes'] += deleted_nodes + + # Update the graph's commit to the new target commit + set_repo_commit(repo, to) + logging.info(f"Graph commit updated to {to}") + + return change_set + diff --git a/api/graph.py b/api/graph.py index b4ac275..3feba0d 100644 --- a/api/graph.py +++ b/api/graph.py @@ -1,7 +1,7 @@ import os import time from .entities import * -from typing import Dict, Optional, List, Tuple +from typing import Optional from falkordb import FalkorDB, Path, Node, QueryResult # Configure the logger @@ -17,7 +17,7 @@ def graph_exists(name: str): return name in db.list_graphs() -def get_repos() -> List[str]: +def get_repos() -> list[str]: """ List processed repositories """ @@ -105,12 +105,12 @@ def disable_backlog(self) -> None: self.backlog = None logging.debug("Backlog disabled") - def clear_backlog(self) -> Tuple[List[str], List[dict]]: + def clear_backlog(self) -> tuple[list[str], list[dict]]: """ Clears and returns the backlog of queries and parameters. Returns: - Tuple[List[str], List[dict]]: A tuple containing two lists: + tuple[list[str], list[dict]]: A tuple containing two lists: - The first list contains the backlog of queries. - The second list contains the backlog of query parameters. """ @@ -194,7 +194,7 @@ def get_sub_graph(self, l: int) -> dict: return sub_graph - def get_neighbors(self, node_ids: List[int], rel: Optional[str] = None, lbl: Optional[str] = None) -> Dict[str, List[dict]]: + def get_neighbors(self, node_ids: list[int], rel: Optional[str] = None, lbl: Optional[str] = None) -> dict[str, list[dict]]: """ Fetch the neighbors of a given nodes in the graph based on relationship type and/or label. @@ -240,58 +240,42 @@ def get_neighbors(self, node_ids: List[int], rel: Optional[str] = None, lbl: Opt logging.error(f"Error fetching neighbors for node {node_ids}: {e}") return {'nodes': [], 'edges': []} - - def _class_from_node(self, n: Node) -> Class: - """ - Create a Class from a graph node - """ - - doc = n.properties.get('doc') - name = n.properties.get('name') - path = n.properties.get('path') - src_end = n.properties.get('src_end') - src_start = n.properties.get('src_start') - - c = Class(path, name, doc, src_start, src_end) - c.id = n.id - - return c - - def add_class(self, c: Class) -> None: + def add_entity(self, label: str, name: str, doc: str, path: str, src_start: int, src_end: int, props: dict) -> int: """ - Adds a class node to the graph database. + Adds a node to the graph database. Args: - c (Class): The Class object to be added. """ - q = """MERGE (c:Class:Searchable {name: $name, path: $path, src_start: $src_start, - src_end: $src_end}) + q = f"""MERGE (c:{label}:Searchable {{name: $name, path: $path, src_start: $src_start, + src_end: $src_end}}) SET c.doc = $doc + SET c += $props RETURN c""" params = { - 'doc': c.doc, - 'name': c.name, - 'path': c.path, - 'src_start': c.src_start, - 'src_end': c.src_end, + 'doc': doc, + 'name': name, + 'path': path, + 'src_start': src_start, + 'src_end': src_end, + 'props': props } res = self._query(q, params) node = res.result_set[0][0] - c.id = node.id + return node.id - def get_class_by_name(self, class_name: str) -> Optional[Class]: + def get_class_by_name(self, class_name: str) -> Optional[Node]: q = "MATCH (c:Class) WHERE c.name = $name RETURN c LIMIT 1" res = self._query(q, {'name': class_name}).result_set if len(res) == 0: return None - return self._class_from_node(res[0][0]) + return res[0][0] - def get_class(self, class_id: int) -> Optional[Class]: + def get_class(self, class_id: int) -> Optional[Node]: q = """MATCH (c:Class) WHERE ID(c) = $class_id RETURN c""" @@ -301,65 +285,10 @@ def get_class(self, class_id: int) -> Optional[Class]: if len(res.result_set) == 0: return None - c = res.result_set[0][0] - return self._class_from_node(c) - - def _function_from_node(self, n: Node) -> Function: - """ - Create a Function from a graph node - """ - - src = n.properties.get('src') - doc = n.properties.get('doc') - path = n.properties.get('path') - name = n.properties.get('name') - args = n.properties.get('args') - src_end = n.properties.get('src_end') - ret_type = n.properties.get('ret_type') - src_start = n.properties.get('src_start') - - f = Function(path, name, doc, ret_type, src, src_start, src_end) - for arg in args: - name = arg[0] - type_ = arg[1] - f.add_argument(name, type_) - - f.id = n.id - - return f - - def add_function(self, func: Function) -> None: - """ - Adds a function node to the graph database. - - Args: - func (Function): The Function object to be added. - """ - - q = """MERGE (f:Function:Searchable {path: $path, name: $name, - src_start: $src_start, src_end: $src_end}) - SET f.args = $args, f.ret_type = $ret_type, f.src = $src, f.doc = $doc - RETURN f""" - - # Prepare arguments in a more straightforward manner - args = [[arg.name, arg.type] for arg in func.args] - params = { - 'src': func.src, - 'doc': func.doc, - 'path': func.path, - 'name': func.name, - 'src_start': func.src_start, - 'src_end': func.src_end, - 'args': args, - 'ret_type': func.ret_type - } - - res = self._query(q, params) - node = res.result_set[0][0] - func.id = node.id + return res.result_set[0][0] # set functions metadata - def set_functions_metadata(self, ids: List[int], metadata: List[dict]) -> None: + def set_functions_metadata(self, ids: list[int], metadata: list[dict]) -> None: assert(len(ids) == len(metadata)) # TODO: Match (f:Function) @@ -375,24 +304,22 @@ def set_functions_metadata(self, ids: List[int], metadata: List[dict]) -> None: self._query(q, params) # get all functions defined by file - def get_functions_in_file(self, path: str, name: str, ext: str) -> List[Function]: + def get_functions_in_file(self, path: str, name: str, ext: str) -> list[Node]: q = """MATCH (f:File {path: $path, name: $name, ext: $ext}) MATCH (f)-[:DEFINES]->(func:Function) RETURN collect(func)""" params = {'path': path, 'name': name, 'ext': ext} - funcs = self._query(q, params).result_set[0][0] - - return [self._function_from_node(n) for n in funcs] + return self._query(q, params).result_set[0][0] - def get_function_by_name(self, name: str) -> Optional[Function]: + def get_function_by_name(self, name: str) -> Optional[Node]: q = "MATCH (f:Function) WHERE f.name = $name RETURN f LIMIT 1" res = self._query(q, {'name': name}).result_set if len(res) == 0: return None - return self._function_from_node(res[0][0]) + return res[0][0] def prefix_search(self, prefix: str) -> str: """ @@ -430,7 +357,7 @@ def prefix_search(self, prefix: str) -> str: return completions - def get_function(self, func_id: int) -> Optional[Function]: + def get_function(self, func_id: int) -> Optional[Node]: q = """MATCH (f:Function) WHERE ID(f) = $func_id RETURN f""" @@ -440,59 +367,45 @@ def get_function(self, func_id: int) -> Optional[Function]: if len(res.result_set) == 0: return None - node = res.result_set[0][0] - - return self._function_from_node(node) + return res.result_set[0][0] - def function_calls(self, func_id: int) -> List[Function]: + def function_calls(self, func_id: int) -> list[Node]: q = """MATCH (f:Function) WHERE ID(f) = $func_id MATCH (f)-[:CALLS]->(callee) - RETURN callee""" + RETURN collect(callee)""" res = self._query(q, {'func_id': func_id}) - callees = [] - for row in res.result_set: - callee = row[0] - callees.append(self._function_from_node(callee)) - - return callees + return res.result_set[0][0] - def function_called_by(self, func_id: int) -> List[Function]: + def function_called_by(self, func_id: int) -> list[Node]: q = """MATCH (f:Function) WHERE ID(f) = $func_id MATCH (caller)-[:CALLS]->(f) - RETURN caller""" + RETURN collect(caller)""" res = self._query(q, {'func_id': func_id}) - callers = [] - for row in res.result_set: - caller = row[0] - callers.append(self._function_from_node(caller)) - - return callers + return res.result_set[0][0] def add_file(self, file: File) -> None: """ Add a file node to the graph database. Args: - file_path (str): Path of the file. - file_name (str): Name of the file. - file_ext (str): Extension of the file. + file (File): The file. """ q = """MERGE (f:File:Searchable {path: $path, name: $name, ext: $ext}) RETURN f""" - params = {'path': file.path, 'name': file.name, 'ext': file.ext} + params = {'path': str(file.path), 'name': file.path.name, 'ext': file.path.suffix} res = self._query(q, params) node = res.result_set[0][0] file.id = node.id - def delete_files(self, files: List[dict]) -> tuple[str, dict, List[int]]: + def delete_files(self, files: list[dict]) -> tuple[str, dict, list[int]]: """ Deletes file(s) from the graph in addition to any other entity defined in the file @@ -607,67 +520,16 @@ def function_calls_function(self, caller_id: int, callee_id: int, pos: int) -> N params = {'caller_id': caller_id, 'callee_id': callee_id, 'pos': pos} self._query(q, params) - def _struct_from_node(self, n: Node) -> Struct: - """ - Create a Struct from a graph node - """ - - doc = n.properties.get('doc') - name = n.properties.get('name') - path = n.properties.get('path') - src_end = n.properties.get('src_end') - src_start = n.properties.get('src_start') - fields = n.properties.get('fields') - - s = Struct(path, name, doc, src_start, src_end) - - # Populate struct fields - if fields is not None: - for field in fields: - field_name = field[0] - field_type = field[1] - s.add_field(field_name, field_type) - - s.id = n.id - - return s - - def add_struct(self, s: Struct) -> None: - """ - Adds a struct node to the graph database. - - Args: - s (Struct): The Struct object to be added. - """ - - q = """MERGE (s:Struct:Searchable {name: $name, path: $path, src_start: $src_start, - src_end: $src_end}) - SET s.doc = $doc, s.fields = $fields - RETURN s""" - - params = { - 'doc': s.doc, - 'name': s.name, - 'path': s.path, - 'src_start': s.src_start, - 'src_end': s.src_end, - 'fields': s.fields - } - - res = self._query(q, params) - node = res.result_set[0][0] - s.id = node.id - - def get_struct_by_name(self, struct_name: str) -> Optional[Struct]: + def get_struct_by_name(self, struct_name: str) -> Optional[Node]: q = "MATCH (s:Struct) WHERE s.name = $name RETURN s LIMIT 1" res = self._query(q, {'name': struct_name}).result_set if len(res) == 0: return None - return self._struct_from_node(res[0][0]) + return res[0][0] - def get_struct(self, struct_id: int) -> Optional[Struct]: + def get_struct(self, struct_id: int) -> Optional[Node]: q = """MATCH (s:Struct) WHERE ID(s) = $struct_id RETURN s""" @@ -678,7 +540,7 @@ def get_struct(self, struct_id: int) -> Optional[Struct]: return None s = res.result_set[0][0] - return self._struct_from_node(s) + return s def rerun_query(self, q: str, params: dict) -> QueryResult: """ @@ -687,7 +549,7 @@ def rerun_query(self, q: str, params: dict) -> QueryResult: return self._query(q, params) - def find_paths(self, src: int, dest: int) -> List[Path]: + def find_paths(self, src: int, dest: int) -> list[Path]: """ Find all paths between the source (src) and destination (dest) nodes. @@ -752,7 +614,7 @@ def stats(self) -> dict: # Return the statistics return {'node_count': node_count, 'edge_count': edge_count} - def unreachable_entities(self, lbl: Optional[str], rel: Optional[str]) -> List[dict]: + def unreachable_entities(self, lbl: Optional[str], rel: Optional[str]) -> list[dict]: lbl = f": {lbl}" if lbl else "" rel = f": {rel}" if rel else "" diff --git a/api/index.py b/api/index.py index 06e3b96..406ec22 100644 --- a/api/index.py +++ b/api/index.py @@ -1,20 +1,16 @@ import os -import datetime from api import * from pathlib import Path -from typing import Optional from functools import wraps -from falkordb import FalkorDB from dotenv import load_dotenv -from urllib.parse import urlparse + +from api.project import Project from .auto_complete import prefix_search -from flask import Flask, request, jsonify, abort +from flask import Flask, request, jsonify # Load environment variables from .env file load_dotenv() -app = Flask(__name__) - # Configure the logger import logging logging.basicConfig(level=logging.DEBUG, @@ -24,343 +20,431 @@ # Function to verify the token SECRET_TOKEN = os.getenv('SECRET_TOKEN') def verify_token(token): - return token == SECRET_TOKEN + return token == SECRET_TOKEN or (token is None and SECRET_TOKEN is None) # Decorator to protect routes with token authentication def token_required(f): @wraps(f) def decorated_function(*args, **kwargs): token = request.headers.get('Authorization') # Get token from header - if not token or not verify_token(token): + if not verify_token(token): return jsonify(message="Unauthorized"), 401 return f(*args, **kwargs) return decorated_function -@app.route('/graph_entities', methods=['GET']) -@token_required # Apply token authentication decorator -def graph_entities(): - """ - Endpoint to fetch sub-graph entities from a given repository. - The repository is specified via the 'repo' query parameter. +def create_app(): + app = Flask(__name__) + + # Decorator to protect routes with public access + def public_access(f): + @wraps(f) + def decorated_function(*args, **kwargs): + public = os.environ.get("CODE_GRAPH_PUBLIC", "0") # Get public access setting + if public != "1": + return jsonify(message="Unauthorized"), 401 + return f(*args, **kwargs) + return decorated_function + @app.route('/graph_entities', methods=['GET']) + @token_required # Apply token authentication decorator + def graph_entities(): + """ + Endpoint to fetch sub-graph entities from a given repository. + The repository is specified via the 'repo' query parameter. + + Returns: + - 200: Successfully returns the sub-graph. + - 400: Missing or invalid 'repo' parameter. + - 500: Internal server error or database connection issue. + """ + + # Access the 'repo' parameter from the GET request + repo = request.args.get('repo') + + if not repo: + logging.error("Missing 'repo' parameter in request.") + return jsonify({"status": "Missing 'repo' parameter"}), 400 + + if not graph_exists(repo): + logging.error(f"Missing project {repo}") + return jsonify({"status": f"Missing project {repo}"}), 400 + + try: + # Initialize the graph with the provided repo and credentials + g = Graph(repo) + + # Retrieve a sub-graph of up to 500 entities + sub_graph = g.get_sub_graph(500) + + logging.info(f"Successfully retrieved sub-graph for repo: {repo}") + response = { + 'status': 'success', + 'entities': sub_graph + } + + return jsonify(response), 200 + + except Exception as e: + logging.error(f"Error retrieving sub-graph for repo '{repo}': {e}") + return jsonify({"status": "Internal server error"}), 500 + + + @app.route('/get_neighbors', methods=['POST']) + @token_required # Apply token authentication decorator + def get_neighbors(): + """ + Endpoint to get neighbors of a nodes list in the graph. + Expects 'repo' and 'node_ids' as body parameters. + + Returns: + JSON response containing neighbors or error messages. + """ + + # Get JSON data from the request + data = request.get_json() + + # Get query parameters + repo = data.get('repo') + node_ids = data.get('node_ids') + + # Validate 'repo' parameter + if not repo: + logging.error("Repository name is missing in the request.") + return jsonify({"status": "Repository name is required."}), 400 + + # Validate 'node_ids' parameter + if not node_ids: + logging.error("Node IDs is missing in the request.") + return jsonify({"status": "Node IDs is required."}), 400 + + # Validate repo exists + if not graph_exists(repo): + logging.error(f"Missing project {repo}") + return jsonify({"status": f"Missing project {repo}"}), 400 + + # Initialize the graph with the provided repository + g = Graph(repo) + + # Fetch the neighbors of the specified node + neighbors = g.get_neighbors(node_ids) + + # Log and return the neighbors + logging.info(f"Successfully retrieved neighbors for node IDs {node_ids} in repo '{repo}'.") + + response = { + 'status': 'success', + 'neighbors': neighbors + } - Returns: - - 200: Successfully returns the sub-graph. - - 400: Missing or invalid 'repo' parameter. - - 500: Internal server error or database connection issue. - """ + return jsonify(response), 200 - # Access the 'repo' parameter from the GET request - repo = request.args.get('repo') + @app.route('/auto_complete', methods=['POST']) + @token_required # Apply token authentication decorator + def auto_complete(): + """ + Endpoint to process auto-completion requests for a repository based on a prefix. - if not repo: - logging.error("Missing 'repo' parameter in request.") - return jsonify({"status": "Missing 'repo' parameter"}), 400 + Returns: + JSON response with auto-completion suggestions or an error message. + """ - if not graph_exists(repo): - logging.error(f"Missing project {repo}") - return jsonify({"status": f"Missing project {repo}"}), 400 + # Get JSON data from the request + data = request.get_json() - try: - # Initialize the graph with the provided repo and credentials - g = Graph(repo) + # Validate that 'repo' is provided + repo = data.get('repo') + if repo is None: + return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 + + # Validate that 'prefix' is provided + prefix = data.get('prefix') + if prefix is None: + return jsonify({'status': f'Missing mandatory parameter "prefix"'}), 400 - # Retrieve a sub-graph of up to 500 entities - sub_graph = g.get_sub_graph(500) + # Validate repo exists + if not graph_exists(repo): + return jsonify({'status': f'Missing project {repo}'}), 400 - logging.info(f"Successfully retrieved sub-graph for repo: {repo}") + # Fetch auto-completion results + completions = prefix_search(repo, prefix) + + # Create a success response response = { 'status': 'success', - 'entities': sub_graph + 'completions': completions } return jsonify(response), 200 - except Exception as e: - logging.error(f"Error retrieving sub-graph for repo '{repo}': {e}") - return jsonify({"status": "Internal server error"}), 500 + @app.route('/list_repos', methods=['GET']) + @token_required # Apply token authentication decorator + def list_repos(): + """ + Endpoint to list all available repositories. + Returns: + JSON response with a list of repositories or an error message. + """ -@app.route('/get_neighbors', methods=['POST']) -@token_required # Apply token authentication decorator -def get_neighbors(): - """ - Endpoint to get neighbors of a nodes list in the graph. - Expects 'repo' and 'node_ids' as body parameters. + # Fetch list of repositories + repos = get_repos() - Returns: - JSON response containing neighbors or error messages. - """ + # Create a success response with the list of repositories + response = { + 'status': 'success', + 'repositories': repos + } - # Get JSON data from the request - data = request.get_json() + return jsonify(response), 200 - # Get query parameters - repo = data.get('repo') - node_ids = data.get('node_ids') + @app.route('/repo_info', methods=['POST']) + @token_required # Apply token authentication decorator + def repo_info(): + """ + Endpoint to retrieve information about a specific repository. - # Validate 'repo' parameter - if not repo: - logging.error("Repository name is missing in the request.") - return jsonify({"status": "Repository name is required."}), 400 + Expected JSON payload: + { + "repo": + } - # Validate 'node_ids' parameter - if not node_ids: - logging.error("Node IDs is missing in the request.") - return jsonify({"status": "Node IDs is required."}), 400 + Returns: + JSON: A response containing the status and graph statistics (node and edge counts). + - 'status': 'success' if successful, or an error message. + - 'info': A dictionary with the node and edge counts if the request is successful. + """ - # Validate repo exists - if not graph_exists(repo): - logging.error(f"Missing project {repo}") - return jsonify({"status": f"Missing project {repo}"}), 400 + # Get JSON data from the request + data = request.get_json() - # Initialize the graph with the provided repository - g = Graph(repo) + # Validate the 'repo' parameter + repo = data.get('repo') + if repo is None: + return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 - # Fetch the neighbors of the specified node - neighbors = g.get_neighbors(node_ids) + # Initialize the graph with the provided repository name + g = Graph(repo) - # Log and return the neighbors - logging.info(f"Successfully retrieved neighbors for node IDs {node_ids} in repo '{repo}'.") + # Retrieve statistics from the graph + stats = g.stats() + info = get_repo_info(repo) - response = { - 'status': 'success', - 'neighbors': neighbors - } + if stats is None or info is None: + return jsonify({'status': f'Missing repository "{repo}"'}), 400 - return jsonify(response), 200 + stats |= info -@app.route('/auto_complete', methods=['POST']) -@token_required # Apply token authentication decorator -def auto_complete(): - """ - Endpoint to process auto-completion requests for a repository based on a prefix. + # Create a response + response = { + 'status': 'success', + 'info': stats + } + + return jsonify(response), 200 - Returns: - JSON response with auto-completion suggestions or an error message. - """ + @app.route('/find_paths', methods=['POST']) + @token_required # Apply token authentication decorator + def find_paths(): + """ + Finds all paths between a source node (src) and a destination node (dest) in the graph. + The graph is associated with the repository (repo) provided in the request. + + Request Body (JSON): + - repo (str): Name of the repository. + - src (int): ID of the source node. + - dest (int): ID of the destination node. + + Returns: + A JSON response with: + - status (str): Status of the request ("success" or "error"). + - paths (list): List of paths between the source and destination nodes. + """ + + # Get JSON data from the request + data = request.get_json() + + # Validate 'repo' parameter + repo = data.get('repo') + if repo is None: + return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 + + # Validate 'src' parameter + src = data.get('src') + if src is None: + return jsonify({'status': f'Missing mandatory parameter "src"'}), 400 + if not isinstance(src, int): + return jsonify({'status': "src node id must be int"}), 400 + + # Validate 'dest' parameter + dest = data.get('dest') + if dest is None: + return jsonify({'status': f'Missing mandatory parameter "dest"'}), 400 + if not isinstance(dest, int): + return jsonify({'status': "dest node id must be int"}), 400 + + if not graph_exists(repo): + logging.error(f"Missing project {repo}") + return jsonify({"status": f"Missing project {repo}"}), 400 + + # Initialize graph with provided repo and credentials + g = Graph(repo) - # Get JSON data from the request - data = request.get_json() + # Find paths between the source and destination nodes + paths = g.find_paths(src, dest) - # Validate that 'repo' is provided - repo = data.get('repo') - if repo is None: - return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 + # Create and return a successful response + response = { 'status': 'success', 'paths': paths } - # Validate that 'prefix' is provided - prefix = data.get('prefix') - if prefix is None: - return jsonify({'status': f'Missing mandatory parameter "prefix"'}), 400 + return jsonify(response), 200 - # Validate repo exists - if not graph_exists(repo): - return jsonify({'status': f'Missing project {repo}'}), 400 + @app.route('/chat', methods=['POST']) + @token_required # Apply token authentication decorator + def chat(): + # Get JSON data from the request + data = request.get_json() - # Fetch auto-completion results - completions = prefix_search(repo, prefix) + # Validate 'repo' parameter + repo = data.get('repo') + if repo is None: + return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 - # Create a success response - response = { - 'status': 'success', - 'completions': completions - } + # Get optional 'label' and 'relation' parameters + msg = data.get('msg') + if msg is None: + return jsonify({'status': f'Missing mandatory parameter "msg"'}), 400 - return jsonify(response), 200 + answer = ask(repo, msg) -@app.route('/list_repos', methods=['GET']) -@token_required # Apply token authentication decorator -def list_repos(): - """ - Endpoint to list all available repositories. + # Create and return a successful response + response = { 'status': 'success', 'response': answer } - Returns: - JSON response with a list of repositories or an error message. - """ + return jsonify(response), 200 - # Fetch list of repositories - repos = get_repos() - - # Create a success response with the list of repositories - response = { - 'status': 'success', - 'repositories': repos - } + @app.route('/analyze_folder', methods=['POST']) + @token_required # Apply token authentication decorator + def analyze_folder(): + """ + Endpoint to analyze local source code + Expects 'path' and optionally an ignore list. + + Returns: + JSON response with status and error message if applicable + Status codes: + 200: Success + 400: Invalid input + 500: Internal server error + """ + + # Get JSON data from the request + data = request.get_json() + + # Get query parameters + path = data.get('path') + ignore = data.get('ignore', []) + + # Validate input parameters + if not path: + logging.error("'path' is missing from the request.") + return jsonify({"status": "'path' is required."}), 400 + + # Validate path exists and is a directory + if not os.path.isdir(path): + logging.error(f"Path '{path}' does not exist or is not a directory") + return jsonify({"status": "Invalid path: must be an existing directory"}), 400 + + # Validate ignore list contains valid paths + if not isinstance(ignore, list): + logging.error("'ignore' must be a list of paths") + return jsonify({"status": "'ignore' must be a list of paths"}), 400 + + proj_name = Path(path).name + + # Initialize the graph with the provided project name + g = Graph(proj_name) + + # Analyze source code within given folder + analyzer = SourceAnalyzer() + analyzer.analyze_local_folder(path, g, ignore) + + # Return response + response = { + 'status': 'success', + 'project': proj_name + } + return jsonify(response), 200 - return jsonify(response), 200 - -@app.route('/repo_info', methods=['POST']) -@token_required # Apply token authentication decorator -def repo_info(): - """ - Endpoint to retrieve information about a specific repository. + @app.route('/analyze_repo', methods=['POST']) + @public_access # Apply public access decorator + @token_required # Apply token authentication decorator + def analyze_repo(): + """ + Analyze a GitHub repository. - Expected JSON payload: + Expected JSON payload: { - "repo": + "repo_url": "string", + "ignore": ["string"] # optional } - Returns: - JSON: A response containing the status and graph statistics (node and edge counts). - - 'status': 'success' if successful, or an error message. - - 'info': A dictionary with the node and edge counts if the request is successful. - """ - - # Get JSON data from the request - data = request.get_json() - - # Validate the 'repo' parameter - repo = data.get('repo') - if repo is None: - return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 + Returns: + JSON response with processing status + """ + + data = request.get_json() + url = data.get('repo_url') + if url is None: + return jsonify({'status': f'Missing mandatory parameter "url"'}), 400 + logger.debug(f'Received repo_url: {url}') - # Initialize the graph with the provided repository name - g = Graph(repo) - - # Retrieve statistics from the graph - stats = g.stats() - info = get_repo_info(repo) - - if stats is None or info is None: - return jsonify({'status': f'Missing repository "{repo}"'}), 400 - - stats |= info - - # Create a response - response = { - 'status': 'success', - 'info': stats - } - - return jsonify(response), 200 - -@app.route('/find_paths', methods=['POST']) -@token_required # Apply token authentication decorator -def find_paths(): - """ - Finds all paths between a source node (src) and a destination node (dest) in the graph. - The graph is associated with the repository (repo) provided in the request. - - Request Body (JSON): - - repo (str): Name of the repository. - - src (int): ID of the source node. - - dest (int): ID of the destination node. - - Returns: - A JSON response with: - - status (str): Status of the request ("success" or "error"). - - paths (list): List of paths between the source and destination nodes. - """ - - # Get JSON data from the request - data = request.get_json() - - # Validate 'repo' parameter - repo = data.get('repo') - if repo is None: - return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 - - # Validate 'src' parameter - src = data.get('src') - if src is None: - return jsonify({'status': f'Missing mandatory parameter "src"'}), 400 - if not isinstance(src, int): - return jsonify({'status': "src node id must be int"}), 400 - - # Validate 'dest' parameter - dest = data.get('dest') - if dest is None: - return jsonify({'status': f'Missing mandatory parameter "dest"'}), 400 - if not isinstance(dest, int): - return jsonify({'status': "dest node id must be int"}), 400 - - if not graph_exists(repo): - logging.error(f"Missing project {repo}") - return jsonify({"status": f"Missing project {repo}"}), 400 - - # Initialize graph with provided repo and credentials - g = Graph(repo) - - # Find paths between the source and destination nodes - paths = g.find_paths(src, dest) - - # Create and return a successful response - response = { 'status': 'success', 'paths': paths } - - return jsonify(response), 200 - -@app.route('/chat', methods=['POST']) -@token_required # Apply token authentication decorator -def chat(): - # Get JSON data from the request - data = request.get_json() - - # Validate 'repo' parameter - repo = data.get('repo') - if repo is None: - return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 - - # Get optional 'label' and 'relation' parameters - msg = data.get('msg') - if msg is None: - return jsonify({'status': f'Missing mandatory parameter "msg"'}), 400 - - answer = ask(repo, msg) - - # Create and return a successful response - response = { 'status': 'success', 'response': answer } - - return jsonify(response), 200 - -@app.route('/analyze_folder', methods=['POST']) -@token_required # Apply token authentication decorator -def analyze_folder(): - """ - Endpoint to analyze local source code - Expects 'path' and optionally an ignore list. - - Returns: - JSON response with status and error message if applicable - Status codes: - 200: Success - 400: Invalid input - 500: Internal server error - """ - - # Get JSON data from the request - data = request.get_json() - - # Get query parameters - path = data.get('path') - ignore = data.get('ignore', []) - - # Validate input parameters - if not path: - logging.error("'path' is missing from the request.") - return jsonify({"status": "'path' is required."}), 400 - - # Validate path exists and is a directory - if not os.path.isdir(path): - logging.error(f"Path '{path}' does not exist or is not a directory") - return jsonify({"status": "Invalid path: must be an existing directory"}), 400 - - # Validate ignore list contains valid paths - if not isinstance(ignore, list): - logging.error("'ignore' must be a list of paths") - return jsonify({"status": "'ignore' must be a list of paths"}), 400 - - proj_name = Path(path).name - - # Initialize the graph with the provided project name - g = Graph(proj_name) - - # Analyze source code within given folder - analyzer = SourceAnalyzer() - analyzer.analyze_local_folder(path, g, ignore) - - # Return response - response = { + ignore = data.get('ignore', []) + + proj = Project.from_git_repository(url) + proj.analyze_sources(ignore) + proj.process_git_history(ignore) + + # Create a response + response = { 'status': 'success', - 'project': proj_name } - return jsonify(response), 200 + return jsonify(response), 200 + + @app.route('/switch_commit', methods=['POST']) + @public_access # Apply public access decorator + @token_required # Apply token authentication decorator + def switch_commit(): + """ + Endpoint to switch a repository to a specific commit. + + Returns: + JSON response with the change set or an error message. + """ + + # Get JSON data from the request + data = request.get_json() + + # Validate that 'repo' is provided + repo = data.get('repo') + if repo is None: + return jsonify({'status': f'Missing mandatory parameter "repo"'}), 400 + + # Validate that 'commit' is provided + commit = data.get('commit') + if commit is None: + return jsonify({'status': f'Missing mandatory parameter "commit"'}), 400 + + # Attempt to switch the repository to the specified commit + change_set = switch_commit(repo, commit) + + # Create a success response + response = { + 'status': 'success', + 'change_set': change_set + } + + return jsonify(response), 200 + + return app + +if __name__ == '__main__': + app = create_app() + app.run(debug=True) \ No newline at end of file diff --git a/api/info.py b/api/info.py index 001d43c..e54c263 100644 --- a/api/info.py +++ b/api/info.py @@ -18,8 +18,8 @@ def get_redis_connection() -> redis.Redis: """ try: return redis.Redis( - host = os.getenv('FALKORDB_HOST'), - port = os.getenv('FALKORDB_PORT'), + host = os.getenv('FALKORDB_HOST', "localhost"), + port = int(os.getenv('FALKORDB_PORT', "6379")), username = os.getenv('FALKORDB_USERNAME'), password = os.getenv('FALKORDB_PASSWORD'), decode_responses = True # To ensure string responses diff --git a/api/llm.py b/api/llm.py index 94959da..a13da86 100644 --- a/api/llm.py +++ b/api/llm.py @@ -168,10 +168,47 @@ def _define_ontology() -> Ontology: ), ] ) + + interface = Entity( + label="Interface", + attributes=[ + Attribute( + name="name", + attr_type=AttributeType.STRING, + required=True, + unique=True, + ), + Attribute( + name="path", + attr_type=AttributeType.STRING, + required=False, + unique=False, + ), + Attribute( + name="src_start", + attr_type=AttributeType.NUMBER, + required=False, + unique=False, + ), + Attribute( + name="src_end", + attr_type=AttributeType.NUMBER, + required=False, + unique=False, + ), + Attribute( + name="doc", + attr_type=AttributeType.STRING, + required=False, + unique=False, + ), + ] + ) ontology.add_entity(cls) ontology.add_entity(file) ontology.add_entity(function) + ontology.add_entity(interface) # Relations: # File - DEFINES -> Class @@ -187,6 +224,8 @@ def _define_ontology() -> Ontology: ontology.add_relation(Relation("DEFINES", "File", "Class")) ontology.add_relation(Relation("DEFINES", "File", "Function")) ontology.add_relation(Relation("DEFINES", "Class", "Class")) + ontology.add_relation(Relation("EXTENDS", "Class", "Class")) + ontology.add_relation(Relation("IMPLEMENTS", "Class", "Interface")) ontology.add_relation(Relation("DEFINES", "Class", "Function")) ontology.add_relation(Relation("DEFINES", "Function", "Function")) diff --git a/api/project.py b/api/project.py new file mode 100644 index 0000000..360b3e1 --- /dev/null +++ b/api/project.py @@ -0,0 +1,113 @@ +import os +import shutil +import logging +import validators +import subprocess +from git import Repo +from .info import * +from shlex import quote +from pathlib import Path +from .graph import Graph +from typing import Optional, List +from urllib.parse import urlparse +from .analyzers import SourceAnalyzer +from .git_utils import build_commit_graph, GitGraph + +# Configure logging +logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s') + +def _clone_source(url: str, name: str) -> Path: + # path to local repositories + path = Path.cwd() / "repositories" / name + print(f"Cloning repository to: {path}") + + # Delete local repository if exists + if path.exists(): + shutil.rmtree(path) + + # Create directory + path.mkdir(parents=True, exist_ok=True) + + # Clone repository + # Prepare the Git clone command + cmd = ["git", "clone", quote(url), path] + + # Run the git clone command and wait for it to finish + result = subprocess.run(cmd, check=True, capture_output=True, text=True) + + return path + +class Project(): + def __init__(self, name: str, path: Path, url: Optional[str]): + self.url = url + self.name = name + self.path = path + self.graph = Graph(name) + + if url is not None: + save_repo_info(name, url) + + @classmethod + def from_git_repository(cls, url: str): + # Validate url + if not validators.url(url): + raise Exception(f"invalid url: {url}") + + # Extract project name from URL + parsed_url = urlparse(url) + name = parsed_url.path.split('/')[-1] + path = _clone_source(url, name) + + return cls(name, path, url) + + @classmethod + def from_local_repository(cls, path: Path|str): + path = Path(path) if isinstance(path, str) else path + + # Validate path exists + if not path.exists(): + raise Exception(f"missing path: {path}") + + # adjust url + # 'git@github.com:FalkorDB/code_graph.git' + url = Repo(path).remotes[0].url + url = url.replace("git@", "https://").replace(":", "/").replace(".git", "") + + name = path.name + + return cls(name, path, url) + + def analyze_sources(self, ignore: Optional[List[str]] = None) -> Graph: + if ignore is None: + ignore = [] + analyzer = SourceAnalyzer() + analyzer.analyze_local_folder(self.path, self.graph, ignore) + + try: + # Save processed commit hash to the DB + repo = Repo(self.path) + current_commit = repo.head.commit + set_repo_commit(self.name, current_commit.hexsha) + except Exception: + # Probably not .git folder is missing + pass + + return self.graph + + def process_git_history(self, ignore: Optional[List[str]] = []) -> GitGraph: + logging.info(f"processing {self.name} git commit history") + + # Save original working directory for later restore + original_dir = Path.cwd() + + # change working directory to local repository + logging.info(f"Switching current working directory to: {self.path}") + os.chdir(self.path) + + git_graph = build_commit_graph(self.path, self.name, ignore) + + # Restore original working directory + logging.info(f"Restoring current working directory to: {original_dir}") + os.chdir(original_dir) + + return git_graph diff --git a/poetry.lock b/poetry.lock index 8fabb06..2f87c67 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.0.1 and should not be changed by hand. [[package]] name = "aiohappyeyeballs" @@ -6,6 +6,7 @@ version = "2.4.4" description = "Happy Eyeballs for asyncio" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "aiohappyeyeballs-2.4.4-py3-none-any.whl", hash = "sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8"}, {file = "aiohappyeyeballs-2.4.4.tar.gz", hash = "sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745"}, @@ -17,6 +18,7 @@ version = "3.11.11" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8"}, {file = "aiohttp-3.11.11-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5"}, @@ -115,6 +117,7 @@ version = "1.3.2" description = "aiosignal: a list of registered asynchronous callbacks" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "aiosignal-1.3.2-py2.py3-none-any.whl", hash = "sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5"}, {file = "aiosignal-1.3.2.tar.gz", hash = "sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54"}, @@ -129,6 +132,7 @@ version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, @@ -136,13 +140,14 @@ files = [ [[package]] name = "anyio" -version = "4.7.0" +version = "4.8.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "anyio-4.7.0-py3-none-any.whl", hash = "sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352"}, - {file = "anyio-4.7.0.tar.gz", hash = "sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48"}, + {file = "anyio-4.8.0-py3-none-any.whl", hash = "sha256:b5011f270ab5eb0abf13385f851315585cc37ef330dd88e27ec3d34d651fd47a"}, + {file = "anyio-4.8.0.tar.gz", hash = "sha256:1d9fe889df5212298c0c0723fa20479d1b94883a2df44bd3897aa91083316f7a"}, ] [package.dependencies] @@ -153,7 +158,7 @@ typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} [package.extras] doc = ["Sphinx (>=7.4,<8.0)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx_rtd_theme"] -test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "exceptiongroup (>=1.2.0)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "trustme", "truststore (>=0.9.1)", "uvloop (>=0.21)"] trio = ["trio (>=0.26.1)"] [[package]] @@ -162,6 +167,8 @@ version = "0.1.4" description = "Disable App Nap on macOS >= 10.9" optional = false python-versions = ">=3.6" +groups = ["main"] +markers = "platform_system == \"Darwin\"" files = [ {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, @@ -173,6 +180,7 @@ version = "3.0.0" description = "Annotate AST trees with source code positions" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, @@ -188,6 +196,8 @@ version = "5.0.1" description = "Timeout context manager for asyncio programs" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "python_full_version < \"3.11.3\"" files = [ {file = "async_timeout-5.0.1-py3-none-any.whl", hash = "sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c"}, {file = "async_timeout-5.0.1.tar.gz", hash = "sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3"}, @@ -195,13 +205,14 @@ files = [ [[package]] name = "attrs" -version = "24.3.0" +version = "25.1.0" description = "Classes Without Boilerplate" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "attrs-24.3.0-py3-none-any.whl", hash = "sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308"}, - {file = "attrs-24.3.0.tar.gz", hash = "sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff"}, + {file = "attrs-25.1.0-py3-none-any.whl", hash = "sha256:c75a69e28a550a7e93789579c22aa26b0f5b83b75dc4e08fe092980051e1090a"}, + {file = "attrs-25.1.0.tar.gz", hash = "sha256:1c97078a80c814273a76b2a298a932eb681c87415c11dee0a6921de7f1b02c3e"}, ] [package.extras] @@ -218,6 +229,7 @@ version = "2.2.1" description = "Function decoration for backoff and retry" optional = false python-versions = ">=3.7,<4.0" +groups = ["main"] files = [ {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, @@ -229,6 +241,7 @@ version = "4.12.3" description = "Screen-scraping library" optional = false python-versions = ">=3.6.0" +groups = ["main"] files = [ {file = "beautifulsoup4-4.12.3-py3-none-any.whl", hash = "sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed"}, {file = "beautifulsoup4-4.12.3.tar.gz", hash = "sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051"}, @@ -250,6 +263,7 @@ version = "1.9.0" description = "Fast, simple object-to-object and broadcast signaling" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "blinker-1.9.0-py3-none-any.whl", hash = "sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc"}, {file = "blinker-1.9.0.tar.gz", hash = "sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf"}, @@ -261,6 +275,7 @@ version = "0.0.2" description = "Dummy package for Beautiful Soup (beautifulsoup4)" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "bs4-0.0.2-py2.py3-none-any.whl", hash = "sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc"}, {file = "bs4-0.0.2.tar.gz", hash = "sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925"}, @@ -269,12 +284,40 @@ files = [ [package.dependencies] beautifulsoup4 = "*" +[[package]] +name = "cattrs" +version = "24.1.2" +description = "Composable complex class support for attrs and dataclasses." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "cattrs-24.1.2-py3-none-any.whl", hash = "sha256:67c7495b760168d931a10233f979b28dc04daf853b30752246f4f8471c6d68d0"}, + {file = "cattrs-24.1.2.tar.gz", hash = "sha256:8028cfe1ff5382df59dd36474a86e02d817b06eaf8af84555441bac915d2ef85"}, +] + +[package.dependencies] +attrs = ">=23.1.0" +exceptiongroup = {version = ">=1.1.1", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=4.1.0,<4.6.3 || >4.6.3", markers = "python_version < \"3.11\""} + +[package.extras] +bson = ["pymongo (>=4.4.0)"] +cbor2 = ["cbor2 (>=5.4.6)"] +msgpack = ["msgpack (>=1.0.5)"] +msgspec = ["msgspec (>=0.18.5)"] +orjson = ["orjson (>=3.9.2)"] +pyyaml = ["pyyaml (>=6.0)"] +tomlkit = ["tomlkit (>=0.11.8)"] +ujson = ["ujson (>=5.7.0)"] + [[package]] name = "certifi" version = "2024.12.14" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "certifi-2024.12.14-py3-none-any.whl", hash = "sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56"}, {file = "certifi-2024.12.14.tar.gz", hash = "sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db"}, @@ -286,6 +329,8 @@ version = "1.17.1" description = "Foreign Function Interface for Python calling C code." optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "implementation_name == \"pypy\"" files = [ {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, @@ -365,6 +410,7 @@ version = "3.4.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "charset_normalizer-3.4.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de"}, {file = "charset_normalizer-3.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176"}, @@ -466,6 +512,7 @@ version = "8.1.8" description = "Composable command line interface toolkit" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2"}, {file = "click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a"}, @@ -480,10 +527,12 @@ version = "0.4.6" description = "Cross-platform colored terminal text." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["main", "test"] files = [ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] +markers = {main = "sys_platform == \"win32\" or platform_system == \"Windows\"", test = "sys_platform == \"win32\""} [[package]] name = "comm" @@ -491,6 +540,7 @@ version = "0.2.2" description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "comm-0.2.2-py3-none-any.whl", hash = "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3"}, {file = "comm-0.2.2.tar.gz", hash = "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e"}, @@ -502,39 +552,89 @@ traitlets = ">=4" [package.extras] test = ["pytest"] +[[package]] +name = "ct3" +version = "3.4.0" +description = "Cheetah is a template engine and code generation tool" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7" +groups = ["main"] +files = [ + {file = "CT3-3.4.0-cp27-cp27mu-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c172a254e4b35d67cd344e091576c96592f660171d1222ce9074f2fee6476a2"}, + {file = "CT3-3.4.0-cp27-cp27mu-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:f0cd53f145b7a5cbed337a0b571d962f454fe672e0b850f4206b8ea60e939bef"}, + {file = "CT3-3.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:086f74ebd23298383af5d60ec7fc209bdc566a546524cc5435aa99feccaba0bf"}, + {file = "CT3-3.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7637b3e1c40c25424ce41f4f64782ebb3610258e03e8e1bb2fd12c0fb575dce1"}, + {file = "CT3-3.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:8c2e832777ee313489ff13107d99ce5ce14a403fbc2020bd51306d2c02a25855"}, + {file = "CT3-3.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:0bc637e01d5a36cbd4c734d556cf6e1379358117e71f6fc7861c3a22fbe65f96"}, + {file = "CT3-3.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:154331b062a786bf46840c189828cbe2ed7f6c4f3bf1ca68a0204792b04bc963"}, + {file = "CT3-3.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ced0af498c1eab326c6409ac22e2af30e1071742eaed06082952f626eef23f0f"}, + {file = "CT3-3.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:d2bb6e2725955366d460ccbbeb71106b8cae4a1034f9760b43367c736a163446"}, + {file = "CT3-3.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:e599f2d18105d43146b37cc7d3a3bc8e503f6d2b09d0ebc86edaa15ae42a28a8"}, + {file = "CT3-3.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cb8d67c54065884b1f23d8c26f3323f02288e6e70ea613499cab5944dc766683"}, + {file = "CT3-3.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98dcc2c6569a1fa0e396569a392fe62a276329278f9680bf226960025fc294f5"}, + {file = "CT3-3.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:488a639d10f3f3d62c98153f1ac7484dc7f5e364a2bc07dbb27ffc4693199b7d"}, + {file = "CT3-3.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:2f6ca88c4c45155b75383a36bf4e502959d175285d8f510a4593887a2b7a3b59"}, + {file = "CT3-3.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6f81ab7393005d0722b79c221433b4291154ce86f14129dac90e421db8d87a96"}, + {file = "CT3-3.4.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da49c759244a85e7ffe4ebd927d5659e13d299670a2aaabf366c2f3590a0053f"}, + {file = "CT3-3.4.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:1d174196e76d30cfe4d6ddcbbfe3891c82f68bf06cb764f05bfae47e4692f97c"}, + {file = "CT3-3.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:ab3d4082fb90efd5e400e94bc55d75f49964e1b53c9b776462f8c21c71801de3"}, + {file = "CT3-3.4.0-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:d7b9a04cfae26c02920d42a73b035fdea8afcfcc55446f21debc1217b18dcb6b"}, + {file = "CT3-3.4.0-cp35-cp35m-win_amd64.whl", hash = "sha256:b7f346ab370ca251b52fb1a5942cfe7aeef3ef76c873c605b11e122f99b00e2c"}, + {file = "CT3-3.4.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c33327743c6f7b813b3af29456da8b45c6d65f108449ff11e1f07c0ee2365641"}, + {file = "CT3-3.4.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:304fc55eece64152024d4605299dd480baf8be24f17a2c2973473915eb5e395c"}, + {file = "CT3-3.4.0-cp36-cp36m-win_amd64.whl", hash = "sha256:962d3ed8bb1cca00d2d7901737418b9a25019dfc44584baa83eba15778383541"}, + {file = "CT3-3.4.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d510cc795bbb8f4981ce286bca9c7409d742cffc42c713e168e4e95a198b83c"}, + {file = "CT3-3.4.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:b3410aa07888fae83612cec06a1c1107fdebdeb258b0192d58f7de28095d5fca"}, + {file = "CT3-3.4.0-cp37-cp37m-win_amd64.whl", hash = "sha256:1f4c61beacbd473da964d672ef555378874eb7b6bf81c32b507742c931289baf"}, + {file = "CT3-3.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:65776759d9021c50943cf8ac524ddc029247ec10b7b01e303b8b80ca8f58b9be"}, + {file = "CT3-3.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:279975359843d965d9f7ee61289c125baa8c4febf729b580e77ec0f35bb6b15c"}, + {file = "CT3-3.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:04056f9e2498164ec8fc567b6c91850987daa8a586f6846600c2182eef4e3f8a"}, + {file = "CT3-3.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:4fbb0d74f514e1a744c8a752c70f317b2413470ad04314926894fcb33f6607f6"}, + {file = "CT3-3.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:98a57fed5ab4cc45a017e3c777494acf93dad5ce0166653d41bf9a80ffe7e89b"}, + {file = "CT3-3.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0bd57c6935904ffdd3ea5fdf53d7bf060157b24e1422dd190295400f0ad8612"}, + {file = "CT3-3.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:9d299fd001d470f48321f7b172b214dd32f5dba40998d875e736c9ac6d9efe9c"}, + {file = "CT3-3.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:eb2b6b645d4b43e82cb058205a8393aba2800900d525a505fec3101b56faf126"}, + {file = "ct3-3.4.0.tar.gz", hash = "sha256:ddc493b775b02b09737b1fb628a973dbe9aa91d694045a6764a8e3f5296fa1eb"}, +] + +[package.extras] +filters = ["markdown"] +markdown = ["markdown"] + [[package]] name = "debugpy" -version = "1.8.11" +version = "1.8.12" description = "An implementation of the Debug Adapter Protocol for Python" optional = false python-versions = ">=3.8" -files = [ - {file = "debugpy-1.8.11-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:2b26fefc4e31ff85593d68b9022e35e8925714a10ab4858fb1b577a8a48cb8cd"}, - {file = "debugpy-1.8.11-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61bc8b3b265e6949855300e84dc93d02d7a3a637f2aec6d382afd4ceb9120c9f"}, - {file = "debugpy-1.8.11-cp310-cp310-win32.whl", hash = "sha256:c928bbf47f65288574b78518449edaa46c82572d340e2750889bbf8cd92f3737"}, - {file = "debugpy-1.8.11-cp310-cp310-win_amd64.whl", hash = "sha256:8da1db4ca4f22583e834dcabdc7832e56fe16275253ee53ba66627b86e304da1"}, - {file = "debugpy-1.8.11-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:85de8474ad53ad546ff1c7c7c89230db215b9b8a02754d41cb5a76f70d0be296"}, - {file = "debugpy-1.8.11-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8ffc382e4afa4aee367bf413f55ed17bd91b191dcaf979890af239dda435f2a1"}, - {file = "debugpy-1.8.11-cp311-cp311-win32.whl", hash = "sha256:40499a9979c55f72f4eb2fc38695419546b62594f8af194b879d2a18439c97a9"}, - {file = "debugpy-1.8.11-cp311-cp311-win_amd64.whl", hash = "sha256:987bce16e86efa86f747d5151c54e91b3c1e36acc03ce1ddb50f9d09d16ded0e"}, - {file = "debugpy-1.8.11-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308"}, - {file = "debugpy-1.8.11-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768"}, - {file = "debugpy-1.8.11-cp312-cp312-win32.whl", hash = "sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b"}, - {file = "debugpy-1.8.11-cp312-cp312-win_amd64.whl", hash = "sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1"}, - {file = "debugpy-1.8.11-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3"}, - {file = "debugpy-1.8.11-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e"}, - {file = "debugpy-1.8.11-cp313-cp313-win32.whl", hash = "sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28"}, - {file = "debugpy-1.8.11-cp313-cp313-win_amd64.whl", hash = "sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1"}, - {file = "debugpy-1.8.11-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:ad7efe588c8f5cf940f40c3de0cd683cc5b76819446abaa50dc0829a30c094db"}, - {file = "debugpy-1.8.11-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:189058d03a40103a57144752652b3ab08ff02b7595d0ce1f651b9acc3a3a35a0"}, - {file = "debugpy-1.8.11-cp38-cp38-win32.whl", hash = "sha256:32db46ba45849daed7ccf3f2e26f7a386867b077f39b2a974bb5c4c2c3b0a280"}, - {file = "debugpy-1.8.11-cp38-cp38-win_amd64.whl", hash = "sha256:116bf8342062246ca749013df4f6ea106f23bc159305843491f64672a55af2e5"}, - {file = "debugpy-1.8.11-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:654130ca6ad5de73d978057eaf9e582244ff72d4574b3e106fb8d3d2a0d32458"}, - {file = "debugpy-1.8.11-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:23dc34c5e03b0212fa3c49a874df2b8b1b8fda95160bd79c01eb3ab51ea8d851"}, - {file = "debugpy-1.8.11-cp39-cp39-win32.whl", hash = "sha256:52d8a3166c9f2815bfae05f386114b0b2d274456980d41f320299a8d9a5615a7"}, - {file = "debugpy-1.8.11-cp39-cp39-win_amd64.whl", hash = "sha256:52c3cf9ecda273a19cc092961ee34eb9ba8687d67ba34cc7b79a521c1c64c4c0"}, - {file = "debugpy-1.8.11-py2.py3-none-any.whl", hash = "sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920"}, - {file = "debugpy-1.8.11.tar.gz", hash = "sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57"}, +groups = ["main"] +files = [ + {file = "debugpy-1.8.12-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:a2ba7ffe58efeae5b8fad1165357edfe01464f9aef25e814e891ec690e7dd82a"}, + {file = "debugpy-1.8.12-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbd4149c4fc5e7d508ece083e78c17442ee13b0e69bfa6bd63003e486770f45"}, + {file = "debugpy-1.8.12-cp310-cp310-win32.whl", hash = "sha256:b202f591204023b3ce62ff9a47baa555dc00bb092219abf5caf0e3718ac20e7c"}, + {file = "debugpy-1.8.12-cp310-cp310-win_amd64.whl", hash = "sha256:9649eced17a98ce816756ce50433b2dd85dfa7bc92ceb60579d68c053f98dff9"}, + {file = "debugpy-1.8.12-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:36f4829839ef0afdfdd208bb54f4c3d0eea86106d719811681a8627ae2e53dd5"}, + {file = "debugpy-1.8.12-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a28ed481d530e3138553be60991d2d61103ce6da254e51547b79549675f539b7"}, + {file = "debugpy-1.8.12-cp311-cp311-win32.whl", hash = "sha256:4ad9a94d8f5c9b954e0e3b137cc64ef3f579d0df3c3698fe9c3734ee397e4abb"}, + {file = "debugpy-1.8.12-cp311-cp311-win_amd64.whl", hash = "sha256:4703575b78dd697b294f8c65588dc86874ed787b7348c65da70cfc885efdf1e1"}, + {file = "debugpy-1.8.12-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:7e94b643b19e8feb5215fa508aee531387494bf668b2eca27fa769ea11d9f498"}, + {file = "debugpy-1.8.12-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086b32e233e89a2740c1615c2f775c34ae951508b28b308681dbbb87bba97d06"}, + {file = "debugpy-1.8.12-cp312-cp312-win32.whl", hash = "sha256:2ae5df899732a6051b49ea2632a9ea67f929604fd2b036613a9f12bc3163b92d"}, + {file = "debugpy-1.8.12-cp312-cp312-win_amd64.whl", hash = "sha256:39dfbb6fa09f12fae32639e3286112fc35ae976114f1f3d37375f3130a820969"}, + {file = "debugpy-1.8.12-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:696d8ae4dff4cbd06bf6b10d671e088b66669f110c7c4e18a44c43cf75ce966f"}, + {file = "debugpy-1.8.12-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:898fba72b81a654e74412a67c7e0a81e89723cfe2a3ea6fcd3feaa3395138ca9"}, + {file = "debugpy-1.8.12-cp313-cp313-win32.whl", hash = "sha256:22a11c493c70413a01ed03f01c3c3a2fc4478fc6ee186e340487b2edcd6f4180"}, + {file = "debugpy-1.8.12-cp313-cp313-win_amd64.whl", hash = "sha256:fdb3c6d342825ea10b90e43d7f20f01535a72b3a1997850c0c3cefa5c27a4a2c"}, + {file = "debugpy-1.8.12-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:b0232cd42506d0c94f9328aaf0d1d0785f90f87ae72d9759df7e5051be039738"}, + {file = "debugpy-1.8.12-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9af40506a59450f1315168d47a970db1a65aaab5df3833ac389d2899a5d63b3f"}, + {file = "debugpy-1.8.12-cp38-cp38-win32.whl", hash = "sha256:5cc45235fefac57f52680902b7d197fb2f3650112379a6fa9aa1b1c1d3ed3f02"}, + {file = "debugpy-1.8.12-cp38-cp38-win_amd64.whl", hash = "sha256:557cc55b51ab2f3371e238804ffc8510b6ef087673303890f57a24195d096e61"}, + {file = "debugpy-1.8.12-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:b5c6c967d02fee30e157ab5227706f965d5c37679c687b1e7bbc5d9e7128bd41"}, + {file = "debugpy-1.8.12-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a77f422f31f170c4b7e9ca58eae2a6c8e04da54121900651dfa8e66c29901a"}, + {file = "debugpy-1.8.12-cp39-cp39-win32.whl", hash = "sha256:a4042edef80364239f5b7b5764e55fd3ffd40c32cf6753da9bda4ff0ac466018"}, + {file = "debugpy-1.8.12-cp39-cp39-win_amd64.whl", hash = "sha256:f30b03b0f27608a0b26c75f0bb8a880c752c0e0b01090551b9d87c7d783e2069"}, + {file = "debugpy-1.8.12-py2.py3-none-any.whl", hash = "sha256:274b6a2040349b5c9864e475284bce5bb062e63dce368a394b8cc865ae3b00c6"}, + {file = "debugpy-1.8.12.tar.gz", hash = "sha256:646530b04f45c830ceae8e491ca1c9320a2d2f0efea3141487c82130aba70dce"}, ] [[package]] @@ -543,6 +643,7 @@ version = "5.1.1" description = "Decorators for Humans" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "decorator-5.1.1-py3-none-any.whl", hash = "sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186"}, {file = "decorator-5.1.1.tar.gz", hash = "sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330"}, @@ -554,17 +655,32 @@ version = "1.9.0" description = "Distro - an OS platform information API" optional = false python-versions = ">=3.6" +groups = ["main"] 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 = "docstring-to-markdown" +version = "0.15" +description = "On the fly conversion of Python docstrings to markdown" +optional = false +python-versions = ">=3.6" +groups = ["main"] +files = [ + {file = "docstring-to-markdown-0.15.tar.gz", hash = "sha256:e146114d9c50c181b1d25505054a8d0f7a476837f0da2c19f07e06eaed52b73d"}, + {file = "docstring_to_markdown-0.15-py3-none-any.whl", hash = "sha256:27afb3faedba81e34c33521c32bbd258d7fbb79eedf7d29bc4e81080e854aec0"}, +] + [[package]] name = "exceptiongroup" version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" +groups = ["main", "test"] +markers = "python_version < \"3.11\"" files = [ {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, @@ -575,13 +691,14 @@ test = ["pytest (>=6)"] [[package]] name = "executing" -version = "2.1.0" +version = "2.2.0" description = "Get the currently executing AST node of a frame, and other information" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "executing-2.1.0-py2.py3-none-any.whl", hash = "sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf"}, - {file = "executing-2.1.0.tar.gz", hash = "sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab"}, + {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, + {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, ] [package.extras] @@ -593,6 +710,7 @@ version = "1.0.10" description = "Python client for interacting with FalkorDB database" optional = false python-versions = "<4.0,>=3.8" +groups = ["main"] files = [ {file = "falkordb-1.0.10.tar.gz", hash = "sha256:f3db65e4e1f85f1b68a8cda97b1f7d756af4942a88712696fb2cfa53537025b8"}, ] @@ -602,18 +720,19 @@ redis = ">=5.0.1,<6.0.0" [[package]] name = "filelock" -version = "3.16.1" +version = "3.17.0" description = "A platform independent file lock." optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0"}, - {file = "filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435"}, + {file = "filelock-3.17.0-py3-none-any.whl", hash = "sha256:533dc2f7ba78dc2f0f531fc6c4940addf7b70a481e269a5a3b93be94ffbe8338"}, + {file = "filelock-3.17.0.tar.gz", hash = "sha256:ee4e77401ef576ebb38cd7f13b9b28893194acc20a8e68e18730ba9c0e54660e"}, ] [package.extras] -docs = ["furo (>=2024.8.6)", "sphinx (>=8.0.2)", "sphinx-autodoc-typehints (>=2.4.1)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.6.1)", "diff-cover (>=9.2)", "pytest (>=8.3.3)", "pytest-asyncio (>=0.24)", "pytest-cov (>=5)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.26.4)"] +docs = ["furo (>=2024.8.6)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.6.10)", "diff-cover (>=9.2.1)", "pytest (>=8.3.4)", "pytest-asyncio (>=0.25.2)", "pytest-cov (>=6)", "pytest-mock (>=3.14)", "pytest-timeout (>=2.3.1)", "virtualenv (>=20.28.1)"] typing = ["typing-extensions (>=4.12.2)"] [[package]] @@ -622,6 +741,7 @@ version = "0.0.18" description = "Fixes broken JSON string objects" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "fix-busted-json-0.0.18.tar.gz", hash = "sha256:93c5dab7cae3b5d0b055f2c7043f9fe727a88a80d0be753c5f2c20bb9b69672f"}, {file = "fix_busted_json-0.0.18-py3-none-any.whl", hash = "sha256:fdce0e02c9a810b3aa28e1c3c32c24b21b44e89f6315ec25d2b963bd52a6ef03"}, @@ -633,6 +753,7 @@ version = "3.1.0" description = "A simple framework for building complex web applications." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "flask-3.1.0-py3-none-any.whl", hash = "sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136"}, {file = "flask-3.1.0.tar.gz", hash = "sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac"}, @@ -641,7 +762,6 @@ files = [ [package.dependencies] blinker = ">=1.9" click = ">=8.1.3" -importlib-metadata = {version = ">=3.6", markers = "python_version < \"3.10\""} itsdangerous = ">=2.2" Jinja2 = ">=3.1.2" Werkzeug = ">=3.1" @@ -656,6 +776,7 @@ version = "1.5.0" description = "A list-like structure which implements collections.abc.MutableSequence" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a"}, {file = "frozenlist-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb"}, @@ -757,6 +878,7 @@ version = "2024.12.0" description = "File-system specification" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "fsspec-2024.12.0-py3-none-any.whl", hash = "sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2"}, {file = "fsspec-2024.12.0.tar.gz", hash = "sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f"}, @@ -790,14 +912,49 @@ test-downstream = ["aiobotocore (>=2.5.4,<3.0.0)", "dask-expr", "dask[dataframe, test-full = ["adlfs", "aiohttp (!=4.0.0a0,!=4.0.0a1)", "cloudpickle", "dask", "distributed", "dropbox", "dropboxdrivefs", "fastparquet", "fusepy", "gcsfs", "jinja2", "kerchunk", "libarchive-c", "lz4", "notebook", "numpy", "ocifs", "pandas", "panel", "paramiko", "pyarrow", "pyarrow (>=1)", "pyftpdlib", "pygit2", "pytest", "pytest-asyncio (!=0.22.0)", "pytest-benchmark", "pytest-cov", "pytest-mock", "pytest-recording", "pytest-rerunfailures", "python-snappy", "requests", "smbprotocol", "tqdm", "urllib3", "zarr", "zstandard"] tqdm = ["tqdm"] +[[package]] +name = "gitdb" +version = "4.0.12" +description = "Git Object Database" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "gitdb-4.0.12-py3-none-any.whl", hash = "sha256:67073e15955400952c6565cc3e707c554a4eea2e428946f7a4c162fab9bd9bcf"}, + {file = "gitdb-4.0.12.tar.gz", hash = "sha256:5ef71f855d191a3326fcfbc0d5da835f26b13fbcba60c32c21091c349ffdb571"}, +] + +[package.dependencies] +smmap = ">=3.0.1,<6" + +[[package]] +name = "gitpython" +version = "3.1.44" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "GitPython-3.1.44-py3-none-any.whl", hash = "sha256:9e0e10cda9bed1ee64bc9a6de50e7e38a9c9943241cd7f585f6df3ed28011110"}, + {file = "gitpython-3.1.44.tar.gz", hash = "sha256:c87e30b26253bf5418b01b0660f818967f3c503193838337fe5e573331249269"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +doc = ["sphinx (>=7.1.2,<7.2)", "sphinx-autodoc-typehints", "sphinx_rtd_theme"] +test = ["coverage[toml]", "ddt (>=1.1.1,!=1.4.3)", "mock", "mypy", "pre-commit", "pytest (>=7.3.1)", "pytest-cov", "pytest-instafail", "pytest-mock", "pytest-sugar", "typing-extensions"] + [[package]] name = "graphrag-sdk" -version = "0.4.1" +version = "0.5.0" description = "Enables graph-based RAG and integration with LLMs for advanced querying and knowledge graph creation." optional = false python-versions = "<4.0.0,>=3.9.0" +groups = ["main"] files = [ - {file = "graphrag_sdk-0.4.1.tar.gz", hash = "sha256:ca70df46c2373b80f804e0f20fab47191161fa54d419df5af4015657349f7c68"}, + {file = "graphrag_sdk-0.5.0.tar.gz", hash = "sha256:e3c0bd76774988f05a6c14fe538bad6502fe33bba33f649a00254d328dec82b0"}, ] [package.dependencies] @@ -829,6 +986,7 @@ version = "0.14.0" description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, @@ -840,6 +998,7 @@ version = "1.0.7" description = "A minimal low-level HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpcore-1.0.7-py3-none-any.whl", hash = "sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd"}, {file = "httpcore-1.0.7.tar.gz", hash = "sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c"}, @@ -861,6 +1020,7 @@ version = "0.27.2" description = "The next generation HTTP client." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "httpx-0.27.2-py3-none-any.whl", hash = "sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0"}, {file = "httpx-0.27.2.tar.gz", hash = "sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2"}, @@ -882,13 +1042,14 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "huggingface-hub" -version = "0.27.0" +version = "0.28.0" description = "Client library to download and publish models, datasets and other repos on the huggingface.co hub" optional = false python-versions = ">=3.8.0" +groups = ["main"] files = [ - {file = "huggingface_hub-0.27.0-py3-none-any.whl", hash = "sha256:8f2e834517f1f1ddf1ecc716f91b120d7333011b7485f665a9a412eacb1a2a81"}, - {file = "huggingface_hub-0.27.0.tar.gz", hash = "sha256:902cce1a1be5739f5589e560198a65a8edcfd3b830b1666f36e4b961f0454fac"}, + {file = "huggingface_hub-0.28.0-py3-none-any.whl", hash = "sha256:71cff4e500efe68061d94b7f6d3114e183715088be7a90bf4dd84af83b5f5cdb"}, + {file = "huggingface_hub-0.28.0.tar.gz", hash = "sha256:c2b18c02a47d4384763caddb4d0ab2a8fc6c16e0800d6de4d55d0a896244aba3"}, ] [package.dependencies] @@ -901,13 +1062,13 @@ tqdm = ">=4.42.1" typing-extensions = ">=3.7.4.3" [package.extras] -all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +all = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] cli = ["InquirerPy (==0.3.4)"] -dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.5.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] +dev = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "libcst (==1.4.0)", "mypy (==1.5.1)", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "ruff (>=0.9.0)", "soundfile", "types-PyYAML", "types-requests", "types-simplejson", "types-toml", "types-tqdm", "types-urllib3", "typing-extensions (>=4.8.0)", "urllib3 (<2.0)"] fastai = ["fastai (>=2.4)", "fastcore (>=1.3.27)", "toml"] hf-transfer = ["hf-transfer (>=0.1.4)"] inference = ["aiohttp"] -quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.5.0)"] +quality = ["libcst (==1.4.0)", "mypy (==1.5.1)", "ruff (>=0.9.0)"] tensorflow = ["graphviz", "pydot", "tensorflow"] tensorflow-testing = ["keras (<3.0)", "tensorflow"] testing = ["InquirerPy (==0.3.4)", "Jinja2", "Pillow", "aiohttp", "fastapi", "gradio (>=4.0.0)", "jedi", "numpy", "pytest (>=8.1.1,<8.2.2)", "pytest-asyncio", "pytest-cov", "pytest-env", "pytest-mock", "pytest-rerunfailures", "pytest-vcr", "pytest-xdist", "soundfile", "urllib3 (<2.0)"] @@ -920,6 +1081,7 @@ version = "3.10" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, @@ -930,13 +1092,14 @@ all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2 [[package]] name = "importlib-metadata" -version = "8.5.0" +version = "8.6.1" description = "Read metadata from Python packages" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "importlib_metadata-8.5.0-py3-none-any.whl", hash = "sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b"}, - {file = "importlib_metadata-8.5.0.tar.gz", hash = "sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7"}, + {file = "importlib_metadata-8.6.1-py3-none-any.whl", hash = "sha256:02a89390c1e15fdfdc0d7c6b25cb3e62650d0494005c97d6f148bf5b9787525e"}, + {file = "importlib_metadata-8.6.1.tar.gz", hash = "sha256:310b41d755445d74569f993ccfc22838295d9fe005425094fad953d7f15c8580"}, ] [package.dependencies] @@ -948,7 +1111,7 @@ cover = ["pytest-cov"] doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] enabler = ["pytest-enabler (>=2.2)"] perf = ["ipython"] -test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] +test = ["flufl.flake8", "importlib_resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-perf (>=0.9.2)"] type = ["pytest-mypy"] [[package]] @@ -957,6 +1120,7 @@ version = "2.0.0" description = "brain-dead simple config-ini parsing" optional = false python-versions = ">=3.7" +groups = ["test"] files = [ {file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"}, {file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"}, @@ -968,6 +1132,7 @@ version = "6.29.5" description = "IPython Kernel for Jupyter" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "ipykernel-6.29.5-py3-none-any.whl", hash = "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5"}, {file = "ipykernel-6.29.5.tar.gz", hash = "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215"}, @@ -997,13 +1162,14 @@ test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0)", "pytest-asyncio [[package]] name = "ipython" -version = "8.18.1" +version = "8.31.0" description = "IPython: Productive Interactive Computing" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" +groups = ["main"] files = [ - {file = "ipython-8.18.1-py3-none-any.whl", hash = "sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397"}, - {file = "ipython-8.18.1.tar.gz", hash = "sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27"}, + {file = "ipython-8.31.0-py3-none-any.whl", hash = "sha256:46ec58f8d3d076a61d128fe517a51eb730e3aaf0c184ea8c17d16e366660c6a6"}, + {file = "ipython-8.31.0.tar.gz", hash = "sha256:b6a2274606bec6166405ff05e54932ed6e5cfecaca1fc05f2cacde7bb074d70b"}, ] [package.dependencies] @@ -1012,25 +1178,26 @@ decorator = "*" exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} jedi = ">=0.16" matplotlib-inline = "*" -pexpect = {version = ">4.3", markers = "sys_platform != \"win32\""} -prompt-toolkit = ">=3.0.41,<3.1.0" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt_toolkit = ">=3.0.41,<3.1.0" pygments = ">=2.4.0" -stack-data = "*" -traitlets = ">=5" -typing-extensions = {version = "*", markers = "python_version < \"3.10\""} +stack_data = "*" +traitlets = ">=5.13.0" +typing_extensions = {version = ">=4.6", markers = "python_version < \"3.12\""} [package.extras] -all = ["black", "curio", "docrepr", "exceptiongroup", "ipykernel", "ipyparallel", "ipywidgets", "matplotlib", "matplotlib (!=3.2.0)", "nbconvert", "nbformat", "notebook", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "qtconsole", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "trio", "typing-extensions"] +all = ["ipython[black,doc,kernel,matplotlib,nbconvert,nbformat,notebook,parallel,qtconsole]", "ipython[test,test-extra]"] black = ["black"] -doc = ["docrepr", "exceptiongroup", "ipykernel", "matplotlib", "pickleshare", "pytest (<7)", "pytest (<7.1)", "pytest-asyncio (<0.22)", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "stack-data", "testpath", "typing-extensions"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinxcontrib-jquery", "tomli", "typing_extensions"] kernel = ["ipykernel"] +matplotlib = ["matplotlib"] nbconvert = ["nbconvert"] nbformat = ["nbformat"] notebook = ["ipywidgets", "notebook"] parallel = ["ipyparallel"] qtconsole = ["qtconsole"] -test = ["pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath"] -test-extra = ["curio", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.22)", "pandas", "pickleshare", "pytest (<7.1)", "pytest-asyncio (<0.22)", "testpath", "trio"] +test = ["packaging", "pickleshare", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipython[test]", "matplotlib (!=3.2.0)", "nbformat", "numpy (>=1.23)", "pandas", "trio"] [[package]] name = "itsdangerous" @@ -1038,17 +1205,38 @@ version = "2.2.0" description = "Safely pass data to untrusted environments and back." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "itsdangerous-2.2.0-py3-none-any.whl", hash = "sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef"}, {file = "itsdangerous-2.2.0.tar.gz", hash = "sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173"}, ] +[[package]] +name = "javatools" +version = "1.6.0" +description = "Tools for working with Java class files and JARs" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "javatools-1.6.0-py2-none-any.whl", hash = "sha256:f6c025260d06719e7b1c241112b5d779b87b324aecab4cf40dc37a77daed95c0"}, + {file = "javatools-1.6.0-py3-none-any.whl", hash = "sha256:b92ac541baa10c623aeba50f3e2041781d80bbdaea2624e7d730a240b5f379df"}, +] + +[package.dependencies] +CT3 = "*" +six = "*" + +[package.extras] +crypto = ["M2Crypto (>=0.26.0)"] + [[package]] name = "jedi" version = "0.19.2" description = "An autocompletion tool for Python that can be used for text editors." optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, @@ -1062,12 +1250,32 @@ docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alab qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] +[[package]] +name = "jedi-language-server" +version = "0.41.1" +description = "A language server for Jedi!" +optional = false +python-versions = ">=3.8,<4.0" +groups = ["main"] +files = [ + {file = "jedi_language_server-0.41.1-py3-none-any.whl", hash = "sha256:ca9b3e7f48b70f0988d85ffde4f01dd1ab94c8e0f69e8c6424e6657117b44f91"}, + {file = "jedi_language_server-0.41.1.tar.gz", hash = "sha256:3f15ca5cc28e728564f7d63583e171b418025582447ce023512e3f2b2d71ebae"}, +] + +[package.dependencies] +cattrs = ">=23.1.2" +docstring-to-markdown = "==0.*" +jedi = ">=0.19.0,<0.20.0" +lsprotocol = ">=2022.0.0a9" +pygls = ">=1.0.1,<2.0.0" + [[package]] name = "jinja2" version = "3.1.5" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "jinja2-3.1.5-py3-none-any.whl", hash = "sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb"}, {file = "jinja2-3.1.5.tar.gz", hash = "sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb"}, @@ -1085,6 +1293,7 @@ version = "0.8.2" description = "Fast iterable JSON parser." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jiter-0.8.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b"}, {file = "jiter-0.8.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393"}, @@ -1170,6 +1379,7 @@ version = "4.23.0" description = "An implementation of JSON Schema validation for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566"}, {file = "jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4"}, @@ -1191,6 +1401,7 @@ version = "2024.10.1" description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf"}, {file = "jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272"}, @@ -1205,13 +1416,13 @@ version = "8.6.3" description = "Jupyter protocol implementation and client libraries" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, ] [package.dependencies] -importlib-metadata = {version = ">=4.8.3", markers = "python_version < \"3.10\""} jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" python-dateutil = ">=2.8.2" pyzmq = ">=23.0" @@ -1228,6 +1439,7 @@ version = "5.7.2" description = "Jupyter core package. A base package on which Jupyter projects rely." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "jupyter_core-5.7.2-py3-none-any.whl", hash = "sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409"}, {file = "jupyter_core-5.7.2.tar.gz", hash = "sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9"}, @@ -1244,13 +1456,14 @@ test = ["ipykernel", "pre-commit", "pytest (<8)", "pytest-cov", "pytest-timeout" [[package]] name = "litellm" -version = "1.56.6" +version = "1.59.9" description = "Library to easily interface with LLM API providers" optional = false python-versions = "!=2.7.*,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,!=3.7.*,>=3.8" +groups = ["main"] files = [ - {file = "litellm-1.56.6-py3-none-any.whl", hash = "sha256:dc04becae6b09b401edfc13e9e648443e425a52c1d7217351c7841811dc8dbec"}, - {file = "litellm-1.56.6.tar.gz", hash = "sha256:24612fff40f31044257c16bc29aa086cbb084b830e427a19f4adb96deeea626d"}, + {file = "litellm-1.59.9-py3-none-any.whl", hash = "sha256:f2012e98d61d7aeb1d103a70215ddc713eb62973c58da0cd71942e771cc5f511"}, + {file = "litellm-1.59.9.tar.gz", hash = "sha256:51d6801529042a613bc3ef8d6f9bb2dbaf265ebcbeb44735cbb2503293fc6375"}, ] [package.dependencies] @@ -1268,7 +1481,23 @@ tokenizers = "*" [package.extras] extra-proxy = ["azure-identity (>=1.15.0,<2.0.0)", "azure-keyvault-secrets (>=4.8.0,<5.0.0)", "google-cloud-kms (>=2.21.3,<3.0.0)", "prisma (==0.11.0)", "resend (>=0.8.0,<0.9.0)"] -proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "cryptography (>=43.0.1,<44.0.0)", "fastapi (>=0.115.5,<0.116.0)", "fastapi-sso (>=0.16.0,<0.17.0)", "gunicorn (>=22.0.0,<23.0.0)", "orjson (>=3.9.7,<4.0.0)", "pynacl (>=1.5.0,<2.0.0)", "python-multipart (>=0.0.18,<0.0.19)", "pyyaml (>=6.0.1,<7.0.0)", "rq", "uvicorn (>=0.22.0,<0.23.0)"] +proxy = ["PyJWT (>=2.8.0,<3.0.0)", "apscheduler (>=3.10.4,<4.0.0)", "backoff", "cryptography (>=43.0.1,<44.0.0)", "fastapi (>=0.115.5,<0.116.0)", "fastapi-sso (>=0.16.0,<0.17.0)", "gunicorn (>=22.0.0,<23.0.0)", "orjson (>=3.9.7,<4.0.0)", "pynacl (>=1.5.0,<2.0.0)", "python-multipart (>=0.0.18,<0.0.19)", "pyyaml (>=6.0.1,<7.0.0)", "rq", "uvicorn (>=0.29.0,<0.30.0)", "uvloop (>=0.21.0,<0.22.0)"] + +[[package]] +name = "lsprotocol" +version = "2023.0.1" +description = "Python implementation of the Language Server Protocol." +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "lsprotocol-2023.0.1-py3-none-any.whl", hash = "sha256:c75223c9e4af2f24272b14c6375787438279369236cd568f596d4951052a60f2"}, + {file = "lsprotocol-2023.0.1.tar.gz", hash = "sha256:cc5c15130d2403c18b734304339e51242d3018a05c4f7d0f198ad6e0cd21861d"}, +] + +[package.dependencies] +attrs = ">=21.3.0" +cattrs = "!=23.2.1" [[package]] name = "markupsafe" @@ -1276,6 +1505,7 @@ version = "3.0.2" description = "Safely add untrusted strings to HTML/XML markup." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, @@ -1346,6 +1576,7 @@ version = "0.1.7" description = "Inline Matplotlib backend for Jupyter" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, @@ -1360,6 +1591,7 @@ version = "6.1.0" description = "multidict implementation" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60"}, {file = "multidict-6.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1"}, @@ -1458,12 +1690,33 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} +[[package]] +name = "multilspy" +version = "0.0.11" +description = "A language-agnostic LSP client in Python, with a library interface. Intended to be used to build applications around language servers. Currently multilspy supports language servers for Python, Rust, Java, Go, JavaScript and C#. Originally appeared as part of Monitor-Guided Decoding (https://github.com/microsoft/monitors4codegen)" +optional = false +python-versions = ">=3.8 <4.0" +groups = ["main"] +files = [] +develop = false + +[package.dependencies] +jedi-language-server = "0.41.1" +requests = "2.32.3" + +[package.source] +type = "git" +url = "https://github.com/AviAvni/multilspy.git" +reference = "update-pydantic" +resolved_reference = "77249c40e62be7fdb7afc62b3985dff686b6c7c3" + [[package]] name = "nest-asyncio" version = "1.6.0" description = "Patch asyncio to allow nested event loops" optional = false python-versions = ">=3.5" +groups = ["main"] files = [ {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, @@ -1475,6 +1728,7 @@ version = "0.2.1" description = "The official Python client for Ollama." optional = false python-versions = "<4.0,>=3.8" +groups = ["main"] files = [ {file = "ollama-0.2.1-py3-none-any.whl", hash = "sha256:b6e2414921c94f573a903d1069d682ba2fb2607070ea9e19ca4a7872f2a460ec"}, {file = "ollama-0.2.1.tar.gz", hash = "sha256:fa316baa9a81eac3beb4affb0a17deb3008fdd6ed05b123c26306cfbe4c349b6"}, @@ -1485,13 +1739,14 @@ httpx = ">=0.27.0,<0.28.0" [[package]] name = "openai" -version = "1.58.1" +version = "1.60.2" description = "The official Python library for the openai API" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "openai-1.58.1-py3-none-any.whl", hash = "sha256:e2910b1170a6b7f88ef491ac3a42c387f08bd3db533411f7ee391d166571d63c"}, - {file = "openai-1.58.1.tar.gz", hash = "sha256:f5a035fd01e141fc743f4b0e02c41ca49be8fab0866d3b67f5f29b4f4d3c0973"}, + {file = "openai-1.60.2-py3-none-any.whl", hash = "sha256:993bd11b96900b9098179c728026f016b4982ded7ee30dfcf4555eab1171fff9"}, + {file = "openai-1.60.2.tar.gz", hash = "sha256:a8f843e10f2855713007f491d96afb2694b11b5e02cb97c7d01a0be60bc5bb51"}, ] [package.dependencies] @@ -1514,6 +1769,7 @@ version = "24.2" description = "Core utilities for Python packages" optional = false python-versions = ">=3.8" +groups = ["main", "test"] files = [ {file = "packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759"}, {file = "packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f"}, @@ -1525,6 +1781,7 @@ version = "0.8.4" description = "A Python Parser" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, @@ -1540,6 +1797,8 @@ version = "4.9.0" description = "Pexpect allows easy control of interactive console applications." optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, @@ -1554,6 +1813,7 @@ version = "4.3.6" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb"}, {file = "platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907"}, @@ -1570,6 +1830,7 @@ version = "1.5.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" +groups = ["test"] files = [ {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, @@ -1581,13 +1842,14 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "prompt-toolkit" -version = "3.0.48" +version = "3.0.50" description = "Library for building powerful interactive command lines in Python" optional = false -python-versions = ">=3.7.0" +python-versions = ">=3.8.0" +groups = ["main"] files = [ - {file = "prompt_toolkit-3.0.48-py3-none-any.whl", hash = "sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e"}, - {file = "prompt_toolkit-3.0.48.tar.gz", hash = "sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90"}, + {file = "prompt_toolkit-3.0.50-py3-none-any.whl", hash = "sha256:9b6427eb19e479d98acff65196a307c555eb567989e6d88ebbb1b509d9779198"}, + {file = "prompt_toolkit-3.0.50.tar.gz", hash = "sha256:544748f3860a2623ca5cd6d2795e7a14f3d0e1c3c9728359013f79877fc89bab"}, ] [package.dependencies] @@ -1599,6 +1861,7 @@ version = "0.2.1" description = "Accelerated property cache" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6"}, {file = "propcache-0.2.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2"}, @@ -1690,6 +1953,7 @@ version = "6.1.1" description = "Cross-platform lib for process and system monitoring in Python." optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["main"] files = [ {file = "psutil-6.1.1-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8"}, {file = "psutil-6.1.1-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777"}, @@ -1720,6 +1984,8 @@ version = "0.7.0" description = "Run a subprocess in a pseudo terminal" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" files = [ {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, @@ -1731,6 +1997,7 @@ version = "0.2.3" description = "Safely evaluate AST nodes without side effects" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, @@ -1745,6 +2012,8 @@ version = "2.22" description = "C parser in Python" optional = false python-versions = ">=3.8" +groups = ["main"] +markers = "implementation_name == \"pypy\"" files = [ {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, @@ -1752,13 +2021,14 @@ files = [ [[package]] name = "pydantic" -version = "2.10.4" +version = "2.10.6" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pydantic-2.10.4-py3-none-any.whl", hash = "sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d"}, - {file = "pydantic-2.10.4.tar.gz", hash = "sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06"}, + {file = "pydantic-2.10.6-py3-none-any.whl", hash = "sha256:427d664bf0b8a2b34ff5dd0f5a18df00591adcee7198fbd71981054cef37b584"}, + {file = "pydantic-2.10.6.tar.gz", hash = "sha256:ca5daa827cce33de7a42be142548b0096bf05a7e7b365aebfa5f8eeec7128236"}, ] [package.dependencies] @@ -1776,6 +2046,7 @@ version = "2.27.2" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "pydantic_core-2.27.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa"}, {file = "pydantic_core-2.27.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c"}, @@ -1882,15 +2153,35 @@ files = [ [package.dependencies] typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" +[[package]] +name = "pygls" +version = "1.3.1" +description = "A pythonic generic language server (pronounced like 'pie glass')" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "pygls-1.3.1-py3-none-any.whl", hash = "sha256:6e00f11efc56321bdeb6eac04f6d86131f654c7d49124344a9ebb968da3dd91e"}, + {file = "pygls-1.3.1.tar.gz", hash = "sha256:140edceefa0da0e9b3c533547c892a42a7d2fd9217ae848c330c53d266a55018"}, +] + +[package.dependencies] +cattrs = ">=23.1.2" +lsprotocol = "2023.0.1" + +[package.extras] +ws = ["websockets (>=11.0.3)"] + [[package]] name = "pygments" -version = "2.18.0" +version = "2.19.1" description = "Pygments is a syntax highlighting package written in Python." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ - {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, - {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, + {file = "pygments-2.19.1-py3-none-any.whl", hash = "sha256:9ea1544ad55cecf4b8242fab6dd35a93bbce657034b0611ee383099054ab6d8c"}, + {file = "pygments-2.19.1.tar.gz", hash = "sha256:61c16d2a8576dc0649d9f39e089b5f02bcd27fba10d8fb4dcc28173f7a45151f"}, ] [package.extras] @@ -1902,6 +2193,7 @@ version = "4.3.1" description = "A pure-python PDF library capable of splitting, merging, cropping, and transforming PDF files" optional = false python-versions = ">=3.6" +groups = ["main"] files = [ {file = "pypdf-4.3.1-py3-none-any.whl", hash = "sha256:64b31da97eda0771ef22edb1bfecd5deee4b72c3d1736b7df2689805076d6418"}, {file = "pypdf-4.3.1.tar.gz", hash = "sha256:b2f37fe9a3030aa97ca86067a56ba3f9d3565f9a791b305c7355d8392c30d91b"}, @@ -1923,6 +2215,7 @@ version = "8.3.4" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" +groups = ["test"] files = [ {file = "pytest-8.3.4-py3-none-any.whl", hash = "sha256:50e16d954148559c9a74109af1eaf0c945ba2d8f30f0a3d3335edde19788b6f6"}, {file = "pytest-8.3.4.tar.gz", hash = "sha256:965370d062bce11e73868e0335abac31b4d3de0e82f4007408d242b4f8610761"}, @@ -1945,6 +2238,7 @@ version = "0.2.0" description = "A python implementation of the ABC Software metric" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "python-abc-0.2.0.tar.gz", hash = "sha256:90017d09fbac7bde4b64b2c7e1b5d22da9055b64b821d1a2b4dc805b450b251a"}, ] @@ -1955,6 +2249,7 @@ version = "2.9.0.post0" description = "Extensions to the standard Python datetime module" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, @@ -1969,6 +2264,7 @@ version = "1.0.1" description = "Read key-value pairs from a .env file and set them as environment variables" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "python-dotenv-1.0.1.tar.gz", hash = "sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca"}, {file = "python_dotenv-1.0.1-py3-none-any.whl", hash = "sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a"}, @@ -1983,6 +2279,8 @@ version = "308" description = "Python for Window Extensions" optional = false python-versions = "*" +groups = ["main"] +markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"" files = [ {file = "pywin32-308-cp310-cp310-win32.whl", hash = "sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e"}, {file = "pywin32-308-cp310-cp310-win_amd64.whl", hash = "sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e"}, @@ -2010,6 +2308,7 @@ version = "6.0.2" description = "YAML parser and emitter for Python" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, @@ -2072,6 +2371,7 @@ version = "26.2.0" description = "Python bindings for 0MQ" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629"}, {file = "pyzmq-26.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b"}, @@ -2193,6 +2493,7 @@ version = "2.2.1" description = "API rate limit decorator" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "ratelimit-2.2.1.tar.gz", hash = "sha256:af8a9b64b821529aca09ebaf6d8d279100d766f19e90b5059ac6a718ca6dee42"}, ] @@ -2203,6 +2504,7 @@ version = "5.2.1" description = "Python client for Redis database and key-value store" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4"}, {file = "redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f"}, @@ -2217,18 +2519,20 @@ ocsp = ["cryptography (>=36.0.1)", "pyopenssl (==23.2.1)", "requests (>=2.31.0)" [[package]] name = "referencing" -version = "0.35.1" +version = "0.36.2" description = "JSON Referencing + Python" optional = false -python-versions = ">=3.8" +python-versions = ">=3.9" +groups = ["main"] files = [ - {file = "referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de"}, - {file = "referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c"}, + {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, + {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, ] [package.dependencies] attrs = ">=22.2.0" rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} [[package]] name = "regex" @@ -2236,6 +2540,7 @@ version = "2024.11.6" description = "Alternative regular expression module, to replace re." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91"}, {file = "regex-2024.11.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0"}, @@ -2339,6 +2644,7 @@ version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, @@ -2360,6 +2666,7 @@ version = "0.22.3" description = "Python bindings to Rust's persistent data structures (rpds)" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "rpds_py-0.22.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967"}, {file = "rpds_py-0.22.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37"}, @@ -2472,17 +2779,31 @@ version = "1.17.0" description = "Python 2 and 3 compatibility utilities" optional = false python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main"] files = [ {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, ] +[[package]] +name = "smmap" +version = "5.0.2" +description = "A pure Python implementation of a sliding window memory map manager" +optional = false +python-versions = ">=3.7" +groups = ["main"] +files = [ + {file = "smmap-5.0.2-py3-none-any.whl", hash = "sha256:b30115f0def7d7531d22a0fb6502488d879e75b260a9db4d0819cfb25403af5e"}, + {file = "smmap-5.0.2.tar.gz", hash = "sha256:26ea65a03958fa0c8a1c7e8c7a58fdc77221b8910f6be2131affade476898ad5"}, +] + [[package]] name = "sniffio" version = "1.3.1" description = "Sniff out which async library your code is running under" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, @@ -2494,6 +2815,7 @@ version = "2.6" description = "A modern CSS selector implementation for Beautiful Soup." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"}, {file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"}, @@ -2505,6 +2827,7 @@ version = "0.6.3" description = "Extract data from python stack frames and tracebacks for informative displays" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, @@ -2524,6 +2847,7 @@ version = "0.8.0" description = "tiktoken is a fast BPE tokeniser for use with OpenAI's models" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tiktoken-0.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b07e33283463089c81ef1467180e3e00ab00d46c2c4bbcef0acab5f771d6695e"}, {file = "tiktoken-0.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9269348cb650726f44dd3bbb3f9110ac19a8dcc8f54949ad3ef652ca22a38e21"}, @@ -2571,6 +2895,7 @@ version = "0.21.0" description = "" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tokenizers-0.21.0-cp39-abi3-macosx_10_12_x86_64.whl", hash = "sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2"}, {file = "tokenizers-0.21.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e"}, @@ -2603,6 +2928,8 @@ version = "2.2.1" description = "A lil' TOML parser" optional = false python-versions = ">=3.8" +groups = ["test"] +markers = "python_version < \"3.11\"" files = [ {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"}, {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"}, @@ -2644,6 +2971,7 @@ version = "6.4.2" description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1"}, {file = "tornado-6.4.2-cp38-abi3-macosx_10_9_x86_64.whl", hash = "sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803"}, @@ -2664,6 +2992,7 @@ version = "4.67.1" description = "Fast, Extensible Progress Meter" optional = false python-versions = ">=3.7" +groups = ["main"] files = [ {file = "tqdm-4.67.1-py3-none-any.whl", hash = "sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2"}, {file = "tqdm-4.67.1.tar.gz", hash = "sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2"}, @@ -2685,6 +3014,7 @@ version = "5.14.3" description = "Traitlets Python configuration system" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, @@ -2696,57 +3026,46 @@ test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0, [[package]] name = "tree-sitter" -version = "0.23.2" +version = "0.24.0" description = "Python bindings to the Tree-sitter parsing library" optional = false -python-versions = ">=3.9" -files = [ - {file = "tree-sitter-0.23.2.tar.gz", hash = "sha256:66bae8dd47f1fed7bdef816115146d3a41c39b5c482d7bad36d9ba1def088450"}, - {file = "tree_sitter-0.23.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:3a937f5d8727bc1c74c4bf2a9d1c25ace049e8628273016ad0d45914ae904e10"}, - {file = "tree_sitter-0.23.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2c7eae7fe2af215645a38660d2d57d257a4c461fe3ec827cca99a79478284e80"}, - {file = "tree_sitter-0.23.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a71d607595270b6870eaf778a1032d146b2aa79bfcfa60f57a82a7b7584a4c7"}, - {file = "tree_sitter-0.23.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6fe9b9ea7a0aa23b52fd97354da95d1b2580065bc12a4ac868f9164a127211d6"}, - {file = "tree_sitter-0.23.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d74d00a8021719eae14d10d1b1e28649e15d8b958c01c2b2c3dad7a2ebc4dbae"}, - {file = "tree_sitter-0.23.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:6de18d8d8a7f67ab71f472d1fcb01cc506e080cbb5e13d52929e4b6fdce6bbee"}, - {file = "tree_sitter-0.23.2-cp310-cp310-win_amd64.whl", hash = "sha256:12b60dca70d2282af942b650a6d781be487485454668c7c956338a367b98cdee"}, - {file = "tree_sitter-0.23.2-cp310-cp310-win_arm64.whl", hash = "sha256:3346a4dd0447a42aabb863443b0fd8c92b909baf40ed2344fae4b94b625d5955"}, - {file = "tree_sitter-0.23.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:91fda41d4f8824335cc43c64e2c37d8089c8c563bd3900a512d2852d075af719"}, - {file = "tree_sitter-0.23.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:92b2b489d5ce54b41f94c6f23fbaf592bd6e84dc2877048fd1cb060480fa53f7"}, - {file = "tree_sitter-0.23.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64859bd4aa1567d0d6016a811b2b49c59d4a4427d096e3d8c84b2521455f62b7"}, - {file = "tree_sitter-0.23.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:614590611636044e071d3a0b748046d52676dbda3bc9fa431216231e11dd98f7"}, - {file = "tree_sitter-0.23.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:08466953c78ae57be61057188fb88c89791b0a562856010228e0ccf60e2ac453"}, - {file = "tree_sitter-0.23.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:8a33f03a562de91f7fd05eefcedd8994a06cd44c62f7aabace811ad82bc11cbd"}, - {file = "tree_sitter-0.23.2-cp311-cp311-win_amd64.whl", hash = "sha256:03b70296b569ef64f7b92b42ca5da9bf86d81bee2afd480bea35092687f51dae"}, - {file = "tree_sitter-0.23.2-cp311-cp311-win_arm64.whl", hash = "sha256:7cb4bb953ea7c0b50eeafc4454783e030357179d2a93c3dd5ebed2da5588ddd0"}, - {file = "tree_sitter-0.23.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a014498b6a9e6003fae8c6eb72f5927d62da9dcb72b28b3ce8cd15c6ff6a6572"}, - {file = "tree_sitter-0.23.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:04f8699b131d4bcbe3805c37e4ef3d159ee9a82a0e700587625623999ba0ea53"}, - {file = "tree_sitter-0.23.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4471577df285059c71686ecb208bc50fb472099b38dcc8e849b0e86652891e87"}, - {file = "tree_sitter-0.23.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f342c925290dd4e20ecd5787ef7ae8749981597ab364783a1eb73173efe65226"}, - {file = "tree_sitter-0.23.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a4e9e53d07dd076bede72e4f7d3a0173d7b9ad6576572dd86da008a740a9bb22"}, - {file = "tree_sitter-0.23.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8caebe65bc358759dac2500d8f8feed3aed939c4ade9a684a1783fe07bc7d5db"}, - {file = "tree_sitter-0.23.2-cp312-cp312-win_amd64.whl", hash = "sha256:fc5a72eb50d43485000dbbb309acb350467b7467e66dc747c6bb82ce63041582"}, - {file = "tree_sitter-0.23.2-cp312-cp312-win_arm64.whl", hash = "sha256:a0320eb6c7993359c5f7b371d22719ccd273f440d41cf1bd65dac5e9587f2046"}, - {file = "tree_sitter-0.23.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:eff630dddee7ba05accb439b17e559e15ce13f057297007c246237ceb6306332"}, - {file = "tree_sitter-0.23.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4780ba8f3894f2dea869fad2995c2aceab3fd5ab9e6a27c45475d2acd7f7e84e"}, - {file = "tree_sitter-0.23.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f0b609460b8e3e256361fb12e94fae5b728cb835b16f0f9d590b5aadbf9d109b"}, - {file = "tree_sitter-0.23.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78d070d8eaeaeb36cf535f55e5578fddbfc3bf53c1980f58bf1a99d57466b3b5"}, - {file = "tree_sitter-0.23.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:878580b2ad5054c410ba3418edca4d34c81cc26706114d8f5b5541688bc2d785"}, - {file = "tree_sitter-0.23.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:29224bdc2a3b9af535b7725e249d3ee291b2e90708e82832e73acc175e40dc48"}, - {file = "tree_sitter-0.23.2-cp313-cp313-win_amd64.whl", hash = "sha256:c58d89348162fbc3aea1fe6511a66ee189fc0e4e4bbe937026f29e4ecef17763"}, - {file = "tree_sitter-0.23.2-cp313-cp313-win_arm64.whl", hash = "sha256:0ff2037be5edab7801de3f6a721b9cf010853f612e2008ee454e0e0badb225a6"}, - {file = "tree_sitter-0.23.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a5db8e585205faef8bf219da77d8993e2ef04d08eda2e3c8ad7e4df8297ee344"}, - {file = "tree_sitter-0.23.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9dbd110a30cf28be5da734ae4cd0e9031768228dbf6a79f2973962aa51de4ec7"}, - {file = "tree_sitter-0.23.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569514b9a996a0fd458b3a891c46ca125298be0c03cf82f2b6f0c13d5d8f25dc"}, - {file = "tree_sitter-0.23.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a357ed98a74e47787b812df99a74a2c35c0fe11e55c2095cc01d1cad144ef552"}, - {file = "tree_sitter-0.23.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:c2dfb8e8f760f4cc67888d03ef9e2dbd3353245f67f5efba375c2a14d944ac0e"}, - {file = "tree_sitter-0.23.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:3ead958df87a21d706903987e665e9e0e5df7b2c5021ff69ea349826840adc6a"}, - {file = "tree_sitter-0.23.2-cp39-cp39-win_amd64.whl", hash = "sha256:611cae16be332213c0e6ece72c0bfca202e30ff320a8b309b1526c6cb79ee4ba"}, - {file = "tree_sitter-0.23.2-cp39-cp39-win_arm64.whl", hash = "sha256:b848e0fdd522fbb8888cdb4f4d93f8fad97ae10d70c122fb922e51363c7febcd"}, +python-versions = ">=3.10" +groups = ["main"] +files = [ + {file = "tree-sitter-0.24.0.tar.gz", hash = "sha256:abd95af65ca2f4f7eca356343391ed669e764f37748b5352946f00f7fc78e734"}, + {file = "tree_sitter-0.24.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f3f00feff1fc47a8e4863561b8da8f5e023d382dd31ed3e43cd11d4cae445445"}, + {file = "tree_sitter-0.24.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f9691be48d98c49ef8f498460278884c666b44129222ed6217477dffad5d4831"}, + {file = "tree_sitter-0.24.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:098a81df9f89cf254d92c1cd0660a838593f85d7505b28249216661d87adde4a"}, + {file = "tree_sitter-0.24.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b26bf9e958da6eb7e74a081aab9d9c7d05f9baeaa830dbb67481898fd16f1f5"}, + {file = "tree_sitter-0.24.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2a84ff87a2f2a008867a1064aba510ab3bd608e3e0cd6e8fef0379efee266c73"}, + {file = "tree_sitter-0.24.0-cp310-cp310-win_amd64.whl", hash = "sha256:c012e4c345c57a95d92ab5a890c637aaa51ab3b7ff25ed7069834b1087361c95"}, + {file = "tree_sitter-0.24.0-cp310-cp310-win_arm64.whl", hash = "sha256:033506c1bc2ba7bd559b23a6bdbeaf1127cee3c68a094b82396718596dfe98bc"}, + {file = "tree_sitter-0.24.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de0fb7c18c6068cacff46250c0a0473e8fc74d673e3e86555f131c2c1346fb13"}, + {file = "tree_sitter-0.24.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7c9c89666dea2ce2b2bf98e75f429d2876c569fab966afefdcd71974c6d8538"}, + {file = "tree_sitter-0.24.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ddb113e6b8b3e3b199695b1492a47d87d06c538e63050823d90ef13cac585fd"}, + {file = "tree_sitter-0.24.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01ea01a7003b88b92f7f875da6ba9d5d741e0c84bb1bd92c503c0eecd0ee6409"}, + {file = "tree_sitter-0.24.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:464fa5b2cac63608915a9de8a6efd67a4da1929e603ea86abaeae2cb1fe89921"}, + {file = "tree_sitter-0.24.0-cp311-cp311-win_amd64.whl", hash = "sha256:3b1f3cbd9700e1fba0be2e7d801527e37c49fc02dc140714669144ef6ab58dce"}, + {file = "tree_sitter-0.24.0-cp311-cp311-win_arm64.whl", hash = "sha256:f3f08a2ca9f600b3758792ba2406971665ffbad810847398d180c48cee174ee2"}, + {file = "tree_sitter-0.24.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:14beeff5f11e223c37be7d5d119819880601a80d0399abe8c738ae2288804afc"}, + {file = "tree_sitter-0.24.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26a5b130f70d5925d67b47db314da209063664585a2fd36fa69e0717738efaf4"}, + {file = "tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5fc5c3c26d83c9d0ecb4fc4304fba35f034b7761d35286b936c1db1217558b4e"}, + {file = "tree_sitter-0.24.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:772e1bd8c0931c866b848d0369b32218ac97c24b04790ec4b0e409901945dd8e"}, + {file = "tree_sitter-0.24.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:24a8dd03b0d6b8812425f3b84d2f4763322684e38baf74e5bb766128b5633dc7"}, + {file = "tree_sitter-0.24.0-cp312-cp312-win_amd64.whl", hash = "sha256:f9e8b1605ab60ed43803100f067eed71b0b0e6c1fb9860a262727dbfbbb74751"}, + {file = "tree_sitter-0.24.0-cp312-cp312-win_arm64.whl", hash = "sha256:f733a83d8355fc95561582b66bbea92ffd365c5d7a665bc9ebd25e049c2b2abb"}, + {file = "tree_sitter-0.24.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:0d4a6416ed421c4210f0ca405a4834d5ccfbb8ad6692d4d74f7773ef68f92071"}, + {file = "tree_sitter-0.24.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:e0992d483677e71d5c5d37f30dfb2e3afec2f932a9c53eec4fca13869b788c6c"}, + {file = "tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:57277a12fbcefb1c8b206186068d456c600dbfbc3fd6c76968ee22614c5cd5ad"}, + {file = "tree_sitter-0.24.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d25fa22766d63f73716c6fec1a31ee5cf904aa429484256bd5fdf5259051ed74"}, + {file = "tree_sitter-0.24.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:7d5d9537507e1c8c5fa9935b34f320bfec4114d675e028f3ad94f11cf9db37b9"}, + {file = "tree_sitter-0.24.0-cp313-cp313-win_amd64.whl", hash = "sha256:f58bb4956917715ec4d5a28681829a8dad5c342cafd4aea269f9132a83ca9b34"}, + {file = "tree_sitter-0.24.0-cp313-cp313-win_arm64.whl", hash = "sha256:23641bd25dcd4bb0b6fa91b8fb3f46cc9f1c9f475efe4d536d3f1f688d1b84c8"}, ] [package.extras] -docs = ["sphinx (>=7.3,<8.0)", "sphinx-book-theme"] -tests = ["tree-sitter-html (>=0.23.0)", "tree-sitter-javascript (>=0.23.0)", "tree-sitter-json (>=0.23.0)", "tree-sitter-python (>=0.23.0)", "tree-sitter-rust (>=0.23.0)"] +docs = ["sphinx (>=8.1,<9.0)", "sphinx-book-theme"] +tests = ["tree-sitter-html (>=0.23.2)", "tree-sitter-javascript (>=0.23.1)", "tree-sitter-json (>=0.24.8)", "tree-sitter-python (>=0.23.6)", "tree-sitter-rust (>=0.23.2)"] [[package]] name = "tree-sitter-c" @@ -2754,6 +3073,7 @@ version = "0.23.4" description = "C grammar for tree-sitter" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tree_sitter_c-0.23.4-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2c92c0571b36b6da06f8882f34151dc11e67a493e9101cc0026a16da27709c05"}, {file = "tree_sitter_c-0.23.4-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:98c285a23bf4fb6fb34140d6ea0f0d25d0a93e0d93692f9dffe3db6d1fe08534"}, @@ -2768,12 +3088,34 @@ files = [ [package.extras] core = ["tree-sitter (>=0.22,<1.0)"] +[[package]] +name = "tree-sitter-java" +version = "0.23.5" +description = "Java grammar for tree-sitter" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "tree_sitter_java-0.23.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:355ce0308672d6f7013ec913dee4a0613666f4cda9044a7824240d17f38209df"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:24acd59c4720dedad80d548fe4237e43ef2b7a4e94c8549b0ca6e4c4d7bf6e69"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9401e7271f0b333df39fc8a8336a0caf1b891d9a2b89ddee99fae66b794fc5b7"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:370b204b9500b847f6d0c5ad584045831cee69e9a3e4d878535d39e4a7e4c4f1"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:aae84449e330363b55b14a2af0585e4e0dae75eb64ea509b7e5b0e1de536846a"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-win_amd64.whl", hash = "sha256:1ee45e790f8d31d416bc84a09dac2e2c6bc343e89b8a2e1d550513498eedfde7"}, + {file = "tree_sitter_java-0.23.5-cp39-abi3-win_arm64.whl", hash = "sha256:402efe136104c5603b429dc26c7e75ae14faaca54cfd319ecc41c8f2534750f4"}, + {file = "tree_sitter_java-0.23.5.tar.gz", hash = "sha256:f5cd57b8f1270a7f0438878750d02ccc79421d45cca65ff284f1527e9ef02e38"}, +] + +[package.extras] +core = ["tree-sitter (>=0.22,<1.0)"] + [[package]] name = "tree-sitter-python" version = "0.23.6" description = "Python grammar for tree-sitter" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "tree_sitter_python-0.23.6-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:28fbec8f74eeb2b30292d97715e60fac9ccf8a8091ce19b9d93e9b580ed280fb"}, {file = "tree_sitter_python-0.23.6-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:680b710051b144fedf61c95197db0094f2245e82551bf7f0c501356333571f7a"}, @@ -2794,6 +3136,7 @@ version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, @@ -2805,6 +3148,7 @@ version = "2.3.0" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "urllib3-2.3.0-py3-none-any.whl", hash = "sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df"}, {file = "urllib3-2.3.0.tar.gz", hash = "sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d"}, @@ -2822,6 +3166,7 @@ version = "0.34.0" description = "Python Data Validation for Humansâ„¢" optional = false python-versions = ">=3.8" +groups = ["main"] files = [ {file = "validators-0.34.0-py3-none-any.whl", hash = "sha256:c804b476e3e6d3786fa07a30073a4ef694e617805eb1946ceee3fe5a9b8b1321"}, {file = "validators-0.34.0.tar.gz", hash = "sha256:647fe407b45af9a74d245b943b18e6a816acf4926974278f6dd617778e1e781f"}, @@ -2836,6 +3181,7 @@ version = "0.2.13" description = "Measures the displayed width of unicode strings in a terminal" optional = false python-versions = "*" +groups = ["main"] files = [ {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, @@ -2847,6 +3193,7 @@ version = "3.1.3" description = "The comprehensive WSGI web application library." optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "werkzeug-3.1.3-py3-none-any.whl", hash = "sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e"}, {file = "werkzeug-3.1.3.tar.gz", hash = "sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746"}, @@ -2864,6 +3211,7 @@ version = "1.18.3" description = "Yet another URL library" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34"}, {file = "yarl-1.18.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7"}, @@ -2960,6 +3308,7 @@ version = "3.21.0" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.9" +groups = ["main"] files = [ {file = "zipp-3.21.0-py3-none-any.whl", hash = "sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931"}, {file = "zipp-3.21.0.tar.gz", hash = "sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4"}, @@ -2974,6 +3323,6 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", type = ["pytest-mypy"] [metadata] -lock-version = "2.0" -python-versions = "^3.9" -content-hash = "971202a22f922ad50b8e95b2e0b183daabcfa72eda53bae9e70c032ed9650a12" +lock-version = "2.1" +python-versions = "^3.10" +content-hash = "9d646b05112ec62c8ef904449138f595644790d9771938b7d89c83793effbdb4" diff --git a/pyproject.toml b/pyproject.toml index 8e55ec4..9ed862a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -6,15 +6,19 @@ authors = ["Roi Lipman "] readme = "README.md" [tool.poetry.dependencies] -python = "^3.9" -graphrag-sdk = { version = "^0.4.1", extras = ["litellm"] } -tree-sitter = "^0.23.2" +python = "^3.10" +graphrag-sdk = { version = "^0.5.0", extras = ["litellm"] } +tree-sitter = "^0.24.0" validators = "^0.34.0" -falkordb = "^1.0.5" -tree-sitter-c = "^0.23.2" +GitPython = "^3.1.44" +falkordb = "^1.0.10" +tree-sitter-c = "^0.23.4" tree-sitter-python = "^0.23.6" +tree-sitter-java = "^0.23.5" flask = "^3.1.0" python-dotenv = "^1.0.1" +multilspy = {git = "https://github.com/AviAvni/multilspy.git", rev = "update-pydantic"} +javatools = "^1.6.0" [tool.poetry.group.test.dependencies] pytest = "^8.2.0" diff --git a/requirements.txt b/requirements.txt index 6cc531c..f3224ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,1601 +1,111 @@ -aiohappyeyeballs==2.4.4 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:5fdd7d87889c63183afc18ce9271f9b0a7d32c2303e394468dd45d514a757745 \ - --hash=sha256:a980909d50efcd44795c4afeca523296716d50cd756ddca6af8c65b996e27de8 -aiohttp==3.11.11 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0882c2820fd0132240edbb4a51eb8ceb6eef8181db9ad5291ab3332e0d71df5f \ - --hash=sha256:0a6d3fbf2232e3a08c41eca81ae4f1dff3d8f1a30bae415ebe0af2d2458b8a33 \ - --hash=sha256:0b7fb429ab1aafa1f48578eb315ca45bd46e9c37de11fe45c7f5f4138091e2f1 \ - --hash=sha256:0eb98d90b6690827dcc84c246811feeb4e1eea683c0eac6caed7549be9c84665 \ - --hash=sha256:0fd82b8e9c383af11d2b26f27a478640b6b83d669440c0a71481f7c865a51da9 \ - --hash=sha256:10b4ff0ad793d98605958089fabfa350e8e62bd5d40aa65cdc69d6785859f94e \ - --hash=sha256:1642eceeaa5ab6c9b6dfeaaa626ae314d808188ab23ae196a34c9d97efb68350 \ - --hash=sha256:1dac54e8ce2ed83b1f6b1a54005c87dfed139cf3f777fdc8afc76e7841101226 \ - --hash=sha256:1e69966ea6ef0c14ee53ef7a3d68b564cc408121ea56c0caa2dc918c1b2f553d \ - --hash=sha256:1f21bb8d0235fc10c09ce1d11ffbd40fc50d3f08a89e4cf3a0c503dc2562247a \ - --hash=sha256:2170816e34e10f2fd120f603e951630f8a112e1be3b60963a1f159f5699059a6 \ - --hash=sha256:21fef42317cf02e05d3b09c028712e1d73a9606f02467fd803f7c1f39cc59add \ - --hash=sha256:249cc6912405917344192b9f9ea5cd5b139d49e0d2f5c7f70bdfaf6b4dbf3a2e \ - --hash=sha256:3499c7ffbfd9c6a3d8d6a2b01c26639da7e43d47c7b4f788016226b1e711caa8 \ - --hash=sha256:3af41686ccec6a0f2bdc66686dc0f403c41ac2089f80e2214a0f82d001052c03 \ - --hash=sha256:3e23419d832d969f659c208557de4a123e30a10d26e1e14b73431d3c13444c2e \ - --hash=sha256:3ea1b59dc06396b0b424740a10a0a63974c725b1c64736ff788a3689d36c02d2 \ - --hash=sha256:44167fc6a763d534a6908bdb2592269b4bf30a03239bcb1654781adf5e49caf1 \ - --hash=sha256:479b8c6ebd12aedfe64563b85920525d05d394b85f166b7873c8bde6da612f9c \ - --hash=sha256:4af57160800b7a815f3fe0eba9b46bf28aafc195555f1824555fa2cfab6c1538 \ - --hash=sha256:4b4fa1cb5f270fb3eab079536b764ad740bb749ce69a94d4ec30ceee1b5940d5 \ - --hash=sha256:4eed954b161e6b9b65f6be446ed448ed3921763cc432053ceb606f89d793927e \ - --hash=sha256:541d823548ab69d13d23730a06f97460f4238ad2e5ed966aaf850d7c369782d9 \ - --hash=sha256:568c1236b2fde93b7720f95a890741854c1200fba4a3471ff48b2934d2d93fd3 \ - --hash=sha256:5854be2f3e5a729800bac57a8d76af464e160f19676ab6aea74bde18ad19d438 \ - --hash=sha256:620598717fce1b3bd14dd09947ea53e1ad510317c85dda2c9c65b622edc96b12 \ - --hash=sha256:6526e5fb4e14f4bbf30411216780c9967c20c5a55f2f51d3abd6de68320cc2f3 \ - --hash=sha256:6fba278063559acc730abf49845d0e9a9e1ba74f85f0ee6efd5803f08b285853 \ - --hash=sha256:70d1f9dde0e5dd9e292a6d4d00058737052b01f3532f69c0c65818dac26dc287 \ - --hash=sha256:731468f555656767cda219ab42e033355fe48c85fbe3ba83a349631541715ba2 \ - --hash=sha256:81b8fe282183e4a3c7a1b72f5ade1094ed1c6345a8f153506d114af5bf8accd9 \ - --hash=sha256:84a585799c58b795573c7fa9b84c455adf3e1d72f19a2bf498b54a95ae0d194c \ - --hash=sha256:85992ee30a31835fc482468637b3e5bd085fa8fe9392ba0bdcbdc1ef5e9e3c55 \ - --hash=sha256:8811f3f098a78ffa16e0ea36dffd577eb031aea797cbdba81be039a4169e242c \ - --hash=sha256:88a12ad8ccf325a8a5ed80e6d7c3bdc247d66175afedbe104ee2aaca72960d8e \ - --hash=sha256:8be8508d110d93061197fd2d6a74f7401f73b6d12f8822bbcd6d74f2b55d71b1 \ - --hash=sha256:8e2bf8029dbf0810c7bfbc3e594b51c4cc9101fbffb583a3923aea184724203c \ - --hash=sha256:929f3ed33743a49ab127c58c3e0a827de0664bfcda566108989a14068f820194 \ - --hash=sha256:92cde43018a2e17d48bb09c79e4d4cb0e236de5063ce897a5e40ac7cb4878773 \ - --hash=sha256:92fc484e34b733704ad77210c7957679c5c3877bd1e6b6d74b185e9320cc716e \ - --hash=sha256:943a8b052e54dfd6439fd7989f67fc6a7f2138d0a2cf0a7de5f18aa4fe7eb3b1 \ - --hash=sha256:9d73ee3725b7a737ad86c2eac5c57a4a97793d9f442599bea5ec67ac9f4bdc3d \ - --hash=sha256:9f5b3c1ed63c8fa937a920b6c1bec78b74ee09593b3f5b979ab2ae5ef60d7600 \ - --hash=sha256:9fd46ce0845cfe28f108888b3ab17abff84ff695e01e73657eec3f96d72eef34 \ - --hash=sha256:a344d5dc18074e3872777b62f5f7d584ae4344cd6006c17ba12103759d407af3 \ - --hash=sha256:a60804bff28662cbcf340a4d61598891f12eea3a66af48ecfdc975ceec21e3c8 \ - --hash=sha256:a8f5f7515f3552d899c61202d99dcb17d6e3b0de777900405611cd747cecd1b8 \ - --hash=sha256:a9b7371665d4f00deb8f32208c7c5e652059b0fda41cf6dbcac6114a041f1cc2 \ - --hash=sha256:aa54f8ef31d23c506910c21163f22b124facb573bff73930735cf9fe38bf7dff \ - --hash=sha256:aba807f9569455cba566882c8938f1a549f205ee43c27b126e5450dc9f83cc62 \ - --hash=sha256:ae545f31489548c87b0cced5755cfe5a5308d00407000e72c4fa30b19c3220ac \ - --hash=sha256:af01e42ad87ae24932138f154105e88da13ce7d202a6de93fafdafb2883a00ef \ - --hash=sha256:b540bd67cfb54e6f0865ceccd9979687210d7ed1a1cc8c01f8e67e2f1e883d28 \ - --hash=sha256:b6212a60e5c482ef90f2d788835387070a88d52cf6241d3916733c9176d39eab \ - --hash=sha256:b63de12e44935d5aca7ed7ed98a255a11e5cb47f83a9fded7a5e41c40277d104 \ - --hash=sha256:ba74ec819177af1ef7f59063c6d35a214a8fde6f987f7661f4f0eecc468a8f76 \ - --hash=sha256:bb49c7f1e6ebf3821a42d81d494f538107610c3a705987f53068546b0e90303e \ - --hash=sha256:bd176afcf8f5d2aed50c3647d4925d0db0579d96f75a31e77cbaf67d8a87742d \ - --hash=sha256:bd7227b87a355ce1f4bf83bfae4399b1f5bb42e0259cb9405824bd03d2f4336a \ - --hash=sha256:bf8d9bfee991d8acc72d060d53860f356e07a50f0e0d09a8dfedea1c554dd0d5 \ - --hash=sha256:bfde76a8f430cf5c5584553adf9926534352251d379dcb266ad2b93c54a29745 \ - --hash=sha256:c341c7d868750e31961d6d8e60ff040fb9d3d3a46d77fd85e1ab8e76c3e9a5c4 \ - --hash=sha256:c7a06301c2fb096bdb0bd25fe2011531c1453b9f2c163c8031600ec73af1cc99 \ - --hash=sha256:cb23d8bb86282b342481cad4370ea0853a39e4a32a0042bb52ca6bdde132df43 \ - --hash=sha256:d119fafe7b634dbfa25a8c597718e69a930e4847f0b88e172744be24515140da \ - --hash=sha256:d40f9da8cabbf295d3a9dae1295c69975b86d941bc20f0a087f0477fa0a66231 \ - --hash=sha256:d6c9af134da4bc9b3bd3e6a70072509f295d10ee60c697826225b60b9959acdd \ - --hash=sha256:dd7659baae9ccf94ae5fe8bfaa2c7bc2e94d24611528395ce88d009107e00c6d \ - --hash=sha256:de8d38f1c2810fa2a4f1d995a2e9c70bb8737b18da04ac2afbf3971f65781d87 \ - --hash=sha256:e595c591a48bbc295ebf47cb91aebf9bd32f3ff76749ecf282ea7f9f6bb73886 \ - --hash=sha256:ec2aa89305006fba9ffb98970db6c8221541be7bee4c1d027421d6f6df7d1ce2 \ - --hash=sha256:ec82bf1fda6cecce7f7b915f9196601a1bd1a3079796b76d16ae4cce6d0ef89b \ - --hash=sha256:ed9ee95614a71e87f1a70bc81603f6c6760128b140bc4030abe6abaa988f1c3d \ - --hash=sha256:f047569d655f81cb70ea5be942ee5d4421b6219c3f05d131f64088c73bb0917f \ - --hash=sha256:ffa336210cf9cd8ed117011085817d00abe4c08f99968deef0013ea283547204 \ - --hash=sha256:ffb3dc385f6bb1568aa974fe65da84723210e5d9707e360e9ecb51f59406cd2e -aiosignal==1.3.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 \ - --hash=sha256:a8c255c66fafb1e499c9351d0bf32ff2d8a0321595ebac3b93713656d2436f54 -annotated-types==0.7.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53 \ - --hash=sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89 -anyio==4.7.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:2f834749c602966b7d456a7567cafcb309f96482b5081d14ac93ccd457f9dd48 \ - --hash=sha256:ea60c3723ab42ba6fff7e8ccb0488c898ec538ff4df1f1d5e642c3601d07e352 -appnope==0.1.4 ; python_version >= "3.9" and python_version < "4.0" and platform_system == "Darwin" \ - --hash=sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee \ - --hash=sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c -asttokens==3.0.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7 \ - --hash=sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2 -async-timeout==5.0.1 ; python_version >= "3.9" and python_full_version < "3.11.3" \ - --hash=sha256:39e3809566ff85354557ec2398b55e096c8364bacac9405a7a1fa429e77fe76c \ - --hash=sha256:d9321a7a3d5a6a5e187e824d2fa0793ce379a202935782d555d6e9d2735677d3 -attrs==24.3.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8f5c07333d543103541ba7be0e2ce16eeee8130cb0b3f9238ab904ce1e85baff \ - --hash=sha256:ac96cd038792094f438ad1f6ff80837353805ac950cd2aa0e0625ef19850c308 -backoff==2.2.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba \ - --hash=sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8 -beautifulsoup4==4.12.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:74e3d1928edc070d21748185c46e3fb33490f22f52a3addee9aee0f4f7781051 \ - --hash=sha256:b80878c9f40111313e55da8ba20bdba06d8fa3969fc68304167741bbf9e082ed -blinker==1.9.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:b4ce2265a7abece45e7cc896e98dbebe6cead56bcf805a3d23136d145f5445bf \ - --hash=sha256:ba0efaa9080b619ff2f3459d1d500c57bddea4a6b424b60a91141db6fd2f08bc -bs4==0.0.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:a48685c58f50fe127722417bae83fe6badf500d54b55f7e39ffe43b798653925 \ - --hash=sha256:abf8742c0805ef7f662dce4b51cca104cffe52b835238afc169142ab9b3fbccc -certifi==2024.12.14 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:1275f7a45be9464efc1173084eaa30f866fe2e47d389406136d332ed4967ec56 \ - --hash=sha256:b650d30f370c2b724812bee08008be0c4163b163ddaec3f2546c1caf65f191db -cffi==1.17.1 ; python_version >= "3.9" and python_version < "4.0" and implementation_name == "pypy" \ - --hash=sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8 \ - --hash=sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2 \ - --hash=sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1 \ - --hash=sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15 \ - --hash=sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36 \ - --hash=sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824 \ - --hash=sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8 \ - --hash=sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36 \ - --hash=sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17 \ - --hash=sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf \ - --hash=sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc \ - --hash=sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3 \ - --hash=sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed \ - --hash=sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702 \ - --hash=sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1 \ - --hash=sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8 \ - --hash=sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903 \ - --hash=sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6 \ - --hash=sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d \ - --hash=sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b \ - --hash=sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e \ - --hash=sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be \ - --hash=sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c \ - --hash=sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683 \ - --hash=sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9 \ - --hash=sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c \ - --hash=sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8 \ - --hash=sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1 \ - --hash=sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4 \ - --hash=sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655 \ - --hash=sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67 \ - --hash=sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595 \ - --hash=sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0 \ - --hash=sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65 \ - --hash=sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41 \ - --hash=sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6 \ - --hash=sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401 \ - --hash=sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6 \ - --hash=sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3 \ - --hash=sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16 \ - --hash=sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93 \ - --hash=sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e \ - --hash=sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4 \ - --hash=sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964 \ - --hash=sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c \ - --hash=sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576 \ - --hash=sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0 \ - --hash=sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3 \ - --hash=sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662 \ - --hash=sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3 \ - --hash=sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff \ - --hash=sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5 \ - --hash=sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd \ - --hash=sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f \ - --hash=sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5 \ - --hash=sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14 \ - --hash=sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d \ - --hash=sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9 \ - --hash=sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7 \ - --hash=sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382 \ - --hash=sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a \ - --hash=sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e \ - --hash=sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a \ - --hash=sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4 \ - --hash=sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99 \ - --hash=sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87 \ - --hash=sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b -charset-normalizer==3.4.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0167ddc8ab6508fe81860a57dd472b2ef4060e8d378f0cc555707126830f2537 \ - --hash=sha256:01732659ba9b5b873fc117534143e4feefecf3b2078b0a6a2e925271bb6f4cfa \ - --hash=sha256:01ad647cdd609225c5350561d084b42ddf732f4eeefe6e678765636791e78b9a \ - --hash=sha256:04432ad9479fa40ec0f387795ddad4437a2b50417c69fa275e212933519ff294 \ - --hash=sha256:0907f11d019260cdc3f94fbdb23ff9125f6b5d1039b76003b5b0ac9d6a6c9d5b \ - --hash=sha256:0924e81d3d5e70f8126529951dac65c1010cdf117bb75eb02dd12339b57749dd \ - --hash=sha256:09b26ae6b1abf0d27570633b2b078a2a20419c99d66fb2823173d73f188ce601 \ - --hash=sha256:09b5e6733cbd160dcc09589227187e242a30a49ca5cefa5a7edd3f9d19ed53fd \ - --hash=sha256:0af291f4fe114be0280cdd29d533696a77b5b49cfde5467176ecab32353395c4 \ - --hash=sha256:0f55e69f030f7163dffe9fd0752b32f070566451afe180f99dbeeb81f511ad8d \ - --hash=sha256:1a2bc9f351a75ef49d664206d51f8e5ede9da246602dc2d2726837620ea034b2 \ - --hash=sha256:22e14b5d70560b8dd51ec22863f370d1e595ac3d024cb8ad7d308b4cd95f8313 \ - --hash=sha256:234ac59ea147c59ee4da87a0c0f098e9c8d169f4dc2a159ef720f1a61bbe27cd \ - --hash=sha256:2369eea1ee4a7610a860d88f268eb39b95cb588acd7235e02fd5a5601773d4fa \ - --hash=sha256:237bdbe6159cff53b4f24f397d43c6336c6b0b42affbe857970cefbb620911c8 \ - --hash=sha256:28bf57629c75e810b6ae989f03c0828d64d6b26a5e205535585f96093e405ed1 \ - --hash=sha256:2967f74ad52c3b98de4c3b32e1a44e32975e008a9cd2a8cc8966d6a5218c5cb2 \ - --hash=sha256:2a75d49014d118e4198bcee5ee0a6f25856b29b12dbf7cd012791f8a6cc5c496 \ - --hash=sha256:2bdfe3ac2e1bbe5b59a1a63721eb3b95fc9b6817ae4a46debbb4e11f6232428d \ - --hash=sha256:2d074908e1aecee37a7635990b2c6d504cd4766c7bc9fc86d63f9c09af3fa11b \ - --hash=sha256:2fb9bd477fdea8684f78791a6de97a953c51831ee2981f8e4f583ff3b9d9687e \ - --hash=sha256:311f30128d7d333eebd7896965bfcfbd0065f1716ec92bd5638d7748eb6f936a \ - --hash=sha256:329ce159e82018d646c7ac45b01a430369d526569ec08516081727a20e9e4af4 \ - --hash=sha256:345b0426edd4e18138d6528aed636de7a9ed169b4aaf9d61a8c19e39d26838ca \ - --hash=sha256:363e2f92b0f0174b2f8238240a1a30142e3db7b957a5dd5689b0e75fb717cc78 \ - --hash=sha256:3a3bd0dcd373514dcec91c411ddb9632c0d7d92aed7093b8c3bbb6d69ca74408 \ - --hash=sha256:3bed14e9c89dcb10e8f3a29f9ccac4955aebe93c71ae803af79265c9ca5644c5 \ - --hash=sha256:44251f18cd68a75b56585dd00dae26183e102cd5e0f9f1466e6df5da2ed64ea3 \ - --hash=sha256:44ecbf16649486d4aebafeaa7ec4c9fed8b88101f4dd612dcaf65d5e815f837f \ - --hash=sha256:4532bff1b8421fd0a320463030c7520f56a79c9024a4e88f01c537316019005a \ - --hash=sha256:49402233c892a461407c512a19435d1ce275543138294f7ef013f0b63d5d3765 \ - --hash=sha256:4c0907b1928a36d5a998d72d64d8eaa7244989f7aaaf947500d3a800c83a3fd6 \ - --hash=sha256:4d86f7aff21ee58f26dcf5ae81a9addbd914115cdebcbb2217e4f0ed8982e146 \ - --hash=sha256:5777ee0881f9499ed0f71cc82cf873d9a0ca8af166dfa0af8ec4e675b7df48e6 \ - --hash=sha256:5df196eb874dae23dcfb968c83d4f8fdccb333330fe1fc278ac5ceeb101003a9 \ - --hash=sha256:619a609aa74ae43d90ed2e89bdd784765de0a25ca761b93e196d938b8fd1dbbd \ - --hash=sha256:6e27f48bcd0957c6d4cb9d6fa6b61d192d0b13d5ef563e5f2ae35feafc0d179c \ - --hash=sha256:6ff8a4a60c227ad87030d76e99cd1698345d4491638dfa6673027c48b3cd395f \ - --hash=sha256:73d94b58ec7fecbc7366247d3b0b10a21681004153238750bb67bd9012414545 \ - --hash=sha256:7461baadb4dc00fd9e0acbe254e3d7d2112e7f92ced2adc96e54ef6501c5f176 \ - --hash=sha256:75832c08354f595c760a804588b9357d34ec00ba1c940c15e31e96d902093770 \ - --hash=sha256:7709f51f5f7c853f0fb938bcd3bc59cdfdc5203635ffd18bf354f6967ea0f824 \ - --hash=sha256:78baa6d91634dfb69ec52a463534bc0df05dbd546209b79a3880a34487f4b84f \ - --hash=sha256:7974a0b5ecd505609e3b19742b60cee7aa2aa2fb3151bc917e6e2646d7667dcf \ - --hash=sha256:7a4f97a081603d2050bfaffdefa5b02a9ec823f8348a572e39032caa8404a487 \ - --hash=sha256:7b1bef6280950ee6c177b326508f86cad7ad4dff12454483b51d8b7d673a2c5d \ - --hash=sha256:7d053096f67cd1241601111b698f5cad775f97ab25d81567d3f59219b5f1adbd \ - --hash=sha256:804a4d582ba6e5b747c625bf1255e6b1507465494a40a2130978bda7b932c90b \ - --hash=sha256:807f52c1f798eef6cf26beb819eeb8819b1622ddfeef9d0977a8502d4db6d534 \ - --hash=sha256:80ed5e856eb7f30115aaf94e4a08114ccc8813e6ed1b5efa74f9f82e8509858f \ - --hash=sha256:8417cb1f36cc0bc7eaba8ccb0e04d55f0ee52df06df3ad55259b9a323555fc8b \ - --hash=sha256:8436c508b408b82d87dc5f62496973a1805cd46727c34440b0d29d8a2f50a6c9 \ - --hash=sha256:89149166622f4db9b4b6a449256291dc87a99ee53151c74cbd82a53c8c2f6ccd \ - --hash=sha256:8bfa33f4f2672964266e940dd22a195989ba31669bd84629f05fab3ef4e2d125 \ - --hash=sha256:8c60ca7339acd497a55b0ea5d506b2a2612afb2826560416f6894e8b5770d4a9 \ - --hash=sha256:91b36a978b5ae0ee86c394f5a54d6ef44db1de0815eb43de826d41d21e4af3de \ - --hash=sha256:955f8851919303c92343d2f66165294848d57e9bba6cf6e3625485a70a038d11 \ - --hash=sha256:97f68b8d6831127e4787ad15e6757232e14e12060bec17091b85eb1486b91d8d \ - --hash=sha256:9b23ca7ef998bc739bf6ffc077c2116917eabcc901f88da1b9856b210ef63f35 \ - --hash=sha256:9f0b8b1c6d84c8034a44893aba5e767bf9c7a211e313a9605d9c617d7083829f \ - --hash=sha256:aabfa34badd18f1da5ec1bc2715cadc8dca465868a4e73a0173466b688f29dda \ - --hash=sha256:ab36c8eb7e454e34e60eb55ca5d241a5d18b2c6244f6827a30e451c42410b5f7 \ - --hash=sha256:b010a7a4fd316c3c484d482922d13044979e78d1861f0e0650423144c616a46a \ - --hash=sha256:b1ac5992a838106edb89654e0aebfc24f5848ae2547d22c2c3f66454daa11971 \ - --hash=sha256:b7b2d86dd06bfc2ade3312a83a5c364c7ec2e3498f8734282c6c3d4b07b346b8 \ - --hash=sha256:b97e690a2118911e39b4042088092771b4ae3fc3aa86518f84b8cf6888dbdb41 \ - --hash=sha256:bc2722592d8998c870fa4e290c2eec2c1569b87fe58618e67d38b4665dfa680d \ - --hash=sha256:c0429126cf75e16c4f0ad00ee0eae4242dc652290f940152ca8c75c3a4b6ee8f \ - --hash=sha256:c30197aa96e8eed02200a83fba2657b4c3acd0f0aa4bdc9f6c1af8e8962e0757 \ - --hash=sha256:c4c3e6da02df6fa1410a7680bd3f63d4f710232d3139089536310d027950696a \ - --hash=sha256:c75cb2a3e389853835e84a2d8fb2b81a10645b503eca9bcb98df6b5a43eb8886 \ - --hash=sha256:c96836c97b1238e9c9e3fe90844c947d5afbf4f4c92762679acfe19927d81d77 \ - --hash=sha256:d7f50a1f8c450f3925cb367d011448c39239bb3eb4117c36a6d354794de4ce76 \ - --hash=sha256:d973f03c0cb71c5ed99037b870f2be986c3c05e63622c017ea9816881d2dd247 \ - --hash=sha256:d98b1668f06378c6dbefec3b92299716b931cd4e6061f3c875a71ced1780ab85 \ - --hash=sha256:d9c3cdf5390dcd29aa8056d13e8e99526cda0305acc038b96b30352aff5ff2bb \ - --hash=sha256:dad3e487649f498dd991eeb901125411559b22e8d7ab25d3aeb1af367df5efd7 \ - --hash=sha256:dccbe65bd2f7f7ec22c4ff99ed56faa1e9f785482b9bbd7c717e26fd723a1d1e \ - --hash=sha256:dd78cfcda14a1ef52584dbb008f7ac81c1328c0f58184bf9a84c49c605002da6 \ - --hash=sha256:e218488cd232553829be0664c2292d3af2eeeb94b32bea483cf79ac6a694e037 \ - --hash=sha256:e358e64305fe12299a08e08978f51fc21fac060dcfcddd95453eabe5b93ed0e1 \ - --hash=sha256:ea0d8d539afa5eb2728aa1932a988a9a7af94f18582ffae4bc10b3fbdad0626e \ - --hash=sha256:eab677309cdb30d047996b36d34caeda1dc91149e4fdca0b1a039b3f79d9a807 \ - --hash=sha256:eb8178fe3dba6450a3e024e95ac49ed3400e506fd4e9e5c32d30adda88cbd407 \ - --hash=sha256:ecddf25bee22fe4fe3737a399d0d177d72bc22be6913acfab364b40bce1ba83c \ - --hash=sha256:eea6ee1db730b3483adf394ea72f808b6e18cf3cb6454b4d86e04fa8c4327a12 \ - --hash=sha256:f08ff5e948271dc7e18a35641d2f11a4cd8dfd5634f55228b691e62b37125eb3 \ - --hash=sha256:f30bf9fd9be89ecb2360c7d94a711f00c09b976258846efe40db3d05828e8089 \ - --hash=sha256:fa88b843d6e211393a37219e6a1c1df99d35e8fd90446f1118f4216e307e48cd \ - --hash=sha256:fc54db6c8593ef7d4b2a331b58653356cf04f67c960f584edb7c3d8c97e8f39e \ - --hash=sha256:fd4ec41f914fa74ad1b8304bbc634b3de73d2a0889bd32076342a573e0779e00 \ - --hash=sha256:ffc9202a29ab3920fa812879e95a9e78b2465fd10be7fcbd042899695d75e616 -click==8.1.8 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2 \ - --hash=sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a -colorama==0.4.6 ; python_version >= "3.9" and python_version < "4.0" and (platform_system == "Windows" or sys_platform == "win32") \ - --hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \ - --hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6 -comm==0.2.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e \ - --hash=sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3 -debugpy==1.8.11 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0e22f846f4211383e6a416d04b4c13ed174d24cc5d43f5fd52e7821d0ebc8920 \ - --hash=sha256:116bf8342062246ca749013df4f6ea106f23bc159305843491f64672a55af2e5 \ - --hash=sha256:189058d03a40103a57144752652b3ab08ff02b7595d0ce1f651b9acc3a3a35a0 \ - --hash=sha256:23dc34c5e03b0212fa3c49a874df2b8b1b8fda95160bd79c01eb3ab51ea8d851 \ - --hash=sha256:28e45b3f827d3bf2592f3cf7ae63282e859f3259db44ed2b129093ca0ac7940b \ - --hash=sha256:2b26fefc4e31ff85593d68b9022e35e8925714a10ab4858fb1b577a8a48cb8cd \ - --hash=sha256:32db46ba45849daed7ccf3f2e26f7a386867b077f39b2a974bb5c4c2c3b0a280 \ - --hash=sha256:40499a9979c55f72f4eb2fc38695419546b62594f8af194b879d2a18439c97a9 \ - --hash=sha256:44b1b8e6253bceada11f714acf4309ffb98bfa9ac55e4fce14f9e5d4484287a1 \ - --hash=sha256:52c3cf9ecda273a19cc092961ee34eb9ba8687d67ba34cc7b79a521c1c64c4c0 \ - --hash=sha256:52d8a3166c9f2815bfae05f386114b0b2d274456980d41f320299a8d9a5615a7 \ - --hash=sha256:61bc8b3b265e6949855300e84dc93d02d7a3a637f2aec6d382afd4ceb9120c9f \ - --hash=sha256:654130ca6ad5de73d978057eaf9e582244ff72d4574b3e106fb8d3d2a0d32458 \ - --hash=sha256:6ad2688b69235c43b020e04fecccdf6a96c8943ca9c2fb340b8adc103c655e57 \ - --hash=sha256:6c1f6a173d1140e557347419767d2b14ac1c9cd847e0b4c5444c7f3144697e4e \ - --hash=sha256:84e511a7545d11683d32cdb8f809ef63fc17ea2a00455cc62d0a4dbb4ed1c308 \ - --hash=sha256:85de8474ad53ad546ff1c7c7c89230db215b9b8a02754d41cb5a76f70d0be296 \ - --hash=sha256:8988f7163e4381b0da7696f37eec7aca19deb02e500245df68a7159739bbd0d3 \ - --hash=sha256:8da1db4ca4f22583e834dcabdc7832e56fe16275253ee53ba66627b86e304da1 \ - --hash=sha256:8ffc382e4afa4aee367bf413f55ed17bd91b191dcaf979890af239dda435f2a1 \ - --hash=sha256:987bce16e86efa86f747d5151c54e91b3c1e36acc03ce1ddb50f9d09d16ded0e \ - --hash=sha256:ad7efe588c8f5cf940f40c3de0cd683cc5b76819446abaa50dc0829a30c094db \ - --hash=sha256:bb3b15e25891f38da3ca0740271e63ab9db61f41d4d8541745cfc1824252cb28 \ - --hash=sha256:c928bbf47f65288574b78518449edaa46c82572d340e2750889bbf8cd92f3737 \ - --hash=sha256:ce291a5aca4985d82875d6779f61375e959208cdf09fcec40001e65fb0a54768 \ - --hash=sha256:d8768edcbeb34da9e11bcb8b5c2e0958d25218df7a6e56adf415ef262cd7b6d1 -decorator==5.1.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:637996211036b6385ef91435e4fae22989472f9d571faba8927ba8253acbc330 \ - --hash=sha256:b8c3f85900b9dc423225913c5aace94729fe1fa9763b38939a95226f02d37186 -distro==1.9.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed \ - --hash=sha256:7bffd925d65168f85027d8da9af6bddab658135b840670a223589bc0c8ef02b2 -exceptiongroup==1.2.2 ; python_version >= "3.9" and python_version < "3.11" \ - --hash=sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b \ - --hash=sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc -executing==2.1.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8d63781349375b5ebccc3142f4b30350c0cd9c79f921cde38be2be4637e98eaf \ - --hash=sha256:8ea27ddd260da8150fa5a708269c4a10e76161e2496ec3e587da9e3c0fe4b9ab -falkordb==1.0.10 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:f3db65e4e1f85f1b68a8cda97b1f7d756af4942a88712696fb2cfa53537025b8 -filelock==3.16.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0 \ - --hash=sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435 -fix-busted-json==0.0.18 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:93c5dab7cae3b5d0b055f2c7043f9fe727a88a80d0be753c5f2c20bb9b69672f \ - --hash=sha256:fdce0e02c9a810b3aa28e1c3c32c24b21b44e89f6315ec25d2b963bd52a6ef03 -flask==3.1.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:5f873c5184c897c8d9d1b05df1e3d01b14910ce69607a117bd3277098a5836ac \ - --hash=sha256:d667207822eb83f1c4b50949b1623c8fc8d51f2341d65f72e1a1815397551136 -frozenlist==1.5.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:000a77d6034fbad9b6bb880f7ec073027908f1b40254b5d6f26210d2dab1240e \ - --hash=sha256:03d33c2ddbc1816237a67f66336616416e2bbb6beb306e5f890f2eb22b959cdf \ - --hash=sha256:04a5c6babd5e8fb7d3c871dc8b321166b80e41b637c31a995ed844a6139942b6 \ - --hash=sha256:0996c66760924da6e88922756d99b47512a71cfd45215f3570bf1e0b694c206a \ - --hash=sha256:0cc974cc93d32c42e7b0f6cf242a6bd941c57c61b618e78b6c0a96cb72788c1d \ - --hash=sha256:0f253985bb515ecd89629db13cb58d702035ecd8cfbca7d7a7e29a0e6d39af5f \ - --hash=sha256:11aabdd62b8b9c4b84081a3c246506d1cddd2dd93ff0ad53ede5defec7886b28 \ - --hash=sha256:12f78f98c2f1c2429d42e6a485f433722b0061d5c0b0139efa64f396efb5886b \ - --hash=sha256:140228863501b44b809fb39ec56b5d4071f4d0aa6d216c19cbb08b8c5a7eadb9 \ - --hash=sha256:1431d60b36d15cda188ea222033eec8e0eab488f39a272461f2e6d9e1a8e63c2 \ - --hash=sha256:15538c0cbf0e4fa11d1e3a71f823524b0c46299aed6e10ebb4c2089abd8c3bec \ - --hash=sha256:15b731db116ab3aedec558573c1a5eec78822b32292fe4f2f0345b7f697745c2 \ - --hash=sha256:17dcc32fc7bda7ce5875435003220a457bcfa34ab7924a49a1c19f55b6ee185c \ - --hash=sha256:1893f948bf6681733aaccf36c5232c231e3b5166d607c5fa77773611df6dc336 \ - --hash=sha256:189f03b53e64144f90990d29a27ec4f7997d91ed3d01b51fa39d2dbe77540fd4 \ - --hash=sha256:1a8ea951bbb6cacd492e3948b8da8c502a3f814f5d20935aae74b5df2b19cf3d \ - --hash=sha256:1b96af8c582b94d381a1c1f51ffaedeb77c821c690ea5f01da3d70a487dd0a9b \ - --hash=sha256:1e76bfbc72353269c44e0bc2cfe171900fbf7f722ad74c9a7b638052afe6a00c \ - --hash=sha256:2150cc6305a2c2ab33299453e2968611dacb970d2283a14955923062c8d00b10 \ - --hash=sha256:226d72559fa19babe2ccd920273e767c96a49b9d3d38badd7c91a0fdeda8ea08 \ - --hash=sha256:237f6b23ee0f44066219dae14c70ae38a63f0440ce6750f868ee08775073f942 \ - --hash=sha256:29d94c256679247b33a3dc96cce0f93cbc69c23bf75ff715919332fdbb6a32b8 \ - --hash=sha256:2b5e23253bb709ef57a8e95e6ae48daa9ac5f265637529e4ce6b003a37b2621f \ - --hash=sha256:2d0da8bbec082bf6bf18345b180958775363588678f64998c2b7609e34719b10 \ - --hash=sha256:2f3f7a0fbc219fb4455264cae4d9f01ad41ae6ee8524500f381de64ffaa077d5 \ - --hash=sha256:30c72000fbcc35b129cb09956836c7d7abf78ab5416595e4857d1cae8d6251a6 \ - --hash=sha256:31115ba75889723431aa9a4e77d5f398f5cf976eea3bdf61749731f62d4a4a21 \ - --hash=sha256:31a9ac2b38ab9b5a8933b693db4939764ad3f299fcaa931a3e605bc3460e693c \ - --hash=sha256:366d8f93e3edfe5a918c874702f78faac300209a4d5bf38352b2c1bdc07a766d \ - --hash=sha256:374ca2dabdccad8e2a76d40b1d037f5bd16824933bf7bcea3e59c891fd4a0923 \ - --hash=sha256:44c49271a937625619e862baacbd037a7ef86dd1ee215afc298a417ff3270608 \ - --hash=sha256:45e0896250900b5aa25180f9aec243e84e92ac84bd4a74d9ad4138ef3f5c97de \ - --hash=sha256:498524025a5b8ba81695761d78c8dd7382ac0b052f34e66939c42df860b8ff17 \ - --hash=sha256:50cf5e7ee9b98f22bdecbabf3800ae78ddcc26e4a435515fc72d97903e8488e0 \ - --hash=sha256:52ef692a4bc60a6dd57f507429636c2af8b6046db8b31b18dac02cbc8f507f7f \ - --hash=sha256:561eb1c9579d495fddb6da8959fd2a1fca2c6d060d4113f5844b433fc02f2641 \ - --hash=sha256:5a3ba5f9a0dfed20337d3e966dc359784c9f96503674c2faf015f7fe8e96798c \ - --hash=sha256:5b6a66c18b5b9dd261ca98dffcb826a525334b2f29e7caa54e182255c5f6a65a \ - --hash=sha256:5c28f4b5dbef8a0d8aad0d4de24d1e9e981728628afaf4ea0792f5d0939372f0 \ - --hash=sha256:5d7f5a50342475962eb18b740f3beecc685a15b52c91f7d975257e13e029eca9 \ - --hash=sha256:6321899477db90bdeb9299ac3627a6a53c7399c8cd58d25da094007402b039ab \ - --hash=sha256:6482a5851f5d72767fbd0e507e80737f9c8646ae7fd303def99bfe813f76cf7f \ - --hash=sha256:666534d15ba8f0fda3f53969117383d5dc021266b3c1a42c9ec4855e4b58b9d3 \ - --hash=sha256:683173d371daad49cffb8309779e886e59c2f369430ad28fe715f66d08d4ab1a \ - --hash=sha256:6e9080bb2fb195a046e5177f10d9d82b8a204c0736a97a153c2466127de87784 \ - --hash=sha256:73f2e31ea8dd7df61a359b731716018c2be196e5bb3b74ddba107f694fbd7604 \ - --hash=sha256:7437601c4d89d070eac8323f121fcf25f88674627505334654fd027b091db09d \ - --hash=sha256:76e4753701248476e6286f2ef492af900ea67d9706a0155335a40ea21bf3b2f5 \ - --hash=sha256:7707a25d6a77f5d27ea7dc7d1fc608aa0a478193823f88511ef5e6b8a48f9d03 \ - --hash=sha256:7948140d9f8ece1745be806f2bfdf390127cf1a763b925c4a805c603df5e697e \ - --hash=sha256:7a1a048f9215c90973402e26c01d1cff8a209e1f1b53f72b95c13db61b00f953 \ - --hash=sha256:7d57d8f702221405a9d9b40f9da8ac2e4a1a8b5285aac6100f3393675f0a85ee \ - --hash=sha256:7f3c8c1dacd037df16e85227bac13cca58c30da836c6f936ba1df0c05d046d8d \ - --hash=sha256:81d5af29e61b9c8348e876d442253723928dce6433e0e76cd925cd83f1b4b817 \ - --hash=sha256:828afae9f17e6de596825cf4228ff28fbdf6065974e5ac1410cecc22f699d2b3 \ - --hash=sha256:87f724d055eb4785d9be84e9ebf0f24e392ddfad00b3fe036e43f489fafc9039 \ - --hash=sha256:8969190d709e7c48ea386db202d708eb94bdb29207a1f269bab1196ce0dcca1f \ - --hash=sha256:90646abbc7a5d5c7c19461d2e3eeb76eb0b204919e6ece342feb6032c9325ae9 \ - --hash=sha256:91d6c171862df0a6c61479d9724f22efb6109111017c87567cfeb7b5d1449fdf \ - --hash=sha256:9272fa73ca71266702c4c3e2d4a28553ea03418e591e377a03b8e3659d94fa76 \ - --hash=sha256:92b5278ed9d50fe610185ecd23c55d8b307d75ca18e94c0e7de328089ac5dcba \ - --hash=sha256:97160e245ea33d8609cd2b8fd997c850b56db147a304a262abc2b3be021a9171 \ - --hash=sha256:977701c081c0241d0955c9586ffdd9ce44f7a7795df39b9151cd9a6fd0ce4cfb \ - --hash=sha256:9b7dc0c4338e6b8b091e8faf0db3168a37101943e687f373dce00959583f7439 \ - --hash=sha256:9b93d7aaa36c966fa42efcaf716e6b3900438632a626fb09c049f6a2f09fc631 \ - --hash=sha256:9bbcdfaf4af7ce002694a4e10a0159d5a8d20056a12b05b45cea944a4953f972 \ - --hash=sha256:9c2623347b933fcb9095841f1cc5d4ff0b278addd743e0e966cb3d460278840d \ - --hash=sha256:a2fe128eb4edeabe11896cb6af88fca5346059f6c8d807e3b910069f39157869 \ - --hash=sha256:a72b7a6e3cd2725eff67cd64c8f13335ee18fc3c7befc05aed043d24c7b9ccb9 \ - --hash=sha256:a9fe0f1c29ba24ba6ff6abf688cb0b7cf1efab6b6aa6adc55441773c252f7411 \ - --hash=sha256:b97f7b575ab4a8af9b7bc1d2ef7f29d3afee2226bd03ca3875c16451ad5a7723 \ - --hash=sha256:bdac3c7d9b705d253b2ce370fde941836a5f8b3c5c2b8fd70940a3ea3af7f4f2 \ - --hash=sha256:c03eff4a41bd4e38415cbed054bbaff4a075b093e2394b6915dca34a40d1e38b \ - --hash=sha256:c16d2fa63e0800723139137d667e1056bee1a1cf7965153d2d104b62855e9b99 \ - --hash=sha256:c1fac3e2ace2eb1052e9f7c7db480818371134410e1f5c55d65e8f3ac6d1407e \ - --hash=sha256:ce3aa154c452d2467487765e3adc730a8c153af77ad84096bc19ce19a2400840 \ - --hash=sha256:cee6798eaf8b1416ef6909b06f7dc04b60755206bddc599f52232606e18179d3 \ - --hash=sha256:d1b3eb7b05ea246510b43a7e53ed1653e55c2121019a97e60cad7efb881a97bb \ - --hash=sha256:d994863bba198a4a518b467bb971c56e1db3f180a25c6cf7bb1949c267f748c3 \ - --hash=sha256:dd47a5181ce5fcb463b5d9e17ecfdb02b678cca31280639255ce9d0e5aa67af0 \ - --hash=sha256:dd94994fc91a6177bfaafd7d9fd951bc8689b0a98168aa26b5f543868548d3ca \ - --hash=sha256:de537c11e4aa01d37db0d403b57bd6f0546e71a82347a97c6a9f0dcc532b3a45 \ - --hash=sha256:df6e2f325bfee1f49f81aaac97d2aa757c7646534a06f8f577ce184afe2f0a9e \ - --hash=sha256:e66cc454f97053b79c2ab09c17fbe3c825ea6b4de20baf1be28919460dd7877f \ - --hash=sha256:e79225373c317ff1e35f210dd5f1344ff31066ba8067c307ab60254cd3a78ad5 \ - --hash=sha256:f1577515d35ed5649d52ab4319db757bb881ce3b2b796d7283e6634d99ace307 \ - --hash=sha256:f1e6540b7fa044eee0bb5111ada694cf3dc15f2b0347ca125ee9ca984d5e9e6e \ - --hash=sha256:f2ac49a9bedb996086057b75bf93538240538c6d9b38e57c82d51f75a73409d2 \ - --hash=sha256:f47c9c9028f55a04ac254346e92977bf0f166c483c74b4232bee19a6697e4778 \ - --hash=sha256:f5f9da7f5dbc00a604fe74aa02ae7c98bcede8a3b8b9666f9f86fc13993bc71a \ - --hash=sha256:fd74520371c3c4175142d02a976aee0b4cb4a7cc912a60586ffd8d5929979b30 \ - --hash=sha256:feeb64bc9bcc6b45c6311c9e9b99406660a9c05ca8a5b30d14a78555088b0b3a -fsspec==2024.12.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:670700c977ed2fb51e0d9f9253177ed20cbde4a3e5c0283cc5385b5870c8533f \ - --hash=sha256:b520aed47ad9804237ff878b504267a3b0b441e97508bd6d2d8774e3db85cee2 -graphrag-sdk[litellm]==0.4.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:ca70df46c2373b80f804e0f20fab47191161fa54d419df5af4015657349f7c68 -h11==0.14.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d \ - --hash=sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761 -httpcore==1.0.7 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8551cb62a169ec7162ac7be8d4817d561f60e08eaa485234898414bb5a8a0b4c \ - --hash=sha256:a3fff8f43dc260d5bd363d9f9cf1830fa3a458b332856f34282de498ed420edd -httpx==0.27.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:7bb2708e112d8fdd7829cd4243970f0c223274051cb35ee80c03301ee29a3df0 \ - --hash=sha256:f7c2be1d2f3c3c3160d441802406b206c2b76f5947b11115e6df10c6c65e66c2 -huggingface-hub==0.27.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8f2e834517f1f1ddf1ecc716f91b120d7333011b7485f665a9a412eacb1a2a81 \ - --hash=sha256:902cce1a1be5739f5589e560198a65a8edcfd3b830b1666f36e4b961f0454fac -idna==3.10 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9 \ - --hash=sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3 -importlib-metadata==8.5.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:45e54197d28b7a7f1559e60b95e7c567032b602131fbd588f1497f47880aa68b \ - --hash=sha256:71522656f0abace1d072b9e5481a48f07c138e00f079c38c8f883823f9c26bd7 -ipykernel==6.29.5 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5 \ - --hash=sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215 -ipython==8.18.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:ca6f079bb33457c66e233e4580ebfc4128855b4cf6370dddd73842a9563e8a27 \ - --hash=sha256:e8267419d72d81955ec1177f8a29aaa90ac80ad647499201119e2f05e99aa397 -itsdangerous==2.2.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:c6242fc49e35958c8b15141343aa660db5fc54d4f13a1db01a3f5891b98700ef \ - --hash=sha256:e0050c0b7da1eea53ffaf149c0cfbb5c6e2e2b69c4bef22c81fa6eb73e5f6173 -jedi==0.19.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0 \ - --hash=sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9 -jinja2==3.1.5 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8fefff8dc3034e27bb80d67c671eb8a9bc424c0ef4c0826edbff304cceff43bb \ - --hash=sha256:aba0f4dc9ed8013c424088f68a5c226f7d6097ed89b246d7749c2ec4175c6adb -jiter==0.8.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:025337859077b41548bdcbabe38698bcd93cfe10b06ff66617a48ff92c9aec60 \ - --hash=sha256:03c9df035d4f8d647f8c210ddc2ae0728387275340668fb30d2421e17d9a0841 \ - --hash=sha256:08d4c92bf480e19fc3f2717c9ce2aa31dceaa9163839a311424b6862252c943e \ - --hash=sha256:0cf5dfa9956d96ff2efb0f8e9c7d055904012c952539a774305aaaf3abdf3d6c \ - --hash=sha256:14601dcac4889e0a1c75ccf6a0e4baf70dbc75041e51bcf8d0e9274519df6887 \ - --hash=sha256:180a8aea058f7535d1c84183c0362c710f4750bef66630c05f40c93c2b152a0f \ - --hash=sha256:1c0dfbd1be3cbefc7510102370d86e35d1d53e5a93d48519688b1bf0f761160a \ - --hash=sha256:2dd61c5afc88a4fda7d8b2cf03ae5947c6ac7516d32b7a15bf4b49569a5c076b \ - --hash=sha256:317b25e98a35ffec5c67efe56a4e9970852632c810d35b34ecdd70cc0e47b3b6 \ - --hash=sha256:32475a42b2ea7b344069dc1e81445cfc00b9d0e3ca837f0523072432332e9f74 \ - --hash=sha256:37b2998606d6dadbb5ccda959a33d6a5e853252d921fec1792fc902351bb4e2c \ - --hash=sha256:3ac9f578c46f22405ff7f8b1f5848fb753cc4b8377fbec8470a7dc3997ca7566 \ - --hash=sha256:3b94a33a241bee9e34b8481cdcaa3d5c2116f575e0226e421bed3f7a6ea71cff \ - --hash=sha256:4a9220497ca0cb1fe94e3f334f65b9b5102a0b8147646118f020d8ce1de70105 \ - --hash=sha256:4ab9a87f3784eb0e098f84a32670cfe4a79cb6512fd8f42ae3d0709f06405d18 \ - --hash=sha256:5127dc1abd809431172bc3fbe8168d6b90556a30bb10acd5ded41c3cfd6f43b6 \ - --hash=sha256:5672a86d55416ccd214c778efccf3266b84f87b89063b582167d803246354be4 \ - --hash=sha256:580ccf358539153db147e40751a0b41688a5ceb275e6f3e93d91c9467f42b2e3 \ - --hash=sha256:58dc9bc9767a1101f4e5e22db1b652161a225874d66f0e5cb8e2c7d1c438b587 \ - --hash=sha256:5a90a923338531b7970abb063cfc087eebae6ef8ec8139762007188f6bc69a9f \ - --hash=sha256:653cf462db4e8c41995e33d865965e79641ef45369d8a11f54cd30888b7e6ff1 \ - --hash=sha256:66227a2c7b575720c1871c8800d3a0122bb8ee94edb43a5685aa9aceb2782d44 \ - --hash=sha256:6e5337bf454abddd91bd048ce0dca5134056fc99ca0205258766db35d0a2ea43 \ - --hash=sha256:70bf4c43652cc294040dbb62256c83c8718370c8b93dd93d934b9a7bf6c4f53c \ - --hash=sha256:711e408732d4e9a0208008e5892c2966b485c783cd2d9a681f3eb147cf36c7ef \ - --hash=sha256:76e324da7b5da060287c54f2fabd3db5f76468006c811831f051942bf68c9d44 \ - --hash=sha256:789361ed945d8d42850f919342a8665d2dc79e7e44ca1c97cc786966a21f627a \ - --hash=sha256:79aec8172b9e3c6d05fd4b219d5de1ac616bd8da934107325a6c0d0e866a21b6 \ - --hash=sha256:7efe4853ecd3d6110301665a5178b9856be7e2a9485f49d91aa4d737ad2ae49e \ - --hash=sha256:7f22b16b35d5c1df9dfd58843ab2cd25e6bf15191f5a236bed177afade507bfc \ - --hash=sha256:83c0efd80b29695058d0fd2fa8a556490dbce9804eac3e281f373bbc99045f6c \ - --hash=sha256:859e8eb3507894093d01929e12e267f83b1d5f6221099d3ec976f0c995cb6bd9 \ - --hash=sha256:8b9931fd36ee513c26b5bf08c940b0ac875de175341cbdd4fa3be109f0492586 \ - --hash=sha256:8bd2a824d08d8977bb2794ea2682f898ad3d8837932e3a74937e93d62ecbb637 \ - --hash=sha256:8f2d5ed877f089862f4c7aacf3a542627c1496f972a34d0474ce85ee7d939c27 \ - --hash=sha256:8ffc86ae5e3e6a93765d49d1ab47b6075a9c978a2b3b80f0f32628f39caa0c88 \ - --hash=sha256:92249669925bc1c54fcd2ec73f70f2c1d6a817928480ee1c65af5f6b81cdf12d \ - --hash=sha256:99d9a1eded738299ba8e106c6779ce5c3893cffa0e32e4485d680588adae6db8 \ - --hash=sha256:9c63eaef32b7bebac8ebebf4dabebdbc6769a09c127294db6babee38e9f405b9 \ - --hash=sha256:9e1fa156ee9454642adb7e7234a383884452532bc9d53d5af2d18d98ada1d79c \ - --hash=sha256:a2ecaa3c23e7a7cf86d00eda3390c232f4d533cd9ddea4b04f5d0644faf642c5 \ - --hash=sha256:a6c710d657c8d1d2adbbb5c0b0c6bfcec28fd35bd6b5f016395f9ac43e878a15 \ - --hash=sha256:a9584de0cd306072635fe4b89742bf26feae858a0683b399ad0c2509011b9dc0 \ - --hash=sha256:ab7f43235d71e03b941c1630f4b6e3055d46b6cb8728a17663eaac9d8e83a865 \ - --hash=sha256:af102d3372e917cffce49b521e4c32c497515119dc7bd8a75665e90a718bbf08 \ - --hash=sha256:b25bd626bde7fb51534190c7e3cb97cee89ee76b76d7585580e22f34f5e3f393 \ - --hash=sha256:b2dd880785088ff2ad21ffee205e58a8c1ddabc63612444ae41e5e4b321b39c0 \ - --hash=sha256:b426f72cd77da3fec300ed3bc990895e2dd6b49e3bfe6c438592a3ba660e41ca \ - --hash=sha256:ba5bdf56969cad2019d4e8ffd3f879b5fdc792624129741d3d83fc832fef8c7d \ - --hash=sha256:bf55846c7b7a680eebaf9c3c48d630e1bf51bdf76c68a5f654b8524335b0ad29 \ - --hash=sha256:ca1f08b8e43dc3bd0594c992fb1fd2f7ce87f7bf0d44358198d6da8034afdf84 \ - --hash=sha256:ca29b6371ebc40e496995c94b988a101b9fbbed48a51190a4461fcb0a68b4a36 \ - --hash=sha256:ca8577f6a413abe29b079bc30f907894d7eb07a865c4df69475e868d73e71c7b \ - --hash=sha256:cadcc978f82397d515bb2683fc0d50103acff2a180552654bb92d6045dec2c49 \ - --hash=sha256:cd646c827b4f85ef4a78e4e58f4f5854fae0caf3db91b59f0d73731448a970c6 \ - --hash=sha256:cd73d3e740666d0e639f678adb176fad25c1bcbdae88d8d7b857e1783bb4212d \ - --hash=sha256:cde031d8413842a1e7501e9129b8e676e62a657f8ec8166e18a70d94d4682855 \ - --hash=sha256:ce0820f4a3a59ddced7fce696d86a096d5cc48d32a4183483a17671a61edfddc \ - --hash=sha256:d20be8b7f606df096e08b0b1b4a3c6f0515e8dac296881fe7461dfa0fb5ec817 \ - --hash=sha256:d21974d246ed0181558087cd9f76e84e8321091ebfb3a93d4c341479a736f099 \ - --hash=sha256:d33f94615fcaf872f7fd8cd98ac3b429e435c77619777e8a449d9d27e01134d1 \ - --hash=sha256:d35c864c2dff13dfd79fb070fc4fc6235d7b9b359efe340e1261deb21b9fcb66 \ - --hash=sha256:d5c826a221851a8dc028eb6d7d6429ba03184fa3c7e83ae01cd6d3bd1d4bd17d \ - --hash=sha256:e41e75344acef3fc59ba4765df29f107f309ca9e8eace5baacabd9217e52a5ee \ - --hash=sha256:e52bf98c7e727dd44f7c4acb980cb988448faeafed8433c867888268899b298b \ - --hash=sha256:e6ec2be506e7d6f9527dae9ff4b7f54e68ea44a0ef6b098256ddf895218a2f8f \ - --hash=sha256:e725edd0929fa79f8349ab4ec7f81c714df51dc4e991539a578e5018fa4a7152 \ - --hash=sha256:eaa58399c01db555346647a907b4ef6d4f584b123943be6ed5588c3f2359c9f4 \ - --hash=sha256:eb21aaa9a200d0a80dacc7a81038d2e476ffe473ffdd9c91eb745d623561de05 \ - --hash=sha256:ecff0dc14f409599bbcafa7e470c00b80f17abc14d1405d38ab02e4b42e55b57 \ - --hash=sha256:f557c55bc2b7676e74d39d19bcb8775ca295c7a028246175d6a8b431e70835e5 \ - --hash=sha256:f7200b8f7619d36aa51c803fd52020a2dfbea36ffec1b5e22cab11fd34d95a6d \ - --hash=sha256:f9d471356dc16f84ed48768b8ee79f29514295c7295cb41e1133ec0b2b8d637d \ - --hash=sha256:fc5adda618205bd4678b146612ce44c3cbfdee9697951f2c0ffdef1f26d72b63 \ - --hash=sha256:fc9043259ee430ecd71d178fccabd8c332a3bf1e81e50cae43cc2b28d19e4cb7 \ - --hash=sha256:ffd9fee7d0775ebaba131f7ca2e2d83839a62ad65e8e02fe2bd8fc975cedeb9e -jsonschema-specifications==2024.10.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272 \ - --hash=sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf -jsonschema==4.23.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4 \ - --hash=sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566 -jupyter-client==8.6.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419 \ - --hash=sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f -jupyter-core==5.7.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:4f7315d2f6b4bcf2e3e7cb6e46772eba760ae459cd1f59d29eb57b0a01bd7409 \ - --hash=sha256:aa5f8d32bbf6b431ac830496da7392035d6f61b4f54872f15c4bd2a9c3f536d9 -litellm==1.56.6 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:24612fff40f31044257c16bc29aa086cbb084b830e427a19f4adb96deeea626d \ - --hash=sha256:dc04becae6b09b401edfc13e9e648443e425a52c1d7217351c7841811dc8dbec -markupsafe==3.0.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4 \ - --hash=sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30 \ - --hash=sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0 \ - --hash=sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9 \ - --hash=sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396 \ - --hash=sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13 \ - --hash=sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028 \ - --hash=sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca \ - --hash=sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557 \ - --hash=sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832 \ - --hash=sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0 \ - --hash=sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b \ - --hash=sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579 \ - --hash=sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a \ - --hash=sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c \ - --hash=sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff \ - --hash=sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c \ - --hash=sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22 \ - --hash=sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094 \ - --hash=sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb \ - --hash=sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e \ - --hash=sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5 \ - --hash=sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a \ - --hash=sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d \ - --hash=sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a \ - --hash=sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b \ - --hash=sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8 \ - --hash=sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225 \ - --hash=sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c \ - --hash=sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144 \ - --hash=sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f \ - --hash=sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87 \ - --hash=sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d \ - --hash=sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93 \ - --hash=sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf \ - --hash=sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158 \ - --hash=sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84 \ - --hash=sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb \ - --hash=sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48 \ - --hash=sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171 \ - --hash=sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c \ - --hash=sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6 \ - --hash=sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd \ - --hash=sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d \ - --hash=sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1 \ - --hash=sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d \ - --hash=sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca \ - --hash=sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a \ - --hash=sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29 \ - --hash=sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe \ - --hash=sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798 \ - --hash=sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c \ - --hash=sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8 \ - --hash=sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f \ - --hash=sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f \ - --hash=sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a \ - --hash=sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178 \ - --hash=sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0 \ - --hash=sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79 \ - --hash=sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430 \ - --hash=sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50 -matplotlib-inline==0.1.7 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90 \ - --hash=sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca -multidict==6.1.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:052e10d2d37810b99cc170b785945421141bf7bb7d2f8799d431e7db229c385f \ - --hash=sha256:06809f4f0f7ab7ea2cabf9caca7d79c22c0758b58a71f9d32943ae13c7ace056 \ - --hash=sha256:071120490b47aa997cca00666923a83f02c7fbb44f71cf7f136df753f7fa8761 \ - --hash=sha256:0c3f390dc53279cbc8ba976e5f8035eab997829066756d811616b652b00a23a3 \ - --hash=sha256:0e2b90b43e696f25c62656389d32236e049568b39320e2735d51f08fd362761b \ - --hash=sha256:0e5f362e895bc5b9e67fe6e4ded2492d8124bdf817827f33c5b46c2fe3ffaca6 \ - --hash=sha256:10524ebd769727ac77ef2278390fb0068d83f3acb7773792a5080f2b0abf7748 \ - --hash=sha256:10a9b09aba0c5b48c53761b7c720aaaf7cf236d5fe394cd399c7ba662d5f9966 \ - --hash=sha256:16e5f4bf4e603eb1fdd5d8180f1a25f30056f22e55ce51fb3d6ad4ab29f7d96f \ - --hash=sha256:188215fc0aafb8e03341995e7c4797860181562380f81ed0a87ff455b70bf1f1 \ - --hash=sha256:189f652a87e876098bbc67b4da1049afb5f5dfbaa310dd67c594b01c10388db6 \ - --hash=sha256:1ca0083e80e791cffc6efce7660ad24af66c8d4079d2a750b29001b53ff59ada \ - --hash=sha256:1e16bf3e5fc9f44632affb159d30a437bfe286ce9e02754759be5536b169b305 \ - --hash=sha256:2090f6a85cafc5b2db085124d752757c9d251548cedabe9bd31afe6363e0aff2 \ - --hash=sha256:20b9b5fbe0b88d0bdef2012ef7dee867f874b72528cf1d08f1d59b0e3850129d \ - --hash=sha256:22ae2ebf9b0c69d206c003e2f6a914ea33f0a932d4aa16f236afc049d9958f4a \ - --hash=sha256:22f3105d4fb15c8f57ff3959a58fcab6ce36814486500cd7485651230ad4d4ef \ - --hash=sha256:23bfd518810af7de1116313ebd9092cb9aa629beb12f6ed631ad53356ed6b86c \ - --hash=sha256:27e5fc84ccef8dfaabb09d82b7d179c7cf1a3fbc8a966f8274fcb4ab2eb4cadb \ - --hash=sha256:3380252550e372e8511d49481bd836264c009adb826b23fefcc5dd3c69692f60 \ - --hash=sha256:3702ea6872c5a2a4eeefa6ffd36b042e9773f05b1f37ae3ef7264b1163c2dcf6 \ - --hash=sha256:37bb93b2178e02b7b618893990941900fd25b6b9ac0fa49931a40aecdf083fe4 \ - --hash=sha256:3914f5aaa0f36d5d60e8ece6a308ee1c9784cd75ec8151062614657a114c4478 \ - --hash=sha256:3a37ffb35399029b45c6cc33640a92bef403c9fd388acce75cdc88f58bd19a81 \ - --hash=sha256:3c8b88a2ccf5493b6c8da9076fb151ba106960a2df90c2633f342f120751a9e7 \ - --hash=sha256:3e97b5e938051226dc025ec80980c285b053ffb1e25a3db2a3aa3bc046bf7f56 \ - --hash=sha256:3ec660d19bbc671e3a6443325f07263be452c453ac9e512f5eb935e7d4ac28b3 \ - --hash=sha256:3efe2c2cb5763f2f1b275ad2bf7a287d3f7ebbef35648a9726e3b69284a4f3d6 \ - --hash=sha256:483a6aea59cb89904e1ceabd2b47368b5600fb7de78a6e4a2c2987b2d256cf30 \ - --hash=sha256:4867cafcbc6585e4b678876c489b9273b13e9fff9f6d6d66add5e15d11d926cb \ - --hash=sha256:48e171e52d1c4d33888e529b999e5900356b9ae588c2f09a52dcefb158b27506 \ - --hash=sha256:4a9cb68166a34117d6646c0023c7b759bf197bee5ad4272f420a0141d7eb03a0 \ - --hash=sha256:4b820514bfc0b98a30e3d85462084779900347e4d49267f747ff54060cc33925 \ - --hash=sha256:4e18b656c5e844539d506a0a06432274d7bd52a7487e6828c63a63d69185626c \ - --hash=sha256:4e9f48f58c2c523d5a06faea47866cd35b32655c46b443f163d08c6d0ddb17d6 \ - --hash=sha256:50b3a2710631848991d0bf7de077502e8994c804bb805aeb2925a981de58ec2e \ - --hash=sha256:55b6d90641869892caa9ca42ff913f7ff1c5ece06474fbd32fb2cf6834726c95 \ - --hash=sha256:57feec87371dbb3520da6192213c7d6fc892d5589a93db548331954de8248fd2 \ - --hash=sha256:58130ecf8f7b8112cdb841486404f1282b9c86ccb30d3519faf301b2e5659133 \ - --hash=sha256:5845c1fd4866bb5dd3125d89b90e57ed3138241540897de748cdf19de8a2fca2 \ - --hash=sha256:59bfeae4b25ec05b34f1956eaa1cb38032282cd4dfabc5056d0a1ec4d696d3aa \ - --hash=sha256:5b48204e8d955c47c55b72779802b219a39acc3ee3d0116d5080c388970b76e3 \ - --hash=sha256:5c09fcfdccdd0b57867577b719c69e347a436b86cd83747f179dbf0cc0d4c1f3 \ - --hash=sha256:6180c0ae073bddeb5a97a38c03f30c233e0a4d39cd86166251617d1bbd0af436 \ - --hash=sha256:682b987361e5fd7a139ed565e30d81fd81e9629acc7d925a205366877d8c8657 \ - --hash=sha256:6b5d83030255983181005e6cfbac1617ce9746b219bc2aad52201ad121226581 \ - --hash=sha256:6bb5992037f7a9eff7991ebe4273ea7f51f1c1c511e6a2ce511d0e7bdb754492 \ - --hash=sha256:73eae06aa53af2ea5270cc066dcaf02cc60d2994bbb2c4ef5764949257d10f43 \ - --hash=sha256:76f364861c3bfc98cbbcbd402d83454ed9e01a5224bb3a28bf70002a230f73e2 \ - --hash=sha256:820c661588bd01a0aa62a1283f20d2be4281b086f80dad9e955e690c75fb54a2 \ - --hash=sha256:82176036e65644a6cc5bd619f65f6f19781e8ec2e5330f51aa9ada7504cc1926 \ - --hash=sha256:87701f25a2352e5bf7454caa64757642734da9f6b11384c1f9d1a8e699758057 \ - --hash=sha256:9079dfc6a70abe341f521f78405b8949f96db48da98aeb43f9907f342f627cdc \ - --hash=sha256:90f8717cb649eea3504091e640a1b8568faad18bd4b9fcd692853a04475a4b80 \ - --hash=sha256:957cf8e4b6e123a9eea554fa7ebc85674674b713551de587eb318a2df3e00255 \ - --hash=sha256:99f826cbf970077383d7de805c0681799491cb939c25450b9b5b3ced03ca99f1 \ - --hash=sha256:9f636b730f7e8cb19feb87094949ba54ee5357440b9658b2a32a5ce4bce53972 \ - --hash=sha256:a114d03b938376557927ab23f1e950827c3b893ccb94b62fd95d430fd0e5cf53 \ - --hash=sha256:a185f876e69897a6f3325c3f19f26a297fa058c5e456bfcff8015e9a27e83ae1 \ - --hash=sha256:a7a9541cd308eed5e30318430a9c74d2132e9a8cb46b901326272d780bf2d423 \ - --hash=sha256:aa466da5b15ccea564bdab9c89175c762bc12825f4659c11227f515cee76fa4a \ - --hash=sha256:aaed8b0562be4a0876ee3b6946f6869b7bcdb571a5d1496683505944e268b160 \ - --hash=sha256:ab7c4ceb38d91570a650dba194e1ca87c2b543488fe9309b4212694174fd539c \ - --hash=sha256:ac10f4c2b9e770c4e393876e35a7046879d195cd123b4f116d299d442b335bcd \ - --hash=sha256:b04772ed465fa3cc947db808fa306d79b43e896beb677a56fb2347ca1a49c1fa \ - --hash=sha256:b1c416351ee6271b2f49b56ad7f308072f6f44b37118d69c2cad94f3fa8a40d5 \ - --hash=sha256:b225d95519a5bf73860323e633a664b0d85ad3d5bede6d30d95b35d4dfe8805b \ - --hash=sha256:b2f59caeaf7632cc633b5cf6fc449372b83bbdf0da4ae04d5be36118e46cc0aa \ - --hash=sha256:b58c621844d55e71c1b7f7c498ce5aa6985d743a1a59034c57a905b3f153c1ef \ - --hash=sha256:bf6bea52ec97e95560af5ae576bdac3aa3aae0b6758c6efa115236d9e07dae44 \ - --hash=sha256:c08be4f460903e5a9d0f76818db3250f12e9c344e79314d1d570fc69d7f4eae4 \ - --hash=sha256:c7053d3b0353a8b9de430a4f4b4268ac9a4fb3481af37dfe49825bf45ca24156 \ - --hash=sha256:c943a53e9186688b45b323602298ab727d8865d8c9ee0b17f8d62d14b56f0753 \ - --hash=sha256:ce2186a7df133a9c895dea3331ddc5ddad42cdd0d1ea2f0a51e5d161e4762f28 \ - --hash=sha256:d093be959277cb7dee84b801eb1af388b6ad3ca6a6b6bf1ed7585895789d027d \ - --hash=sha256:d094ddec350a2fb899fec68d8353c78233debde9b7d8b4beeafa70825f1c281a \ - --hash=sha256:d1a9dd711d0877a1ece3d2e4fea11a8e75741ca21954c919406b44e7cf971304 \ - --hash=sha256:d569388c381b24671589335a3be6e1d45546c2988c2ebe30fdcada8457a31008 \ - --hash=sha256:d618649d4e70ac6efcbba75be98b26ef5078faad23592f9b51ca492953012429 \ - --hash=sha256:d83a047959d38a7ff552ff94be767b7fd79b831ad1cd9920662db05fec24fe72 \ - --hash=sha256:d8fff389528cad1618fb4b26b95550327495462cd745d879a8c7c2115248e399 \ - --hash=sha256:da1758c76f50c39a2efd5e9859ce7d776317eb1dd34317c8152ac9251fc574a3 \ - --hash=sha256:db7457bac39421addd0c8449933ac32d8042aae84a14911a757ae6ca3eef1392 \ - --hash=sha256:e27bbb6d14416713a8bd7aaa1313c0fc8d44ee48d74497a0ff4c3a1b6ccb5167 \ - --hash=sha256:e617fb6b0b6953fffd762669610c1c4ffd05632c138d61ac7e14ad187870669c \ - --hash=sha256:e9aa71e15d9d9beaad2c6b9319edcdc0a49a43ef5c0a4c8265ca9ee7d6c67774 \ - --hash=sha256:ec2abea24d98246b94913b76a125e855eb5c434f7c46546046372fe60f666351 \ - --hash=sha256:f179dee3b863ab1c59580ff60f9d99f632f34ccb38bf67a33ec6b3ecadd0fd76 \ - --hash=sha256:f4c035da3f544b1882bac24115f3e2e8760f10a0107614fc9839fd232200b875 \ - --hash=sha256:f67f217af4b1ff66c68a87318012de788dd95fcfeb24cc889011f4e1c7454dfd \ - --hash=sha256:f90c822a402cb865e396a504f9fc8173ef34212a342d92e362ca498cad308e28 \ - --hash=sha256:ff3827aef427c89a25cc96ded1759271a93603aba9fb977a6d264648ebf989db -nest-asyncio==1.6.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe \ - --hash=sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c -ollama==0.2.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:b6e2414921c94f573a903d1069d682ba2fb2607070ea9e19ca4a7872f2a460ec \ - --hash=sha256:fa316baa9a81eac3beb4affb0a17deb3008fdd6ed05b123c26306cfbe4c349b6 -openai==1.58.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:e2910b1170a6b7f88ef491ac3a42c387f08bd3db533411f7ee391d166571d63c \ - --hash=sha256:f5a035fd01e141fc743f4b0e02c41ca49be8fab0866d3b67f5f29b4f4d3c0973 -packaging==24.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759 \ - --hash=sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f -parso==0.8.4 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18 \ - --hash=sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d -pexpect==4.9.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform != "win32" \ - --hash=sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523 \ - --hash=sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f -platformdirs==4.3.6 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907 \ - --hash=sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb -prompt-toolkit==3.0.48 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:d6623ab0477a80df74e646bdbc93621143f5caf104206aa29294d53de1a03d90 \ - --hash=sha256:f49a827f90062e411f1ce1f854f2aedb3c23353244f8108b89283587397ac10e -propcache==0.2.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:03ff9d3f665769b2a85e6157ac8b439644f2d7fd17615a82fa55739bc97863f4 \ - --hash=sha256:049324ee97bb67285b49632132db351b41e77833678432be52bdd0289c0e05e4 \ - --hash=sha256:081a430aa8d5e8876c6909b67bd2d937bfd531b0382d3fdedb82612c618bc41a \ - --hash=sha256:0f022d381747f0dfe27e99d928e31bc51a18b65bb9e481ae0af1380a6725dd1f \ - --hash=sha256:12d1083f001ace206fe34b6bdc2cb94be66d57a850866f0b908972f90996b3e9 \ - --hash=sha256:14d86fe14b7e04fa306e0c43cdbeebe6b2c2156a0c9ce56b815faacc193e320d \ - --hash=sha256:160291c60081f23ee43d44b08a7e5fb76681221a8e10b3139618c5a9a291b84e \ - --hash=sha256:1672137af7c46662a1c2be1e8dc78cb6d224319aaa40271c9257d886be4363a6 \ - --hash=sha256:19a0f89a7bb9d8048d9c4370c9c543c396e894c76be5525f5e1ad287f1750ddf \ - --hash=sha256:1ac2f5fe02fa75f56e1ad473f1175e11f475606ec9bd0be2e78e4734ad575034 \ - --hash=sha256:1cd9a1d071158de1cc1c71a26014dcdfa7dd3d5f4f88c298c7f90ad6f27bb46d \ - --hash=sha256:1ffc3cca89bb438fb9c95c13fc874012f7b9466b89328c3c8b1aa93cdcfadd16 \ - --hash=sha256:297878dc9d0a334358f9b608b56d02e72899f3b8499fc6044133f0d319e2ec30 \ - --hash=sha256:2d3af2e79991102678f53e0dbf4c35de99b6b8b58f29a27ca0325816364caaba \ - --hash=sha256:30b43e74f1359353341a7adb783c8f1b1c676367b011709f466f42fda2045e95 \ - --hash=sha256:3156628250f46a0895f1f36e1d4fbe062a1af8718ec3ebeb746f1d23f0c5dc4d \ - --hash=sha256:31f5af773530fd3c658b32b6bdc2d0838543de70eb9a2156c03e410f7b0d3aae \ - --hash=sha256:3935bfa5fede35fb202c4b569bb9c042f337ca4ff7bd540a0aa5e37131659348 \ - --hash=sha256:39d51fbe4285d5db5d92a929e3e21536ea3dd43732c5b177c7ef03f918dff9f2 \ - --hash=sha256:3f77ce728b19cb537714499928fe800c3dda29e8d9428778fc7c186da4c09a64 \ - --hash=sha256:4160d9283bd382fa6c0c2b5e017acc95bc183570cd70968b9202ad6d8fc48dce \ - --hash=sha256:4a571d97dbe66ef38e472703067021b1467025ec85707d57e78711c085984e54 \ - --hash=sha256:4e6281aedfca15301c41f74d7005e6e3f4ca143584ba696ac69df4f02f40d629 \ - --hash=sha256:52277518d6aae65536e9cea52d4e7fd2f7a66f4aa2d30ed3f2fcea620ace3c54 \ - --hash=sha256:556fc6c10989f19a179e4321e5d678db8eb2924131e64652a51fe83e4c3db0e1 \ - --hash=sha256:574faa3b79e8ebac7cb1d7930f51184ba1ccf69adfdec53a12f319a06030a68b \ - --hash=sha256:58791550b27d5488b1bb52bc96328456095d96206a250d28d874fafe11b3dfaf \ - --hash=sha256:5b750a8e5a1262434fb1517ddf64b5de58327f1adc3524a5e44c2ca43305eb0b \ - --hash=sha256:5d97151bc92d2b2578ff7ce779cdb9174337390a535953cbb9452fb65164c587 \ - --hash=sha256:5eee736daafa7af6d0a2dc15cc75e05c64f37fc37bafef2e00d77c14171c2097 \ - --hash=sha256:6445804cf4ec763dc70de65a3b0d9954e868609e83850a47ca4f0cb64bd79fea \ - --hash=sha256:647894f5ae99c4cf6bb82a1bb3a796f6e06af3caa3d32e26d2350d0e3e3faf24 \ - --hash=sha256:66d4cfda1d8ed687daa4bc0274fcfd5267873db9a5bc0418c2da19273040eeb7 \ - --hash=sha256:6a9a8c34fb7bb609419a211e59da8887eeca40d300b5ea8e56af98f6fbbb1541 \ - --hash=sha256:6b3f39a85d671436ee3d12c017f8fdea38509e4f25b28eb25877293c98c243f6 \ - --hash=sha256:6b6fb63ae352e13748289f04f37868099e69dba4c2b3e271c46061e82c745634 \ - --hash=sha256:70693319e0b8fd35dd863e3e29513875eb15c51945bf32519ef52927ca883bc3 \ - --hash=sha256:781e65134efaf88feb447e8c97a51772aa75e48b794352f94cb7ea717dedda0d \ - --hash=sha256:819ce3b883b7576ca28da3861c7e1a88afd08cc8c96908e08a3f4dd64a228034 \ - --hash=sha256:857112b22acd417c40fa4595db2fe28ab900c8c5fe4670c7989b1c0230955465 \ - --hash=sha256:887d9b0a65404929641a9fabb6452b07fe4572b269d901d622d8a34a4e9043b2 \ - --hash=sha256:8b3489ff1ed1e8315674d0775dc7d2195fb13ca17b3808721b54dbe9fd020faf \ - --hash=sha256:92fc4500fcb33899b05ba73276dfb684a20d31caa567b7cb5252d48f896a91b1 \ - --hash=sha256:9403db39be1393618dd80c746cb22ccda168efce239c73af13c3763ef56ffc04 \ - --hash=sha256:98110aa363f1bb4c073e8dcfaefd3a5cea0f0834c2aab23dda657e4dab2f53b5 \ - --hash=sha256:999779addc413181912e984b942fbcc951be1f5b3663cd80b2687758f434c583 \ - --hash=sha256:9caac6b54914bdf41bcc91e7eb9147d331d29235a7c967c150ef5df6464fd1bb \ - --hash=sha256:a7a078f5d37bee6690959c813977da5291b24286e7b962e62a94cec31aa5188b \ - --hash=sha256:a7e65eb5c003a303b94aa2c3852ef130230ec79e349632d030e9571b87c4698c \ - --hash=sha256:a96dc1fa45bd8c407a0af03b2d5218392729e1822b0c32e62c5bf7eeb5fb3958 \ - --hash=sha256:aca405706e0b0a44cc6bfd41fbe89919a6a56999157f6de7e182a990c36e37bc \ - --hash=sha256:accb6150ce61c9c4b7738d45550806aa2b71c7668c6942f17b0ac182b6142fd4 \ - --hash=sha256:ad1af54a62ffe39cf34db1aa6ed1a1873bd548f6401db39d8e7cd060b9211f82 \ - --hash=sha256:ae1aa1cd222c6d205853b3013c69cd04515f9d6ab6de4b0603e2e1c33221303e \ - --hash=sha256:b2d0a12018b04f4cb820781ec0dffb5f7c7c1d2a5cd22bff7fb055a2cb19ebce \ - --hash=sha256:b480c6a4e1138e1aa137c0079b9b6305ec6dcc1098a8ca5196283e8a49df95a9 \ - --hash=sha256:b74c261802d3d2b85c9df2dfb2fa81b6f90deeef63c2db9f0e029a3cac50b518 \ - --hash=sha256:ba278acf14471d36316159c94a802933d10b6a1e117b8554fe0d0d9b75c9d536 \ - --hash=sha256:bb6178c241278d5fe853b3de743087be7f5f4c6f7d6d22a3b524d323eecec505 \ - --hash=sha256:bf72af5e0fb40e9babf594308911436c8efde3cb5e75b6f206c34ad18be5c052 \ - --hash=sha256:bfd3223c15bebe26518d58ccf9a39b93948d3dcb3e57a20480dfdd315356baff \ - --hash=sha256:c214999039d4f2a5b2073ac506bba279945233da8c786e490d411dfc30f855c1 \ - --hash=sha256:c2f992c07c0fca81655066705beae35fc95a2fa7366467366db627d9f2ee097f \ - --hash=sha256:cba4cfa1052819d16699e1d55d18c92b6e094d4517c41dd231a8b9f87b6fa681 \ - --hash=sha256:cea7daf9fc7ae6687cf1e2c049752f19f146fdc37c2cc376e7d0032cf4f25347 \ - --hash=sha256:cf6c4150f8c0e32d241436526f3c3f9cbd34429492abddbada2ffcff506c51af \ - --hash=sha256:d09c333d36c1409d56a9d29b3a1b800a42c76a57a5a8907eacdbce3f18768246 \ - --hash=sha256:d27b84d5880f6d8aa9ae3edb253c59d9f6642ffbb2c889b78b60361eed449787 \ - --hash=sha256:d2ccec9ac47cf4e04897619c0e0c1a48c54a71bdf045117d3a26f80d38ab1fb0 \ - --hash=sha256:d71264a80f3fcf512eb4f18f59423fe82d6e346ee97b90625f283df56aee103f \ - --hash=sha256:d93f3307ad32a27bda2e88ec81134b823c240aa3abb55821a8da553eed8d9439 \ - --hash=sha256:d9631c5e8b5b3a0fda99cb0d29c18133bca1e18aea9effe55adb3da1adef80d3 \ - --hash=sha256:ddfab44e4489bd79bda09d84c430677fc7f0a4939a73d2bba3073036f487a0a6 \ - --hash=sha256:e7048abd75fe40712005bcfc06bb44b9dfcd8e101dda2ecf2f5aa46115ad07ca \ - --hash=sha256:e73091191e4280403bde6c9a52a6999d69cdfde498f1fdf629105247599b57ec \ - --hash=sha256:e800776a79a5aabdb17dcc2346a7d66d0777e942e4cd251defeb084762ecd17d \ - --hash=sha256:edc9fc7051e3350643ad929df55c451899bb9ae6d24998a949d2e4c87fb596d3 \ - --hash=sha256:f089118d584e859c62b3da0892b88a83d611c2033ac410e929cb6754eec0ed16 \ - --hash=sha256:f174bbd484294ed9fdf09437f889f95807e5f229d5d93588d34e92106fbf6717 \ - --hash=sha256:f508b0491767bb1f2b87fdfacaba5f7eddc2f867740ec69ece6d1946d29029a6 \ - --hash=sha256:f7a31fc1e1bd362874863fdeed71aed92d348f5336fd84f2197ba40c59f061bd \ - --hash=sha256:f9479aa06a793c5aeba49ce5c5692ffb51fcd9a7016e017d555d5e2b0045d212 -psutil==6.1.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:018aeae2af92d943fdf1da6b58665124897cfc94faa2ca92098838f83e1b1bca \ - --hash=sha256:0bdd4eab935276290ad3cb718e9809412895ca6b5b334f5a9111ee6d9aff9377 \ - --hash=sha256:1924e659d6c19c647e763e78670a05dbb7feaf44a0e9c94bf9e14dfc6ba50468 \ - --hash=sha256:33431e84fee02bc84ea36d9e2c4a6d395d479c9dd9bba2376c1f6ee8f3a4e0b3 \ - --hash=sha256:384636b1a64b47814437d1173be1427a7c83681b17a450bfc309a1953e329603 \ - --hash=sha256:6d4281f5bbca041e2292be3380ec56a9413b790579b8e593b1784499d0005dac \ - --hash=sha256:8be07491f6ebe1a693f17d4f11e69d0dc1811fa082736500f649f79df7735303 \ - --hash=sha256:8df0178ba8a9e5bc84fed9cfa61d54601b371fbec5c8eebad27575f1e105c0d4 \ - --hash=sha256:97f7cb9921fbec4904f522d972f0c0e1f4fabbdd4e0287813b21215074a0f160 \ - --hash=sha256:9ccc4316f24409159897799b83004cb1e24f9819b0dcf9c0b68bdcb6cefee6a8 \ - --hash=sha256:b6e06c20c05fe95a3d7302d74e7097756d4ba1247975ad6905441ae1b5b66003 \ - --hash=sha256:c777eb75bb33c47377c9af68f30e9f11bc78e0f07fbf907be4a5d70b2fe5f030 \ - --hash=sha256:ca9609c77ea3b8481ab005da74ed894035936223422dc591d6772b147421f777 \ - --hash=sha256:cf8496728c18f2d0b45198f06895be52f36611711746b7f30c464b422b50e2f5 \ - --hash=sha256:eaa912e0b11848c4d9279a93d7e2783df352b082f40111e078388701fd479e53 \ - --hash=sha256:f35cfccb065fff93529d2afb4a2e89e363fe63ca1e4a5da22b603a85833c2649 \ - --hash=sha256:fc0ed7fe2231a444fc219b9c42d0376e0a9a1a72f16c5cfa0f68d19f1a0663e8 -ptyprocess==0.7.0 ; python_version >= "3.9" and python_version < "4.0" and sys_platform != "win32" \ - --hash=sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35 \ - --hash=sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220 -pure-eval==0.2.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0 \ - --hash=sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42 -pycparser==2.22 ; python_version >= "3.9" and python_version < "4.0" and implementation_name == "pypy" \ - --hash=sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6 \ - --hash=sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc -pydantic-core==2.27.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:00bad2484fa6bda1e216e7345a798bd37c68fb2d97558edd584942aa41b7d278 \ - --hash=sha256:0296abcb83a797db256b773f45773da397da75a08f5fcaef41f2044adec05f50 \ - --hash=sha256:03d0f86ea3184a12f41a2d23f7ccb79cdb5a18e06993f8a45baa8dfec746f0e9 \ - --hash=sha256:044a50963a614ecfae59bb1eaf7ea7efc4bc62f49ed594e18fa1e5d953c40e9f \ - --hash=sha256:05e3a55d124407fffba0dd6b0c0cd056d10e983ceb4e5dbd10dda135c31071d6 \ - --hash=sha256:08e125dbdc505fa69ca7d9c499639ab6407cfa909214d500897d02afb816e7cc \ - --hash=sha256:097830ed52fd9e427942ff3b9bc17fab52913b2f50f2880dc4a5611446606a54 \ - --hash=sha256:0d1e85068e818c73e048fe28cfc769040bb1f475524f4745a5dc621f75ac7630 \ - --hash=sha256:0d75070718e369e452075a6017fbf187f788e17ed67a3abd47fa934d001863d9 \ - --hash=sha256:14d4a5c49d2f009d62a2a7140d3064f686d17a5d1a268bc641954ba181880236 \ - --hash=sha256:172fce187655fece0c90d90a678424b013f8fbb0ca8b036ac266749c09438cb7 \ - --hash=sha256:18a101c168e4e092ab40dbc2503bdc0f62010e95d292b27827871dc85450d7ee \ - --hash=sha256:1a4207639fb02ec2dbb76227d7c751a20b1a6b4bc52850568e52260cae64ca3b \ - --hash=sha256:1c1fd185014191700554795c99b347d64f2bb637966c4cfc16998a0ca700d048 \ - --hash=sha256:1e2cb691ed9834cd6a8be61228471d0a503731abfb42f82458ff27be7b2186fc \ - --hash=sha256:1ebaf1d0481914d004a573394f4be3a7616334be70261007e47c2a6fe7e50130 \ - --hash=sha256:220f892729375e2d736b97d0e51466252ad84c51857d4d15f5e9692f9ef12be4 \ - --hash=sha256:251136cdad0cb722e93732cb45ca5299fb56e1344a833640bf93b2803f8d1bfd \ - --hash=sha256:26f0d68d4b235a2bae0c3fc585c585b4ecc51382db0e3ba402a22cbc440915e4 \ - --hash=sha256:26f32e0adf166a84d0cb63be85c562ca8a6fa8de28e5f0d92250c6b7e9e2aff7 \ - --hash=sha256:280d219beebb0752699480fe8f1dc61ab6615c2046d76b7ab7ee38858de0a4e7 \ - --hash=sha256:28ccb213807e037460326424ceb8b5245acb88f32f3d2777427476e1b32c48c4 \ - --hash=sha256:2bf14caea37e91198329b828eae1618c068dfb8ef17bb33287a7ad4b61ac314e \ - --hash=sha256:2d367ca20b2f14095a8f4fa1210f5a7b78b8a20009ecced6b12818f455b1e9fa \ - --hash=sha256:30c5f68ded0c36466acede341551106821043e9afaad516adfb6e8fa80a4e6a6 \ - --hash=sha256:337b443af21d488716f8d0b6164de833e788aa6bd7e3a39c005febc1284f4962 \ - --hash=sha256:3911ac9284cd8a1792d3cb26a2da18f3ca26c6908cc434a18f730dc0db7bfa3b \ - --hash=sha256:3d591580c34f4d731592f0e9fe40f9cc1b430d297eecc70b962e93c5c668f15f \ - --hash=sha256:3de3ce3c9ddc8bbd88f6e0e304dea0e66d843ec9de1b0042b0911c1663ffd474 \ - --hash=sha256:3de9961f2a346257caf0aa508a4da705467f53778e9ef6fe744c038119737ef5 \ - --hash=sha256:40d02e7d45c9f8af700f3452f329ead92da4c5f4317ca9b896de7ce7199ea459 \ - --hash=sha256:42c5f762659e47fdb7b16956c71598292f60a03aa92f8b6351504359dbdba6cf \ - --hash=sha256:47956ae78b6422cbd46f772f1746799cbb862de838fd8d1fbd34a82e05b0983a \ - --hash=sha256:491a2b73db93fab69731eaee494f320faa4e093dbed776be1a829c2eb222c34c \ - --hash=sha256:4c9775e339e42e79ec99c441d9730fccf07414af63eac2f0e48e08fd38a64d76 \ - --hash=sha256:4e0b4220ba5b40d727c7f879eac379b822eee5d8fff418e9d3381ee45b3b0362 \ - --hash=sha256:50a68f3e3819077be2c98110c1f9dcb3817e93f267ba80a2c05bb4f8799e2ff4 \ - --hash=sha256:519f29f5213271eeeeb3093f662ba2fd512b91c5f188f3bb7b27bc5973816934 \ - --hash=sha256:521eb9b7f036c9b6187f0b47318ab0d7ca14bd87f776240b90b21c1f4f149320 \ - --hash=sha256:57762139821c31847cfb2df63c12f725788bd9f04bc2fb392790959b8f70f118 \ - --hash=sha256:5e4f4bb20d75e9325cc9696c6802657b58bc1dbbe3022f32cc2b2b632c3fbb96 \ - --hash=sha256:5e68c4446fe0810e959cdff46ab0a41ce2f2c86d227d96dc3847af0ba7def306 \ - --hash=sha256:669e193c1c576a58f132e3158f9dfa9662969edb1a250c54d8fa52590045f046 \ - --hash=sha256:688d3fd9fcb71f41c4c015c023d12a79d1c4c0732ec9eb35d96e3388a120dcf3 \ - --hash=sha256:6fb4aadc0b9a0c063206846d603b92030eb6f03069151a625667f982887153e2 \ - --hash=sha256:7041c36f5680c6e0f08d922aed302e98b3745d97fe1589db0a3eebf6624523af \ - --hash=sha256:71b24c7d61131bb83df10cc7e687433609963a944ccf45190cfc21e0887b08c9 \ - --hash=sha256:77d1bca19b0f7021b3a982e6f903dcd5b2b06076def36a652e3907f596e29f67 \ - --hash=sha256:7969e133a6f183be60e9f6f56bfae753585680f3b7307a8e555a948d443cc05a \ - --hash=sha256:7a66efda2387de898c8f38c0cf7f14fca0b51a8ef0b24bfea5849f1b3c95af27 \ - --hash=sha256:7d0c8399fcc1848491f00e0314bd59fb34a9c008761bcb422a057670c3f65e35 \ - --hash=sha256:7d14bd329640e63852364c306f4d23eb744e0f8193148d4044dd3dacdaacbd8b \ - --hash=sha256:7e17b560be3c98a8e3aa66ce828bdebb9e9ac6ad5466fba92eb74c4c95cb1151 \ - --hash=sha256:8083d4e875ebe0b864ffef72a4304827015cff328a1be6e22cc850753bfb122b \ - --hash=sha256:82f91663004eb8ed30ff478d77c4d1179b3563df6cdb15c0817cd1cdaf34d154 \ - --hash=sha256:82f986faf4e644ffc189a7f1aafc86e46ef70372bb153e7001e8afccc6e54133 \ - --hash=sha256:83097677b8e3bd7eaa6775720ec8e0405f1575015a463285a92bfdfe254529ef \ - --hash=sha256:85210c4d99a0114f5a9481b44560d7d1e35e32cc5634c656bc48e590b669b145 \ - --hash=sha256:8c19d1ea0673cd13cc2f872f6c9ab42acc4e4f492a7ca9d3795ce2b112dd7e15 \ - --hash=sha256:8d9b3388db186ba0c099a6d20f0604a44eabdeef1777ddd94786cdae158729e4 \ - --hash=sha256:8e10c99ef58cfdf2a66fc15d66b16c4a04f62bca39db589ae8cba08bc55331bc \ - --hash=sha256:953101387ecf2f5652883208769a79e48db18c6df442568a0b5ccd8c2723abee \ - --hash=sha256:9c3ed807c7b91de05e63930188f19e921d1fe90de6b4f5cd43ee7fcc3525cb8c \ - --hash=sha256:9e0c8cfefa0ef83b4da9588448b6d8d2a2bf1a53c3f1ae5fca39eb3061e2f0b0 \ - --hash=sha256:9fdbe7629b996647b99c01b37f11170a57ae675375b14b8c13b8518b8320ced5 \ - --hash=sha256:a0fcd29cd6b4e74fe8ddd2c90330fd8edf2e30cb52acda47f06dd615ae72da57 \ - --hash=sha256:ac4dbfd1691affb8f48c2c13241a2e3b60ff23247cbcf981759c768b6633cf8b \ - --hash=sha256:b0cb791f5b45307caae8810c2023a184c74605ec3bcbb67d13846c28ff731ff8 \ - --hash=sha256:ba5dd002f88b78a4215ed2f8ddbdf85e8513382820ba15ad5ad8955ce0ca19a1 \ - --hash=sha256:bca101c00bff0adb45a833f8451b9105d9df18accb8743b08107d7ada14bd7da \ - --hash=sha256:bd8086fa684c4775c27f03f062cbb9eaa6e17f064307e86b21b9e0abc9c0f02e \ - --hash=sha256:bec317a27290e2537f922639cafd54990551725fc844249e64c523301d0822fc \ - --hash=sha256:c10eb4f1659290b523af58fa7cffb452a61ad6ae5613404519aee4bfbf1df993 \ - --hash=sha256:c33939a82924da9ed65dab5a65d427205a73181d8098e79b6b426bdf8ad4e656 \ - --hash=sha256:c61709a844acc6bf0b7dce7daae75195a10aac96a596ea1b776996414791ede4 \ - --hash=sha256:c70c26d2c99f78b125a3459f8afe1aed4d9687c24fd677c6a4436bc042e50d6c \ - --hash=sha256:c817e2b40aba42bac6f457498dacabc568c3b7a986fc9ba7c8d9d260b71485fb \ - --hash=sha256:cabb9bcb7e0d97f74df8646f34fc76fbf793b7f6dc2438517d7a9e50eee4f14d \ - --hash=sha256:cc3f1a99a4f4f9dd1de4fe0312c114e740b5ddead65bb4102884b384c15d8bc9 \ - --hash=sha256:cca63613e90d001b9f2f9a9ceb276c308bfa2a43fafb75c8031c4f66039e8c6e \ - --hash=sha256:ce8918cbebc8da707ba805b7fd0b382816858728ae7fe19a942080c24e5b7cd1 \ - --hash=sha256:d2088237af596f0a524d3afc39ab3b036e8adb054ee57cbb1dcf8e09da5b29cc \ - --hash=sha256:d262606bf386a5ba0b0af3b97f37c83d7011439e3dc1a9298f21efb292e42f1a \ - --hash=sha256:d2d63f1215638d28221f664596b1ccb3944f6e25dd18cd3b86b0a4c408d5ebb9 \ - --hash=sha256:d3e8d504bdd3f10835468f29008d72fc8359d95c9c415ce6e767203db6127506 \ - --hash=sha256:d4041c0b966a84b4ae7a09832eb691a35aec90910cd2dbe7a208de59be77965b \ - --hash=sha256:d716e2e30c6f140d7560ef1538953a5cd1a87264c737643d481f2779fc247fe1 \ - --hash=sha256:d81d2068e1c1228a565af076598f9e7451712700b673de8f502f0334f281387d \ - --hash=sha256:d9640b0059ff4f14d1f37321b94061c6db164fbe49b334b31643e0528d100d99 \ - --hash=sha256:de3cd1899e2c279b140adde9357c4495ed9d47131b4a4eaff9052f23398076b3 \ - --hash=sha256:e0fd26b16394ead34a424eecf8a31a1f5137094cabe84a1bcb10fa6ba39d3d31 \ - --hash=sha256:e2bb4d3e5873c37bb3dd58714d4cd0b0e6238cebc4177ac8fe878f8b3aa8e74c \ - --hash=sha256:eb026e5a4c1fee05726072337ff51d1efb6f59090b7da90d30ea58625b1ffb39 \ - --hash=sha256:eda3f5c2a021bbc5d976107bb302e0131351c2ba54343f8a496dc8783d3d3a6a \ - --hash=sha256:ef592d4bad47296fb11f96cd7dc898b92e795032b4894dfb4076cfccd43a9308 \ - --hash=sha256:f141ee28a0ad2123b6611b6ceff018039df17f32ada8b534e6aa039545a3efb2 \ - --hash=sha256:f66d89ba397d92f840f8654756196d93804278457b5fbede59598a1f9f90b228 \ - --hash=sha256:f6f8e111843bbb0dee4cb6594cdc73e79b3329b526037ec242a3e49012495b3b \ - --hash=sha256:fa8e459d4954f608fa26116118bb67f56b93b209c39b008277ace29937453dc9 \ - --hash=sha256:fd1aea04935a508f62e0d0ef1f5ae968774a32afc306fb8545e06f5ff5cdf3ad -pydantic==2.10.4 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:597e135ea68be3a37552fb524bc7d0d66dcf93d395acd93a00682f1efcb8ee3d \ - --hash=sha256:82f12e9723da6de4fe2ba888b5971157b3be7ad914267dea8f05f82b28254f06 -pygments==2.18.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199 \ - --hash=sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a -pypdf==4.3.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:64b31da97eda0771ef22edb1bfecd5deee4b72c3d1736b7df2689805076d6418 \ - --hash=sha256:b2f37fe9a3030aa97ca86067a56ba3f9d3565f9a791b305c7355d8392c30d91b -python-abc==0.2.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:90017d09fbac7bde4b64b2c7e1b5d22da9055b64b821d1a2b4dc805b450b251a -python-dateutil==2.9.0.post0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3 \ - --hash=sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427 -python-dotenv==1.0.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:e324ee90a023d808f1959c46bcbc04446a10ced277783dc6ee09987c37ec10ca \ - --hash=sha256:f7b63ef50f1b690dddf550d03497b66d609393b40b564ed0d674909a68ebf16a -pywin32==308 ; sys_platform == "win32" and platform_python_implementation != "PyPy" and python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:00b3e11ef09ede56c6a43c71f2d31857cf7c54b0ab6e78ac659497abd2834f47 \ - --hash=sha256:100a5442b7332070983c4cd03f2e906a5648a5104b8a7f50175f7906efd16bb6 \ - --hash=sha256:13dcb914ed4347019fbec6697a01a0aec61019c1046c2b905410d197856326a6 \ - --hash=sha256:1c44539a37a5b7b21d02ab34e6a4d314e0788f1690d65b48e9b0b89f31abbbed \ - --hash=sha256:1f696ab352a2ddd63bd07430080dd598e6369152ea13a25ebcdd2f503a38f1ff \ - --hash=sha256:3b92622e29d651c6b783e368ba7d6722b1634b8e70bd376fd7610fe1992e19de \ - --hash=sha256:4fc888c59b3c0bef905ce7eb7e2106a07712015ea1c8234b703a088d46110e8e \ - --hash=sha256:575621b90f0dc2695fec346b2d6302faebd4f0f45c05ea29404cefe35d89442b \ - --hash=sha256:5794e764ebcabf4ff08c555b31bd348c9025929371763b2183172ff4708152f0 \ - --hash=sha256:587f3e19696f4bf96fde9d8a57cec74a57021ad5f204c9e627e15c33ff568897 \ - --hash=sha256:5d8c8015b24a7d6855b1550d8e660d8daa09983c80e5daf89a273e5c6fb5095a \ - --hash=sha256:71b3322d949b4cc20776436a9c9ba0eeedcbc9c650daa536df63f0ff111bb920 \ - --hash=sha256:7873ca4dc60ab3287919881a7d4f88baee4a6e639aa6962de25a98ba6b193341 \ - --hash=sha256:796ff4426437896550d2981b9c2ac0ffd75238ad9ea2d3bfa67a1abd546d262e \ - --hash=sha256:9b4de86c8d909aed15b7011182c8cab38c8850de36e6afb1f0db22b8959e3091 \ - --hash=sha256:a5ab5381813b40f264fa3495b98af850098f814a25a63589a8e9eb12560f450c \ - --hash=sha256:ef313c46d4c18dfb82a2431e3051ac8f112ccee1a34f29c263c583c568db63cd \ - --hash=sha256:fd380990e792eaf6827fcb7e187b2b4b1cede0585e3d0c9e84201ec27b9905e4 -pyyaml==6.0.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff \ - --hash=sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48 \ - --hash=sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086 \ - --hash=sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e \ - --hash=sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133 \ - --hash=sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5 \ - --hash=sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484 \ - --hash=sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee \ - --hash=sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5 \ - --hash=sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68 \ - --hash=sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a \ - --hash=sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf \ - --hash=sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99 \ - --hash=sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8 \ - --hash=sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85 \ - --hash=sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19 \ - --hash=sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc \ - --hash=sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a \ - --hash=sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1 \ - --hash=sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317 \ - --hash=sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c \ - --hash=sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631 \ - --hash=sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d \ - --hash=sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652 \ - --hash=sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5 \ - --hash=sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e \ - --hash=sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b \ - --hash=sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8 \ - --hash=sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476 \ - --hash=sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706 \ - --hash=sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563 \ - --hash=sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237 \ - --hash=sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b \ - --hash=sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083 \ - --hash=sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180 \ - --hash=sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425 \ - --hash=sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e \ - --hash=sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f \ - --hash=sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725 \ - --hash=sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183 \ - --hash=sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab \ - --hash=sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774 \ - --hash=sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725 \ - --hash=sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e \ - --hash=sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5 \ - --hash=sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d \ - --hash=sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290 \ - --hash=sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44 \ - --hash=sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed \ - --hash=sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4 \ - --hash=sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba \ - --hash=sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12 \ - --hash=sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4 -pyzmq==26.2.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:007137c9ac9ad5ea21e6ad97d3489af654381324d5d3ba614c323f60dab8fae6 \ - --hash=sha256:034da5fc55d9f8da09015d368f519478a52675e558c989bfcb5cf6d4e16a7d2a \ - --hash=sha256:05590cdbc6b902101d0e65d6a4780af14dc22914cc6ab995d99b85af45362cc9 \ - --hash=sha256:070672c258581c8e4f640b5159297580a9974b026043bd4ab0470be9ed324f1f \ - --hash=sha256:0aca98bc423eb7d153214b2df397c6421ba6373d3397b26c057af3c904452e37 \ - --hash=sha256:0bed0e799e6120b9c32756203fb9dfe8ca2fb8467fed830c34c877e25638c3fc \ - --hash=sha256:0d987a3ae5a71c6226b203cfd298720e0086c7fe7c74f35fa8edddfbd6597eed \ - --hash=sha256:0eaa83fc4c1e271c24eaf8fb083cbccef8fde77ec8cd45f3c35a9a123e6da097 \ - --hash=sha256:160c7e0a5eb178011e72892f99f918c04a131f36056d10d9c1afb223fc952c2d \ - --hash=sha256:17bf5a931c7f6618023cdacc7081f3f266aecb68ca692adac015c383a134ca52 \ - --hash=sha256:17c412bad2eb9468e876f556eb4ee910e62d721d2c7a53c7fa31e643d35352e6 \ - --hash=sha256:18c8dc3b7468d8b4bdf60ce9d7141897da103c7a4690157b32b60acb45e333e6 \ - --hash=sha256:1a534f43bc738181aa7cbbaf48e3eca62c76453a40a746ab95d4b27b1111a7d2 \ - --hash=sha256:1c17211bc037c7d88e85ed8b7d8f7e52db6dc8eca5590d162717c654550f7282 \ - --hash=sha256:1f3496d76b89d9429a656293744ceca4d2ac2a10ae59b84c1da9b5165f429ad3 \ - --hash=sha256:1fcc03fa4997c447dce58264e93b5aa2d57714fbe0f06c07b7785ae131512732 \ - --hash=sha256:226af7dcb51fdb0109f0016449b357e182ea0ceb6b47dfb5999d569e5db161d5 \ - --hash=sha256:23f4aad749d13698f3f7b64aad34f5fc02d6f20f05999eebc96b89b01262fb18 \ - --hash=sha256:25bf2374a2a8433633c65ccb9553350d5e17e60c8eb4de4d92cc6bd60f01d306 \ - --hash=sha256:28ad5233e9c3b52d76196c696e362508959741e1a005fb8fa03b51aea156088f \ - --hash=sha256:28c812d9757fe8acecc910c9ac9dafd2ce968c00f9e619db09e9f8f54c3a68a3 \ - --hash=sha256:29c6a4635eef69d68a00321e12a7d2559fe2dfccfa8efae3ffb8e91cd0b36a8b \ - --hash=sha256:29c7947c594e105cb9e6c466bace8532dc1ca02d498684128b339799f5248277 \ - --hash=sha256:2a50625acdc7801bc6f74698c5c583a491c61d73c6b7ea4dee3901bb99adb27a \ - --hash=sha256:2ae90ff9dad33a1cfe947d2c40cb9cb5e600d759ac4f0fd22616ce6540f72797 \ - --hash=sha256:2c4a71d5d6e7b28a47a394c0471b7e77a0661e2d651e7ae91e0cab0a587859ca \ - --hash=sha256:2ea4ad4e6a12e454de05f2949d4beddb52460f3de7c8b9d5c46fbb7d7222e02c \ - --hash=sha256:2eb7735ee73ca1b0d71e0e67c3739c689067f055c764f73aac4cc8ecf958ee3f \ - --hash=sha256:31507f7b47cc1ead1f6e86927f8ebb196a0bab043f6345ce070f412a59bf87b5 \ - --hash=sha256:35cffef589bcdc587d06f9149f8d5e9e8859920a071df5a2671de2213bef592a \ - --hash=sha256:367b4f689786fca726ef7a6c5ba606958b145b9340a5e4808132cc65759abd44 \ - --hash=sha256:39887ac397ff35b7b775db7201095fc6310a35fdbae85bac4523f7eb3b840e20 \ - --hash=sha256:3a495b30fc91db2db25120df5847d9833af237546fd59170701acd816ccc01c4 \ - --hash=sha256:3b55a4229ce5da9497dd0452b914556ae58e96a4381bb6f59f1305dfd7e53fc8 \ - --hash=sha256:402b190912935d3db15b03e8f7485812db350d271b284ded2b80d2e5704be780 \ - --hash=sha256:43a47408ac52647dfabbc66a25b05b6a61700b5165807e3fbd40063fcaf46386 \ - --hash=sha256:4661c88db4a9e0f958c8abc2b97472e23061f0bc737f6f6179d7a27024e1faa5 \ - --hash=sha256:46a446c212e58456b23af260f3d9fb785054f3e3653dbf7279d8f2b5546b21c2 \ - --hash=sha256:470d4a4f6d48fb34e92d768b4e8a5cc3780db0d69107abf1cd7ff734b9766eb0 \ - --hash=sha256:49d34ab71db5a9c292a7644ce74190b1dd5a3475612eefb1f8be1d6961441971 \ - --hash=sha256:4d29ab8592b6ad12ebbf92ac2ed2bedcfd1cec192d8e559e2e099f648570e19b \ - --hash=sha256:4d80b1dd99c1942f74ed608ddb38b181b87476c6a966a88a950c7dee118fdf50 \ - --hash=sha256:4da04c48873a6abdd71811c5e163bd656ee1b957971db7f35140a2d573f6949c \ - --hash=sha256:4f78c88905461a9203eac9faac157a2a0dbba84a0fd09fd29315db27be40af9f \ - --hash=sha256:4ff9dc6bc1664bb9eec25cd17506ef6672d506115095411e237d571e92a58231 \ - --hash=sha256:5506f06d7dc6ecf1efacb4a013b1f05071bb24b76350832c96449f4a2d95091c \ - --hash=sha256:55cf66647e49d4621a7e20c8d13511ef1fe1efbbccf670811864452487007e08 \ - --hash=sha256:5a509df7d0a83a4b178d0f937ef14286659225ef4e8812e05580776c70e155d5 \ - --hash=sha256:5c2b3bfd4b9689919db068ac6c9911f3fcb231c39f7dd30e3138be94896d18e6 \ - --hash=sha256:6835dd60355593de10350394242b5757fbbd88b25287314316f266e24c61d073 \ - --hash=sha256:689c5d781014956a4a6de61d74ba97b23547e431e9e7d64f27d4922ba96e9d6e \ - --hash=sha256:6a96179a24b14fa6428cbfc08641c779a53f8fcec43644030328f44034c7f1f4 \ - --hash=sha256:6ace4f71f1900a548f48407fc9be59c6ba9d9aaf658c2eea6cf2779e72f9f317 \ - --hash=sha256:6b274e0762c33c7471f1a7471d1a2085b1a35eba5cdc48d2ae319f28b6fc4de3 \ - --hash=sha256:706e794564bec25819d21a41c31d4df2d48e1cc4b061e8d345d7fb4dd3e94072 \ - --hash=sha256:70fc7fcf0410d16ebdda9b26cbd8bf8d803d220a7f3522e060a69a9c87bf7bad \ - --hash=sha256:7133d0a1677aec369d67dd78520d3fa96dd7f3dcec99d66c1762870e5ea1a50a \ - --hash=sha256:7445be39143a8aa4faec43b076e06944b8f9d0701b669df4af200531b21e40bb \ - --hash=sha256:76589c020680778f06b7e0b193f4b6dd66d470234a16e1df90329f5e14a171cd \ - --hash=sha256:76589f2cd6b77b5bdea4fca5992dc1c23389d68b18ccc26a53680ba2dc80ff2f \ - --hash=sha256:77eb0968da535cba0470a5165468b2cac7772cfb569977cff92e240f57e31bef \ - --hash=sha256:794a4562dcb374f7dbbfb3f51d28fb40123b5a2abadee7b4091f93054909add5 \ - --hash=sha256:7ad1bc8d1b7a18497dda9600b12dc193c577beb391beae5cd2349184db40f187 \ - --hash=sha256:7f98f6dfa8b8ccaf39163ce872bddacca38f6a67289116c8937a02e30bbe9711 \ - --hash=sha256:8423c1877d72c041f2c263b1ec6e34360448decfb323fa8b94e85883043ef988 \ - --hash=sha256:8685fa9c25ff00f550c1fec650430c4b71e4e48e8d852f7ddcf2e48308038640 \ - --hash=sha256:878206a45202247781472a2d99df12a176fef806ca175799e1c6ad263510d57c \ - --hash=sha256:89289a5ee32ef6c439086184529ae060c741334b8970a6855ec0b6ad3ff28764 \ - --hash=sha256:8ab5cad923cc95c87bffee098a27856c859bd5d0af31bd346035aa816b081fe1 \ - --hash=sha256:8b435f2753621cd36e7c1762156815e21c985c72b19135dac43a7f4f31d28dd1 \ - --hash=sha256:8be4700cd8bb02cc454f630dcdf7cfa99de96788b80c51b60fe2fe1dac480289 \ - --hash=sha256:8c997098cc65e3208eca09303630e84d42718620e83b733d0fd69543a9cab9cb \ - --hash=sha256:8ea039387c10202ce304af74def5021e9adc6297067f3441d348d2b633e8166a \ - --hash=sha256:8f7e66c7113c684c2b3f1c83cdd3376103ee0ce4c49ff80a648643e57fb22218 \ - --hash=sha256:90412f2db8c02a3864cbfc67db0e3dcdbda336acf1c469526d3e869394fe001c \ - --hash=sha256:92a78853d7280bffb93df0a4a6a2498cba10ee793cc8076ef797ef2f74d107cf \ - --hash=sha256:989d842dc06dc59feea09e58c74ca3e1678c812a4a8a2a419046d711031f69c7 \ - --hash=sha256:9cb3a6460cdea8fe8194a76de8895707e61ded10ad0be97188cc8463ffa7e3a8 \ - --hash=sha256:9dd8cd1aeb00775f527ec60022004d030ddc51d783d056e3e23e74e623e33726 \ - --hash=sha256:9ed69074a610fad1c2fda66180e7b2edd4d31c53f2d1872bc2d1211563904cd9 \ - --hash=sha256:9edda2df81daa129b25a39b86cb57dfdfe16f7ec15b42b19bfac503360d27a93 \ - --hash=sha256:a2224fa4a4c2ee872886ed00a571f5e967c85e078e8e8c2530a2fb01b3309b88 \ - --hash=sha256:a4f96f0d88accc3dbe4a9025f785ba830f968e21e3e2c6321ccdfc9aef755115 \ - --hash=sha256:aedd5dd8692635813368e558a05266b995d3d020b23e49581ddd5bbe197a8ab6 \ - --hash=sha256:aee22939bb6075e7afededabad1a56a905da0b3c4e3e0c45e75810ebe3a52672 \ - --hash=sha256:b1d464cb8d72bfc1a3adc53305a63a8e0cac6bc8c5a07e8ca190ab8d3faa43c2 \ - --hash=sha256:b8f86dd868d41bea9a5f873ee13bf5551c94cf6bc51baebc6f85075971fe6eea \ - --hash=sha256:bc6bee759a6bddea5db78d7dcd609397449cb2d2d6587f48f3ca613b19410cfc \ - --hash=sha256:bea2acdd8ea4275e1278350ced63da0b166421928276c7c8e3f9729d7402a57b \ - --hash=sha256:bfa832bfa540e5b5c27dcf5de5d82ebc431b82c453a43d141afb1e5d2de025fa \ - --hash=sha256:c0e6091b157d48cbe37bd67233318dbb53e1e6327d6fc3bb284afd585d141003 \ - --hash=sha256:c3789bd5768ab5618ebf09cef6ec2b35fed88709b104351748a63045f0ff9797 \ - --hash=sha256:c530e1eecd036ecc83c3407f77bb86feb79916d4a33d11394b8234f3bd35b940 \ - --hash=sha256:c811cfcd6a9bf680236c40c6f617187515269ab2912f3d7e8c0174898e2519db \ - --hash=sha256:c92d73464b886931308ccc45b2744e5968cbaade0b1d6aeb40d8ab537765f5bc \ - --hash=sha256:cccba051221b916a4f5e538997c45d7d136a5646442b1231b916d0164067ea27 \ - --hash=sha256:cdeabcff45d1c219636ee2e54d852262e5c2e085d6cb476d938aee8d921356b3 \ - --hash=sha256:ced65e5a985398827cc9276b93ef6dfabe0273c23de8c7931339d7e141c2818e \ - --hash=sha256:d049df610ac811dcffdc147153b414147428567fbbc8be43bb8885f04db39d98 \ - --hash=sha256:dacd995031a01d16eec825bf30802fceb2c3791ef24bcce48fa98ce40918c27b \ - --hash=sha256:ddf33d97d2f52d89f6e6e7ae66ee35a4d9ca6f36eda89c24591b0c40205a3629 \ - --hash=sha256:ded0fc7d90fe93ae0b18059930086c51e640cdd3baebdc783a695c77f123dcd9 \ - --hash=sha256:e3e0210287329272539eea617830a6a28161fbbd8a3271bf4150ae3e58c5d0e6 \ - --hash=sha256:e6fa2e3e683f34aea77de8112f6483803c96a44fd726d7358b9888ae5bb394ec \ - --hash=sha256:ea0eb6af8a17fa272f7b98d7bebfab7836a0d62738e16ba380f440fceca2d951 \ - --hash=sha256:ea7f69de383cb47522c9c208aec6dd17697db7875a4674c4af3f8cfdac0bdeae \ - --hash=sha256:eac5174677da084abf378739dbf4ad245661635f1600edd1221f150b165343f4 \ - --hash=sha256:fc4f7a173a5609631bb0c42c23d12c49df3966f89f496a51d3eb0ec81f4519d6 \ - --hash=sha256:fdb5b3e311d4d4b0eb8b3e8b4d1b0a512713ad7e6a68791d0923d1aec433d919 -ratelimit==2.2.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:af8a9b64b821529aca09ebaf6d8d279100d766f19e90b5059ac6a718ca6dee42 -redis==5.2.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f \ - --hash=sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4 -referencing==0.35.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c \ - --hash=sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de -regex==2024.11.6 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:02a02d2bb04fec86ad61f3ea7f49c015a0681bf76abb9857f945d26159d2968c \ - --hash=sha256:02e28184be537f0e75c1f9b2f8847dc51e08e6e171c6bde130b2687e0c33cf60 \ - --hash=sha256:040df6fe1a5504eb0f04f048e6d09cd7c7110fef851d7c567a6b6e09942feb7d \ - --hash=sha256:068376da5a7e4da51968ce4c122a7cd31afaaec4fccc7856c92f63876e57b51d \ - --hash=sha256:06eb1be98df10e81ebaded73fcd51989dcf534e3c753466e4b60c4697a003b67 \ - --hash=sha256:072623554418a9911446278f16ecb398fb3b540147a7828c06e2011fa531e773 \ - --hash=sha256:086a27a0b4ca227941700e0b31425e7a28ef1ae8e5e05a33826e17e47fbfdba0 \ - --hash=sha256:08986dce1339bc932923e7d1232ce9881499a0e02925f7402fb7c982515419ef \ - --hash=sha256:0a86e7eeca091c09e021db8eb72d54751e527fa47b8d5787caf96d9831bd02ad \ - --hash=sha256:0c32f75920cf99fe6b6c539c399a4a128452eaf1af27f39bce8909c9a3fd8cbe \ - --hash=sha256:0d7f453dca13f40a02b79636a339c5b62b670141e63efd511d3f8f73fba162b3 \ - --hash=sha256:1062b39a0a2b75a9c694f7a08e7183a80c63c0d62b301418ffd9c35f55aaa114 \ - --hash=sha256:13291b39131e2d002a7940fb176e120bec5145f3aeb7621be6534e46251912c4 \ - --hash=sha256:149f5008d286636e48cd0b1dd65018548944e495b0265b45e1bffecce1ef7f39 \ - --hash=sha256:164d8b7b3b4bcb2068b97428060b2a53be050085ef94eca7f240e7947f1b080e \ - --hash=sha256:167ed4852351d8a750da48712c3930b031f6efdaa0f22fa1933716bfcd6bf4a3 \ - --hash=sha256:1c4de13f06a0d54fa0d5ab1b7138bfa0d883220965a29616e3ea61b35d5f5fc7 \ - --hash=sha256:202eb32e89f60fc147a41e55cb086db2a3f8cb82f9a9a88440dcfc5d37faae8d \ - --hash=sha256:220902c3c5cc6af55d4fe19ead504de80eb91f786dc102fbd74894b1551f095e \ - --hash=sha256:2b3361af3198667e99927da8b84c1b010752fa4b1115ee30beaa332cabc3ef1a \ - --hash=sha256:2c89a8cc122b25ce6945f0423dc1352cb9593c68abd19223eebbd4e56612c5b7 \ - --hash=sha256:2d548dafee61f06ebdb584080621f3e0c23fff312f0de1afc776e2a2ba99a74f \ - --hash=sha256:2e34b51b650b23ed3354b5a07aab37034d9f923db2a40519139af34f485f77d0 \ - --hash=sha256:32f9a4c643baad4efa81d549c2aadefaeba12249b2adc5af541759237eee1c54 \ - --hash=sha256:3a51ccc315653ba012774efca4f23d1d2a8a8f278a6072e29c7147eee7da446b \ - --hash=sha256:3cde6e9f2580eb1665965ce9bf17ff4952f34f5b126beb509fee8f4e994f143c \ - --hash=sha256:40291b1b89ca6ad8d3f2b82782cc33807f1406cf68c8d440861da6304d8ffbbd \ - --hash=sha256:41758407fc32d5c3c5de163888068cfee69cb4c2be844e7ac517a52770f9af57 \ - --hash=sha256:4181b814e56078e9b00427ca358ec44333765f5ca1b45597ec7446d3a1ef6e34 \ - --hash=sha256:4f51f88c126370dcec4908576c5a627220da6c09d0bff31cfa89f2523843316d \ - --hash=sha256:50153825ee016b91549962f970d6a4442fa106832e14c918acd1c8e479916c4f \ - --hash=sha256:5056b185ca113c88e18223183aa1a50e66507769c9640a6ff75859619d73957b \ - --hash=sha256:5071b2093e793357c9d8b2929dfc13ac5f0a6c650559503bb81189d0a3814519 \ - --hash=sha256:525eab0b789891ac3be914d36893bdf972d483fe66551f79d3e27146191a37d4 \ - --hash=sha256:52fb28f528778f184f870b7cf8f225f5eef0a8f6e3778529bdd40c7b3920796a \ - --hash=sha256:5478c6962ad548b54a591778e93cd7c456a7a29f8eca9c49e4f9a806dcc5d638 \ - --hash=sha256:5670bce7b200273eee1840ef307bfa07cda90b38ae56e9a6ebcc9f50da9c469b \ - --hash=sha256:5704e174f8ccab2026bd2f1ab6c510345ae8eac818b613d7d73e785f1310f839 \ - --hash=sha256:59dfe1ed21aea057a65c6b586afd2a945de04fc7db3de0a6e3ed5397ad491b07 \ - --hash=sha256:5e7e351589da0850c125f1600a4c4ba3c722efefe16b297de54300f08d734fbf \ - --hash=sha256:63b13cfd72e9601125027202cad74995ab26921d8cd935c25f09c630436348ff \ - --hash=sha256:658f90550f38270639e83ce492f27d2c8d2cd63805c65a13a14d36ca126753f0 \ - --hash=sha256:684d7a212682996d21ca12ef3c17353c021fe9de6049e19ac8481ec35574a70f \ - --hash=sha256:69ab78f848845569401469da20df3e081e6b5a11cb086de3eed1d48f5ed57c95 \ - --hash=sha256:6f44ec28b1f858c98d3036ad5d7d0bfc568bdd7a74f9c24e25f41ef1ebfd81a4 \ - --hash=sha256:70b7fa6606c2881c1db9479b0eaa11ed5dfa11c8d60a474ff0e095099f39d98e \ - --hash=sha256:764e71f22ab3b305e7f4c21f1a97e1526a25ebdd22513e251cf376760213da13 \ - --hash=sha256:7ab159b063c52a0333c884e4679f8d7a85112ee3078fe3d9004b2dd875585519 \ - --hash=sha256:805e6b60c54bf766b251e94526ebad60b7de0c70f70a4e6210ee2891acb70bf2 \ - --hash=sha256:8447d2d39b5abe381419319f942de20b7ecd60ce86f16a23b0698f22e1b70008 \ - --hash=sha256:86fddba590aad9208e2fa8b43b4c098bb0ec74f15718bb6a704e3c63e2cef3e9 \ - --hash=sha256:89d75e7293d2b3e674db7d4d9b1bee7f8f3d1609428e293771d1a962617150cc \ - --hash=sha256:93c0b12d3d3bc25af4ebbf38f9ee780a487e8bf6954c115b9f015822d3bb8e48 \ - --hash=sha256:94d87b689cdd831934fa3ce16cc15cd65748e6d689f5d2b8f4f4df2065c9fa20 \ - --hash=sha256:9714398225f299aa85267fd222f7142fcb5c769e73d7733344efc46f2ef5cf89 \ - --hash=sha256:982e6d21414e78e1f51cf595d7f321dcd14de1f2881c5dc6a6e23bbbbd68435e \ - --hash=sha256:997d6a487ff00807ba810e0f8332c18b4eb8d29463cfb7c820dc4b6e7562d0cf \ - --hash=sha256:a03e02f48cd1abbd9f3b7e3586d97c8f7a9721c436f51a5245b3b9483044480b \ - --hash=sha256:a36fdf2af13c2b14738f6e973aba563623cb77d753bbbd8d414d18bfaa3105dd \ - --hash=sha256:a6ba92c0bcdf96cbf43a12c717eae4bc98325ca3730f6b130ffa2e3c3c723d84 \ - --hash=sha256:a7c2155f790e2fb448faed6dd241386719802296ec588a8b9051c1f5c481bc29 \ - --hash=sha256:a93c194e2df18f7d264092dc8539b8ffb86b45b899ab976aa15d48214138e81b \ - --hash=sha256:abfa5080c374a76a251ba60683242bc17eeb2c9818d0d30117b4486be10c59d3 \ - --hash=sha256:ac10f2c4184420d881a3475fb2c6f4d95d53a8d50209a2500723d831036f7c45 \ - --hash=sha256:ad182d02e40de7459b73155deb8996bbd8e96852267879396fb274e8700190e3 \ - --hash=sha256:b2837718570f95dd41675328e111345f9b7095d821bac435aac173ac80b19983 \ - --hash=sha256:b489578720afb782f6ccf2840920f3a32e31ba28a4b162e13900c3e6bd3f930e \ - --hash=sha256:b583904576650166b3d920d2bcce13971f6f9e9a396c673187f49811b2769dc7 \ - --hash=sha256:b85c2530be953a890eaffde05485238f07029600e8f098cdf1848d414a8b45e4 \ - --hash=sha256:b97c1e0bd37c5cd7902e65f410779d39eeda155800b65fc4d04cc432efa9bc6e \ - --hash=sha256:ba9b72e5643641b7d41fa1f6d5abda2c9a263ae835b917348fc3c928182ad467 \ - --hash=sha256:bb26437975da7dc36b7efad18aa9dd4ea569d2357ae6b783bf1118dabd9ea577 \ - --hash=sha256:bb8f74f2f10dbf13a0be8de623ba4f9491faf58c24064f32b65679b021ed0001 \ - --hash=sha256:bde01f35767c4a7899b7eb6e823b125a64de314a8ee9791367c9a34d56af18d0 \ - --hash=sha256:bec9931dfb61ddd8ef2ebc05646293812cb6b16b60cf7c9511a832b6f1854b55 \ - --hash=sha256:c36f9b6f5f8649bb251a5f3f66564438977b7ef8386a52460ae77e6070d309d9 \ - --hash=sha256:cdf58d0e516ee426a48f7b2c03a332a4114420716d55769ff7108c37a09951bf \ - --hash=sha256:d1cee317bfc014c2419a76bcc87f071405e3966da434e03e13beb45f8aced1a6 \ - --hash=sha256:d22326fcdef5e08c154280b71163ced384b428343ae16a5ab2b3354aed12436e \ - --hash=sha256:d3660c82f209655a06b587d55e723f0b813d3a7db2e32e5e7dc64ac2a9e86fde \ - --hash=sha256:da8f5fc57d1933de22a9e23eec290a0d8a5927a5370d24bda9a6abe50683fe62 \ - --hash=sha256:df951c5f4a1b1910f1a99ff42c473ff60f8225baa1cdd3539fe2819d9543e9df \ - --hash=sha256:e5364a4502efca094731680e80009632ad6624084aff9a23ce8c8c6820de3e51 \ - --hash=sha256:ea1bfda2f7162605f6e8178223576856b3d791109f15ea99a9f95c16a7636fb5 \ - --hash=sha256:f02f93b92358ee3f78660e43b4b0091229260c5d5c408d17d60bf26b6c900e86 \ - --hash=sha256:f056bf21105c2515c32372bbc057f43eb02aae2fda61052e2f7622c801f0b4e2 \ - --hash=sha256:f1ac758ef6aebfc8943560194e9fd0fa18bcb34d89fd8bd2af18183afd8da3a2 \ - --hash=sha256:f2a19f302cd1ce5dd01a9099aaa19cae6173306d1302a43b627f62e21cf18ac0 \ - --hash=sha256:f654882311409afb1d780b940234208a252322c24a93b442ca714d119e68086c \ - --hash=sha256:f65557897fc977a44ab205ea871b690adaef6b9da6afda4790a2484b04293a5f \ - --hash=sha256:f9d1e379028e0fc2ae3654bac3cbbef81bf3fd571272a42d56c24007979bafb6 \ - --hash=sha256:fdabbfc59f2c6edba2a6622c647b716e34e8e3867e0ab975412c5c2f79b82da2 \ - --hash=sha256:fdd6028445d2460f33136c55eeb1f601ab06d74cb3347132e1c24250187500d9 \ - --hash=sha256:ff590880083d60acc0433f9c3f713c51f7ac6ebb9adf889c79a261ecf541aa91 -requests==2.32.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760 \ - --hash=sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6 -rpds-py==0.22.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:009de23c9c9ee54bf11303a966edf4d9087cd43a6003672e6aa7def643d06518 \ - --hash=sha256:02fbb9c288ae08bcb34fb41d516d5eeb0455ac35b5512d03181d755d80810059 \ - --hash=sha256:0a0461200769ab3b9ab7e513f6013b7a97fdeee41c29b9db343f3c5a8e2b9e61 \ - --hash=sha256:0b09865a9abc0ddff4e50b5ef65467cd94176bf1e0004184eb915cbc10fc05c5 \ - --hash=sha256:0b8db6b5b2d4491ad5b6bdc2bc7c017eec108acbf4e6785f42a9eb0ba234f4c9 \ - --hash=sha256:0c150c7a61ed4a4f4955a96626574e9baf1adf772c2fb61ef6a5027e52803543 \ - --hash=sha256:0f3cec041684de9a4684b1572fe28c7267410e02450f4561700ca5a3bc6695a2 \ - --hash=sha256:1352ae4f7c717ae8cba93421a63373e582d19d55d2ee2cbb184344c82d2ae55a \ - --hash=sha256:177c7c0fce2855833819c98e43c262007f42ce86651ffbb84f37883308cb0e7d \ - --hash=sha256:1978d0021e943aae58b9b0b196fb4895a25cc53d3956b8e35e0b7682eefb6d56 \ - --hash=sha256:1a60bce91f81ddaac922a40bbb571a12c1070cb20ebd6d49c48e0b101d87300d \ - --hash=sha256:1aef18820ef3e4587ebe8b3bc9ba6e55892a6d7b93bac6d29d9f631a3b4befbd \ - --hash=sha256:1e9663daaf7a63ceccbbb8e3808fe90415b0757e2abddbfc2e06c857bf8c5e2b \ - --hash=sha256:20070c65396f7373f5df4005862fa162db5d25d56150bddd0b3e8214e8ef45b4 \ - --hash=sha256:214b7a953d73b5e87f0ebece4a32a5bd83c60a3ecc9d4ec8f1dca968a2d91e99 \ - --hash=sha256:22bebe05a9ffc70ebfa127efbc429bc26ec9e9b4ee4d15a740033efda515cf3d \ - --hash=sha256:24e8abb5878e250f2eb0d7859a8e561846f98910326d06c0d51381fed59357bd \ - --hash=sha256:26fd7cac7dd51011a245f29a2cc6489c4608b5a8ce8d75661bb4a1066c52dfbe \ - --hash=sha256:27b1d3b3915a99208fee9ab092b8184c420f2905b7d7feb4aeb5e4a9c509b8a1 \ - --hash=sha256:27e98004595899949bd7a7b34e91fa7c44d7a97c40fcaf1d874168bb652ec67e \ - --hash=sha256:2b8f60e1b739a74bab7e01fcbe3dddd4657ec685caa04681df9d562ef15b625f \ - --hash=sha256:2de29005e11637e7a2361fa151f780ff8eb2543a0da1413bb951e9f14b699ef3 \ - --hash=sha256:2e8b55d8517a2fda8d95cb45d62a5a8bbf9dd0ad39c5b25c8833efea07b880ca \ - --hash=sha256:2fa4331c200c2521512595253f5bb70858b90f750d39b8cbfd67465f8d1b596d \ - --hash=sha256:3445e07bf2e8ecfeef6ef67ac83de670358abf2996916039b16a218e3d95e97e \ - --hash=sha256:3453e8d41fe5f17d1f8e9c383a7473cd46a63661628ec58e07777c2fff7196dc \ - --hash=sha256:378753b4a4de2a7b34063d6f95ae81bfa7b15f2c1a04a9518e8644e81807ebea \ - --hash=sha256:3af6e48651c4e0d2d166dc1b033b7042ea3f871504b6805ba5f4fe31581d8d38 \ - --hash=sha256:3dfcbc95bd7992b16f3f7ba05af8a64ca694331bd24f9157b49dadeeb287493b \ - --hash=sha256:3f21f0495edea7fdbaaa87e633a8689cd285f8f4af5c869f27bc8074638ad69c \ - --hash=sha256:4041711832360a9b75cfb11b25a6a97c8fb49c07b8bd43d0d02b45d0b499a4ff \ - --hash=sha256:44d61b4b7d0c2c9ac019c314e52d7cbda0ae31078aabd0f22e583af3e0d79723 \ - --hash=sha256:4617e1915a539a0d9a9567795023de41a87106522ff83fbfaf1f6baf8e85437e \ - --hash=sha256:4b232061ca880db21fa14defe219840ad9b74b6158adb52ddf0e87bead9e8493 \ - --hash=sha256:5246b14ca64a8675e0a7161f7af68fe3e910e6b90542b4bfb5439ba752191df6 \ - --hash=sha256:5725dd9cc02068996d4438d397e255dcb1df776b7ceea3b9cb972bdb11260a83 \ - --hash=sha256:583f6a1993ca3369e0f80ba99d796d8e6b1a3a2a442dd4e1a79e652116413091 \ - --hash=sha256:59259dc58e57b10e7e18ce02c311804c10c5a793e6568f8af4dead03264584d1 \ - --hash=sha256:593eba61ba0c3baae5bc9be2f5232430453fb4432048de28399ca7376de9c627 \ - --hash=sha256:59f4a79c19232a5774aee369a0c296712ad0e77f24e62cad53160312b1c1eaa1 \ - --hash=sha256:5f0e260eaf54380380ac3808aa4ebe2d8ca28b9087cf411649f96bad6900c728 \ - --hash=sha256:62d9cfcf4948683a18a9aff0ab7e1474d407b7bab2ca03116109f8464698ab16 \ - --hash=sha256:64607d4cbf1b7e3c3c8a14948b99345eda0e161b852e122c6bb71aab6d1d798c \ - --hash=sha256:655ca44a831ecb238d124e0402d98f6212ac527a0ba6c55ca26f616604e60a45 \ - --hash=sha256:666ecce376999bf619756a24ce15bb14c5bfaf04bf00abc7e663ce17c3f34fe7 \ - --hash=sha256:68049202f67380ff9aa52f12e92b1c30115f32e6895cd7198fa2a7961621fc5a \ - --hash=sha256:69803198097467ee7282750acb507fba35ca22cc3b85f16cf45fb01cb9097730 \ - --hash=sha256:6c7b99ca52c2c1752b544e310101b98a659b720b21db00e65edca34483259967 \ - --hash=sha256:6dd9412824c4ce1aca56c47b0991e65bebb7ac3f4edccfd3f156150c96a7bf25 \ - --hash=sha256:70eb60b3ae9245ddea20f8a4190bd79c705a22f8028aaf8bbdebe4716c3fab24 \ - --hash=sha256:70fb28128acbfd264eda9bf47015537ba3fe86e40d046eb2963d75024be4d055 \ - --hash=sha256:7b2513ba235829860b13faa931f3b6846548021846ac808455301c23a101689d \ - --hash=sha256:7ef9d9da710be50ff6809fed8f1963fecdfecc8b86656cadfca3bc24289414b0 \ - --hash=sha256:81e69b0a0e2537f26d73b4e43ad7bc8c8efb39621639b4434b76a3de50c6966e \ - --hash=sha256:8633e471c6207a039eff6aa116e35f69f3156b3989ea3e2d755f7bc41754a4a7 \ - --hash=sha256:8bd7c8cfc0b8247c8799080fbff54e0b9619e17cdfeb0478ba7295d43f635d7c \ - --hash=sha256:9253fc214112405f0afa7db88739294295f0e08466987f1d70e29930262b4c8f \ - --hash=sha256:99b37292234e61325e7a5bb9689e55e48c3f5f603af88b1642666277a81f1fbd \ - --hash=sha256:9bd7228827ec7bb817089e2eb301d907c0d9827a9e558f22f762bb690b131652 \ - --hash=sha256:9beeb01d8c190d7581a4d59522cd3d4b6887040dcfc744af99aa59fef3e041a8 \ - --hash=sha256:a63cbdd98acef6570c62b92a1e43266f9e8b21e699c363c0fef13bd530799c11 \ - --hash=sha256:a76e42402542b1fae59798fab64432b2d015ab9d0c8c47ba7addddbaf7952333 \ - --hash=sha256:ac0a03221cdb5058ce0167ecc92a8c89e8d0decdc9e99a2ec23380793c4dcb96 \ - --hash=sha256:b0b4136a252cadfa1adb705bb81524eee47d9f6aab4f2ee4fa1e9d3cd4581f64 \ - --hash=sha256:b25bc607423935079e05619d7de556c91fb6adeae9d5f80868dde3468657994b \ - --hash=sha256:b3d504047aba448d70cf6fa22e06cb09f7cbd761939fdd47604f5e007675c24e \ - --hash=sha256:bb47271f60660803ad11f4c61b42242b8c1312a31c98c578f79ef9387bbde21c \ - --hash=sha256:bbb232860e3d03d544bc03ac57855cd82ddf19c7a07651a7c0fdb95e9efea8b9 \ - --hash=sha256:bc27863442d388870c1809a87507727b799c8460573cfbb6dc0eeaef5a11b5ec \ - --hash=sha256:bc51abd01f08117283c5ebf64844a35144a0843ff7b2983e0648e4d3d9f10dbb \ - --hash=sha256:be2eb3f2495ba669d2a985f9b426c1797b7d48d6963899276d22f23e33d47e37 \ - --hash=sha256:bf9db5488121b596dbfc6718c76092fda77b703c1f7533a226a5a9f65248f8ad \ - --hash=sha256:c58e2339def52ef6b71b8f36d13c3688ea23fa093353f3a4fee2556e62086ec9 \ - --hash=sha256:cfbc454a2880389dbb9b5b398e50d439e2e58669160f27b60e5eca11f68ae17c \ - --hash=sha256:cff63a0272fcd259dcc3be1657b07c929c466b067ceb1c20060e8d10af56f5bf \ - --hash=sha256:d115bffdd417c6d806ea9069237a4ae02f513b778e3789a359bc5856e0404cc4 \ - --hash=sha256:d20cfb4e099748ea39e6f7b16c91ab057989712d31761d3300d43134e26e165f \ - --hash=sha256:d48424e39c2611ee1b84ad0f44fb3b2b53d473e65de061e3f460fc0be5f1939d \ - --hash=sha256:e0fa2d4ec53dc51cf7d3bb22e0aa0143966119f42a0c3e4998293a3dd2856b09 \ - --hash=sha256:e32fee8ab45d3c2db6da19a5323bc3362237c8b653c70194414b892fd06a080d \ - --hash=sha256:e35ba67d65d49080e8e5a1dd40101fccdd9798adb9b050ff670b7d74fa41c566 \ - --hash=sha256:e3fb866d9932a3d7d0c82da76d816996d1667c44891bd861a0f97ba27e84fc74 \ - --hash=sha256:e61b02c3f7a1e0b75e20c3978f7135fd13cb6cf551bf4a6d29b999a88830a338 \ - --hash=sha256:e67ba3c290821343c192f7eae1d8fd5999ca2dc99994114643e2f2d3e6138b15 \ - --hash=sha256:e79dd39f1e8c3504be0607e5fc6e86bb60fe3584bec8b782578c3b0fde8d932c \ - --hash=sha256:e89391e6d60251560f0a8f4bd32137b077a80d9b7dbe6d5cab1cd80d2746f648 \ - --hash=sha256:ea7433ce7e4bfc3a85654aeb6747babe3f66eaf9a1d0c1e7a4435bbdf27fea84 \ - --hash=sha256:eaf16ae9ae519a0e237a0f528fd9f0197b9bb70f40263ee57ae53c2b8d48aeb3 \ - --hash=sha256:eb0c341fa71df5a4595f9501df4ac5abfb5a09580081dffbd1ddd4654e6e9123 \ - --hash=sha256:f276b245347e6e36526cbd4a266a417796fc531ddf391e43574cf6466c492520 \ - --hash=sha256:f47ad3d5f3258bd7058d2d506852217865afefe6153a36eb4b6928758041d831 \ - --hash=sha256:f56a6b404f74ab372da986d240e2e002769a7d7102cc73eb238a4f72eec5284e \ - --hash=sha256:f5cf2a0c2bdadf3791b5c205d55a37a54025c6e18a71c71f82bb536cf9a454bf \ - --hash=sha256:f5d36399a1b96e1a5fdc91e0522544580dbebeb1f77f27b2b0ab25559e103b8b \ - --hash=sha256:f60bd8423be1d9d833f230fdbccf8f57af322d96bcad6599e5a771b151398eb2 \ - --hash=sha256:f612463ac081803f243ff13cccc648578e2279295048f2a8d5eb430af2bae6e3 \ - --hash=sha256:f73d3fef726b3243a811121de45193c0ca75f6407fe66f3f4e183c983573e130 \ - --hash=sha256:f82a116a1d03628a8ace4859556fb39fd1424c933341a08ea3ed6de1edb0283b \ - --hash=sha256:fb0ba113b4983beac1a2eb16faffd76cb41e176bf58c4afe3e14b9c681f702de \ - --hash=sha256:fb4f868f712b2dd4bcc538b0a0c1f63a2b1d584c925e69a224d759e7070a12d5 \ - --hash=sha256:fb6116dfb8d1925cbdb52595560584db42a7f664617a1f7d7f6e32f138cdf37d \ - --hash=sha256:fda7cb070f442bf80b642cd56483b5548e43d366fe3f39b98e67cce780cded00 \ - --hash=sha256:feea821ee2a9273771bae61194004ee2fc33f8ec7db08117ef9147d4bbcbca8e -six==1.17.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274 \ - --hash=sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81 -sniffio==1.3.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2 \ - --hash=sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc -soupsieve==2.6 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb \ - --hash=sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9 -stack-data==0.6.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9 \ - --hash=sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695 -tiktoken==0.8.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:02be1666096aff7da6cbd7cdaa8e7917bfed3467cd64b38b1f112e96d3b06a24 \ - --hash=sha256:1473cfe584252dc3fa62adceb5b1c763c1874e04511b197da4e6de51d6ce5a02 \ - --hash=sha256:18228d624807d66c87acd8f25fc135665617cab220671eb65b50f5d70fa51f69 \ - --hash=sha256:25e13f37bc4ef2d012731e93e0fef21dc3b7aea5bb9009618de9a4026844e560 \ - --hash=sha256:294440d21a2a51e12d4238e68a5972095534fe9878be57d905c476017bff99fc \ - --hash=sha256:2efaf6199717b4485031b4d6edb94075e4d79177a172f38dd934d911b588d54a \ - --hash=sha256:326624128590def898775b722ccc327e90b073714227175ea8febbc920ac0a99 \ - --hash=sha256:4177faa809bd55f699e88c96d9bb4635d22e3f59d635ba6fd9ffedf7150b9953 \ - --hash=sha256:5376b6f8dc4753cd81ead935c5f518fa0fbe7e133d9e25f648d8c4dabdd4bad7 \ - --hash=sha256:5637e425ce1fc49cf716d88df3092048359a4b3bbb7da762840426e937ada06d \ - --hash=sha256:56edfefe896c8f10aba372ab5706b9e3558e78db39dd497c940b47bf228bc419 \ - --hash=sha256:6adc8323016d7758d6de7313527f755b0fc6c72985b7d9291be5d96d73ecd1e1 \ - --hash=sha256:6b231f5e8982c245ee3065cd84a4712d64692348bc609d84467c57b4b72dcbc5 \ - --hash=sha256:6b2ddbc79a22621ce8b1166afa9f9a888a664a579350dc7c09346a3b5de837d9 \ - --hash=sha256:7e17807445f0cf1f25771c9d86496bd8b5c376f7419912519699f3cc4dc5c12e \ - --hash=sha256:845287b9798e476b4d762c3ebda5102be87ca26e5d2c9854002825d60cdb815d \ - --hash=sha256:881839cfeae051b3628d9823b2e56b5cc93a9e2efb435f4cf15f17dc45f21586 \ - --hash=sha256:886f80bd339578bbdba6ed6d0567a0d5c6cfe198d9e587ba6c447654c65b8edc \ - --hash=sha256:9269348cb650726f44dd3bbb3f9110ac19a8dcc8f54949ad3ef652ca22a38e21 \ - --hash=sha256:9a58deb7075d5b69237a3ff4bb51a726670419db6ea62bdcd8bd80c78497d7ab \ - --hash=sha256:9ccbb2740f24542534369c5635cfd9b2b3c2490754a78ac8831d99f89f94eeb2 \ - --hash=sha256:9fb0e352d1dbe15aba082883058b3cce9e48d33101bdaac1eccf66424feb5b47 \ - --hash=sha256:b07e33283463089c81ef1467180e3e00ab00d46c2c4bbcef0acab5f771d6695e \ - --hash=sha256:b591fb2b30d6a72121a80be24ec7a0e9eb51c5500ddc7e4c2496516dd5e3816b \ - --hash=sha256:c94ff53c5c74b535b2cbf431d907fc13c678bbd009ee633a2aca269a04389f9a \ - --hash=sha256:d2908c0d043a7d03ebd80347266b0e58440bdef5564f84f4d29fb235b5df3b04 \ - --hash=sha256:d622d8011e6d6f239297efa42a2657043aaed06c4f68833550cac9e9bc723ef1 \ - --hash=sha256:d8c2d0e5ba6453a290b86cd65fc51fedf247e1ba170191715b049dac1f628005 \ - --hash=sha256:d8f3192733ac4d77977432947d563d7e1b310b96497acd3c196c9bddb36ed9db \ - --hash=sha256:f13d13c981511331eac0d01a59b5df7c0d4060a8be1e378672822213da51e0a2 \ - --hash=sha256:fe9399bdc3f29d428f16a2f86c3c8ec20be3eac5f53693ce4980371c3245729b -tokenizers==0.21.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:089d56db6782a73a27fd8abf3ba21779f5b85d4a9f35e3b493c7bbcbbf0d539b \ - --hash=sha256:3c4c93eae637e7d2aaae3d376f06085164e1660f89304c0ab2b1d08a406636b2 \ - --hash=sha256:400832c0904f77ce87c40f1a8a27493071282f785724ae62144324f171377273 \ - --hash=sha256:4145505a973116f91bc3ac45988a92e618a6f83eb458f49ea0790df94ee243ff \ - --hash=sha256:6b177fb54c4702ef611de0c069d9169f0004233890e0c4c5bd5508ae05abf193 \ - --hash=sha256:6b43779a269f4629bebb114e19c3fca0223296ae9fea8bb9a7a6c6fb0657ff8e \ - --hash=sha256:87841da5a25a3a5f70c102de371db120f41873b854ba65e52bccd57df5a3780c \ - --hash=sha256:9aeb255802be90acfd363626753fda0064a8df06031012fe7d52fd9a905eb00e \ - --hash=sha256:c87ca3dc48b9b1222d984b6b7490355a6fdb411a2d810f6f05977258400ddb74 \ - --hash=sha256:d8b09dbeb7a8d73ee204a70f94fc06ea0f17dcf0844f16102b9f414f0b7463ba \ - --hash=sha256:e84ca973b3a96894d1707e189c14a774b701596d579ffc7e69debfc036a61a04 \ - --hash=sha256:eb1702c2f27d25d9dd5b389cc1f2f51813e99f8ca30d9e25348db6585a97e24a \ - --hash=sha256:eb7202d231b273c34ec67767378cd04c767e967fda12d4a9e36208a34e2f137e \ - --hash=sha256:ee0894bf311b75b0c03079f33859ae4b2334d675d4e93f5a4132e1eae2834fe4 \ - --hash=sha256:f53ea537c925422a2e0e92a24cce96f6bc5046bbef24a1652a5edc8ba975f62e -tornado==6.4.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:072ce12ada169c5b00b7d92a99ba089447ccc993ea2143c9ede887e0937aa803 \ - --hash=sha256:1a017d239bd1bb0919f72af256a970624241f070496635784d9bf0db640d3fec \ - --hash=sha256:2876cef82e6c5978fde1e0d5b1f919d756968d5b4282418f3146b79b58556482 \ - --hash=sha256:304463bd0772442ff4d0f5149c6f1c2135a1fae045adf070821c6cdc76980634 \ - --hash=sha256:908b71bf3ff37d81073356a5fadcc660eb10c1476ee6e2725588626ce7e5ca38 \ - --hash=sha256:92bad5b4746e9879fd7bf1eb21dce4e3fc5128d71601f80005afa39237ad620b \ - --hash=sha256:932d195ca9015956fa502c6b56af9eb06106140d844a335590c1ec7f5277d10c \ - --hash=sha256:bca9eb02196e789c9cb5c3c7c0f04fb447dc2adffd95265b2c7223a8a615ccbf \ - --hash=sha256:c36e62ce8f63409301537222faffcef7dfc5284f27eec227389f2ad11b09d946 \ - --hash=sha256:c82c46813ba483a385ab2a99caeaedf92585a1f90defb5693351fa7e4ea0bf73 \ - --hash=sha256:e828cce1123e9e44ae2a50a9de3055497ab1d0aeb440c5ac23064d9e44880da1 -tqdm==4.67.1 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:26445eca388f82e72884e0d580d5464cd801a3ea01e63e5601bdff9ba6a48de2 \ - --hash=sha256:f8aef9c52c08c13a65f30ea34f4e5aac3fd1a34959879d7e59e63027286627f2 -traitlets==5.14.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7 \ - --hash=sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f -tree-sitter-c==0.23.4 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:013403e74765d74e523f380f9df8f3d99e9fe94132a3fc0c8b29cba538a7b2bf \ - --hash=sha256:2c92c0571b36b6da06f8882f34151dc11e67a493e9101cc0026a16da27709c05 \ - --hash=sha256:5e42a3519825ca59c91b2b7aec08dd3c89e02690c7b315d54a1e1743f9be3f15 \ - --hash=sha256:9215c7888dd019038f162ea5646178f6e129cd2b49fc506d14becf5e426121d7 \ - --hash=sha256:98c285a23bf4fb6fb34140d6ea0f0d25d0a93e0d93692f9dffe3db6d1fe08534 \ - --hash=sha256:a4d7bdeaca8f1da72352a945853f56aa5d34e7bc22569ec5bda5d7c1a04e5b0f \ - --hash=sha256:c15c7588c3d95872328019073a8d5eaf7c2691b4d4ef0393a0168399b2ad2356 \ - --hash=sha256:edd36e12cc79b8b5bbc81fc336ff7d2577d0fe16afd18163c9aff7ae3ff69e15 -tree-sitter-python==0.23.6 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:28fbec8f74eeb2b30292d97715e60fac9ccf8a8091ce19b9d93e9b580ed280fb \ - --hash=sha256:29dacdc0cd2f64e55e61d96c6906533ebb2791972bec988450c46cce60092f5d \ - --hash=sha256:354bfa0a2f9217431764a631516f85173e9711af2c13dbd796a8815acfe505d9 \ - --hash=sha256:680b710051b144fedf61c95197db0094f2245e82551bf7f0c501356333571f7a \ - --hash=sha256:71334371bd73d5fe080aed39fbff49ed8efb9506edebe16795b0c7567ed6a272 \ - --hash=sha256:7e048733c36f564b379831689006801feb267d8194f9e793fbb395ef1723335d \ - --hash=sha256:8a9dcef55507b6567207e8ee0a6b053d0688019b47ff7f26edc1764b7f4dc0a4 \ - --hash=sha256:a24027248399fb41594b696f929f9956828ae7cc85596d9f775e6c239cd0c2be -tree-sitter==0.23.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:03b70296b569ef64f7b92b42ca5da9bf86d81bee2afd480bea35092687f51dae \ - --hash=sha256:04f8699b131d4bcbe3805c37e4ef3d159ee9a82a0e700587625623999ba0ea53 \ - --hash=sha256:08466953c78ae57be61057188fb88c89791b0a562856010228e0ccf60e2ac453 \ - --hash=sha256:0ff2037be5edab7801de3f6a721b9cf010853f612e2008ee454e0e0badb225a6 \ - --hash=sha256:12b60dca70d2282af942b650a6d781be487485454668c7c956338a367b98cdee \ - --hash=sha256:29224bdc2a3b9af535b7725e249d3ee291b2e90708e82832e73acc175e40dc48 \ - --hash=sha256:2c7eae7fe2af215645a38660d2d57d257a4c461fe3ec827cca99a79478284e80 \ - --hash=sha256:3346a4dd0447a42aabb863443b0fd8c92b909baf40ed2344fae4b94b625d5955 \ - --hash=sha256:3a71d607595270b6870eaf778a1032d146b2aa79bfcfa60f57a82a7b7584a4c7 \ - --hash=sha256:3a937f5d8727bc1c74c4bf2a9d1c25ace049e8628273016ad0d45914ae904e10 \ - --hash=sha256:3ead958df87a21d706903987e665e9e0e5df7b2c5021ff69ea349826840adc6a \ - --hash=sha256:4471577df285059c71686ecb208bc50fb472099b38dcc8e849b0e86652891e87 \ - --hash=sha256:4780ba8f3894f2dea869fad2995c2aceab3fd5ab9e6a27c45475d2acd7f7e84e \ - --hash=sha256:569514b9a996a0fd458b3a891c46ca125298be0c03cf82f2b6f0c13d5d8f25dc \ - --hash=sha256:611cae16be332213c0e6ece72c0bfca202e30ff320a8b309b1526c6cb79ee4ba \ - --hash=sha256:614590611636044e071d3a0b748046d52676dbda3bc9fa431216231e11dd98f7 \ - --hash=sha256:64859bd4aa1567d0d6016a811b2b49c59d4a4427d096e3d8c84b2521455f62b7 \ - --hash=sha256:66bae8dd47f1fed7bdef816115146d3a41c39b5c482d7bad36d9ba1def088450 \ - --hash=sha256:6de18d8d8a7f67ab71f472d1fcb01cc506e080cbb5e13d52929e4b6fdce6bbee \ - --hash=sha256:6fe9b9ea7a0aa23b52fd97354da95d1b2580065bc12a4ac868f9164a127211d6 \ - --hash=sha256:78d070d8eaeaeb36cf535f55e5578fddbfc3bf53c1980f58bf1a99d57466b3b5 \ - --hash=sha256:7cb4bb953ea7c0b50eeafc4454783e030357179d2a93c3dd5ebed2da5588ddd0 \ - --hash=sha256:878580b2ad5054c410ba3418edca4d34c81cc26706114d8f5b5541688bc2d785 \ - --hash=sha256:8a33f03a562de91f7fd05eefcedd8994a06cd44c62f7aabace811ad82bc11cbd \ - --hash=sha256:8caebe65bc358759dac2500d8f8feed3aed939c4ade9a684a1783fe07bc7d5db \ - --hash=sha256:91fda41d4f8824335cc43c64e2c37d8089c8c563bd3900a512d2852d075af719 \ - --hash=sha256:92b2b489d5ce54b41f94c6f23fbaf592bd6e84dc2877048fd1cb060480fa53f7 \ - --hash=sha256:9dbd110a30cf28be5da734ae4cd0e9031768228dbf6a79f2973962aa51de4ec7 \ - --hash=sha256:a014498b6a9e6003fae8c6eb72f5927d62da9dcb72b28b3ce8cd15c6ff6a6572 \ - --hash=sha256:a0320eb6c7993359c5f7b371d22719ccd273f440d41cf1bd65dac5e9587f2046 \ - --hash=sha256:a357ed98a74e47787b812df99a74a2c35c0fe11e55c2095cc01d1cad144ef552 \ - --hash=sha256:a4e9e53d07dd076bede72e4f7d3a0173d7b9ad6576572dd86da008a740a9bb22 \ - --hash=sha256:a5db8e585205faef8bf219da77d8993e2ef04d08eda2e3c8ad7e4df8297ee344 \ - --hash=sha256:b848e0fdd522fbb8888cdb4f4d93f8fad97ae10d70c122fb922e51363c7febcd \ - --hash=sha256:c2dfb8e8f760f4cc67888d03ef9e2dbd3353245f67f5efba375c2a14d944ac0e \ - --hash=sha256:c58d89348162fbc3aea1fe6511a66ee189fc0e4e4bbe937026f29e4ecef17763 \ - --hash=sha256:d74d00a8021719eae14d10d1b1e28649e15d8b958c01c2b2c3dad7a2ebc4dbae \ - --hash=sha256:eff630dddee7ba05accb439b17e559e15ce13f057297007c246237ceb6306332 \ - --hash=sha256:f0b609460b8e3e256361fb12e94fae5b728cb835b16f0f9d590b5aadbf9d109b \ - --hash=sha256:f342c925290dd4e20ecd5787ef7ae8749981597ab364783a1eb73173efe65226 \ - --hash=sha256:fc5a72eb50d43485000dbbb309acb350467b7467e66dc747c6bb82ce63041582 -typing-extensions==4.12.2 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d \ - --hash=sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8 -urllib3==2.3.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:1cee9ad369867bfdbbb48b7dd50374c0967a0bb7710050facf0dd6911440e3df \ - --hash=sha256:f8c5449b3cf0861679ce7e0503c7b44b5ec981bec0d1d3795a07f1ba96f0204d -validators==0.34.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:647fe407b45af9a74d245b943b18e6a816acf4926974278f6dd617778e1e781f \ - --hash=sha256:c804b476e3e6d3786fa07a30073a4ef694e617805eb1946ceee3fe5a9b8b1321 -wcwidth==0.2.13 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859 \ - --hash=sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5 -werkzeug==3.1.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:54b78bf3716d19a65be4fceccc0d1d7b89e608834989dfae50ea87564639213e \ - --hash=sha256:60723ce945c19328679790e3282cc758aa4a6040e4bb330f53d30fa546d44746 -yarl==1.18.3 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:00e5a1fea0fd4f5bfa7440a47eff01d9822a65b4488f7cff83155a0f31a2ecba \ - --hash=sha256:02ddb6756f8f4517a2d5e99d8b2f272488e18dd0bfbc802f31c16c6c20f22193 \ - --hash=sha256:045b8482ce9483ada4f3f23b3774f4e1bf4f23a2d5c912ed5170f68efb053318 \ - --hash=sha256:09c7907c8548bcd6ab860e5f513e727c53b4a714f459b084f6580b49fa1b9cee \ - --hash=sha256:0b0cad37311123211dc91eadcb322ef4d4a66008d3e1bdc404808992260e1a0e \ - --hash=sha256:0b3c92fa08759dbf12b3a59579a4096ba9af8dd344d9a813fc7f5070d86bbab1 \ - --hash=sha256:0fb2171a4486bb075316ee754c6d8382ea6eb8b399d4ec62fde2b591f879778a \ - --hash=sha256:1a74a13a4c857a84a845505fd2d68e54826a2cd01935a96efb1e9d86c728e186 \ - --hash=sha256:1d407181cfa6e70077df3377938c08012d18893f9f20e92f7d2f314a437c30b1 \ - --hash=sha256:1dd4bdd05407ced96fed3d7f25dbbf88d2ffb045a0db60dbc247f5b3c5c25d50 \ - --hash=sha256:25b411eddcfd56a2f0cd6a384e9f4f7aa3efee14b188de13048c25b5e91f1640 \ - --hash=sha256:2d06d3005e668744e11ed80812e61efd77d70bb7f03e33c1598c301eea20efbb \ - --hash=sha256:2ec9bbba33b2d00999af4631a3397d1fd78290c48e2a3e52d8dd72db3a067ac8 \ - --hash=sha256:3236da9272872443f81fedc389bace88408f64f89f75d1bdb2256069a8730ccc \ - --hash=sha256:35098b24e0327fc4ebdc8ffe336cee0a87a700c24ffed13161af80124b7dc8e5 \ - --hash=sha256:41f7ce59d6ee7741af71d82020346af364949314ed3d87553763a2df1829cc58 \ - --hash=sha256:436c4fc0a4d66b2badc6c5fc5ef4e47bb10e4fd9bf0c79524ac719a01f3607c2 \ - --hash=sha256:4891ed92157e5430874dad17b15eb1fda57627710756c27422200c52d8a4e393 \ - --hash=sha256:4ac515b860c36becb81bb84b667466885096b5fc85596948548b667da3bf9f24 \ - --hash=sha256:5094d9206c64181d0f6e76ebd8fb2f8fe274950a63890ee9e0ebfd58bf9d787b \ - --hash=sha256:54d6921f07555713b9300bee9c50fb46e57e2e639027089b1d795ecd9f7fa910 \ - --hash=sha256:578e281c393af575879990861823ef19d66e2b1d0098414855dd367e234f5b3c \ - --hash=sha256:5a3f356548e34a70b0172d8890006c37be92995f62d95a07b4a42e90fba54272 \ - --hash=sha256:602d98f2c2d929f8e697ed274fbadc09902c4025c5a9963bf4e9edfc3ab6f7ed \ - --hash=sha256:61b1a825a13bef4a5f10b1885245377d3cd0bf87cba068e1d9a88c2ae36880e1 \ - --hash=sha256:61e5e68cb65ac8f547f6b5ef933f510134a6bf31bb178be428994b0cb46c2a04 \ - --hash=sha256:61ee62ead9b68b9123ec24bc866cbef297dd266175d53296e2db5e7f797f902d \ - --hash=sha256:6333c5a377c8e2f5fae35e7b8f145c617b02c939d04110c76f29ee3676b5f9a5 \ - --hash=sha256:6748dbf9bfa5ba1afcc7556b71cda0d7ce5f24768043a02a58846e4a443d808d \ - --hash=sha256:67a283dd2882ac98cc6318384f565bffc751ab564605959df4752d42483ad889 \ - --hash=sha256:75674776d96d7b851b6498f17824ba17849d790a44d282929c42dbb77d4f17ae \ - --hash=sha256:757e81cae69244257d125ff31663249b3013b5dc0a8520d73694aed497fb195b \ - --hash=sha256:77a6e85b90a7641d2e07184df5557132a337f136250caafc9ccaa4a2a998ca2c \ - --hash=sha256:7c33dd1931a95e5d9a772d0ac5e44cac8957eaf58e3c8da8c1414de7dd27c576 \ - --hash=sha256:7df647e8edd71f000a5208fe6ff8c382a1de8edfbccdbbfe649d263de07d8c34 \ - --hash=sha256:7e2ee16578af3b52ac2f334c3b1f92262f47e02cc6193c598502bd46f5cd1477 \ - --hash=sha256:80316a8bd5109320d38eef8833ccf5f89608c9107d02d2a7f985f98ed6876990 \ - --hash=sha256:82123d0c954dc58db301f5021a01854a85bf1f3bb7d12ae0c01afc414a882ca2 \ - --hash=sha256:84b2deecba4a3f1a398df819151eb72d29bfeb3b69abb145a00ddc8d30094512 \ - --hash=sha256:8503ad47387b8ebd39cbbbdf0bf113e17330ffd339ba1144074da24c545f0069 \ - --hash=sha256:877d209b6aebeb5b16c42cbb377f5f94d9e556626b1bfff66d7b0d115be88d0a \ - --hash=sha256:8874027a53e3aea659a6d62751800cf6e63314c160fd607489ba5c2edd753cf6 \ - --hash=sha256:88a19f62ff30117e706ebc9090b8ecc79aeb77d0b1f5ec10d2d27a12bc9f66d0 \ - --hash=sha256:8d39d351e7faf01483cc7ff7c0213c412e38e5a340238826be7e0e4da450fdc8 \ - --hash=sha256:90adb47ad432332d4f0bc28f83a5963f426ce9a1a8809f5e584e704b82685dcb \ - --hash=sha256:913829534200eb0f789d45349e55203a091f45c37a2674678744ae52fae23efa \ - --hash=sha256:93b2e109287f93db79210f86deb6b9bbb81ac32fc97236b16f7433db7fc437d8 \ - --hash=sha256:9d41beda9dc97ca9ab0b9888cb71f7539124bc05df02c0cff6e5acc5a19dcc6e \ - --hash=sha256:a440a2a624683108a1b454705ecd7afc1c3438a08e890a1513d468671d90a04e \ - --hash=sha256:a4bb030cf46a434ec0225bddbebd4b89e6471814ca851abb8696170adb163985 \ - --hash=sha256:a9ca04806f3be0ac6d558fffc2fdf8fcef767e0489d2684a21912cc4ed0cd1b8 \ - --hash=sha256:ac1801c45cbf77b6c99242eeff4fffb5e4e73a800b5c4ad4fc0be5def634d2e1 \ - --hash=sha256:ac36703a585e0929b032fbaab0707b75dc12703766d0b53486eabd5139ebadd5 \ - --hash=sha256:b1771de9944d875f1b98a745bc547e684b863abf8f8287da8466cf470ef52690 \ - --hash=sha256:b464c4ab4bfcb41e3bfd3f1c26600d038376c2de3297760dfe064d2cb7ea8e10 \ - --hash=sha256:b4f6450109834af88cb4cc5ecddfc5380ebb9c228695afc11915a0bf82116789 \ - --hash=sha256:b57f4f58099328dfb26c6a771d09fb20dbbae81d20cfb66141251ea063bd101b \ - --hash=sha256:b643562c12680b01e17239be267bc306bbc6aac1f34f6444d1bded0c5ce438ca \ - --hash=sha256:b958ddd075ddba5b09bb0be8a6d9906d2ce933aee81100db289badbeb966f54e \ - --hash=sha256:b9d60031cf568c627d028239693fd718025719c02c9f55df0a53e587aab951b5 \ - --hash=sha256:ba23302c0c61a9999784e73809427c9dbedd79f66a13d84ad1b1943802eaaf59 \ - --hash=sha256:ba87babd629f8af77f557b61e49e7c7cac36f22f871156b91e10a6e9d4f829e9 \ - --hash=sha256:c017a3b6df3a1bd45b9fa49a0f54005e53fbcad16633870104b66fa1a30a29d8 \ - --hash=sha256:c1e1cc06da1491e6734f0ea1e6294ce00792193c463350626571c287c9a704db \ - --hash=sha256:c654d5207c78e0bd6d749f6dae1dcbbfde3403ad3a4b11f3c5544d9906969dde \ - --hash=sha256:c69697d3adff5aa4f874b19c0e4ed65180ceed6318ec856ebc423aa5850d84f7 \ - --hash=sha256:c7d79f7d9aabd6011004e33b22bc13056a3e3fb54794d138af57f5ee9d9032cb \ - --hash=sha256:ccaa3a4b521b780a7e771cc336a2dba389a0861592bbce09a476190bb0c8b4b3 \ - --hash=sha256:ccd17349166b1bee6e529b4add61727d3f55edb7babbe4069b5764c9587a8cc6 \ - --hash=sha256:ce1af883b94304f493698b00d0f006d56aea98aeb49d75ec7d98cd4a777e9285 \ - --hash=sha256:d0e883008013c0e4aef84dcfe2a0b172c4d23c2669412cf5b3371003941f72bb \ - --hash=sha256:d980e0325b6eddc81331d3f4551e2a333999fb176fd153e075c6d1c2530aa8a8 \ - --hash=sha256:e17c9361d46a4d5addf777c6dd5eab0715a7684c2f11b88c67ac37edfba6c482 \ - --hash=sha256:e2c08cc9b16f4f4bc522771d96734c7901e7ebef70c6c5c35dd0f10845270bcd \ - --hash=sha256:e35ef8683211db69ffe129a25d5634319a677570ab6b2eba4afa860f54eeaf75 \ - --hash=sha256:e3b9fd71836999aad54084906f8663dffcd2a7fb5cdafd6c37713b2e72be1760 \ - --hash=sha256:ef9f7768395923c3039055c14334ba4d926f3baf7b776c923c93d80195624782 \ - --hash=sha256:f52a265001d830bc425f82ca9eabda94a64a4d753b07d623a9f2863fde532b53 \ - --hash=sha256:f91c4803173928a25e1a55b943c81f55b8872f0018be83e3ad4938adffb77dd2 \ - --hash=sha256:fbd6748e8ab9b41171bb95c6142faf068f5ef1511935a0aa07025438dd9a9bc1 \ - --hash=sha256:fe57328fbc1bfd0bd0514470ac692630f3901c0ee39052ae47acd1d90a436719 \ - --hash=sha256:fea09ca13323376a2fdfb353a5fa2e59f90cd18d7ca4eaa1fd31f0a8b4f91e62 -zipp==3.21.0 ; python_version >= "3.9" and python_version < "4.0" \ - --hash=sha256:2c9958f6430a2040341a52eb608ed6dd93ef4392e02ffe219417c1b28b5dd1f4 \ - --hash=sha256:ac1bbe05fd2991f160ebce24ffbac5f6d11d83dc90891255885223d42b3cd931 +aiohappyeyeballs==2.4.4 ; python_version >= "3.10" and python_version < "4.0" +aiohttp==3.11.11 ; python_version >= "3.10" and python_version < "4.0" +aiosignal==1.3.2 ; python_version >= "3.10" and python_version < "4.0" +annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "4.0" +anyio==4.8.0 ; python_version >= "3.10" and python_version < "4.0" +appnope==0.1.4 ; python_version >= "3.10" and python_version < "4.0" and platform_system == "Darwin" +asttokens==3.0.0 ; python_version >= "3.10" and python_version < "4.0" +async-timeout==5.0.1 ; python_version >= "3.10" and python_full_version < "3.11.3" +attrs==25.1.0 ; python_version >= "3.10" and python_version < "4.0" +backoff==2.2.1 ; python_version >= "3.10" and python_version < "4.0" +beautifulsoup4==4.12.3 ; python_version >= "3.10" and python_version < "4.0" +blinker==1.9.0 ; python_version >= "3.10" and python_version < "4.0" +bs4==0.0.2 ; python_version >= "3.10" and python_version < "4.0" +cattrs==24.1.2 ; python_version >= "3.10" and python_version < "4.0" +certifi==2024.12.14 ; python_version >= "3.10" and python_version < "4.0" +cffi==1.17.1 ; python_version >= "3.10" and python_version < "4.0" and implementation_name == "pypy" +charset-normalizer==3.4.1 ; python_version >= "3.10" and python_version < "4.0" +click==8.1.8 ; python_version >= "3.10" and python_version < "4.0" +colorama==0.4.6 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" or python_version >= "3.10" and python_version < "4.0" and platform_system == "Windows" +comm==0.2.2 ; python_version >= "3.10" and python_version < "4.0" +ct3==3.4.0 ; python_version >= "3.10" and python_version < "4.0" +debugpy==1.8.12 ; python_version >= "3.10" and python_version < "4.0" +decorator==5.1.1 ; python_version >= "3.10" and python_version < "4.0" +distro==1.9.0 ; python_version >= "3.10" and python_version < "4.0" +docstring-to-markdown==0.15 ; python_version >= "3.10" and python_version < "4.0" +exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11" +executing==2.2.0 ; python_version >= "3.10" and python_version < "4.0" +falkordb==1.0.10 ; python_version >= "3.10" and python_version < "4.0" +filelock==3.17.0 ; python_version >= "3.10" and python_version < "4.0" +fix-busted-json==0.0.18 ; python_version >= "3.10" and python_version < "4.0" +flask==3.1.0 ; python_version >= "3.10" and python_version < "4.0" +frozenlist==1.5.0 ; python_version >= "3.10" and python_version < "4.0" +fsspec==2024.12.0 ; python_version >= "3.10" and python_version < "4.0" +gitdb==4.0.12 ; python_version >= "3.10" and python_version < "4.0" +gitpython==3.1.44 ; python_version >= "3.10" and python_version < "4.0" +graphrag-sdk==0.5.0 ; python_version >= "3.10" and python_version < "4.0" +h11==0.14.0 ; python_version >= "3.10" and python_version < "4.0" +httpcore==1.0.7 ; python_version >= "3.10" and python_version < "4.0" +httpx==0.27.2 ; python_version >= "3.10" and python_version < "4.0" +huggingface-hub==0.28.0 ; python_version >= "3.10" and python_version < "4.0" +idna==3.10 ; python_version >= "3.10" and python_version < "4.0" +importlib-metadata==8.6.1 ; python_version >= "3.10" and python_version < "4.0" +ipykernel==6.29.5 ; python_version >= "3.10" and python_version < "4.0" +ipython==8.31.0 ; python_version >= "3.10" and python_version < "4.0" +itsdangerous==2.2.0 ; python_version >= "3.10" and python_version < "4.0" +javatools==1.6.0 ; python_version >= "3.10" and python_version < "4.0" +jedi-language-server==0.41.1 ; python_version >= "3.10" and python_version < "4.0" +jedi==0.19.2 ; python_version >= "3.10" and python_version < "4.0" +jinja2==3.1.5 ; python_version >= "3.10" and python_version < "4.0" +jiter==0.8.2 ; python_version >= "3.10" and python_version < "4.0" +jsonschema-specifications==2024.10.1 ; python_version >= "3.10" and python_version < "4.0" +jsonschema==4.23.0 ; python_version >= "3.10" and python_version < "4.0" +jupyter-client==8.6.3 ; python_version >= "3.10" and python_version < "4.0" +jupyter-core==5.7.2 ; python_version >= "3.10" and python_version < "4.0" +litellm==1.59.9 ; python_version >= "3.10" and python_version < "4.0" +lsprotocol==2023.0.1 ; python_version >= "3.10" and python_version < "4.0" +markupsafe==3.0.2 ; python_version >= "3.10" and python_version < "4.0" +matplotlib-inline==0.1.7 ; python_version >= "3.10" and python_version < "4.0" +multidict==6.1.0 ; python_version >= "3.10" and python_version < "4.0" +multilspy @ git+https://github.com/AviAvni/multilspy.git@77249c40e62be7fdb7afc62b3985dff686b6c7c3 ; python_version >= "3.10" and python_version < "4.0" +nest-asyncio==1.6.0 ; python_version >= "3.10" and python_version < "4.0" +ollama==0.2.1 ; python_version >= "3.10" and python_version < "4.0" +openai==1.60.2 ; python_version >= "3.10" and python_version < "4.0" +packaging==24.2 ; python_version >= "3.10" and python_version < "4.0" +parso==0.8.4 ; python_version >= "3.10" and python_version < "4.0" +pexpect==4.9.0 ; python_version >= "3.10" and python_version < "4.0" and (sys_platform != "win32" and sys_platform != "emscripten") +platformdirs==4.3.6 ; python_version >= "3.10" and python_version < "4.0" +prompt-toolkit==3.0.50 ; python_version >= "3.10" and python_version < "4.0" +propcache==0.2.1 ; python_version >= "3.10" and python_version < "4.0" +psutil==6.1.1 ; python_version >= "3.10" and python_version < "4.0" +ptyprocess==0.7.0 ; python_version >= "3.10" and python_version < "4.0" and (sys_platform != "win32" and sys_platform != "emscripten") +pure-eval==0.2.3 ; python_version >= "3.10" and python_version < "4.0" +pycparser==2.22 ; python_version >= "3.10" and python_version < "4.0" and implementation_name == "pypy" +pydantic-core==2.27.2 ; python_version >= "3.10" and python_version < "4.0" +pydantic==2.10.6 ; python_version >= "3.10" and python_version < "4.0" +pygls==1.3.1 ; python_version >= "3.10" and python_version < "4.0" +pygments==2.19.1 ; python_version >= "3.10" and python_version < "4.0" +pypdf==4.3.1 ; python_version >= "3.10" and python_version < "4.0" +python-abc==0.2.0 ; python_version >= "3.10" and python_version < "4.0" +python-dateutil==2.9.0.post0 ; python_version >= "3.10" and python_version < "4.0" +python-dotenv==1.0.1 ; python_version >= "3.10" and python_version < "4.0" +pywin32==308 ; python_version >= "3.10" and python_version < "4.0" and sys_platform == "win32" and platform_python_implementation != "PyPy" +pyyaml==6.0.2 ; python_version >= "3.10" and python_version < "4.0" +pyzmq==26.2.0 ; python_version >= "3.10" and python_version < "4.0" +ratelimit==2.2.1 ; python_version >= "3.10" and python_version < "4.0" +redis==5.2.1 ; python_version >= "3.10" and python_version < "4.0" +referencing==0.36.2 ; python_version >= "3.10" and python_version < "4.0" +regex==2024.11.6 ; python_version >= "3.10" and python_version < "4.0" +requests==2.32.3 ; python_version >= "3.10" and python_version < "4.0" +rpds-py==0.22.3 ; python_version >= "3.10" and python_version < "4.0" +six==1.17.0 ; python_version >= "3.10" and python_version < "4.0" +smmap==5.0.2 ; python_version >= "3.10" and python_version < "4.0" +sniffio==1.3.1 ; python_version >= "3.10" and python_version < "4.0" +soupsieve==2.6 ; python_version >= "3.10" and python_version < "4.0" +stack-data==0.6.3 ; python_version >= "3.10" and python_version < "4.0" +tiktoken==0.8.0 ; python_version >= "3.10" and python_version < "4.0" +tokenizers==0.21.0 ; python_version >= "3.10" and python_version < "4.0" +tornado==6.4.2 ; python_version >= "3.10" and python_version < "4.0" +tqdm==4.67.1 ; python_version >= "3.10" and python_version < "4.0" +traitlets==5.14.3 ; python_version >= "3.10" and python_version < "4.0" +tree-sitter-c==0.23.4 ; python_version >= "3.10" and python_version < "4.0" +tree-sitter-java==0.23.5 ; python_version >= "3.10" and python_version < "4.0" +tree-sitter-python==0.23.6 ; python_version >= "3.10" and python_version < "4.0" +tree-sitter==0.24.0 ; python_version >= "3.10" and python_version < "4.0" +typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "4.0" +urllib3==2.3.0 ; python_version >= "3.10" and python_version < "4.0" +validators==0.34.0 ; python_version >= "3.10" and python_version < "4.0" +wcwidth==0.2.13 ; python_version >= "3.10" and python_version < "4.0" +werkzeug==3.1.3 ; python_version >= "3.10" and python_version < "4.0" +yarl==1.18.3 ; python_version >= "3.10" and python_version < "4.0" +zipp==3.21.0 ; python_version >= "3.10" and python_version < "4.0" diff --git a/tests/test_c_analyzer.py b/tests/test_c_analyzer.py index 76b19bf..ac7f90b 100644 --- a/tests/test_c_analyzer.py +++ b/tests/test_c_analyzer.py @@ -21,7 +21,7 @@ def test_analyzer(self): path = str(path) g = Graph("c") - analyzer.analyze(path, g) + analyzer.analyze_local_folder(path, g) f = g.get_file('', 'src.c', '.c') self.assertEqual(File('', 'src.c', '.c'), f) diff --git a/tests/test_py_analyzer.py b/tests/test_py_analyzer.py index 13e1630..f0040a0 100644 --- a/tests/test_py_analyzer.py +++ b/tests/test_py_analyzer.py @@ -21,7 +21,7 @@ def test_analyzer(self): path = str(path) g = Graph("py") - analyzer.analyze(path, g) + analyzer.analyze_local_folder(path, g) f = g.get_file('', 'src.py', '.py') self.assertEqual(File('', 'src.py', '.py'), f)