isoc-ams 0.0.1__tar.gz → 0.0.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: isoc-ams
3
- Version: 0.0.1
3
+ Version: 0.0.2
4
4
  Summary: A Python 3 module to cope with ISOC-AMS.
5
5
  Author-email: Klaus Birkenbihl <klaus.birkenbihl@isoc.de>
6
6
  Maintainer: Klaus Birkenbihl
@@ -13,19 +13,19 @@ Project-URL: Home, https://github.com/birkenbihl/isoc-ams
13
13
 
14
14
  # isoc-ams
15
15
 
16
- A Python Interface to access the 'Advanced Members Administration System' (AMS) of the 'Internet Society' (ISOC). This especially usefulfor ISOC Chapter Admins who want to synchronize their Chapter Database with AMS (semi)automatically.
16
+ A Python Interface to access the 'Advanced Members Administration System' (AMS) of the 'Internet Society' (ISOC). This especially useful for ISOC Chapter Admins who want to synchronize their Chapter Database with AMS (semi)automatically.
17
17
 
18
18
  After 10 years+ of sorrow, millions minutes of waiting for answers from the AMS web interface, tons of useless clicks, many (in fact) rejected requests to provide an API access: the author decided to build an API himself. Even if it might not be more than a demonstrator for the functionality needed. Anyhow (see below): for now it is running on a weekly basis doing a great job in avoiding manual work.
19
19
 
20
20
  Unfortunately the constraints are severe:
21
- - access had to be through the web interface since this is the only interface provided. As a consequence it is slow, sometimes unreliable and hard to implement. At least there are working implementations of the "W3C webdriver" recommendtion. One of them is Selenium used for this project.
22
- - the existing web interface is far from being stable or guarateed. So changes to the web interface might spoil the whole project. There is great chance that few weeks from now a new "super dooper" AMS will be announced and as always after these announcements things will get worse.
21
+ - access had to be through the web interface since this is the only interface provided. As a consequence it is slow, sometimes unreliable and hard to implement. At least there are working implementations of the "W3C web driver" recommendation. One of them is Selenium used for this project.
22
+ - the existing web interface is far from being stable or guaranteed. So changes to the web interface might spoil the whole project. There is great chance that few weeks from now a new "super duper" AMS will be announced and as always after these announcements things will get worse.
23
23
  - tests are close to impossible. There is no such thing as a TEST AMS.
24
24
 
25
25
  Is there a possible good exit? Well, maybe some day soon - in 10 or 20 years if ISOC still exists - there will be an API provided by ISOC that makes this project obsolete. Or at least may be an all-mighty AI will step in. Let's dream on!
26
26
 
27
27
  ## Features
28
- ISOC maintains two main Lists that are relevant for the operation of this interface:
28
+ AMS maintains two main Lists that are relevant for the operation of this interface:
29
29
  - a list of ISOC members registered as members of the Chapter
30
30
  - a list of ISOC members that applied for a Chapter membership.
31
31
 
@@ -66,11 +66,15 @@ So this happens if we call the module with:
66
66
  ```bash
67
67
  python -m isoc_ams
68
68
  ```
69
-
69
+ Output:
70
70
  ```
71
71
  Username: xxx
72
72
  Password:
73
73
 
74
+ ********************************************
75
+ AMS 2025-07-03 10:49:05 START
76
+ ********************************************
77
+
74
78
  AMS 2025-07-03 10:49:07 logging in
75
79
  AMS 2025-07-03 10:49:11 log in started
76
80
  AMS 2025-07-03 10:49:20 now on community portal
@@ -127,12 +131,76 @@ PENDING APPLICATIONS
127
131
  2 ...
128
132
  ...
129
133
  ```
134
+ As you can see: building the list is rather tedious: reading the Table scroll it to find the end ... and for the members list - in order to get the links for actions - we have to build 2 tables ...
135
+ ### Running with arguments
136
+ Normally isoc_ams won't show any browser output - running headless. To do debugging it might useful to follow the activities in the browser. If you call isoc_ams with a -h option like
137
+ ```bash
138
+ python -m isoc_ams -h
139
+ ```
140
+ the browser will open and you can follow all activities real time.
141
+
142
+ An argument -i tells the module that there will be (or is) input available with actions to execute. An argument -d tells isoc_ams to make a dry run where actions are computed but not executed.
143
+
144
+ Again an example:
145
+ ```bash
146
+ python -m isoc_ams -i -d
147
+ ```
148
+ Output:
149
+ ```
150
+ Username: xxx
151
+ Username:klaus.birkenbihl@isoc.de
152
+ Password:
153
+
154
+ ********************************************
155
+ AMS 2025-07-09 16:25:06 START DRYRUN
156
+ ********************************************
157
+
158
+ AMS 2025-07-09 16:25:06 logging in
159
+ AMS 2025-07-09 16:25:09 log in started
160
+ AMS 2025-07-09 16:25:17 now on community portal
161
+ AMS 2025-07-09 16:25:21 waiting for Chapter Leader portal
162
+ AMS 2025-07-09 16:25:21 Chapter Leader portal OK
163
+
164
+
165
+ AMS 2025-07-09 16:25:21 start build members list
166
+ ...
167
+ AMS 2025-07-09 16:26:12 records collected / total 58 / 58
168
+ AMS 2025-07-09 16:26:12 members list finished
169
+
170
+
171
+ AMS 2025-07-09 16:26:12 start build pending applications
172
+ ...
173
+ AMS 2025-07-09 16:26:25 records collected / total 9 / 9
174
+ AMS 2025-07-09 16:26:25 pending application list finished
130
175
 
131
- Normally isoc_ams wont show any browser output - running headless. To do debugging it might useful to follow the activities in the browser. If you call isoc_ams with a -h option the browser will open.
176
+
177
+ MEMBERS
178
+ 1 2217734 Johannes Piesepampel self@piesepampel.com
179
+ ...
180
+
181
+ PENDING APPLICATIONS
182
+ 1 23232 Franz Piesepampel franz@piesepampel.com 2025-01-22
183
+ 2 22556 Abdul Piesepampel abdul@piesepampel.com 2025-03-21
184
+ ...
185
+ READING COMMANDS:
186
+ deny 23232 22556 123
187
+ AMS 2025-07-09 18:17:51 Denied 2323284 Franz Piesepampel
188
+ AMS 2025-07-09 18:17:51 Denied 2333463 Abdul Piesepampel
189
+ *******************************************************************************
190
+ AMS 2025-07-09 18:17:51 ISOC-ID 123 is not in pending applications list
191
+ *******************************************************************************
192
+
193
+ delete 2217734
194
+ AMS 2025-07-09 18:18:29 Deleted 22842 Franz Piesepampel
195
+ EOF of command input
196
+ Deviations from expected results:
197
+ Dryrun No results expected
198
+ All results as expected
199
+ ```
132
200
 
133
201
  ## Using the API
134
202
 
135
- isoc_ams unleashes its full power when used as API to make things happen without human intervention. Check the file "isoc_de_ams_main.py" as an example for fully automatic synchronizing of local membership administration with AMS.
203
+ isoc_ams unleashes its full power when used as API to make things happen without human intervention. Check the file "[isoc_de_ams_main.py](https://github.com/birkenbihl/isoc-ams/blob/main/isoc_de_ams_main.py)" as an example for fully automatic synchronizing of local membership administration with AMS.
136
204
 
137
205
  Here an excerpt of the output:
138
206
  ```
@@ -152,19 +220,26 @@ Members:
152
220
  ...
153
221
  for the following members a nagging mail will be sent to AMS-support (we are not authorized to fix it!):
154
222
  ...
155
- the following members are in sync
223
+ the following locally registered members are in sync with AMS:
156
224
  ...
157
225
 
158
226
  AMS 2025-07-03 12:00:32 start delete ... from AMS Chapter members list
159
227
  ...
160
228
 
161
- Dear MAS-support team,
229
+ Dear AMS-support team,
230
+
162
231
  this is an automatic, complimentary Message from the ISOC German Chapter
163
232
  Members Administration System (ISOC.DE MAS).
164
233
 
234
+ Assuming you are interested in making ISOC AMS consistent, the purpose
235
+ of this message is to help you with valid, up-to-date data.
236
+
165
237
  The following individuals are legally registered paying members
166
- of ISOC.DE - many of them for more than 25 years.
167
- ...
238
+ of ISOC.DE - many of them for more than 25 years. They all are
239
+ also registered as ISOC (global) members. Unfortunately they are
240
+ not registered with AMS as members of ISOC.DE. Even more we are
241
+ not authorized to fix this. So we forward this data to your attention:
242
+
168
243
  Uwe Mayer, xxx@yyy.com (ISOC-ID=1234567)
169
244
  ...
170
245
 
@@ -180,7 +255,7 @@ not approved from pending applicants list
180
255
  not removed from pending applicants list
181
256
  ...
182
257
  ```
183
- See file isoc_ams.doc for doc on the API interface.
258
+ See file [isoc_ams.doc](https://github.com/birkenbihl/isoc-ams/blob/main/isoc_ams.doc) for doc on the API interface.
184
259
 
185
260
  Have fun!
186
261
 
@@ -1,19 +1,19 @@
1
1
 
2
2
  # isoc-ams
3
3
 
4
- A Python Interface to access the 'Advanced Members Administration System' (AMS) of the 'Internet Society' (ISOC). This especially usefulfor ISOC Chapter Admins who want to synchronize their Chapter Database with AMS (semi)automatically.
4
+ A Python Interface to access the 'Advanced Members Administration System' (AMS) of the 'Internet Society' (ISOC). This especially useful for ISOC Chapter Admins who want to synchronize their Chapter Database with AMS (semi)automatically.
5
5
 
6
6
  After 10 years+ of sorrow, millions minutes of waiting for answers from the AMS web interface, tons of useless clicks, many (in fact) rejected requests to provide an API access: the author decided to build an API himself. Even if it might not be more than a demonstrator for the functionality needed. Anyhow (see below): for now it is running on a weekly basis doing a great job in avoiding manual work.
7
7
 
8
8
  Unfortunately the constraints are severe:
9
- - access had to be through the web interface since this is the only interface provided. As a consequence it is slow, sometimes unreliable and hard to implement. At least there are working implementations of the "W3C webdriver" recommendtion. One of them is Selenium used for this project.
10
- - the existing web interface is far from being stable or guarateed. So changes to the web interface might spoil the whole project. There is great chance that few weeks from now a new "super dooper" AMS will be announced and as always after these announcements things will get worse.
9
+ - access had to be through the web interface since this is the only interface provided. As a consequence it is slow, sometimes unreliable and hard to implement. At least there are working implementations of the "W3C web driver" recommendation. One of them is Selenium used for this project.
10
+ - the existing web interface is far from being stable or guaranteed. So changes to the web interface might spoil the whole project. There is great chance that few weeks from now a new "super duper" AMS will be announced and as always after these announcements things will get worse.
11
11
  - tests are close to impossible. There is no such thing as a TEST AMS.
12
12
 
13
13
  Is there a possible good exit? Well, maybe some day soon - in 10 or 20 years if ISOC still exists - there will be an API provided by ISOC that makes this project obsolete. Or at least may be an all-mighty AI will step in. Let's dream on!
14
14
 
15
15
  ## Features
16
- ISOC maintains two main Lists that are relevant for the operation of this interface:
16
+ AMS maintains two main Lists that are relevant for the operation of this interface:
17
17
  - a list of ISOC members registered as members of the Chapter
18
18
  - a list of ISOC members that applied for a Chapter membership.
19
19
 
@@ -54,11 +54,15 @@ So this happens if we call the module with:
54
54
  ```bash
55
55
  python -m isoc_ams
56
56
  ```
57
-
57
+ Output:
58
58
  ```
59
59
  Username: xxx
60
60
  Password:
61
61
 
62
+ ********************************************
63
+ AMS 2025-07-03 10:49:05 START
64
+ ********************************************
65
+
62
66
  AMS 2025-07-03 10:49:07 logging in
63
67
  AMS 2025-07-03 10:49:11 log in started
64
68
  AMS 2025-07-03 10:49:20 now on community portal
@@ -115,12 +119,76 @@ PENDING APPLICATIONS
115
119
  2 ...
116
120
  ...
117
121
  ```
122
+ As you can see: building the list is rather tedious: reading the Table scroll it to find the end ... and for the members list - in order to get the links for actions - we have to build 2 tables ...
123
+ ### Running with arguments
124
+ Normally isoc_ams won't show any browser output - running headless. To do debugging it might useful to follow the activities in the browser. If you call isoc_ams with a -h option like
125
+ ```bash
126
+ python -m isoc_ams -h
127
+ ```
128
+ the browser will open and you can follow all activities real time.
129
+
130
+ An argument -i tells the module that there will be (or is) input available with actions to execute. An argument -d tells isoc_ams to make a dry run where actions are computed but not executed.
131
+
132
+ Again an example:
133
+ ```bash
134
+ python -m isoc_ams -i -d
135
+ ```
136
+ Output:
137
+ ```
138
+ Username: xxx
139
+ Username:klaus.birkenbihl@isoc.de
140
+ Password:
141
+
142
+ ********************************************
143
+ AMS 2025-07-09 16:25:06 START DRYRUN
144
+ ********************************************
145
+
146
+ AMS 2025-07-09 16:25:06 logging in
147
+ AMS 2025-07-09 16:25:09 log in started
148
+ AMS 2025-07-09 16:25:17 now on community portal
149
+ AMS 2025-07-09 16:25:21 waiting for Chapter Leader portal
150
+ AMS 2025-07-09 16:25:21 Chapter Leader portal OK
151
+
152
+
153
+ AMS 2025-07-09 16:25:21 start build members list
154
+ ...
155
+ AMS 2025-07-09 16:26:12 records collected / total 58 / 58
156
+ AMS 2025-07-09 16:26:12 members list finished
157
+
158
+
159
+ AMS 2025-07-09 16:26:12 start build pending applications
160
+ ...
161
+ AMS 2025-07-09 16:26:25 records collected / total 9 / 9
162
+ AMS 2025-07-09 16:26:25 pending application list finished
118
163
 
119
- Normally isoc_ams wont show any browser output - running headless. To do debugging it might useful to follow the activities in the browser. If you call isoc_ams with a -h option the browser will open.
164
+
165
+ MEMBERS
166
+ 1 2217734 Johannes Piesepampel self@piesepampel.com
167
+ ...
168
+
169
+ PENDING APPLICATIONS
170
+ 1 23232 Franz Piesepampel franz@piesepampel.com 2025-01-22
171
+ 2 22556 Abdul Piesepampel abdul@piesepampel.com 2025-03-21
172
+ ...
173
+ READING COMMANDS:
174
+ deny 23232 22556 123
175
+ AMS 2025-07-09 18:17:51 Denied 2323284 Franz Piesepampel
176
+ AMS 2025-07-09 18:17:51 Denied 2333463 Abdul Piesepampel
177
+ *******************************************************************************
178
+ AMS 2025-07-09 18:17:51 ISOC-ID 123 is not in pending applications list
179
+ *******************************************************************************
180
+
181
+ delete 2217734
182
+ AMS 2025-07-09 18:18:29 Deleted 22842 Franz Piesepampel
183
+ EOF of command input
184
+ Deviations from expected results:
185
+ Dryrun No results expected
186
+ All results as expected
187
+ ```
120
188
 
121
189
  ## Using the API
122
190
 
123
- isoc_ams unleashes its full power when used as API to make things happen without human intervention. Check the file "isoc_de_ams_main.py" as an example for fully automatic synchronizing of local membership administration with AMS.
191
+ isoc_ams unleashes its full power when used as API to make things happen without human intervention. Check the file "[isoc_de_ams_main.py](https://github.com/birkenbihl/isoc-ams/blob/main/isoc_de_ams_main.py)" as an example for fully automatic synchronizing of local membership administration with AMS.
124
192
 
125
193
  Here an excerpt of the output:
126
194
  ```
@@ -140,19 +208,26 @@ Members:
140
208
  ...
141
209
  for the following members a nagging mail will be sent to AMS-support (we are not authorized to fix it!):
142
210
  ...
143
- the following members are in sync
211
+ the following locally registered members are in sync with AMS:
144
212
  ...
145
213
 
146
214
  AMS 2025-07-03 12:00:32 start delete ... from AMS Chapter members list
147
215
  ...
148
216
 
149
- Dear MAS-support team,
217
+ Dear AMS-support team,
218
+
150
219
  this is an automatic, complimentary Message from the ISOC German Chapter
151
220
  Members Administration System (ISOC.DE MAS).
152
221
 
222
+ Assuming you are interested in making ISOC AMS consistent, the purpose
223
+ of this message is to help you with valid, up-to-date data.
224
+
153
225
  The following individuals are legally registered paying members
154
- of ISOC.DE - many of them for more than 25 years.
155
- ...
226
+ of ISOC.DE - many of them for more than 25 years. They all are
227
+ also registered as ISOC (global) members. Unfortunately they are
228
+ not registered with AMS as members of ISOC.DE. Even more we are
229
+ not authorized to fix this. So we forward this data to your attention:
230
+
156
231
  Uwe Mayer, xxx@yyy.com (ISOC-ID=1234567)
157
232
  ...
158
233
 
@@ -168,6 +243,6 @@ not approved from pending applicants list
168
243
  not removed from pending applicants list
169
244
  ...
170
245
  ```
171
- See file isoc_ams.doc for doc on the API interface.
246
+ See file [isoc_ams.doc](https://github.com/birkenbihl/isoc-ams/blob/main/isoc_ams.doc) for doc on the API interface.
172
247
 
173
248
  Have fun!
@@ -67,8 +67,13 @@ _______
67
67
  # check if all went well
68
68
  print(difference_from_expected())
69
69
 
70
+ Changelog
71
+ _________
72
+ Version 0.2
73
+ Allow input if executed as module
74
+ Add dryrun to ISOC_AMS class
70
75
  """
71
- __version__ = "0.0.1"
76
+ __version__ = "0.0.2"
72
77
 
73
78
  from selenium import webdriver
74
79
  from selenium.webdriver.common.by import By
@@ -116,21 +121,29 @@ class ISOC_AMS:
116
121
  password: password for ISO.ORG login
117
122
  logfile: where to write ISOC_AMS log output
118
123
  headless: run without GUI
119
-
124
+ dryrun: only check input, no actions
120
125
  """
121
126
 
122
127
  def __init__(self,
123
128
  user: str,
124
129
  password: str,
125
130
  logfile: io.StringIO | str = sys.stdout,
126
- headless: bool = True):
131
+ headless: bool = True,
132
+ dryrun: bool = False,):
127
133
  if _dr == "firefox" and headless:
128
134
  _options.add_argument("--headless")
129
135
  elif _dr == "chrome" and headless:
130
136
  _options.add_argument("--headless=new")
131
137
  self._members_list: dict | None = None
132
138
  self._pending_applications_list: dict | None = None
133
- self._ams = _ISOC_AMS(user, password, logfile)
139
+ self._dryrun = dryrun
140
+ self._ams = _ISOC_AMS(logfile)
141
+ if self._dryrun:
142
+ self._ams.strong_msg("START DRYRUN")
143
+ else:
144
+ self._ams.strong_msg("START")
145
+ self._ams.login((user, password))
146
+
134
147
 
135
148
  @property
136
149
  def members_list(self) -> dict:
@@ -193,10 +206,15 @@ class ISOC_AMS:
193
206
  deletes delete_list entries from AMS-list of Chapter members
194
207
  """
195
208
  if type(delete_list) in (str, int):
196
- delete_list = str(delete_list),
197
- for deletee in delete_list:
209
+ delete_list = [delete_list]
210
+ for deletee in map(str, delete_list):
198
211
  if deletee in self._members_list:
199
- self._ams.delete(self._members_list[deletee])
212
+ deletee = str(deletee)
213
+ if not self._dryrun:
214
+ self._ams.delete(self._members_list[deletee])
215
+ self._ams.log("Deleted", deletee,
216
+ self._members_list[deletee]["first name"],
217
+ self._members_list[deletee]["last name"])
200
218
  del self._members_list[deletee]
201
219
  else:
202
220
  self._ams.strong_msg("ISOC-ID", deletee,
@@ -214,14 +232,17 @@ class ISOC_AMS:
214
232
  approves pending members on approve_list as Chapter members
215
233
  """
216
234
  if type(approve_list) in (int, str):
217
- approve_list = str(approve_list),
218
- for approvee in approve_list:
235
+ approve_list = [approve_list]
236
+ for approvee in map(str, approve_list):
219
237
  if approvee in self._pending_applications_list:
220
- self._ams.approve(self._pending_applications_list[approvee])
238
+ if not self._dryrun:
239
+ self._ams.approve(self._pending_applications_list[approvee])
240
+ self._ams.log("Approved", approvee,
241
+ self._pending_applications_list[approvee]["name"])
221
242
  del self._pending_applications_list[approvee]
222
243
  else:
223
244
  self._ams.strong_msg("ISOC-ID", approvee,
224
- "is not in pending applications list" )
245
+ "is not in pending applications list")
225
246
 
226
247
  def deny_pending_applications(self,
227
248
  deny_list: list | dict | str | int,
@@ -238,15 +259,18 @@ class ISOC_AMS:
238
259
 
239
260
  """
240
261
  if type(deny_list) in (str, int):
241
- deny_list = str(deny_list),
242
- for denyee in deny_list:
262
+ deny_list = [deny_list],
263
+ for denyee in map(str, deny_list):
243
264
  if denyee in self._pending_applications_list:
244
- self._ams.deny(self._pending_applications_list[denyee],
245
- reason)
265
+ if not self._dryrun:
266
+ self._ams.deny(self._pending_applications_list[denyee],
267
+ reason)
268
+ self._ams.log("Denied", denyee,
269
+ self._pending_applications_list[denyee]["name"])
246
270
  del self._pending_applications_list[denyee]
247
271
  else:
248
272
  self._ams.strong_msg("ISOC-ID", denyee,
249
- "is not in pending applications list" )
273
+ "is not in pending applications list")
250
274
 
251
275
  def difference_from_expected(self) -> dict:
252
276
  """Compare intended outcome of operations with real outcome.
@@ -267,38 +291,43 @@ class ISOC_AMS:
267
291
  }
268
292
 
269
293
  """
270
- self._ams.log(date=False)
271
- self._ams.log("collect differences from expected result after operations")
272
-
273
- not_deleted = {}
274
- not_approved = {}
275
- not_removed_from_pending = {}
276
- new_members_list = self._ams.build_members_list()
277
- for nm in new_members_list:
278
- if nm not in self._members_list:
279
- not_deleted[nm] = new_members_list[nm]
280
- for nm in self._members_list:
281
- if nm not in new_members_list:
282
- not_approved[nm] = self._members_list[nm]
283
- new_pending_applications_list = self._ams.build_pending_applicants_list()
284
- for np in new_pending_applications_list:
285
- if np not in self._pending_applications_list:
286
- not_removed_from_pending[np] = new_pending_applications_list[np]
287
-
288
- return {"not deleted from members": not_deleted,
289
- "not approved from pending applicants list": not_approved,
290
- "not removed from pending applicants list": not_removed_from_pending}
294
+ if not self._dryrun:
295
+
296
+ self._ams.log(date=False)
297
+
298
+ self._ams.strong_msg("we have to read the AMS Database tables again :(")
299
+ self._ams.log("... to find deviations from expected result after actions")
300
+
301
+ not_deleted = {}
302
+ not_approved = {}
303
+ not_removed_from_pending = {}
304
+ new_members_list = self._ams.build_members_list()
305
+ for nm in new_members_list:
306
+ if nm not in self._members_list:
307
+ not_deleted[nm] = new_members_list[nm]
308
+ for nm in self._members_list:
309
+ if nm not in new_members_list:
310
+ not_approved[nm] = self._members_list[nm]
311
+ new_pending_applications_list = self._ams.build_pending_applicants_list()
312
+ for np in new_pending_applications_list:
313
+ if np not in self._pending_applications_list:
314
+ not_removed_from_pending[np] = new_pending_applications_list[np]
315
+
316
+ return {"not deleted from members": not_deleted,
317
+ "not approved from pending applicants list": not_approved,
318
+ "not removed from pending applicants list": not_removed_from_pending}
319
+ else:
320
+ return {"Dryrun": "No results expected"}
291
321
 
292
322
  class _ISOC_AMS(Driver):
293
323
 
294
- def __init__(self, user: str, password: str, logfile: str = sys.stdout):
324
+ def __init__(self, logfile: str = sys.stdout):
295
325
 
296
326
  super().__init__(_options)
297
327
  self.windows = {}
298
328
  self.logfile = logfile
299
329
  if type(self.logfile) is str:
300
330
  self.logfile = open(self.log, "a")
301
- self.login(user, password)
302
331
 
303
332
  def __del__(self):
304
333
  self.quit()
@@ -364,7 +393,7 @@ class _ISOC_AMS(Driver):
364
393
  # setup session, init windows
365
394
  #
366
395
 
367
- def login(self, user: str, password: str):
396
+ def login(self, credentials):
368
397
  # Sign on user and navigate to the Chapter leaders page,
369
398
 
370
399
  self.log(date=False)
@@ -383,7 +412,7 @@ class _ISOC_AMS(Driver):
383
412
  "document.getElementById('signInName').value='%s';"
384
413
  "document.getElementById('password').value='%s';"
385
414
  "arguments[0].click();"
386
- % (user, password),
415
+ % credentials,
387
416
  elem)
388
417
 
389
418
  # self.set_window_size(1600, 300)
@@ -792,14 +821,22 @@ if __name__ == "__main__":
792
821
  from getpass import getpass
793
822
  headless = True
794
823
  if "-h" in sys.argv:
795
- headless=False
824
+ headless = False
825
+ inp = False
826
+ if "-i" in sys.argv:
827
+ inp = True
828
+ dryrun = False
829
+ if "-d" in sys.argv:
830
+ dryrun = True
831
+
796
832
  print("Username", end=":")
797
833
  user_id = input()
798
834
  password = getpass()
799
835
  ams = ISOC_AMS(
800
836
  user_id,
801
837
  password,
802
- headless=headless)
838
+ headless=headless,
839
+ dryrun=dryrun)
803
840
  members = ams.members_list
804
841
  pendings = ams.pending_applications_list
805
842
 
@@ -807,12 +844,46 @@ if __name__ == "__main__":
807
844
  i = 0
808
845
  for k, v in members.items():
809
846
  i += 1
810
- print(i, k + ":", v["first name"], v["last name"], v["email"], v["action link"])
847
+ print(i, k, v["first name"], v["last name"], v["email"])
811
848
 
812
849
  print("\nPENDING APPLICATIONS")
813
850
  i = 0
814
851
  for k, v in pendings.items():
815
852
  i += 1
816
853
  # print(i, k, v)
817
- print(i, k, v["name"], v["email"], v["action link"],
818
- v["date"].isoformat()[:19])
854
+ print(i, k, v["name"], v["email"], v["date"].isoformat()[:10])
855
+
856
+ if inp:
857
+ print('READING COMMANDS:')
858
+ import re
859
+ patt = re.compile(r'(approve|deny|delete):?\s*([\d, ]+)')
860
+ func = {"approve": ams.approve_pending_applications,
861
+ "deny": ams.deny_pending_applications,
862
+ "delete": ams.delete_members
863
+ }
864
+ splitter = re.compile(r'[\s,]+')
865
+ for rec in sys.stdin:
866
+ if m := patt.match(rec):
867
+ command = m.group(1)
868
+ keys = splitter.split(m.group(2))
869
+ func[command](keys)
870
+ else:
871
+ print(rec, "contains an error")
872
+ print("EOF of command input")
873
+
874
+ devs = 0
875
+ for data in ams.difference_from_expected().items():
876
+ print("Deviations from expected results:")
877
+ print(data[0], end=" ")
878
+ if type(data[1]) is str:
879
+ print(data[1])
880
+ else:
881
+ if data[1]:
882
+ devs = 1
883
+ for k, v in data[1].items():
884
+ if "members" in data[0]:
885
+ print(" ", v["first name"], v["last name"], v["email"], "("+k+")")
886
+ else:
887
+ print(" ", v["name"], v["email"], "("+k+")")
888
+ if devs == 0:
889
+ print("All results as expected")
File without changes
File without changes