Skip to content

Commit d763434

Browse files
committed
add --limit and --write args to buildUserHistory.py. Address dependabot issues
1 parent 6d4106d commit d763434

2 files changed

Lines changed: 44 additions & 15 deletions

File tree

ide/shell_cmds/buildUserHistory.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,39 @@
88
Usage (local emulator):
99
DATASTORE_EMULATOR_HOST=localhost:8081 python ide/shell_cmds/buildUserHistory.py
1010
11+
Usage (dry-run on first N users, no write):
12+
GOOGLE_CLOUD_PROJECT=glowscript-py38 python ide/shell_cmds/buildUserHistory.py --limit 500
13+
14+
Usage (limited run + write):
15+
GOOGLE_CLOUD_PROJECT=glowscript-py38 python ide/shell_cmds/buildUserHistory.py --limit 500 --write
16+
1117
Cost: ~$0.16 (reads ~315k User entities). Run once only.
1218
"""
1319

20+
import argparse
1421
from collections import defaultdict
1522
from datetime import datetime, timezone
1623
import json
1724
import os
25+
import sys
1826

1927
from google.cloud import ndb
2028
from ide.models import User, Setting
2129

2230

23-
def build_history(client):
31+
def build_history(client, limit=None, write=True):
2432
monthly_new = defaultdict(int)
2533
count = 0
2634
skipped = 0
2735

2836
with client.context():
29-
for user in User.query(): # NDB iterates in batches — does not load all into memory
37+
query = User.query()
38+
if limit:
39+
query = query.fetch(limit)
40+
else:
41+
query = query.iter() # NDB iterates in batches — does not load all into memory
42+
43+
for user in query:
3044
count += 1
3145
if count % 10000 == 0:
3246
print(f" {count} users processed...")
@@ -56,29 +70,44 @@ def build_history(client):
5670
'points': points,
5771
}
5872

73+
print(f"Built {len(points)} monthly data points")
74+
if points:
75+
print(f"Latest: {points[-1]}")
76+
77+
if not write:
78+
print("Dry-run: skipping Datastore write (pass --write to persist)")
79+
return
80+
5981
existing = ndb.Key('Setting', 'user_count_history').get()
6082
if not existing:
6183
existing = Setting(id='user_count_history')
6284
existing.value = json.dumps(history)
6385
try:
6486
existing.put()
6587
except Exception as e:
66-
import sys
6788
print(f"ERROR: Failed to store user history: {e}", file=sys.stderr)
6889
sys.exit(1)
6990

7091
print(f"Stored {len(points)} monthly data points")
71-
if points:
72-
print(f"Latest: {points[-1]}")
7392

7493

7594
if __name__ == '__main__':
76-
import sys
95+
parser = argparse.ArgumentParser()
96+
parser.add_argument('--limit', type=int, default=None,
97+
help='Process only the first N users (implies dry-run unless --write is also set)')
98+
parser.add_argument('--write', action='store_true',
99+
help='Write results to Datastore (required when using --limit; always writes without --limit)')
100+
args = parser.parse_args()
101+
102+
write = args.write if args.limit else True
103+
77104
project = os.environ.get('GOOGLE_CLOUD_PROJECT', 'glowscript')
78105
emulator = os.environ.get('DATASTORE_EMULATOR_HOST')
79106
client = ndb.Client(project=project)
80107
print(f"Connecting to {'emulator at ' + emulator if emulator else 'production Datastore'}...")
108+
if args.limit:
109+
print(f"Limit: {args.limit} users ({'will write' if write else 'dry-run, no write'})")
81110
try:
82-
build_history(client)
111+
build_history(client, limit=args.limit, write=write)
83112
finally:
84113
client.close()

requirements.txt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
async-timeout==4.0.2
2-
Authlib==1.6.7
2+
Authlib==1.6.12
33
blinker==1.9.0
44
cachetools==5.3.0
55
certifi==2024.7.4
66
cffi==2.0.0
77
charset-normalizer==3.1.0
88
click==8.1.3
9-
cryptography==46.0.5
9+
cryptography==46.0.7
1010
Flask==3.1.3
1111
google-api-core==2.29.0
1212
google-api-python-client==2.189.0
@@ -21,23 +21,23 @@ grpc-google-iam-v1==0.14.2
2121
grpcio==1.73.1
2222
grpcio-status==1.63.0rc1
2323
httplib2==0.22.0
24-
idna==3.7
24+
idna==3.15
2525
itsdangerous==2.2.0
2626
Jinja2==3.1.6
2727
MarkupSafe==2.1.2
2828
proto-plus==1.27.1
2929
protobuf==6.33.5
30-
pyasn1==0.5.0
31-
pyasn1-modules==0.3.0
30+
pyasn1==0.6.3
31+
pyasn1-modules==0.4.2
3232
pycparser==2.21
3333
pymemcache==4.0.0
3434
pyparsing==3.0.9
35-
python-dotenv==1.0.0
35+
python-dotenv==1.2.2
3636
pytz==2023.3
3737
redis==4.5.5
38-
requests==2.32.4
38+
requests==2.33.0
3939
rsa==4.9
4040
six==1.16.0
4141
uritemplate==4.1.1
42-
urllib3==2.6.3
42+
urllib3==2.7.0
4343
Werkzeug==3.1.6

0 commit comments

Comments
 (0)