Skip to content

Commit 6f9c6c5

Browse files
Merge pull request #31 from cityofaustin/charlie/new-task-order-fields
new fields for Task Orders
2 parents 09b942b + 75442c1 commit 6f9c6c5

8 files changed

Lines changed: 102 additions & 15 deletions

File tree

.dockerignore

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,13 @@
1-
env_file
2-
.git
3-
*.env
1+
# Ignores everything
2+
*
3+
4+
# Only allows the following files:
5+
!config.py
6+
!fdu_program_tagging.py
7+
!prefix_maps.py
8+
!queries.py
9+
!s3_to_knack.py
10+
!s3_to_socrata.py
11+
!upload_to_s3.py
12+
!utils.py
13+
!requirements.txt

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,3 +75,10 @@ Required environmental variables, which are available in the DTS credential stor
7575
- `AWS_SECRET_ACCESS_KEY`: The secret key for your AWS account
7676
- `KNACK_APP_ID`: The Knack app ID of the destiantion knack app
7777
- `KNACK_API_KEY`: The kanck API key of the destination knack app
78+
79+
You can also pass a `-p` or `--progress-bar` flag to see a progress bar while the script is running. This can be helpful
80+
if you are running this script on a large dataset for the first time.
81+
82+
```shell
83+
$ python s3_to_knack.py task_orders data-tracker -p
84+
```

config.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,18 @@ def stringify_value(value):
112112
"finance-purchasing": "field_997",
113113
"handler": add_comma_separator,
114114
},
115+
{
116+
"src": "LN_AMOUNT",
117+
"data-tracker": "field_5365",
118+
"finance-purchasing": "field_1350",
119+
"handler": add_comma_separator,
120+
},
121+
{
122+
"src": "TASK_ORDER_REM_AMT",
123+
"data-tracker": "field_5366",
124+
"finance-purchasing": "field_1351",
125+
"handler": add_comma_separator,
126+
},
115127
{
116128
"src": "TASK_ORDER_ESTIMATOR",
117129
"data-tracker": "field_4495",

env_template

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# AWS S3 (1pass: atd-finance-data)
2+
AWS_ACCESS_KEY_ID=
3+
AWS_SECRET_ACCESS_KEY=
4+
BUCKET=
5+
6+
# Knack API (depends on which Knack app you want to update.)
7+
KNACK_API_KEY=
8+
KNACK_APP_ID=
9+
10+
# Finance Data Warehouse Oracle DB (1pass: atd-finance-data)
11+
HOST=
12+
PASSWORD=
13+
PORT=
14+
SERVICE=
15+
USER=
16+
17+
# 1pass: Socrata Key ID, Secret, and Token
18+
SO_USER=<apiKeyId>
19+
SO_PASS=<apiKeySecret>
20+
SO_TOKEN=<appToken>
21+
SO_WEB=datahub.austintexas.gov
22+
23+
# Socrata Dataset Resource IDs
24+
TASK_DATASET=ggav-ufvc
25+
FDU_DATASET=jega-nqf6
26+
DEPT_UNITS_DATASET=bgrt-2m2z
27+
SUBPROJECTS_DATASET=x454-x7cu

queries.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
atd_tk.CHARGED_AMOUNT,
1919
atd_tk.TASK_ORDER_BAL,
2020
atd_tk.TASK_ORDER_ESTIMATOR,
21+
atd_tk.LN_AMOUNT,
22+
atd_tk.TASK_ORDER_REM_AMT,
2123
buyer_tk.BYR_FDU
2224
FROM
2325
DEPT_2400_TK_VW atd_tk

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ knackpy==1.0.*
33
sodapy==2.1.*
44
boto3==1.19.*
55
oracledb==2.1.*
6+
tqdm==4.67.*

s3_to_knack.py

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import boto3
1313
import knackpy
14+
from tqdm import tqdm
1415

1516
from config import FIELD_MAPS
1617

@@ -35,6 +36,17 @@ def cli_args():
3536
choices=["data-tracker", "finance-purchasing"],
3637
help="The name of the destination Knack app",
3738
)
39+
parser.add_argument(
40+
"--progress-bar",
41+
"-p",
42+
action="store_true",
43+
help=(
44+
"Display a tqdm progress bar instead of the default periodic log "
45+
"messages. Not recommended when running under Airflow, since the "
46+
"bar's carriage-return redraws don't render cleanly in Airflow's "
47+
"log viewer."
48+
),
49+
)
3850
return parser.parse_args()
3951

4052

@@ -182,10 +194,10 @@ def coalesce_records(records_current, coalesce_fields, current_pk, separator=",\
182194
return list(index.values())
183195

184196

185-
def process_record(record, knack_obj, app, count):
197+
def process_record(record, knack_obj, app, count=None):
186198
method = "create" if not record.get("id") else "update"
187199
app.record(data=record, method=method, obj=knack_obj)
188-
if count % 10 == 0:
200+
if count is not None and count % 10 == 0:
189201
logging.info(f"{count} records processed so far...")
190202

191203

@@ -234,17 +246,31 @@ def main():
234246
logging.info(f"{len(todos)} records to process.")
235247

236248
# Process todos with 10 workers
237-
count = 0
238249
with ThreadPoolExecutor(max_workers=10) as executor:
239-
futures = []
240-
for record in todos:
241-
futures.append(
242-
executor.submit(process_record, record, knack_obj, app, count)
243-
)
244-
count += 1
245-
246-
for future in futures:
247-
future.result() # This will re-raise any exceptions encountered in the threads
250+
if args.progress_bar:
251+
# tqdm progress bar (best for interactive/terminal use; the
252+
# carriage-return redraws don't render cleanly in Airflow logs)
253+
futures = [
254+
executor.submit(process_record, record, knack_obj, app)
255+
for record in todos
256+
]
257+
for future in tqdm(
258+
futures, total=len(futures), desc="Processing records", unit="rec"
259+
):
260+
future.result() # This will re-raise any exceptions encountered in the threads
261+
else:
262+
# Default: periodic log messages, which render cleanly in Airflow's
263+
# log viewer
264+
futures = []
265+
count = 0
266+
for record in todos:
267+
futures.append(
268+
executor.submit(process_record, record, knack_obj, app, count)
269+
)
270+
count += 1
271+
272+
for future in futures:
273+
future.result() # This will re-raise any exceptions encountered in the threads
248274

249275

250276
if __name__ == "__main__":

s3_to_socrata.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ def transform_tks(data):
153153
"CHARGED_AMOUNT": "CHARGEDAMOUNT",
154154
"TASK_ORDER_BAL": "BALANCE",
155155
"BYR_FDU": "BUYER_FDUS",
156+
"LN_AMOUNT": "LN_AMOUNT",
157+
"TASK_ORDER_REM_AMT": "TASK_ORDER_REM_AMT",
156158
}
157159

158160
replaced_data = []

0 commit comments

Comments
 (0)