diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index c896a363a..57c097dec 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,8 +4,18 @@ permissions: write-all on: pull_request: + paths: + - compass/** + - .github/workflows/docs.yml + - pyproject.toml + - pixi.lock push: branches: [main] + paths: + - compass/** + - .github/workflows/docs.yml + - pyproject.toml + - pixi.lock release: types: [created, published] workflow_dispatch: @@ -26,15 +36,11 @@ jobs: with: pixi-version: v0.50.2 locked: true - cache: false + cache: false # Don't use cache because we use the ``pdoc`` environment environments: pdoc - name: Build Docs - # Make documentation with warnings as errors. - # The stricter Sphinx options below are currently disabled due to known documentation warnings. - # Once all warnings are resolved, consider enabling this line to catch documentation issues early. - # run: SPHINXOPTS="-W --keep-going -n" pixi run -e pdoc make-html - run: pixi run -e pdoc make-html + run: pixi run -e pdoc python-doc # This errors on warnings - name: deploy uses: peaceiris/actions-gh-pages@v4.0.0 diff --git a/.github/workflows/lint-python.yml b/.github/workflows/lint-python.yml index 83f4c53cd..6956405f8 100644 --- a/.github/workflows/lint-python.yml +++ b/.github/workflows/lint-python.yml @@ -6,13 +6,15 @@ on: - 'gh-pages' paths: - compass/** - - pyproject.toml - .github/workflows/lint-python.yml + - pyproject.toml + - pixi.lock pull_request: paths: - compass/** - - pyproject.toml - .github/workflows/lint-python.yml + - pyproject.toml + - pixi.lock jobs: lint: diff --git a/compass/common/base.py b/compass/common/base.py index 45fe91031..81f8cac31 100644 --- a/compass/common/base.py +++ b/compass/common/base.py @@ -66,7 +66,7 @@ def setup_graph_no_nodes(d_tree_name="Unknown Decision Tree", **kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph with no nodes but with global keywords set. """ feat = kwargs.get("feature_id", kwargs.get("feature", kwargs.get("url"))) @@ -180,7 +180,7 @@ def setup_base_setback_graph(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -256,7 +256,7 @@ def setup_participating_owner(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -373,7 +373,7 @@ def setup_graph_extra_restriction(is_numerical=True, **kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -762,7 +762,7 @@ def setup_graph_permitted_use_districts(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -858,6 +858,7 @@ class BaseTextExtractor: "the relevant content appears within a table, return the entire " "table, including headers and footers, exactly as formatted." ) + """System message for text extraction LLM calls""" _USAGE_LABEL = LLMUsageCategory.DOCUMENT_ORDINANCE_SUMMARY def __init__(self, llm_caller): @@ -865,7 +866,7 @@ def __init__(self, llm_caller): Parameters ---------- - llm_caller : compass.llm.LLMCaller + llm_caller : LLMCaller LLM Caller instance used to extract ordinance info with. """ self.llm_caller = llm_caller diff --git a/compass/common/tree.py b/compass/common/tree.py index 90b31f353..2d948cb45 100644 --- a/compass/common/tree.py +++ b/compass/common/tree.py @@ -31,8 +31,7 @@ class AsyncDecisionTree(DecisionTree): graph. Key Relationships: Inherits from :class:`~elm.tree.DecisionTree` to add ``async`` - capabilities. Uses a - :class:`~compass.llm.calling.ChatLLMCaller` for LLm queries. + capabilities. Uses a ChatLLMCaller for LLm queries. """ def __init__(self, graph, usage_sub_label=None): @@ -40,7 +39,7 @@ def __init__(self, graph, usage_sub_label=None): Parameters ---------- - graph : nx.DiGraph + graph : networkx.DiGraph Directed acyclic graph where nodes are LLM prompts and edges are logical transitions based on the response. Must have high-level graph attribute "chat_llm_caller" which is a @@ -138,7 +137,7 @@ async def async_run(self, node0="init"): Returns ------- - out : str | None + out : str or None Final response from LLM at the leaf node or ``None`` if an ``AttributeError`` was raised during execution. """ diff --git a/compass/extraction/apply.py b/compass/extraction/apply.py index a585b89d2..ccf0866d8 100644 --- a/compass/extraction/apply.py +++ b/compass/extraction/apply.py @@ -32,20 +32,19 @@ async def check_for_ordinance_info( Parameters ---------- doc : elm.web.document.BaseDocument - A document potentially containing ordinance information. Note - that if the document's attrs contains the - ``"contains_ord_info"`` key, it will not be processed. To force - a document to be processed by this function, remove that key - from the documents attrs. + A document instance (PDF, HTML, etc) potentially containing + ordinance information. Note that if the document's ``attrs`` + has the ``"contains_ord_info"`` key, it will not be processed. + To force a document to be processed by this function, remove + that key from the documents ``attrs``. tech : str Technology of interest (e.g. "solar", "wind", etc). This is used to set up some document validation decision trees. - text_splitter : obj - Instance of an object that implements a `split_text` method. - The method should take text as input (str) and return a list - of text chunks. Langchain's text splitters should work for this - input. - usage_tracker : compass.services.usage.UsageTracker, optional + text_splitter : LCTextSplitter, optional + Optional Langchain text splitter (or subclass instance), or any + object that implements a `split_text` method. The method should + take text as input (str) and return a list of text chunks. + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. @@ -131,7 +130,7 @@ async def extract_date(doc, model_config, usage_tracker=None): ---------- doc : elm.web.document.BaseDocument A document potentially containing date information. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. @@ -165,20 +164,17 @@ async def extract_ordinance_text_with_llm( doc : elm.web.document.BaseDocument A document known to contain ordinance information. This means it must contain an ``"ordinance_text"`` key in the attrs. You can - run :func:`~compass.extraction.apply.check_for_ordinance_info` + run :func:`check_for_ordinance_info` to have this attribute populated automatically for documents that are found to contain ordinance data. Note that if the document's attrs does not contain the ``"ordinance_text"`` key, you will get an error. - text_splitter : obj - Instance of an object that implements a `split_text` method. - The method should take text as input (str) and return a list - of text chunks. Langchain's text splitters should work for this - input. - extractor : compass.extraction.ordinance.WindOrdinanceTextExtractor - Instance of - :class:`~compass.extraction.ordinance.WindOrdinanceTextExtractor` - used for ordinance text extraction. + text_splitter : LCTextSplitter, optional + Optional Langchain text splitter (or subclass instance), or any + object that implements a `split_text` method. The method should + take text as input (str) and return a list of text chunks. + extractor : WindOrdinanceTextExtractor + Object used for ordinance text extraction. original_text_key : str String corresponding to the `doc.attrs` key containing the original text (before extraction). @@ -237,11 +233,10 @@ async def extract_ordinance_text_with_ngram_validation( that are found to contain ordinance data. Note that if the document's attrs does not contain the ``"ordinance_text"`` key, it will not be processed. - text_splitter : obj - Instance of an object that implements a `split_text` method. - The method should take text as input (str) and return a list - of text chunks. Langchain's text splitters should work for this - input. + text_splitter : LCTextSplitter, optional + Optional Langchain text splitter (or subclass instance), or any + object that implements a `split_text` method. The method should + take text as input (str) and return a list of text chunks. original_text_key : str String corresponding to the `doc.attrs` key containing the original text (before extraction). diff --git a/compass/extraction/date.py b/compass/extraction/date.py index 66240e0e4..8c01d4176 100644 --- a/compass/extraction/date.py +++ b/compass/extraction/date.py @@ -35,20 +35,19 @@ class DateExtractor: "if you are confident that they represent the latest date this " "ordinance was enacted/updated" ) + """System message for date extraction LLM calls""" def __init__(self, structured_llm_caller, text_splitter=None): """ Parameters ---------- - structured_llm_caller : compass.llm.StructuredLLMCaller - StructuredLLMCaller instance. Used for structured validation - queries. - text_splitter : TextSplitter, optional - Optional - :class:`langchain_text_splitters.character.TextSplitter` - text splitter instance to attach to doc (used for - splitting out pages in an HTML document). + structured_llm_caller : StructuredLLMCaller + Instance used for structured validation queries. + text_splitter : LCTextSplitter, optional + Optional text splitter (or subclass instance, or any object + that implements a `split_text` method) to attach to doc + (used for splitting out pages in an HTML document). By default, ``None``. """ self.slc = structured_llm_caller diff --git a/compass/extraction/features.py b/compass/extraction/features.py index 7eefc1538..b3e479e71 100644 --- a/compass/extraction/features.py +++ b/compass/extraction/features.py @@ -33,6 +33,7 @@ class SetbackFeatures: ], "water": ["lakes", "reservoirs", "streams", "rivers", "wetlands"], } + """Aliases for mutually-exclusive setback features""" FEATURES_AS_IGNORE = { "structures": "structures", "property line": "property lines", @@ -41,6 +42,7 @@ class SetbackFeatures: "transmission": "transmission lines", "water": "wetlands", } + """Features as they should appear in ignore phrases""" FEATURE_CLARIFICATIONS = { "structures": "", "property line": ( @@ -54,6 +56,7 @@ class SetbackFeatures: "transmission": "", "water": "", } + """Clarifications to add to feature prompts""" def __init__(self): self._validate_descriptions() diff --git a/compass/extraction/solar/graphs.py b/compass/extraction/solar/graphs.py index ca6555194..15625750c 100644 --- a/compass/extraction/solar/graphs.py +++ b/compass/extraction/solar/graphs.py @@ -18,7 +18,7 @@ def setup_graph_sef_types(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -156,7 +156,7 @@ def setup_multiplier(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ diff --git a/compass/extraction/solar/ordinance.py b/compass/extraction/solar/ordinance.py index 6a9f6de8e..9090beb82 100644 --- a/compass/extraction/solar/ordinance.py +++ b/compass/extraction/solar/ordinance.py @@ -58,8 +58,11 @@ class SolarHeuristic(Heuristic): "solar data", "solar resource", ] + """Words and phrases that indicate text is NOT about solar farms""" GOOD_TECH_KEYWORDS = ["solar", "setback"] + """Words that indicate we should keep a chunk for analysis""" GOOD_TECH_ACRONYMS = ["secs", "sef", "ses", "cses"] + """Acronyms for solar farms that we want to capture""" GOOD_TECH_PHRASES = [ "commercial solar energy system", "solar energy conversion", @@ -69,6 +72,7 @@ class SolarHeuristic(Heuristic): "solar energy farm", "utility solar energy system", ] + """Phrases that indicate text is about solar farms""" class SolarOrdinanceTextCollector(StructuredLLMCaller): @@ -91,6 +95,7 @@ class SolarOrdinanceTextCollector(StructuredLLMCaller): "that is set to True if the text excerpt explicitly details " f"{_SEARCH_TERMS_OR} for a solar energy system and False otherwise." ) + """Prompt to check if chunk contains SEF ordinance info""" IS_UTILITY_SCALE_PROMPT = ( "You are a legal scholar that reads ordinance text and determines " @@ -109,17 +114,9 @@ class SolarOrdinanceTextCollector(StructuredLLMCaller): "energy conversion systems** (or similar) that the client is " "interested in and False otherwise." ) + """Prompt to check if chunk is for utility-scale SEF""" def __init__(self, *args, **kwargs): - """ - - Parameters - ---------- - *args, **kwargs - Parameters to pass to the - :class:`~compass.llm.calling.StructuredLLMCaller` - initializer. - """ super().__init__(*args, **kwargs) self._ordinance_chunks = {} @@ -129,8 +126,7 @@ async def check_chunk(self, chunk_parser, ind): Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains a - `parse_from_ind` method. + Instance that contains a ``parse_from_ind`` method. ind : int Index of the chunk to check. @@ -232,17 +228,9 @@ class SolarPermittedUseDistrictsTextCollector(StructuredLLMCaller): "on districts where **large solar energy farms** (or similar) are a " "permitted use and False otherwise." ) + """Prompt to check if chunk contains info on permitted districts""" def __init__(self, *args, **kwargs): - """ - - Parameters - ---------- - *args, **kwargs - Parameters to pass to the - :class:`~compass.llm.calling.StructuredLLMCaller` - initializer. - """ super().__init__(*args, **kwargs) self._district_chunks = {} @@ -252,8 +240,7 @@ async def check_chunk(self, chunk_parser, ind): Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains a - `parse_from_ind` method. + Instance that contains a ``parse_from_ind`` method. ind : int Index of the chunk to check. @@ -314,8 +301,7 @@ class SolarOrdinanceTextExtractor(BaseTextExtractor): particular ordinance type (e.g. solar zoning for utility-scale systems). Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries. + Uses a StructuredLLMCaller for LLM queries. """ SOLAR_ENERGY_SYSTEM_FILTER_PROMPT = ( @@ -360,6 +346,7 @@ class SolarOrdinanceTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for SEF""" async def extract_solar_energy_system_section(self, text_chunks): """Extract ordinance text from input text chunks for SEF @@ -390,9 +377,9 @@ def parsers(self): ------ name : str Name describing the type of text output by the parser. - parser - Parser that takes a `text_chunks` input and outputs parsed - text. + parser : callable + Async function that takes a ``text_chunks`` input and + outputs parsed text. """ yield ( "cleaned_ordinance_text", @@ -410,8 +397,7 @@ class SolarPermittedUseDistrictsTextExtractor(BaseTextExtractor): particular ordinance type (e.g. solar zoning for utility-scale systems). Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries. + Uses a StructuredLLMCaller for LLM queries. """ _USAGE_LABEL = LLMUsageCategory.DOCUMENT_PERMITTED_USE_DISTRICTS_SUMMARY @@ -460,6 +446,7 @@ class SolarPermittedUseDistrictsTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for permitted uses""" SEF_PERMITTED_USES_FILTER_PROMPT = ( "# CONTEXT #\n" @@ -504,6 +491,7 @@ class SolarPermittedUseDistrictsTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for permitted uses for SEF""" async def extract_permitted_uses(self, text_chunks): """Extract permitted uses text from input text chunks @@ -555,9 +543,9 @@ def parsers(self): ------ name : str Name describing the type of text output by the parser. - parser - Parser that takes a `text_chunks` input and outputs parsed - text. + parser : callable + Async function that takes a ``text_chunks`` input and + outputs parsed text. """ yield "permitted_use_only_text", self.extract_permitted_uses yield "districts_text", self.extract_sef_permitted_uses diff --git a/compass/extraction/solar/parse.py b/compass/extraction/solar/parse.py index d65364b64..9c4cd45cb 100644 --- a/compass/extraction/solar/parse.py +++ b/compass/extraction/solar/parse.py @@ -192,10 +192,9 @@ class StructuredSolarOrdinanceParser(StructuredSolarParser): a decision-tree-based chain-of-thought prompt on the text for each value to be extracted. Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries and multiple - :class:`~compass.extraction.tree.AsyncDecisionTree` instances - to guide the extraction of individual values. + Uses a StructuredLLMCaller for LLM queries and multiple + AsyncDecisionTree instances to guide the extraction of + individual values. """ async def parse(self, text): @@ -211,7 +210,7 @@ async def parse(self, text): Returns ------- - pd.DataFrame | None + pandas.DataFrame or None DataFrame containing parsed-out ordinance values. Can also be ``None`` if a large solar energy system is not found in the text. @@ -472,10 +471,9 @@ class StructuredSolarPermittedUseDistrictsParser(StructuredSolarParser): a decision-tree-based chain-of-thought prompt on the text for each value to be extracted. Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries and multiple - :class:`~compass.extraction.tree.AsyncDecisionTree` instances - to guide the extraction of individual values. + Uses a StructuredLLMCaller for LLM queries and multiple + AsyncDecisionTree instances to guide the extraction of + individual values. """ _LARGE_SEF_CLARIFICATION = ( @@ -548,7 +546,7 @@ async def parse(self, text): Returns ------- - pd.DataFrame | None + pandas.DataFrame or None DataFrame containing parsed-out allowed-use district names. Can also be ``None`` if a large solar energy system is not found in the text. diff --git a/compass/extraction/wind/graphs.py b/compass/extraction/wind/graphs.py index 234cd73bf..580cd9e0d 100644 --- a/compass/extraction/wind/graphs.py +++ b/compass/extraction/wind/graphs.py @@ -25,7 +25,7 @@ def setup_graph_wes_types(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -155,7 +155,7 @@ def setup_multiplier(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -366,7 +366,7 @@ def setup_conditional_min(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -446,7 +446,7 @@ def setup_conditional_max(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ diff --git a/compass/extraction/wind/ordinance.py b/compass/extraction/wind/ordinance.py index 90cc01236..722c50079 100644 --- a/compass/extraction/wind/ordinance.py +++ b/compass/extraction/wind/ordinance.py @@ -73,8 +73,11 @@ class WindHeuristic(Heuristic): "prevailing wind", "downwind", ] + """Words and phrases that indicate text is NOT about WECS""" GOOD_TECH_KEYWORDS = ["wind", "setback"] + """Words that indicate we should keep a chunk for analysis""" GOOD_TECH_ACRONYMS = ["wecs", "wes", "lwet", "uwet", "wef"] + """Acronyms for WECS that we want to capture""" GOOD_TECH_PHRASES = [ "wind energy conversion", "wind turbine", @@ -84,6 +87,7 @@ class WindHeuristic(Heuristic): "wind energy farm", "utility wind energy system", ] + """Phrases that indicate text is about WECS""" class WindOrdinanceTextCollector(StructuredLLMCaller): @@ -108,6 +112,7 @@ class WindOrdinanceTextCollector(StructuredLLMCaller): f"{_SEARCH_TERMS_OR} for a wind energy system (or wind turbine/tower) " "and False otherwise. " ) + """Prompt to check if chunk contains WES ordinance info""" IS_UTILITY_SCALE_PROMPT = ( "You are a legal scholar that reads ordinance text and determines " @@ -126,17 +131,9 @@ class WindOrdinanceTextCollector(StructuredLLMCaller): "conversion systems** (or similar) that the client is interested in " "and False otherwise." ) + """Prompt to check if chunk is for utility-scale WES""" def __init__(self, *args, **kwargs): - """ - - Parameters - ---------- - *args, **kwargs - Parameters to pass to the - :class:`~compass.llm.calling.StructuredLLMCaller` - initializer. - """ super().__init__(*args, **kwargs) self._ordinance_chunks = {} @@ -146,8 +143,7 @@ async def check_chunk(self, chunk_parser, ind): Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains a - `parse_from_ind` method. + Instance that contains a ``parse_from_ind`` method. ind : int Index of the chunk to check. @@ -249,17 +245,9 @@ class WindPermittedUseDistrictsTextCollector(StructuredLLMCaller): "on districts where **large wind energy systems** (or similar) are a " "permitted use in and False otherwise." ) + """Prompt to check if chunk contains info on permitted districts""" def __init__(self, *args, **kwargs): - """ - - Parameters - ---------- - *args, **kwargs - Parameters to pass to the - :class:`~compass.llm.calling.StructuredLLMCaller` - initializer. - """ super().__init__(*args, **kwargs) self._district_chunks = {} @@ -269,8 +257,7 @@ async def check_chunk(self, chunk_parser, ind): Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains a - `parse_from_ind` method. + Instance that contains a ``parse_from_ind`` method. ind : int Index of the chunk to check. @@ -332,8 +319,7 @@ class WindOrdinanceTextExtractor(BaseTextExtractor): particular ordinance type (e.g. wind zoning for utility-scale systems). Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries. + Uses a StructuredLLMCaller for LLM queries. """ WIND_ENERGY_SYSTEM_FILTER_PROMPT = ( @@ -376,6 +362,8 @@ class WindOrdinanceTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for WECS""" + LARGE_WIND_ENERGY_SYSTEM_SECTION_FILTER_PROMPT = ( "# CONTEXT #\n" "We want to reduce the provided excerpt to only contain information " @@ -430,6 +418,7 @@ class WindOrdinanceTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for utility-scale WECS""" async def extract_wind_energy_system_section(self, text_chunks): """Extract ordinance text from input text chunks for WES @@ -481,9 +470,9 @@ def parsers(self): ------ name : str Name describing the type of text output by the parser. - parser - Parser that takes a `text_chunks` input and outputs parsed - text. + parser : callable + Async function that takes a ``text_chunks`` input and + outputs parsed text. """ yield ( "wind_energy_systems_text", @@ -505,8 +494,7 @@ class WindPermittedUseDistrictsTextExtractor(BaseTextExtractor): particular ordinance type (e.g. wind zoning for utility-scale systems). Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries. + Uses a StructuredLLMCaller for LLM queries. """ _USAGE_LABEL = LLMUsageCategory.DOCUMENT_PERMITTED_USE_DISTRICTS_SUMMARY @@ -555,6 +543,7 @@ class WindPermittedUseDistrictsTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for permitted uses""" WES_PERMITTED_USES_FILTER_PROMPT = ( "# CONTEXT #\n" @@ -599,6 +588,7 @@ class WindPermittedUseDistrictsTextExtractor(BaseTextExtractor): "- If **no relevant text** is found, return the response: " "'No relevant text.'" ) + """Prompt to extract ordinance text for permitted uses for WECS""" async def extract_permitted_uses(self, text_chunks): """Extract permitted uses text from input text chunks @@ -650,9 +640,9 @@ def parsers(self): ------ name : str Name describing the type of text output by the parser. - parser - Parser that takes a `text_chunks` input and outputs parsed - text. + parser : callable + Async function that takes a ``text_chunks`` input and + outputs parsed text. """ yield "permitted_use_only_text", self.extract_permitted_uses yield "districts_text", self.extract_wes_permitted_uses diff --git a/compass/extraction/wind/parse.py b/compass/extraction/wind/parse.py index c63472276..c339879f8 100644 --- a/compass/extraction/wind/parse.py +++ b/compass/extraction/wind/parse.py @@ -176,10 +176,9 @@ class StructuredWindOrdinanceParser(StructuredWindParser): a decision-tree-based chain-of-thought prompt on the text for each value to be extracted. Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries and multiple - :class:`~compass.extraction.tree.AsyncDecisionTree` instances - to guide the extraction of individual values. + Uses a StructuredLLMCaller for LLM queries and multiple + AsyncDecisionTree instances to guide the extraction of + individual values. """ async def parse(self, text): @@ -195,7 +194,7 @@ async def parse(self, text): Returns ------- - pd.DataFrame | None + pandas.DataFrame or None DataFrame containing parsed-out ordinance values. Can also be ``None`` if a large wind energy system is not found in the text. @@ -469,10 +468,9 @@ class StructuredWindPermittedUseDistrictsParser(StructuredWindParser): a decision-tree-based chain-of-thought prompt on the text for each value to be extracted. Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries and multiple - :class:`~compass.extraction.tree.AsyncDecisionTree` instances - to guide the extraction of individual values. + Uses a StructuredLLMCaller for LLM queries and multiple + AsyncDecisionTree instances to guide the extraction of + individual values. """ _LARGE_WES_CLARIFICATION = ( @@ -546,7 +544,7 @@ async def parse(self, text): Returns ------- - pd.DataFrame | None + pandas.DataFrame or None DataFrame containing parsed-out allowed-use district names. Can also be ``None`` if a large wind energy system is not found in the text. diff --git a/compass/llm/calling.py b/compass/llm/calling.py index 76a0859e4..d41dfa72e 100644 --- a/compass/llm/calling.py +++ b/compass/llm/calling.py @@ -20,14 +20,15 @@ class BaseLLMCaller: :class:`~compass.services.openai.OpenAIService`) to query an LLM. 2. Maintain a useful context to simplify LLM query. + - Typically these classes are initialized with a single LLM model (and optionally a usage tracker) - This context is passed to every ``Service.call`` invocation, allowing user to focus on only the message. - 3. Track message history - (:class:`~compass.llm.calling.ChatLLMCaller`) - or convert output into JSON - (:class:`~compass.llm.calling.StructuredLLMCaller`). + + 3. Track message history (ChatLLMCaller) or convert output into + JSON (StructuredLLMCaller). + Key Relationships: Delegates most of work to underlying ``Service`` class. """ @@ -37,15 +38,15 @@ def __init__(self, llm_service, usage_tracker=None, **kwargs): Parameters ---------- - llm_service : compass.services.base.Service + llm_service : Service LLM service used for queries. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. **kwargs Keyword arguments to be passed to the underlying service - processing function (i.e. `llm_service.call(**kwargs)`). - Should *not* contain the following keys: + processing function (i.e. ``llm_service.call(**kwargs)``). + Should **not** contain the following keys: - usage_sub_label - messages @@ -58,12 +59,20 @@ def __init__(self, llm_service, usage_tracker=None, **kwargs): class LLMCaller(BaseLLMCaller): - """Simple LLM caller, with no memory and no parsing utilities.""" + """Simple LLM caller, with no memory and no parsing utilities + + See Also + -------- + ChatLLMCaller + Chat-like LLM calling functionality. + StructuredLLMCaller + Structured (JSON) LLM calling functionality. + """ async def call( self, sys_msg, content, usage_sub_label=LLMUsageCategory.DEFAULT ): - """Call LLM. + """Call LLM Parameters ---------- @@ -92,7 +101,15 @@ async def call( class ChatLLMCaller(BaseLLMCaller): - """Class to support chat-like LLM calling functionality.""" + """Class to support chat-like LLM calling functionality + + See Also + -------- + LLMCaller + Simple LLM caller, with no memory and no parsing utilities. + StructuredLLMCaller + Structured (JSON) LLM calling functionality. + """ def __init__( self, llm_service, system_message, usage_tracker=None, **kwargs @@ -105,7 +122,7 @@ def __init__( LLM service used for queries. system_message : str System message to use for chat with LLM. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. **kwargs @@ -122,7 +139,7 @@ def __init__( self.messages = [{"role": "system", "content": system_message}] async def call(self, content, usage_sub_label=LLMUsageCategory.CHAT): - """Chat with the LLM. + """Chat with the LLM Parameters ---------- @@ -154,12 +171,20 @@ async def call(self, content, usage_sub_label=LLMUsageCategory.CHAT): class StructuredLLMCaller(BaseLLMCaller): - """Class to support structured (JSON) LLM calling functionality.""" + """Class to support structured (JSON) LLM calling functionality + + See Also + -------- + LLMCaller + Simple LLM caller, with no memory and no parsing utilities. + ChatLLMCaller + Chat-like LLM calling functionality. + """ async def call( self, sys_msg, content, usage_sub_label=LLMUsageCategory.DEFAULT ): - """Call LLM for structured data retrieval. + """Call LLM for structured data retrieval Parameters ---------- @@ -193,7 +218,7 @@ async def call( def _add_json_instructions_if_needed(system_message): - """Add JSON instruction to system message if needed.""" + """Add JSON instruction to system message if needed""" if "JSON format" not in system_message: logger.debug( "JSON instructions not found in system message. Adding..." diff --git a/compass/llm/config.py b/compass/llm/config.py index c18486e27..42428f506 100644 --- a/compass/llm/config.py +++ b/compass/llm/config.py @@ -68,7 +68,7 @@ def __init__( @cached_property def text_splitter(self): - """TextSplitter: Object that can be used to chunk text""" + """:class:`~langchain_text_splitters.character.RecursiveCharacterTextSplitter`: Text splitter for ordinance text""" # noqa: W505, E501 return RecursiveCharacterTextSplitter( RTS_SEPARATORS, chunk_size=self.text_splitter_chunk_size, diff --git a/compass/scripts/download.py b/compass/scripts/download.py index 14a23591f..f3adad7b4 100644 --- a/compass/scripts/download.py +++ b/compass/scripts/download.py @@ -39,7 +39,7 @@ async def download_known_urls( Parameters ---------- - jurisdiction : :class:`~compass.utilities.location.Jurisdiction` + jurisdiction : Jurisdiction Jurisdiction instance representing the jurisdiction corresponding to the documents. urls : iterable of str @@ -107,7 +107,7 @@ async def find_jurisdiction_website( Parameters ---------- - jurisdiction : :class:`~compass.utilities.location.Jurisdiction` + jurisdiction : Jurisdiction Jurisdiction instance representing the jurisdiction to find the main webpage for. model_configs : dict @@ -129,13 +129,13 @@ async def find_jurisdiction_website( Semaphore instance that can be used to limit the number of playwright browsers open concurrently. If ``None``, no limits are applied. By default, ``None``. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. Returns ------- - str | None + str or None URL for the jurisdiction website, if found; ``None`` otherwise. """ kwargs.update(file_loader_kwargs or {}) @@ -208,11 +208,11 @@ async def download_jurisdiction_ordinances_from_website( used for the Google URL search. By default, ``None``. browser_config_kwargs : dict, optional Dictionary of keyword arguments pairs to initialize the - :class:`crawl4ai.async_configs.BrowserConfig` class used for the + ``crawl4ai.async_configs.BrowserConfig`` class used for the web crawl. By default, ``None``. crawler_config_kwargs : dict, optional Dictionary of keyword arguments pairs to initialize the - :class:`crawl4ai.async_configs.CrawlerConfig` class used for the + ``crawl4ai.async_configs.CrawlerConfig`` class used for the web crawl. By default, ``None``. max_urls : int, optional Max number of URLs to check from the website before terminating @@ -415,7 +415,7 @@ async def download_jurisdiction_ordinance_using_search_engine( Parameters ---------- - jurisdiction : :class:`~compass.utilities.location.Jurisdiction` + jurisdiction : Jurisdiction Location objects representing the jurisdiction. model_configs : dict Dictionary of :class:`~compass.llm.config.LLMConfig` instances. @@ -442,7 +442,7 @@ async def download_jurisdiction_ordinance_using_search_engine( playwright browsers used to download content from the web open concurrently. If ``None``, no limits are applied. By default, ``None``. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. @@ -514,16 +514,15 @@ async def filter_ordinance_docs( Parameters ---------- - jurisdiction : :class:`~compass.utilities.location.Jurisdiction` + jurisdiction : Jurisdiction Location objects representing the jurisdiction. model_configs : dict - Dictionary of :class:`~compass.llm.config.LLMConfig` instances. - Should have at minium a "default" key that is used as a fallback - for all tasks. + Dictionary of LLMConfig instances. Should have at minium a + "default" key that is used as a fallback for all tasks. tech : str Technology of interest (e.g. "solar", "wind", etc). This is used to set up some document validation decision trees. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. diff --git a/compass/scripts/process.py b/compass/scripts/process.py index 510c2476b..7dafb1058 100644 --- a/compass/scripts/process.py +++ b/compass/scripts/process.py @@ -257,7 +257,7 @@ async def process_jurisdictions_with_openai( # noqa: PLR0917, PLR0913 all websites on the NREL domain, and the specific file located at `www.co.delaware.in.us/documents/1649699794_0382.pdf`. By default, ``None``. - known_doc_urls : dict | str, optional + known_doc_urls : dict or str, optional A dictionary where keys are the jurisdiction codes (as strings) and values are a string or list of strings representing known URL's to check for those jurisdictions. If provided, these URL's diff --git a/compass/services/base.py b/compass/services/base.py index b03a470a2..b6c9e4cb7 100644 --- a/compass/services/base.py +++ b/compass/services/base.py @@ -26,7 +26,19 @@ class Service(ABC): - """Abstract base class for a Service that can be queued to run""" + """Abstract base class for a Service that can be queued to run + + See Also + -------- + LLMService + Base class for LLM services. + OpenAIService + LLM service for OpenAI models. + ~compass.services.cpu.ProcessPoolService + Service that contains a ProcessPoolExecutor instance. + ~compass.services.threaded.ThreadedService + Service that contains a ThreadPoolExecutor instance. + """ MAX_CONCURRENT_JOBS = 10_000 """Max number of concurrent job submissions.""" @@ -53,7 +65,7 @@ async def call(cls, *args, **kwargs): Returns ------- - obj + object A response object from the underlying service. """ fut = asyncio.Future() @@ -117,11 +129,16 @@ async def process(self, *args, **kwargs): class LLMService(Service): - """Base class for LLm service + """Base class for LLM service This service differs from other services in that it must be used as an object, not as a class. that is, users must initialize it and pass it around in functions in order to use it. + + See Also + -------- + OpenAIService + LLM service for OpenAI models. """ def __init__(self, model_name, rate_limit, rate_tracker, service_tag=None): @@ -136,9 +153,9 @@ def __init__(self, model_name, rate_limit, rate_tracker, service_tag=None): if the rate tracker is set to compute the total over minute-long intervals, this value should be the max usage per minute. - rate_tracker : `TimeBoundedUsageTracker` - A TimeBoundedUsageTracker instance. This will be used to - track usage per time interval and compare to `rate_limit`. + rate_tracker : TimeBoundedUsageTracker + Instance used to track usage per time interval and compare + to `rate_limit` input. service_tag : str, optional Optional tag to use to distinguish service (i.e. make unique from other services). Must set this if multiple models with @@ -178,7 +195,7 @@ async def call(self, *args, **kwargs): Returns ------- - obj + object A response object from the underlying service. """ fut = asyncio.Future() diff --git a/compass/services/cpu.py b/compass/services/cpu.py index 524547e6c..77135bd82 100644 --- a/compass/services/cpu.py +++ b/compass/services/cpu.py @@ -50,11 +50,11 @@ async def process(self, fn, pdf_bytes, **kwargs): Parameters ---------- - doc : elm.web.document.Document + doc : elm.web.document.BaseDocument Document containing meta information about the file. Must have a "source" key in the ``attrs`` dict containing the URL, which will be converted to a file name using - :func:`compute_fn_from_url`. + :func:`elm.web.utilities.compute_fn_from_url`. file_content : str or bytes File content, typically string text for HTML files and bytes for PDF file. diff --git a/compass/services/openai.py b/compass/services/openai.py index c38069e83..c8f080490 100644 --- a/compass/services/openai.py +++ b/compass/services/openai.py @@ -28,9 +28,10 @@ def usage_from_response(current_usage, response): already existing tracking information. Empty dictionaries are allowed, in which case the three keys above will be added to this input. - response : openai.Completion - OpenAI Completion object. Must contain a ``usage`` attribute - that + response : object + OpenAI Completion object (``openai.Completion``). Must contain a + ``usage`` attribute that contains ``prompt_tokens`` and + ``completion_tokens`` counts as attributes. Returns ------- @@ -59,7 +60,7 @@ def count_tokens(messages, model): "content" key containing the string to count tokens for. model : str The OpenAI model being used. This input will be passed to - :func:`tiktoken.encoding_for_model`. + ``tiktoken.encoding_for_model``. Returns ------- @@ -108,9 +109,10 @@ def __init__( Parameters ---------- - client : openai.AsyncOpenAI or openai.AsyncAzureOpenAI - Async OpenAI client instance. Must have an async - `client.chat.completions.create` method. + client : object + Async OpenAI client instance (``openai.AsyncOpenAI`` or + ``openai.AsyncAzureOpenAI``). Must have an async + ``client.chat.completions.create`` method. model_name : str Name of model being used. rate_limit : int or float, optional @@ -118,10 +120,10 @@ def __init__( interval is ultimately controlled by the `rate_tracker` instance). By default, ``1e3``. rate_tracker : TimeBoundedUsageTracker, optional - A TimeBoundedUsageTracker instance. This will be used to - track usage per time interval and compare to `rate_limit`. - If ``None``, a `TimeBoundedUsageTracker` instance is created - with default parameters. By default, ``None``. + Instance used to track usage per time interval and compare + to `rate_limit` input. If ``None``, a + TimeBoundedUsageTracker instance is created with default + parameters. By default, ``None``. service_tag : str, optional Optional tag to use to distinguish service (i.e. make unique from other services). Must set this if multiple models with @@ -150,7 +152,7 @@ async def process( ---------- model : str OpenAI GPT model to query. - usage_tracker : `compass.services.usage.UsageTracker`, optional + usage_tracker : UsageTracker, optional UsageTracker instance. Providing this input will update your tracker with this call's token usage info. By default, ``None``. diff --git a/compass/services/provider.py b/compass/services/provider.py index 0d7d9066b..5261a5625 100644 --- a/compass/services/provider.py +++ b/compass/services/provider.py @@ -168,10 +168,10 @@ def run(cls, services, coroutine): Parameters ---------- - services : iterable of :class:`compass.services.base.Service` + services : iterable of Service An iterable (i.e. a list) of Services that are needed to run the asynchronous function. - coroutine : coroutine + coroutine : callable A coroutine that should be run with the services. Returns diff --git a/compass/services/queues.py b/compass/services/queues.py index b9cc80ba3..4ff7e01d0 100644 --- a/compass/services/queues.py +++ b/compass/services/queues.py @@ -18,7 +18,7 @@ def initialize_service_queue(service_name): Returns ------- - asyncio.Queue() + asyncio.Queue Queue instance for this service. """ return _QUEUES.setdefault(service_name, asyncio.Queue()) diff --git a/compass/services/threaded.py b/compass/services/threaded.py index 168eb26d3..c5bbb10c9 100644 --- a/compass/services/threaded.py +++ b/compass/services/threaded.py @@ -201,11 +201,11 @@ async def process(self, doc, file_content, make_name_unique=False): Parameters ---------- - doc : elm.web.document.Document + doc : elm.web.document.BaseDocument Document containing meta information about the file. Must have a "source" key in the ``attrs`` dict containing the URL, which will be converted to a file name using - :func:`compute_fn_from_url`. + :func:`elm.web.utilities.compute_fn_from_url`. file_content : str or bytes File content, typically string text for HTML files and bytes for PDF file. @@ -241,11 +241,11 @@ async def process(self, doc, file_content, make_name_unique=False): Parameters ---------- - doc : elm.web.document.Document + doc : elm.web.document.BaseDocument Document containing meta information about the file. Must have a "source" key in the ``attrs`` dict containing the URL, which will be converted to a file name using - :func:`compute_fn_from_url`. + :func:`elm.web.utilities.compute_fn_from_url`. file_content : str or bytes File content, typically string text for HTML files and bytes for PDF file. @@ -301,7 +301,7 @@ async def process(self, doc): Parameters ---------- - doc : elm.web.document.Document + doc : elm.web.document.BaseDocument Document containing meta information about the file. Must have relevant processing keys in the ``attrs`` dict, otherwise the file may not be stored in the output @@ -375,7 +375,7 @@ async def process(self, tracker): Parameters ---------- - tracker : elm.ods.services.usage.UsageTracker + tracker : UsageTracker A usage tracker instance that contains usage info to be added to output file. """ @@ -425,9 +425,9 @@ async def process( Parameters ---------- - jurisdiction : compass.utilities.location.Jurisdiction - Jurisdiction to record. - doc : elm.web.document.Document | None + jurisdiction : Jurisdiction + The jurisdiction instance to record. + doc : elm.web.document.BaseDocument or None Document containing meta information about the jurisdiction. Must have relevant processing keys in the ``attrs`` dict, otherwise the jurisdiction may not be recorded properly. @@ -436,7 +436,7 @@ async def process( seconds_elapsed : int or float Total number of seconds it took to look for (and possibly parse) this document. - usage_tracker : compass.services.usage.UsageTracker, optional + usage_tracker : UsageTracker, optional Optional tracker instance to monitor token usage during LLM calls. By default, ``None``. """ diff --git a/compass/services/usage.py b/compass/services/usage.py index 47a96456a..0df00c332 100644 --- a/compass/services/usage.py +++ b/compass/services/usage.py @@ -25,7 +25,7 @@ def __init__(self, value): Parameters ---------- - value : obj + value : object Some value to store as an entry. """ self.value = value @@ -96,7 +96,7 @@ def _discard_old_values(self): class UsageTracker(UserDict): - """Rate or AIP usage tracker""" + """Rate or API usage tracker""" UNKNOWN_MODEL_LABEL = "unknown_model" """Label used in the usage dictionary for unknown models""" diff --git a/compass/utilities/enums.py b/compass/utilities/enums.py index 18ecbd73b..cf0864089 100644 --- a/compass/utilities/enums.py +++ b/compass/utilities/enums.py @@ -7,18 +7,31 @@ class LLMUsageCategory(StrEnum): """COMPASS LLM usage categories""" CHAT = auto() + """Usage related to general LLM chat calls""" DATE_EXTRACTION = auto() + """Usage related to date extraction tasks""" DECISION_TREE = auto() + """Usage related to decision tree calls""" DEFAULT = auto() + """Usage related to default/fallback calls""" DOCUMENT_CONTENT_VALIDATION = auto() + """Usage related to document content validation tasks""" DOCUMENT_ORDINANCE_SUMMARY = auto() + """Usage related to ordinance summary tasks""" DOCUMENT_PERMITTED_USE_CONTENT_VALIDATION = auto() + """Usage related to permitted use content validation tasks""" DOCUMENT_PERMITTED_USE_DISTRICTS_SUMMARY = auto() + """Usage related to permitted use districts summary tasks""" DOCUMENT_JURISDICTION_VALIDATION = auto() + """Usage related to document jurisdiction validation tasks""" URL_JURISDICTION_VALIDATION = auto() + """Usage related to URL jurisdiction validation tasks""" JURISDICTION_MAIN_WEBSITE_VALIDATION = auto() + """Usage related to jurisdiction main website validation tasks""" ORDINANCE_VALUE_EXTRACTION = auto() + """Usage related to ordinance value extraction tasks""" PERMITTED_USE_VALUE_EXTRACTION = auto() + """Usage related to permitted use value extraction tasks""" class LLMTasks(StrEnum): diff --git a/compass/utilities/finalize.py b/compass/utilities/finalize.py index 5775926cf..5eaafe099 100644 --- a/compass/utilities/finalize.py +++ b/compass/utilities/finalize.py @@ -61,9 +61,8 @@ def save_run_meta( directories used for the run. tech : {"wind", "solar"} Technology that was the target of the run. - start_date, end_date : datetime - ``datetime`` instances representing the start and end dates, - respectively. + start_date, end_date : datetime.datetime + Instances representing the start and end dates, respectively. num_jurisdictions_searched, num_jurisdictions_found : int Total number of jurisdictions that were searched and actually found, respectively. @@ -129,7 +128,7 @@ def doc_infos_to_db(doc_infos): Parameters ---------- - doc_infos : iter of dicts + doc_infos : iterable of dict Iterable of dictionaries, where each dictionary has at least the following keys: @@ -138,17 +137,15 @@ def doc_infos_to_db(doc_infos): extracted - "date": Tuple of (year, month, day). Any of the values can be ``None``. - - "jurisdiction": Instance of - :class:`compass.utilities.location.Jurisdiction` - representing the jurisdiction associated with these - ordinance values. + - "jurisdiction": Instance of Jurisdiction representing the + jurisdiction associated with these ordinance values. If this iterable is empty, and empty DataFrame (with the correct columns) is returned. Returns ------- - ordinances : pd.DataFrame + ordinances : pandas.DataFrame DataFrame containing ordinances collected from all individual CSV's. count : int @@ -187,7 +184,7 @@ def save_db(db, out_dir): Parameters ---------- - db : pd.DataFrame + db : pandas.DataFrame Pandas DataFrame containing ordinance data to save. Must have all columns in :obj:`QUANT_OUT_COLS` and :obj:`QUAL_OUT_COLS` as well as a ``"quantitative"`` column that contains a boolean @@ -279,9 +276,9 @@ def compile_run_summary_message( Parameters ---------- - total_seconds : int | float + total_seconds : int or float Total number of seconds the run took to complete. - total_cost : int | float + total_cost : int or float Total cost of the run, in $. out_dir : path-like Path to output directory where the run results are saved. diff --git a/compass/utilities/jurisdictions.py b/compass/utilities/jurisdictions.py index 6c0b34ec9..0dfbe0682 100644 --- a/compass/utilities/jurisdictions.py +++ b/compass/utilities/jurisdictions.py @@ -22,7 +22,7 @@ def load_all_jurisdiction_info(): Returns ------- - pd.DataFrame + pandas.DataFrame DataFrame containing info like names, FIPS, websites, etc. for all jurisdictions. """ @@ -34,10 +34,10 @@ def jurisdiction_websites(jurisdiction_info=None): Parameters ---------- - jurisdiction_info : pd.DataFrame, optional + jurisdiction_info : pandas.DataFrame, optional DataFrame containing jurisdiction names and websites. If ``None``, this info is loaded using - :func:`load_jurisdiction_info`. + :func:`load_all_jurisdiction_info`. By default, ``None``. Returns @@ -65,7 +65,7 @@ def load_jurisdictions_from_fp(jurisdiction_fp): Returns ------- - pd.DataFrame + pandas.DataFrame DataFrame containing jurisdiction info like names, FIPS, websites, etc. for all requested jurisdictions (that were found). diff --git a/compass/utilities/logs.py b/compass/utilities/logs.py index 8e0c00e00..bf44332e3 100644 --- a/compass/utilities/logs.py +++ b/compass/utilities/logs.py @@ -118,7 +118,7 @@ def filter(self, record): # noqa: PLR6301 return True -class LocalProcessQueueHandler(QueueHandler): +class _LocalProcessQueueHandler(QueueHandler): """QueueHandler that works within a single process (locally)""" def emit(self, record): @@ -155,7 +155,7 @@ def __init__(self, logger_names, level="INFO"): self.logger_names = logger_names self.level = level self._listener = None - self._queue_handler = LocalProcessQueueHandler(LOGGING_QUEUE) + self._queue_handler = _LocalProcessQueueHandler(LOGGING_QUEUE) self._queue_handler.addFilter(AddLocationFilter()) def _setup_listener(self): @@ -249,7 +249,7 @@ def __init__( Parameters ---------- - listener : `LoggingListener` + listener : LogListener A listener instance. The file handler will be added to this listener. log_dir : path-like @@ -260,7 +260,7 @@ def __init__( contain only characters valid in a file name. level : str, optional Log level. By default, ``"INFO"``. - max_teardown_time : int | float, default=30 + max_teardown_time : int or float, default=30 Max number of seconds to wait for logs to flush to file before unhooking the handler from the queue listener. By default, ``30``. @@ -288,7 +288,7 @@ def _setup_handler(self): def _setup_exception_handler(self): """Setup file handler for tracking errors for this location""" - self._exception_handler = JsonExceptionFileHandler( + self._exception_handler = _JsonExceptionFileHandler( self.log_dir / f"{self.location} exceptions.json", encoding="utf-8" ) self._exception_handler.addFilter(LocationFilter(self.location)) @@ -373,10 +373,10 @@ def filter(self, record): # noqa: D102, PLR6301 return bool(record.exc_info) -class JsonFormatter(logging.Formatter): +class _JsonFormatter(logging.Formatter): """Formatter that converts a record into a dictionary""" - def format(self, record): # noqa: D102 + def format(self, record): exc_info = record.exc_info exc_text = None if exc_info: @@ -405,7 +405,7 @@ def format(self, record): # noqa: D102 } -class JsonExceptionFileHandler(logging.Handler): +class _JsonExceptionFileHandler(logging.Handler): """File handler that writes exception info to JSON file""" def __init__(self, filename, encoding="utf-8"): @@ -416,7 +416,7 @@ def __init__(self, filename, encoding="utf-8"): filename : path-like Path to file where JSON output on exceptions should be stored. - encoding : str, optional + encoding : str, default="utf-8" File read/write encoding. By default, ``"utf-8"``. """ super().__init__() @@ -436,7 +436,7 @@ def _init_hooks(self): self.addFilter(ExceptionOnlyFilter()) self.setLevel(logging.ERROR) - self.setFormatter(JsonFormatter()) + self.setFormatter(_JsonFormatter()) def emit(self, record): """Log the specified logging record to a JSON file diff --git a/compass/utilities/parsing.py b/compass/utilities/parsing.py index fd4a512a3..f0caa38fb 100644 --- a/compass/utilities/parsing.py +++ b/compass/utilities/parsing.py @@ -129,7 +129,7 @@ def num_ordinances_in_doc(doc, exclude_features=None): Parameters ---------- - doc : elm.web.document.Document + doc : elm.web.document.BaseDocument Document potentially containing ordinances for a jurisdiction. If no ordinance values are found, this function returns ``0``. exclude_features : iterable of str, optional @@ -154,7 +154,7 @@ def num_ordinances_dataframe(data, exclude_features=None): Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame DataFrame potentially containing ordinances for a jurisdiction. If no ordinance values are found, this function returns ``0``. exclude_features : iterable of str, optional @@ -178,7 +178,7 @@ def ordinances_bool_index(data): Parameters ---------- - data : pd.DataFrame + data : pandas.DataFrame DataFrame potentially containing ordinances for a jurisdiction. If no ordinance values are found, this function returns ``0``. diff --git a/compass/validation/content.py b/compass/validation/content.py index 480459cba..a7c478797 100644 --- a/compass/validation/content.py +++ b/compass/validation/content.py @@ -194,25 +194,25 @@ def _count_phrase_matches(self, heuristics_text): @property @abstractmethod def NOT_TECH_WORDS(self): # noqa: N802 - """iter: Iterable of words that don't pertain to the tech""" + """:class:`~collections.abc.Iterable`: Not tech keywords""" raise NotImplementedError @property @abstractmethod def GOOD_TECH_KEYWORDS(self): # noqa: N802 - """iter: Iterable of keywords that pertain to the tech""" + """:class:`~collections.abc.Iterable`: Tech keywords""" raise NotImplementedError @property @abstractmethod def GOOD_TECH_ACRONYMS(self): # noqa: N802 - """iter: Iterable of acronyms that pertain to the tech""" + """:class:`~collections.abc.Iterable`: Tech acronyms""" raise NotImplementedError @property @abstractmethod def GOOD_TECH_PHRASES(self): # noqa: N802 - """iter: Iterable of phrases that pertain to the tech""" + """:class:`~collections.abc.Iterable`: Tech phrases""" raise NotImplementedError @@ -226,6 +226,7 @@ class LegalTextValidator(StructuredLLMCaller): "enforceable bans)** and filter out text that was extracted from " "anything other than a legal statute for an existing jurisdiction." ) + """System message for legal text validation LLM calls""" def __init__( self, tech, *args, score_threshold=0.8, doc_is_from_ocr=False, **kwargs @@ -242,9 +243,7 @@ def __init__( check for the whole document to be considered legal text. By default, ``0.8``. *args, **kwargs - Parameters to pass to the - :class:`~compass.llm.calling.StructuredLLMCaller` - initializer. + Parameters to pass to the StructuredLLMCaller initializer. """ super().__init__(*args, **kwargs) self.tech = tech @@ -266,8 +265,7 @@ async def check_chunk(self, chunk_parser, ind): Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains a - `parse_from_ind` method. + Instance that contains a ``parse_from_ind`` method. ind : int Index of the chunk to check. @@ -328,9 +326,9 @@ async def parse_by_chunks( Parameters ---------- chunk_parser : ParseChunksWithMemory - Instance of `ParseChunksWithMemory` that contains the attributes - `text_chunks` and `num_to_recall`. The chunks in the - `text_chunks` attribute will be iterated over. + Instance that contains the attributes ``text_chunks`` and + ``num_to_recall``. The chunks in the ``text_chunks`` attribute + will be iterated over. heuristic : Heuristic Instance of `Heuristic` with a `check` method. This should be a fast check meant to quickly dispose of chunks of text. Any chunk diff --git a/compass/validation/graphs.py b/compass/validation/graphs.py index 5f3d74a42..31c2287d9 100644 --- a/compass/validation/graphs.py +++ b/compass/validation/graphs.py @@ -17,7 +17,7 @@ def setup_graph_correct_document_type(**kwargs): Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -281,14 +281,14 @@ def setup_graph_correct_jurisdiction_type(jurisdiction, **kwargs): Parameters ---------- - jurisdiction : compass.utilities.location.Jurisdiction + jurisdiction : Jurisdiction Jurisdiction for which validation is being performed. **kwargs Keyword-value pairs to add to graph. Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ @@ -501,14 +501,14 @@ def setup_graph_correct_jurisdiction_from_url(jurisdiction, **kwargs): Parameters ---------- - jurisdiction : compass.utilities.location.Jurisdiction + jurisdiction : Jurisdiction Jurisdiction for which validation is being performed. **kwargs Keyword-value pairs to add to graph. Returns ------- - nx.DiGraph + networkx.DiGraph Graph instance that can be used to initialize an `elm.tree.DecisionTree`. """ diff --git a/compass/validation/location.py b/compass/validation/location.py index 4def34af8..0d2145c02 100644 --- a/compass/validation/location.py +++ b/compass/validation/location.py @@ -29,15 +29,15 @@ class DTreeURLJurisdictionValidator(BaseLLMCaller): "they contain information about jurisdictions. Only ever answer " "based on the information in the URL itself." ) + """System message for URL jurisdiction validation LLM calls""" def __init__(self, jurisdiction, **kwargs): """ Parameters ---------- - structured_llm_caller : `StructuredLLMCaller` - StructuredLLMCaller instance. Used for structured validation - queries. + structured_llm_caller : StructuredLLMCaller + Instance used for structured validation queries. **kwargs Additional keyword arguments to pass to the :class:`~compass.llm.calling.BaseLLMCaller` instance. @@ -90,19 +90,21 @@ class DTreeJurisdictionValidator(BaseLLMCaller): """Jurisdiction Validation using a decision tree""" META_SCORE_KEY = "Jurisdiction Validation Score" + """Key in doc.attrs where score is stored""" + SYSTEM_MESSAGE = ( "You are a legal expert assisting a user with determining the scope " "of applicability for their legal ordinance documents." ) + """System message for jurisdiction validation LLM calls""" def __init__(self, jurisdiction, **kwargs): """ Parameters ---------- - structured_llm_caller : `StructuredLLMCaller` - StructuredLLMCaller instance. Used for structured validation - queries. + structured_llm_caller : StructuredLLMCaller + Instance used for structured validation queries. **kwargs Additional keyword arguments to pass to the :class:`~compass.llm.calling.BaseLLMCaller` instance. @@ -162,8 +164,8 @@ class JurisdictionValidator: 1. Use a combination of heuristics and LLM queries to determine whether or not a document pertains to a particular county. Key Relationships: - Uses a :class:`~compass.llm.calling.StructuredLLMCaller` for - LLM queries and delegates sub-validation to + Uses a StructuredLLMCaller for LLM queries and delegates + sub-validation to :class:`DTreeJurisdictionValidator`, and :class:`DTreeURLJurisdictionValidator`. """ @@ -176,10 +178,8 @@ def __init__(self, score_thresh=0.8, text_splitter=None, **kwargs): score_thresh : float, optional Score threshold to exceed when voting on content from raw pages. By default, ``0.8``. - text_splitter : TextSplitter, optional - Optional - :class:`langchain_text_splitters.character.TextSplitter` - text splitter instance to attach to doc (used for + text_splitter : LCTextSplitter, optional + Optional text splitter instance to attach to doc (used for splitting out pages in an HTML document). By default, ``None``. **kwargs @@ -195,7 +195,7 @@ async def check(self, doc, jurisdiction): Parameters ---------- - doc : :class:`elm.web.document.BaseDocument` + doc : elm.web.document.BaseDocument Document instance. Should contain a "source" key in the ``attrs`` that contains a URL (used for the URL validation check). Raw content will be parsed for county name and @@ -252,6 +252,7 @@ class JurisdictionWebsiteValidator: "jurisdiction. Only ever answer based on the information from the " "website itself." ) + """System message for main jurisdiction website validation calls""" def __init__( self, browser_semaphore=None, file_loader_kwargs=None, **kwargs diff --git a/compass/web/website_crawl.py b/compass/web/website_crawl.py index c4f635dc7..d71694a37 100644 --- a/compass/web/website_crawl.py +++ b/compass/web/website_crawl.py @@ -82,7 +82,7 @@ def _assign_value(self, text): return score -class Link(c4AILink): +class _Link(c4AILink): """Crawl4AI Link subclass with a few utilities""" def __hash__(self): @@ -155,7 +155,7 @@ def __init__( initialize the playwright instances used for the crawl. By default, ``None``. already_visited : set, optional - A set of URLs (either strings or :class:``Link`` objects) + A set of URLs (either strings or ``Link`` objects) that have already been visited. This is used to avoid re-visiting links that have already been checked. By default, ``None``. @@ -212,7 +212,7 @@ async def run( on_new_page_visit_hook : callable, optional An async callable that is called every time a new page is found during the crawl. The callable should accept a single - argument, which is the page :class:`Link` instance. + argument, which is the page ``Link`` instance. If ``None``, no additional processing is done on new pages. By default, ``None``. @@ -267,7 +267,7 @@ async def _run( prev_len = len(self._out_docs) await self._run( base_url, - link=Link( + link=_Link( title=next_link["title"], href=next_link["href"], base_domain=base_url, @@ -312,7 +312,7 @@ def _reset_crawl(self, base_url): self._out_docs = [] self._already_visited = {} base_url = _sanitize_url(base_url) - return base_url, Link( + return base_url, _Link( title="Landing Page", href=_sanitize_url(urljoin(base_url, base_url.split(" ")[0])), base_domain=base_url, @@ -530,7 +530,7 @@ def _extract_links_from_html(text, base_url): ] return { - Link( + _Link( title=title, href=_sanitize_url(urljoin(base_url, path)), base_domain=base_url, diff --git a/docs/source/conf.py b/docs/source/conf.py index e2cda62dc..09b52e872 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -60,15 +60,16 @@ ] intersphinx_mapping = { - "python": ("https://docs.python.org/3/", None), - "numpy": ("https://numpy.org/doc/stable/", None), - "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), + "elm": ("https://nrel.github.io/elm", None), + "lc": ("https://python.langchain.com/api_reference/", None), "matplotlib": ("https://matplotlib.org/stable", None), "networkx": ("https://networkx.org/documentation/stable", None), - "sqlalchemy": ("https://docs.sqlalchemy.org/en/20/", None), - "psycopg": ("https://www.psycopg.org/psycopg3/docs", None), + "numpy": ("https://numpy.org/doc/stable/", None), + "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), "plotly": ("https://plotly.com/python-api-reference", None), - "elm": ("https://nrel.github.io/elm", None), + "psycopg": ("https://www.psycopg.org/psycopg3/docs", None), + "python": ("https://docs.python.org/3/", None), + "sqlalchemy": ("https://docs.sqlalchemy.org/en/20/", None), } # Add any paths that contain templates here, relative to this directory. @@ -108,6 +109,9 @@ # Avoid errors with self-signed certificates tls_verify = False +# Avoid warning about api.rst not in TOC +suppress_warnings = ["toc.not_included"] + # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for @@ -200,26 +204,64 @@ "COMPASS Documentation", author, "COMPASS", - "Geospatial Analysis Pipelines.", "Miscellaneous", ), ] -def skip_pydantic_methods(app, what, name, obj, skip, options): - if name in ( +def skip_external_methods(app, what, name, obj, skip, options): + if name in { + "clear", + "pop", + "popitem", + "setdefault", + "update", + } and "MutableMapping" in str(obj): + return True + + if name in {"copy", "fromkeys"} and "UsageTracker" in str(obj): + return True + + if name in {"items", "keys", "values"} and "Mapping" in str(obj): + return True + + if name in {"copy", "get"} and "UserDict" in str(obj): + return True + + if name in { "model_dump_json", "model_json_schema", "model_dump", "model_construct", "model_copy", - ): + "model_fields", + "model_computed_fields", + "model_rebuild", + "model_parametrized_name", + "model_post_init", + "model_validate", + "model_validate_json", + "model_validate_strings", + "copy", + "construct", + "dict", + "from_orm", + "json", + "parse_file", + "parse_obj", + "parse_raw", + "schema", + "schema_json", + "update_forward_refs", + "validate", + } and "BaseModel" in str(obj): return True + return None def setup(app): - app.connect("autodoc-skip-member", skip_pydantic_methods) + app.connect("autodoc-skip-member", skip_external_methods) # -- Extension configuration ------------------------------------------------- @@ -234,14 +276,14 @@ def setup(app): mermaid_version = "11.6.0" numpy_show_class_member = True napoleon_google_docstring = False -napoleon_use_param = False napoleon_use_ivar = False napoleon_use_rtype = False napoleon_preprocess_types = True +napoleon_use_param = True napoleon_type_aliases = { # general terms "sequence": ":term:`sequence`", - "iterable": ":term:`iterable`", + "iterable": ":class:`~collections.abc.Iterable`", "callable": ":py:func:`callable`", "dict_like": ":term:`dict-like `", "dict-like": ":term:`dict-like `", @@ -282,8 +324,27 @@ def setup(app): "Series": "~pandas.Series", "DataFrame": "~pandas.DataFrame", "Categorical": "~pandas.Categorical", - "Path": "~~pathlib.Path", + "Path": "~pathlib.Path", # objects with abbreviated namespace (from pandas) "pd.Index": "~pandas.Index", "pd.NaT": "~pandas.NaT", + # Langchain + "LCTextSplitter": ":class:`~langchain_text_splitters.base.TextSplitter`", + "RCTextSplitter": ":class:`~langchain_text_splitters.character.RecursiveCharacterTextSplitter`", + # fixing ELM docstrings + "nx.DiGraph": ":class:`networkx.DiGraph`", + "ApiBase": ":class:`~elm.base.ApiBase`", + # objects from COMPASS + "AsyncDecisionTree": ":class:`~compass.common.tree.AsyncDecisionTree`", + "Jurisdiction": ":class:`~compass.utilities.location.Jurisdiction`", + "LLMCaller": ":class:`~compass.llm.calling.LLMCaller`", + "ChatLLMCaller": ":class:`~compass.llm.calling.ChatLLMCaller`", + "StructuredLLMCaller": ":class:`~compass.llm.calling.StructuredLLMCaller`", + "Service": ":class:`~compass.services.base.Service`", + "LLMService": ":class:`~compass.services.base.LLMService`", + "OpenAIService": ":class:`~compass.services.openai.OpenAIService`", + "TimeBoundedUsageTracker": ":class:`~compass.services.usage.TimeBoundedUsageTracker`", + "UsageTracker": ":class:`~compass.services.usage.UsageTracker`", + "ParseChunksWithMemory": ":class:`~compass.validation.content.ParseChunksWithMemory`", + "WindOrdinanceTextExtractor": ":class:`~compass.extraction.wind.ordinance.WindOrdinanceTextExtractor`", } diff --git a/docs/source/dev/README.rst b/docs/source/dev/README.rst index 332507ee3..6def65ac9 100644 --- a/docs/source/dev/README.rst +++ b/docs/source/dev/README.rst @@ -191,6 +191,9 @@ As such, please adhere to these guidelines: For example, use ``:class:`plotly.graph_objects.Figure```, which renders as :class:`plotly.graph_objects.Figure` * Networkx: ``networkx`` For example, use ``:class:`~networkx.MultiDiGraph```, which renders as :class:`~networkx.MultiDiGraph` + * langchain_text_splitters : ``langchain_text_splitters`` + For example, use ``:class:`~langchain_text_splitters.character.RecursiveCharacterTextSplitter```, + which renders as :class:`~langchain_text_splitters.character.RecursiveCharacterTextSplitter` * elm: ``elm`` For example, use ``:class:`elm.web.document.PDFDocument```, which renders as :class:`elm.web.document.PDFDocument` @@ -199,7 +202,7 @@ To check your docstring additions/updates, you can build a local version of the .. code-block:: shell - pixi r -e pdoc make-html + pixi r -e pdoc python-doc After running this command, simply open ``docs/_build/html/index.html`` using your favorite browser, e.g.: diff --git a/pixi.lock b/pixi.lock index e19d24886..17adb0187 100644 --- a/pixi.lock +++ b/pixi.lock @@ -261,7 +261,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/67/c3/135fdbbbf84e0979712df58e5e22b4f257b3f5e52a3c4aacf1b8abec0d09/matplotlib-3.10.6-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl - pypi: https://files.pythonhosted.org/packages/66/7a/ba7995d1f6b405c057e6f4bd5751fe667535b0ba84f65ee6eb1493bccb80/maxminddb-2.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/5c/c948539727ee833688958d711dd8237c1ccd04a2383ad26c84aec6705b7c/NREL_rex-0.2.99-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/cb/e7cd2f6161e30a4009cf38dd00024b1303197afcd4297081b0ccd21016a8/patchright-1.51.3-py3-none-manylinux1_x86_64.whl @@ -592,7 +592,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/9c/be/c443ea428fb2488a3ea7608714b1bd85a82738c45da21b447dc49e2f8e5d/matplotlib-3.10.6-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/41/21/05c8f50c1b4138516f2bde2810d32c97b84c6d0aefe7e1a1b41635241041/maxminddb-2.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/5c/c948539727ee833688958d711dd8237c1ccd04a2383ad26c84aec6705b7c/NREL_rex-0.2.99-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/09/e6126d32175f96ea963616debbb8e380e7c987ca913efeb59bf7e7f39438/patchright-1.51.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl @@ -870,7 +870,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl - pypi: https://files.pythonhosted.org/packages/ea/1a/7042f7430055d567cc3257ac409fcf608599ab27459457f13772c2d9778b/matplotlib-3.10.6-cp312-cp312-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/79/44/2703121c2dbba7d03c37294dd407cca2e31dc4542543b93808dd26fd144b/maxminddb-2.8.2-cp312-cp312-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/5c/c948539727ee833688958d711dd8237c1ccd04a2383ad26c84aec6705b7c/NREL_rex-0.2.99-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/55/d62c85fff36e9e9e515ee92407b02acb556e6832d4fbcc8624b638cf70bb/patchright-1.51.3-py3-none-macosx_11_0_universal2.whl @@ -1150,7 +1150,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/a9/5d/1d5f33f5b43f4f9e69e6a5fe1fb9090936ae7bc8e2ff6158e7a76542633b/matplotlib-3.10.6-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/c2/25/99e999e630b1a44936c5261827cc94def5eec82ae57a667a76d641b93925/maxminddb-2.8.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/5c/c948539727ee833688958d711dd8237c1ccd04a2383ad26c84aec6705b7c/NREL_rex-0.2.99-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/55/20/4df3f817c28938e22ee7c7c4b28d8b3a212e5a111c3bd9633bc410267daa/patchright-1.51.3-py3-none-macosx_11_0_arm64.whl @@ -1423,7 +1423,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/45/c3/994ef20eb4154ab84cc08d033834555319e4af970165e6c8894050af0b3c/matplotlib-3.10.6-cp312-cp312-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/63/50/25720ed19f2d62440b94a1333656cccf6c3c1ce2527ed9abf7b35e2557e1/maxminddb-2.8.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/d6/5c/c948539727ee833688958d711dd8237c1ccd04a2383ad26c84aec6705b7c/NREL_rex-0.2.99-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/e7/40fb618334dcdf7c5a316c0e7343c5cd82d3d866edc100d98e29bc945ecd/partd-1.4.2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/fd/97e3e26893904bdeff36d54e6ea5fe5f81a245a96c1b73ebe37e956ce11d/patchright-1.51.3-py3-none-win_amd64.whl @@ -1760,7 +1760,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/7a/ba7995d1f6b405c057e6f4bd5751fe667535b0ba84f65ee6eb1493bccb80/maxminddb-2.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/cb/e7cd2f6161e30a4009cf38dd00024b1303197afcd4297081b0ccd21016a8/patchright-1.51.3-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -2113,7 +2113,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/21/05c8f50c1b4138516f2bde2810d32c97b84c6d0aefe7e1a1b41635241041/maxminddb-2.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/09/e6126d32175f96ea963616debbb8e380e7c987ca913efeb59bf7e7f39438/patchright-1.51.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -2413,7 +2413,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/44/2703121c2dbba7d03c37294dd407cca2e31dc4542543b93808dd26fd144b/maxminddb-2.8.2-cp312-cp312-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/55/d62c85fff36e9e9e515ee92407b02acb556e6832d4fbcc8624b638cf70bb/patchright-1.51.3-py3-none-macosx_11_0_universal2.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -2713,7 +2713,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/25/99e999e630b1a44936c5261827cc94def5eec82ae57a667a76d641b93925/maxminddb-2.8.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/55/20/4df3f817c28938e22ee7c7c4b28d8b3a212e5a111c3bd9633bc410267daa/patchright-1.51.3-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -3006,7 +3006,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/50/25720ed19f2d62440b94a1333656cccf6c3c1ce2527ed9abf7b35e2557e1/maxminddb-2.8.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/fd/97e3e26893904bdeff36d54e6ea5fe5f81a245a96c1b73ebe37e956ce11d/patchright-1.51.3-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/0f/098488de02e3d52fc77e8d55c1467f6703701b6ea6788f40409bb8c00dd4/playwright-1.51.0-py3-none-win_amd64.whl @@ -3475,7 +3475,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/7a/ba7995d1f6b405c057e6f4bd5751fe667535b0ba84f65ee6eb1493bccb80/maxminddb-2.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/cb/e7cd2f6161e30a4009cf38dd00024b1303197afcd4297081b0ccd21016a8/patchright-1.51.3-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -3975,7 +3975,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/21/05c8f50c1b4138516f2bde2810d32c97b84c6d0aefe7e1a1b41635241041/maxminddb-2.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/09/e6126d32175f96ea963616debbb8e380e7c987ca913efeb59bf7e7f39438/patchright-1.51.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -4423,7 +4423,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/44/2703121c2dbba7d03c37294dd407cca2e31dc4542543b93808dd26fd144b/maxminddb-2.8.2-cp312-cp312-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/55/d62c85fff36e9e9e515ee92407b02acb556e6832d4fbcc8624b638cf70bb/patchright-1.51.3-py3-none-macosx_11_0_universal2.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -4871,7 +4871,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/25/99e999e630b1a44936c5261827cc94def5eec82ae57a667a76d641b93925/maxminddb-2.8.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/55/20/4df3f817c28938e22ee7c7c4b28d8b3a212e5a111c3bd9633bc410267daa/patchright-1.51.3-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -5313,7 +5313,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/50/25720ed19f2d62440b94a1333656cccf6c3c1ce2527ed9abf7b35e2557e1/maxminddb-2.8.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/fd/97e3e26893904bdeff36d54e6ea5fe5f81a245a96c1b73ebe37e956ce11d/patchright-1.51.3-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/0f/098488de02e3d52fc77e8d55c1467f6703701b6ea6788f40409bb8c00dd4/playwright-1.51.0-py3-none-win_amd64.whl @@ -5636,7 +5636,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/7a/ba7995d1f6b405c057e6f4bd5751fe667535b0ba84f65ee6eb1493bccb80/maxminddb-2.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/cb/e7cd2f6161e30a4009cf38dd00024b1303197afcd4297081b0ccd21016a8/patchright-1.51.3-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -5991,7 +5991,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/21/05c8f50c1b4138516f2bde2810d32c97b84c6d0aefe7e1a1b41635241041/maxminddb-2.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/09/e6126d32175f96ea963616debbb8e380e7c987ca913efeb59bf7e7f39438/patchright-1.51.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -6295,7 +6295,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/44/2703121c2dbba7d03c37294dd407cca2e31dc4542543b93808dd26fd144b/maxminddb-2.8.2-cp312-cp312-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/55/d62c85fff36e9e9e515ee92407b02acb556e6832d4fbcc8624b638cf70bb/patchright-1.51.3-py3-none-macosx_11_0_universal2.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -6599,7 +6599,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/25/99e999e630b1a44936c5261827cc94def5eec82ae57a667a76d641b93925/maxminddb-2.8.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/55/20/4df3f817c28938e22ee7c7c4b28d8b3a212e5a111c3bd9633bc410267daa/patchright-1.51.3-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -6895,7 +6895,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/71/8b/af4b541d2a6e1ea2021dc95f5fd75fc5679462e5b06b155eed65b25cc2eb/make-0.1.6.post2-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/50/25720ed19f2d62440b94a1333656cccf6c3c1ce2527ed9abf7b35e2557e1/maxminddb-2.8.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/fd/97e3e26893904bdeff36d54e6ea5fe5f81a245a96c1b73ebe37e956ce11d/patchright-1.51.3-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/0f/098488de02e3d52fc77e8d55c1467f6703701b6ea6788f40409bb8c00dd4/playwright-1.51.0-py3-none-win_amd64.whl @@ -7216,7 +7216,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/66/7a/ba7995d1f6b405c057e6f4bd5751fe667535b0ba84f65ee6eb1493bccb80/maxminddb-2.8.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/70/cb/e7cd2f6161e30a4009cf38dd00024b1303197afcd4297081b0ccd21016a8/patchright-1.51.3-py3-none-manylinux1_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -7568,7 +7568,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/41/21/05c8f50c1b4138516f2bde2810d32c97b84c6d0aefe7e1a1b41635241041/maxminddb-2.8.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/81/09/e6126d32175f96ea963616debbb8e380e7c987ca913efeb59bf7e7f39438/patchright-1.51.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -7870,7 +7870,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/79/44/2703121c2dbba7d03c37294dd407cca2e31dc4542543b93808dd26fd144b/maxminddb-2.8.2-cp312-cp312-macosx_10_13_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1a/55/d62c85fff36e9e9e515ee92407b02acb556e6832d4fbcc8624b638cf70bb/patchright-1.51.3-py3-none-macosx_11_0_universal2.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -8172,7 +8172,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c2/25/99e999e630b1a44936c5261827cc94def5eec82ae57a667a76d641b93925/maxminddb-2.8.2-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/55/20/4df3f817c28938e22ee7c7c4b28d8b3a212e5a111c3bd9633bc410267daa/patchright-1.51.3-py3-none-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e0/e3/79a2ad7ca71160fb6442772155389881672c98bd44c6022303ce242cbfb9/pdftotext-2.2.2.tar.gz @@ -8466,7 +8466,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/b0/42/327554649ed2dd5ce59d3f5da176c7be20f9352c7c6c51597293660b7b08/language_tags-1.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/bb/dc/ff4f119cd4d783742c9648a03e0ba5c2b52fc385b2ae9f0d32acf3a78241/litellm-1.77.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/63/50/25720ed19f2d62440b94a1333656cccf6c3c1ce2527ed9abf7b35e2557e1/maxminddb-2.8.2-cp312-cp312-win_amd64.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/29/15/b6b2b49b4e5e17f0d2c1006d609b8adb13aa96944c6b8b5eb02a39df99a4/NREL_rex-0.2.98-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6e/fd/97e3e26893904bdeff36d54e6ea5fe5f81a245a96c1b73ebe37e956ce11d/patchright-1.51.3-py3-none-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/20/0f/098488de02e3d52fc77e8d55c1467f6703701b6ea6788f40409bb8c00dd4/playwright-1.51.0-py3-none-win_amd64.whl @@ -8707,7 +8707,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/80/e5/5e22c5bf96a64bdd43518b1834c6d95a4922cc2066b7d8e467dae9b6cee6/multidict-6.6.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/66/404e1cea32ebd39f519d757b7c0c9e5a71e0ce2bac4a70d2098d3ab248f3/nrel_rex-0.4.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9a/a5/bf3db6e66c4b160d6ea10b534c381a1955dfab34cb1017ea93aa33c70ed3/numpy-2.3.3-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl - pypi: https://files.pythonhosted.org/packages/38/87/6ad18ce0e7b910e3706480451df48ff9e0af3b55e5db565adafd68a0706a/openai-1.108.1-py3-none-any.whl @@ -9024,7 +9024,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/c4/1c/8a10c1c25b23156e63b12165a929d8eb49a6ed769fdbefb06e6f07c1e50d/multidict-6.6.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/66/404e1cea32ebd39f519d757b7c0c9e5a71e0ce2bac4a70d2098d3ab248f3/nrel_rex-0.4.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/23/83/377f84aaeb800b64c0ef4de58b08769e782edcefa4fea712910b6f0afd3c/numpy-2.3.3-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl - pypi: https://files.pythonhosted.org/packages/38/87/6ad18ce0e7b910e3706480451df48ff9e0af3b55e5db565adafd68a0706a/openai-1.108.1-py3-none-any.whl @@ -9294,7 +9294,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/4c/aa/8b6f548d839b6c13887253af4e29c939af22a18591bfb5d0ee6f1931dae8/multidict-6.6.4-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/66/404e1cea32ebd39f519d757b7c0c9e5a71e0ce2bac4a70d2098d3ab248f3/nrel_rex-0.4.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7d/b9/984c2b1ee61a8b803bf63582b4ac4242cf76e2dbd663efeafcb620cc0ccb/numpy-2.3.3-cp313-cp313-macosx_10_13_x86_64.whl - pypi: https://files.pythonhosted.org/packages/38/87/6ad18ce0e7b910e3706480451df48ff9e0af3b55e5db565adafd68a0706a/openai-1.108.1-py3-none-any.whl @@ -9566,7 +9566,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/eb/c6/f5e97e5d99a729bc2aa58eb3ebfa9f1e56a9b517cc38c60537c81834a73f/multidict-6.6.4-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/66/404e1cea32ebd39f519d757b7c0c9e5a71e0ce2bac4a70d2098d3ab248f3/nrel_rex-0.4.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a6/e4/07970e3bed0b1384d22af1e9912527ecbeb47d3b26e9b6a3bced068b3bea/numpy-2.3.3-cp313-cp313-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/38/87/6ad18ce0e7b910e3706480451df48ff9e0af3b55e5db565adafd68a0706a/openai-1.108.1-py3-none-any.whl @@ -9819,7 +9819,7 @@ environments: - pypi: https://files.pythonhosted.org/packages/9d/34/746696dffff742e97cd6a23da953e55d0ea51fa601fa2ff387b3edcfaa2c/multidict-6.6.4-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/eb/8d/776adee7bbf76365fdd7f2552710282c79a4ead5d2a46408c9043a2b70ba/networkx-3.5-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/4d/66/7d9e26593edda06e8cb531874633f7c2372279c3b0f46235539fe546df8b/nltk-3.9.1-py3-none-any.whl - - pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a0/66/404e1cea32ebd39f519d757b7c0c9e5a71e0ce2bac4a70d2098d3ab248f3/nrel_rex-0.4.3-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/1b/b5/263ebbbbcede85028f30047eab3d58028d7ebe389d6493fc95ae66c636ab/numpy-2.3.3-cp313-cp313-win_amd64.whl - pypi: https://files.pythonhosted.org/packages/38/87/6ad18ce0e7b910e3706480451df48ff9e0af3b55e5db565adafd68a0706a/openai-1.108.1-py3-none-any.whl @@ -23377,15 +23377,15 @@ packages: timestamp: 1733408419340 - pypi: ./ name: nrel-compass - version: 0.9.1.dev11+g0bb307f.d20251018 - sha256: 3284c40a700567c6bd4489734f1f941862baf893ef62b3831d9866759619a139 + version: 0.9.1.dev34+g66795ea.d20251021 + sha256: e97408171f135facbf5e139a74c893309252e6db67972a730bedc97e859655cb requires_dist: - click>=8.1.7,<9 - html5lib>=1.1,<2 - langchain-text-splitters>=1.0.0,<2 - networkx>=3.4.2,<4 - nltk>=3.9.1,<4 - - nrel-elm>=0.0.29,<1 + - nrel-elm>=0.0.30,<1 - openai>=1.1.0 - pandas>=2.2.3,<3 - pdftotext>=2.2.2,<3 @@ -23421,10 +23421,10 @@ packages: - twine>=6.1.0,<7 ; extra == 'build' requires_python: '>=3.12' editable: true -- pypi: https://files.pythonhosted.org/packages/21/fc/884f5df7dcbd561a2be2f6c94f1cf47f7180ee304217a46e3c98f47ee2c6/nrel_elm-0.0.29-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/e9/c3/ccfcdc784727414ba21bfcdd8b551d97daadc694d7ccbc9f7bf3568d9f21/NREL_elm-0.0.30-py3-none-any.whl name: nrel-elm - version: 0.0.29 - sha256: b0dca139b3ecfaed580763665e5ba495cad44b52dcadc1cd069e196847f62c63 + version: 0.0.30 + sha256: c52ebb189db0f152ad2ec9adce0ef6d39fe0f7b7b5c65b664ec909621784c1f9 requires_dist: - openai>=1.1.0 - aiohttp diff --git a/pyproject.toml b/pyproject.toml index 7d7d0122e..aee8c0f67 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -37,7 +37,7 @@ dependencies = [ "langchain-text-splitters>=1.0.0,<2", "networkx>=3.4.2,<4", "nltk>=3.9.1,<4", - "nrel-elm>=0.0.29,<1", + "nrel-elm>=0.0.30,<1", "openai>=1.1.0", "pandas>=2.2.3,<3", "pdftotext>=2.2.2,<3", @@ -105,7 +105,7 @@ fallback_version = "9999" git_describe_command = [ "git", "describe", "--dirty", "--tags", "--long", "--match", "v*[0-9]*" ] version_file = "compass/_version.py" -[tool.pixi.project] +[tool.pixi.workspace] channels = ["conda-forge", "microsoft", "anaconda", "main"] platforms = ["win-64", "osx-arm64", "osx-64", "linux-64", "linux-aarch64"] @@ -131,7 +131,7 @@ tests-p = "pytest --durations=20 tests/python" # it = "pytest --durations=20 tests/integration" [tool.pixi.feature.python-doc.tasks] -make-html = { cmd = "make html", cwd = "docs"} +python-doc = { cmd = "make html", cwd = "docs", env = { SPHINXOPTS = "--fail-on-warning --keep-going --nitpicky" }} [tool.pixi.feature.python-build.tasks] build-wheels = { cmd = "uv build --sdist --wheel --out-dir dist/ ." } diff --git a/tests/python/web/test_web_crawl.py b/tests/python/web/test_web_crawl.py index 63d26d9e1..1fc62af7a 100644 --- a/tests/python/web/test_web_crawl.py +++ b/tests/python/web/test_web_crawl.py @@ -5,20 +5,20 @@ import pytest from crawl4ai.models import Link as TestLink -from compass.web.website_crawl import Link +from compass.web.website_crawl import _Link def test_link_equality(): """Test equality of Link instances""" - assert Link() == Link() - assert Link() == Link(title="test") - assert Link() == Link(text="test") - assert Link() == Link(base_domain="test") - assert Link() != Link(href="test") + assert _Link() == _Link() + assert _Link() == _Link(title="test") + assert _Link() == _Link(text="test") + assert _Link() == _Link(base_domain="test") + assert _Link() != _Link(href="test") link1 = TestLink(title="test", href="http://example.com/test") - link2 = Link(title="Test", href="http://example.com/test") + link2 = _Link(title="Test", href="http://example.com/test") assert link1 == link2 assert link2 == "http://example.com/test" @@ -31,15 +31,15 @@ def test_link_equality(): "http://example.com/test3", } - assert "http://example.com/test" in {link2} + assert link2 == "http://example.com/test" def test_link_consistent_domain(): """Test `Link.consistent_domain` property""" - assert Link().consistent_domain - assert not Link(base_domain="example.com").consistent_domain - assert Link( + assert _Link().consistent_domain + assert not _Link(base_domain="example.com").consistent_domain + assert _Link( href="example.com/test", base_domain="example.com" ).consistent_domain @@ -47,10 +47,10 @@ def test_link_consistent_domain(): def test_link_resembles_pdf(): """Test `Link.resembles_pdf` property""" - assert not Link().resembles_pdf - assert Link(title="example.pdf").consistent_domain - assert Link(href="example.pdf").consistent_domain - assert not Link(base_domain="example.pdf").consistent_domain + assert not _Link().resembles_pdf + assert _Link(title="example.pdf").resembles_pdf + assert _Link(href="example.pdf").resembles_pdf + assert not _Link(base_domain="example.pdf").resembles_pdf if __name__ == "__main__":