Merge pull request #10 from regulatorystudies/revisions_2024_05
Browse files- README.md +4 -2
- app.py +26 -5
- modules/__init__.py +6 -0
- modules/get_rules_in_window.py +3 -6
- tests/test_get_data.py +32 -0
- tests/test_process_data.py +23 -0
README.md
CHANGED
@@ -11,6 +11,8 @@ python_version: 3.11
|
|
11 |
|
12 |
## Description
|
13 |
|
14 |
-
|
15 |
|
16 |
-
|
|
|
|
|
|
11 |
|
12 |
## Description
|
13 |
|
14 |
+
Dashboard app tracking rules falling within the Congressional Review Act (CRA) window during presidential transitions.
|
15 |
|
16 |
+
**[Link to web accessible dashboard](https://regulatorystudies-cra-window-rules.hf.space/)**
|
17 |
+
|
18 |
+
Developed by the [GW Regulatory Studies Center](https://go.gwu.edu/regstudies).
|
app.py
CHANGED
@@ -34,7 +34,7 @@ with ui.sidebar(title="Settings"):
|
|
34 |
|
35 |
ui.input_switch("switch", "Show significant rules in plots", False)
|
36 |
|
37 |
-
ui.input_select("menu_agency", "Select agencies", choices=["all"] + AGENCIES, selected="all")
|
38 |
|
39 |
#ui.input_checkbox_group(
|
40 |
# "significant",
|
@@ -150,9 +150,30 @@ with ui.accordion(open=False):
|
|
150 |
label="Download data as CSV",
|
151 |
filename=f"rules_in_cra_window_accessed_{date.today()}.csv",
|
152 |
)
|
153 |
-
async def download(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
154 |
await asyncio.sleep(0.25)
|
155 |
-
yield filtered_df().to_csv(index=False)
|
156 |
|
157 |
with ui.accordion(open=False):
|
158 |
|
@@ -187,8 +208,8 @@ def filtered_df():
|
|
187 |
filt_df = filt_df.loc[filt_df["publication_date"] >= datetime.combine(input.start_date(), time(0, 0))]
|
188 |
|
189 |
# filter agencies
|
190 |
-
if input.menu_agency()
|
191 |
-
bool_agency = [True if input.menu_agency()
|
192 |
filt_df = filt_df.loc[bool_agency]
|
193 |
|
194 |
return filt_df
|
|
|
34 |
|
35 |
ui.input_switch("switch", "Show significant rules in plots", False)
|
36 |
|
37 |
+
ui.input_select("menu_agency", "Select agencies", choices=["all"] + AGENCIES, selected="all", multiple=True)
|
38 |
|
39 |
#ui.input_checkbox_group(
|
40 |
# "significant",
|
|
|
150 |
label="Download data as CSV",
|
151 |
filename=f"rules_in_cra_window_accessed_{date.today()}.csv",
|
152 |
)
|
153 |
+
async def download(
|
154 |
+
output_cols: tuple | list = (
|
155 |
+
"document_number",
|
156 |
+
"citation",
|
157 |
+
"publication_date",
|
158 |
+
"title",
|
159 |
+
"type",
|
160 |
+
"action",
|
161 |
+
"abstract",
|
162 |
+
"docket_ids",
|
163 |
+
"json_url",
|
164 |
+
"html_url",
|
165 |
+
"agencies",
|
166 |
+
"independent_reg_agency",
|
167 |
+
"parent_slug",
|
168 |
+
"subagency_slug",
|
169 |
+
"president_id",
|
170 |
+
"significant",
|
171 |
+
"3f1_significant",
|
172 |
+
"other_significant"
|
173 |
+
)
|
174 |
+
):
|
175 |
await asyncio.sleep(0.25)
|
176 |
+
yield filtered_df().loc[:, output_cols].to_csv(index=False)
|
177 |
|
178 |
with ui.accordion(open=False):
|
179 |
|
|
|
208 |
filt_df = filt_df.loc[filt_df["publication_date"] >= datetime.combine(input.start_date(), time(0, 0))]
|
209 |
|
210 |
# filter agencies
|
211 |
+
if (input.menu_agency() is not None) and ("all" not in input.menu_agency()):
|
212 |
+
bool_agency = [True if sum(selected in agency for selected in input.menu_agency()) > 0 else False for agency in filt_df["parent_slug"]]
|
213 |
filt_df = filt_df.loc[bool_agency]
|
214 |
|
215 |
return filt_df
|
modules/__init__.py
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# see: https://docs.python.org/3.11/tutorial/modules.html#packages
|
2 |
+
__all__ = [
|
3 |
+
"get_rules_in_window",
|
4 |
+
"search_columns",
|
5 |
+
"significant",
|
6 |
+
]
|
modules/get_rules_in_window.py
CHANGED
@@ -18,13 +18,13 @@ from plotnine import (
|
|
18 |
try:
|
19 |
from search_columns import search_columns, SearchError
|
20 |
from significant import get_significant_info
|
21 |
-
except ModuleNotFoundError:
|
22 |
from .search_columns import search_columns, SearchError
|
23 |
from .significant import get_significant_info
|
24 |
|
25 |
|
26 |
METADATA, _ = AgencyMetadata().get_agency_metadata()
|
27 |
-
START_DATE = "2024-
|
28 |
GET_SIGNIFICANT = True if date.fromisoformat(START_DATE) >= date(2023, 4, 6) else False
|
29 |
|
30 |
|
@@ -294,11 +294,8 @@ def get_rules_in_window(start_date: str, get_significant: bool = True):
|
|
294 |
|
295 |
|
296 |
def get_list_agencies(start_date, agency_column: str = "agency", metadata: dict | None = None, significant: bool = True):
|
297 |
-
|
298 |
df, _ = get_rules_in_window(start_date, get_significant=significant)
|
299 |
-
df_agency = groupby_agency(df, metadata=metadata, significant=significant)
|
300 |
-
print(df_agency.columns)
|
301 |
-
|
302 |
return sorted(list(set(df_agency.loc[df_agency[agency_column].notna(), agency_column].to_list())))
|
303 |
|
304 |
|
|
|
18 |
try:
|
19 |
from search_columns import search_columns, SearchError
|
20 |
from significant import get_significant_info
|
21 |
+
except (ModuleNotFoundError, ImportError):
|
22 |
from .search_columns import search_columns, SearchError
|
23 |
from .significant import get_significant_info
|
24 |
|
25 |
|
26 |
METADATA, _ = AgencyMetadata().get_agency_metadata()
|
27 |
+
START_DATE = "2024-01-01"
|
28 |
GET_SIGNIFICANT = True if date.fromisoformat(START_DATE) >= date(2023, 4, 6) else False
|
29 |
|
30 |
|
|
|
294 |
|
295 |
|
296 |
def get_list_agencies(start_date, agency_column: str = "agency", metadata: dict | None = None, significant: bool = True):
|
|
|
297 |
df, _ = get_rules_in_window(start_date, get_significant=significant)
|
298 |
+
df_agency = groupby_agency(df, metadata=metadata, significant=significant)
|
|
|
|
|
299 |
return sorted(list(set(df_agency.loc[df_agency[agency_column].notna(), agency_column].to_list())))
|
300 |
|
301 |
|
tests/test_get_data.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from datetime import date
|
2 |
+
|
3 |
+
from modules.get_rules_in_window import (
|
4 |
+
get_date_range,
|
5 |
+
get_rules,
|
6 |
+
)
|
7 |
+
|
8 |
+
|
9 |
+
def test_get_date_range(start_str: str = "2024-05-01"):
|
10 |
+
|
11 |
+
start_date = date.fromisoformat(start_str)
|
12 |
+
end_year = start_date.year + 1
|
13 |
+
|
14 |
+
dates_str = get_date_range(start_str)
|
15 |
+
assert isinstance(dates_str, dict)
|
16 |
+
assert (
|
17 |
+
dates_str.get("start") == start_str
|
18 |
+
and dates_str.get("end") == f"{end_year}-01-31"
|
19 |
+
and dates_str.get("transition_year") == end_year
|
20 |
+
)
|
21 |
+
|
22 |
+
|
23 |
+
def test_get_rules(
|
24 |
+
date_range: dict = {
|
25 |
+
"start": "2024-05-01",
|
26 |
+
"end": "2024-05-10",
|
27 |
+
"transition_year": 2025,
|
28 |
+
}
|
29 |
+
):
|
30 |
+
results = get_rules(date_range)
|
31 |
+
assert isinstance(results, list)
|
32 |
+
assert all(isinstance(item, dict) for item in results)
|
tests/test_process_data.py
ADDED
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import pytest
|
2 |
+
from fr_toolbelt.api_requests import get_documents_by_date
|
3 |
+
from pandas import DataFrame
|
4 |
+
|
5 |
+
from modules.get_rules_in_window import (
|
6 |
+
format_documents,
|
7 |
+
)
|
8 |
+
|
9 |
+
|
10 |
+
START = "2024-03-01"
|
11 |
+
END = "2024-04-30"
|
12 |
+
|
13 |
+
|
14 |
+
#@pytest.fixture
|
15 |
+
def temp_documents():
|
16 |
+
return get_documents_by_date(START, end_date=END, document_types=("RULE", ))[0]
|
17 |
+
TEMP_DOCUMENTS = temp_documents()
|
18 |
+
|
19 |
+
|
20 |
+
def test_format_documents():
|
21 |
+
|
22 |
+
formatted = format_documents(TEMP_DOCUMENTS)
|
23 |
+
assert isinstance(formatted, DataFrame)
|