diff --git a/compass/services/threaded.py b/compass/services/threaded.py index f10a15589..dbe5ab562 100644 --- a/compass/services/threaded.py +++ b/compass/services/threaded.py @@ -613,11 +613,12 @@ def _dump_jurisdiction_info( "subdivision": jurisdiction.subdivision_name, "jurisdiction_type": jurisdiction.type, "FIPS": jurisdiction.code, - "found": False, "total_time": seconds_elapsed, "total_time_string": str(timedelta(seconds=seconds_elapsed)), "jurisdiction_website": None, "cost": None, + "found": False, + "num_features_extracted": None, "documents": None, } @@ -630,6 +631,9 @@ def _dump_jurisdiction_info( new_info["documents"] = [ _compile_doc_info(doc) for doc in extraction_context.data_docs ] + new_info["num_features_extracted"] = extraction_context.attrs.get( + "num_features_extracted" + ) new_info["jurisdiction_website"] = extraction_context.attrs.get( "jurisdiction_website" ) @@ -645,7 +649,6 @@ def _compile_doc_info(doc): out_fp = doc.attrs.get("source_fp", doc.attrs.get("out_fp")) return { "source": doc.attrs.get("source"), - "num_features_extracted": doc.attrs.get("num_features_extracted"), "effective_year": year if year is not None and year > 0 else None, "effective_month": month if month is not None and month > 0 else None, "effective_day": day if day is not None and day > 0 else None, diff --git a/compass/utilities/parsing.py b/compass/utilities/parsing.py index 0b477dead..901285796 100644 --- a/compass/utilities/parsing.py +++ b/compass/utilities/parsing.py @@ -197,7 +197,7 @@ def num_ordinances_dataframe(data, exclude_features=None): mask = ~data["feature"].str.casefold().isin(exclude_features) data = data[mask].copy() - return ordinances_bool_index(data).sum() + return int(ordinances_bool_index(data).sum()) def ordinances_bool_index(data): diff --git a/tests/python/unit/services/test_services_threaded.py b/tests/python/unit/services/test_services_threaded.py index 192a1341f..6eb4397bf 100644 --- a/tests/python/unit/services/test_services_threaded.py +++ b/tests/python/unit/services/test_services_threaded.py @@ -542,6 +542,7 @@ async def test_jurisdiction_updater_process(tmp_path): doc, attrs={ "jurisdiction_website": "http://jurisdiction.gov", + "num_features_extracted": 1, }, ) context.data_docs = [doc] @@ -572,6 +573,7 @@ async def test_jurisdiction_updater_process(tmp_path): second = data["jurisdictions"][1] assert second["found"] is True assert second["jurisdiction_website"] == "http://jurisdiction.gov" + assert second["num_features_extracted"] == 1 assert pytest.approx(second["cost"]) == 22.5 assert second["documents"][0]["ord_filename"] == "doc.pdf" assert second["documents"][0]["effective_year"] == 2023 diff --git a/tests/python/unit/utilities/test_utilities_parsing.py b/tests/python/unit/utilities/test_utilities_parsing.py index 55a2611ec..62d81e6d1 100644 --- a/tests/python/unit/utilities/test_utilities_parsing.py +++ b/tests/python/unit/utilities/test_utilities_parsing.py @@ -150,6 +150,23 @@ def test_num_ordinances_dataframe_with_values(): assert num_ordinances_dataframe(data) == 3 +def test_num_ordinances_dataframe_returns_int_with_missing_values(): + """Test ordinance count type with NaN and None values""" + + data = pd.DataFrame( + { + "feature": ["setback", "height", "noise"], + "value": [100, np.nan, None], + "summary": [None, "test", None], + } + ) + + result = num_ordinances_dataframe(data) + + assert result == 2 + assert type(result) is int + + def test_num_ordinances_dataframe_with_exclude(): """Test `num_ordinances_dataframe` with excluded features""" @@ -163,6 +180,25 @@ def test_num_ordinances_dataframe_with_exclude(): assert num_ordinances_dataframe(data, exclude_features=["height"]) == 2 +def test_num_ordinances_dataframe_with_exclude_all_features(): + """Test ordinance count when exclusions remove all features""" + + data = pd.DataFrame( + { + "feature": ["setback", "HEIGHT", "noise"], + "value": [100, 200, 300], + "summary": ["test", "test", "test"], + } + ) + + result = num_ordinances_dataframe( + data, exclude_features=["setback", "height", "noise"] + ) + + assert result == 0 + assert type(result) is int + + def test_ordinances_bool_index_none(): """Test `ordinances_bool_index` with None data"""