4040import csv
4141import json
4242import os
43- import re
4443import time
45- from email .utils import parseaddr
4644from pprint import pprint
4745
4846import click
4947import requests
5048
49+ from utils import is_valid_email
50+
5151
5252DEFAULT_CHUNK_SIZE = 100
5353
6666}
6767
6868OUTPUT_FIELDNAMES = ['chunk_id' , 'subscription_plan_uuid' , 'email' , 'license_uuid' ]
69- INPUT_FIELDNAMES = ['email ' , 'university_name ' ]
69+ INPUT_FIELDNAMES = ['university_name ' , 'email ' ]
7070PLANS_BY_NAME_FIELDNAMES = ['university_name' , 'subscription_plan_uuid' ]
7171
7272
@@ -80,7 +80,6 @@ def _get_jwt(fetch_jwt=False, environment='local'):
8080 'client_secret' : client_secret ,
8181 'grant_type' : 'client_credentials' ,
8282 'token_type' : 'jwt' ,
83- 'scope' : 'user_id email profile read write' ,
8483 }
8584 # we want to sent with a Content-Type of 'application/x-www-form-urlencoded'
8685 # so send in the `data` param instead of `json`.
@@ -101,7 +100,7 @@ def get_already_processed_emails(results_file):
101100 and returns a dictionary mapping already processed emails to their chunk_id.
102101 """
103102 already_processed_emails = {}
104- with open (results_file , 'a+' ) as f_in :
103+ with open (results_file , 'a+' , encoding = 'latin-1' ) as f_in :
105104 f_in .seek (0 )
106105 reader = csv .DictReader (f_in , fieldnames = OUTPUT_FIELDNAMES , delimiter = ',' )
107106
@@ -123,7 +122,7 @@ def get_already_processed_emails(results_file):
123122
124123def get_plan_uuids_by_name (plans_by_name_file ):
125124 plans_by_name = {}
126- with open (plans_by_name_file , 'a+' ) as f_in :
125+ with open (plans_by_name_file , 'a+' , encoding = 'latin-1' ) as f_in :
127126 f_in .seek (0 )
128127 reader = csv .DictReader (f_in , fieldnames = PLANS_BY_NAME_FIELDNAMES , delimiter = ',' )
129128
@@ -148,11 +147,6 @@ def get_plan_uuids_by_name(plans_by_name_file):
148147 return plans_by_name
149148
150149
151- def is_valid_email (email ):
152- _ , address = parseaddr (email )
153- return bool (address )
154-
155-
156150def get_email_chunks (input_file_path , plans_by_name , chunk_size = DEFAULT_CHUNK_SIZE ):
157151 """
158152 Yield chunks of (chunk_id, subscription_plan, email) from the given input file.
@@ -182,7 +176,9 @@ def get_email_chunks(input_file_path, plans_by_name, chunk_size=DEFAULT_CHUNK_SI
182176 continue
183177
184178 university_name = row ['university_name' ]
185- subscription_plan_uuid = plans_by_name [university_name ]
179+ subscription_plan_uuid = plans_by_name .get (university_name )
180+ if not subscription_plan_uuid :
181+ print (f'No plan matches the given name: { university_name } ' )
186182
187183 # This should only happen on the very first row we process
188184 if not current_subscription_plan_uuid :
@@ -210,7 +206,9 @@ def get_email_chunks(input_file_path, plans_by_name, chunk_size=DEFAULT_CHUNK_SI
210206 yield chunk_id , current_subscription_plan_uuid , current_chunk
211207
212208
213- def _post_assignments (subscription_plan_uuid , emails_for_chunk , environment = 'local' , fetch_jwt = False ):
209+ def _post_assignments (
210+ subscription_plan_uuid , emails_for_chunk , environment = 'local' , fetch_jwt = False , notify_users = False ,
211+ ):
214212 """
215213 Make the POST request to assign licenses.
216214 """
@@ -219,7 +217,7 @@ def _post_assignments(subscription_plan_uuid, emails_for_chunk, environment='loc
219217
220218 payload = {
221219 'user_emails' : emails_for_chunk ,
222- 'notify_users' : False ,
220+ 'notify_users' : notify_users ,
223221 }
224222 headers = {
225223 "Authorization" : "JWT {}" .format (_get_jwt (fetch_jwt , environment = environment )),
@@ -273,7 +271,7 @@ def request_assignments(subscription_plan_uuid, chunk_id, emails_for_chunk, envi
273271
274272def do_assignment_for_chunk (
275273 subscription_plan_uuid , chunk_id , email_chunk ,
276- already_processed , results_file , environment = 'local' , fetch_jwt = False , sleep_interval = DEFAULT_SLEEP_INTERVAL
274+ already_processed , results_file , environment = 'local' , fetch_jwt = False , sleep_interval = DEFAULT_SLEEP_INTERVAL ,
277275):
278276 """
279277 Given a "chunk" list emails for which assignments should be requested, checks if the given
@@ -341,8 +339,13 @@ def do_assignment_for_chunk(
341339 help = 'Whether to fetch JWT based on stored client id and secret.' ,
342340 is_flag = True ,
343341)
342+ @click .option (
343+ '--dry-run' ,
344+ help = 'Just prints what emails would be assigned to plan if true.' ,
345+ is_flag = True ,
346+ )
344347
345- def run (input_file , plans_by_name_file , output_file , chunk_size , environment , sleep_interval , fetch_jwt ):
348+ def run (input_file , plans_by_name_file , output_file , chunk_size , environment , sleep_interval , fetch_jwt , dry_run ):
346349 """
347350 Entry-point for this script.
348351 """
@@ -353,10 +356,13 @@ def run(input_file, plans_by_name_file, output_file, chunk_size, environment, sl
353356 plan_uuids_by_name = get_plan_uuids_by_name (plans_by_name_file )
354357
355358 for chunk_id , subscription_plan_uuid , email_chunk in get_email_chunks (input_file , plan_uuids_by_name , chunk_size ):
356- do_assignment_for_chunk (
357- subscription_plan_uuid , chunk_id , email_chunk ,
358- already_processed , output_file , environment , fetch_jwt , sleep_interval ,
359- )
359+ if dry_run :
360+ print (f'DRY RUN: chunk_id={ chunk_id } would assign to plan { subscription_plan_uuid } emails: { email_chunk } ' )
361+ else :
362+ do_assignment_for_chunk (
363+ subscription_plan_uuid , chunk_id , email_chunk ,
364+ already_processed , output_file , environment , fetch_jwt , sleep_interval ,
365+ )
360366
361367if __name__ == '__main__' :
362368 run ()
0 commit comments