papi-projects 0.1.6__tar.gz → 0.1.8__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.1
2
2
  Name: papi-projects
3
- Version: 0.1.6
3
+ Version: 0.1.8
4
4
  Summary: PAPI is an API for managing projects
5
5
  License: MIT
6
6
  Author: sandyjmacdonald
@@ -20,7 +20,7 @@ PAPI is an API for managing projects.
20
20
 
21
21
  <img src="https://imgur.com/lprJ3mP.jpg" alt="HAHA BUSINESS meme" height="250">
22
22
 
23
- It has functionality for creating User and Project instances, storing users in a TinyDB database, and generating project IDs in the format we use in the Data Science group (at the Bioscience Technology Facility at the University of York). It also has wrappers for Asana and Toggl Track, two tools we use for project management and time tracking, respectively.
23
+ It has functionality for creating User and Project instances, storing users in a TinyDB database, and generating project IDs in the format we use in the Data Science group (at the Bioscience Technology Facility at the University of York). It also has wrappers for Asana and Notion, and Toggl Track, tools we use for project management and time tracking, respectively.
24
24
 
25
25
  Much of the functionality is tailor-made to the way we manage projects in our group, but make of it what you will!
26
26
 
@@ -58,9 +58,14 @@ ASANA_TEAM="My Team Name"
58
58
  TOGGL_TRACK_API_KEY="YOURAPIKEY"
59
59
  TOGGL_TRACK_PASSWORD="api_token"
60
60
  TOGGL_TRACK_WORKSPACE="My Workspace Name"
61
+
62
+ # Notion config
63
+ NOTION_API_SECRET = "YOURAPISECRET"
64
+ NOTION_CLIENTS_DB = "notionclientsdbid"
65
+ NOTION_PROJECTS_DB = "notionprojectsdbid"
61
66
  ```
62
67
 
63
- The `ASANA_PASSWORD` and `TOGGL_TRACK_PASSWORD` values can be left as above, the remaining ones should be replaced with the correct values from your Asana and Toggl Track accounts.
68
+ The `ASANA_PASSWORD` and `TOGGL_TRACK_PASSWORD` values can be left as above, the remaining ones should be replaced with the correct values from your Notion, Asana, and Toggl Track accounts.
64
69
 
65
70
  This .env file can either be put in your working directory or in the top-level papi module folder wherever it is installed.
66
71
 
@@ -68,41 +73,48 @@ Alternatively, these values can be hard-coded in your scripts, but this is not a
68
73
 
69
74
  ## CLI scripts
70
75
 
71
- Two convenience CLI scripts are provided for common Toggl Track tasks. They are:
76
+ Convenience CLI scripts are provided for some common tasks. They are:
72
77
 
73
- ## create-toggl-project
78
+ ### create-toggl-project
74
79
 
75
80
  This script creates a project ID if necessary, and adds the project to your Toggl Track:
76
81
 
77
82
  ```
78
- usage: create-toggl-project [-h] [-u USER_ID] [-g GRANT_CODE] [-n NAME] [-p PROJECT_ID]
83
+ usage: create-toggl-project [-h] [-u USER_ID] [-g GRANT_CODE] [-n NAME] [-p PROJECT_ID] [--enable-logging] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
84
+ [--log-file LOG_FILE]
79
85
 
80
86
  options:
81
87
  -h, --help show this help message and exit
82
88
  -u USER_ID, --user_id USER_ID
83
- three-letter user ID, e.g. CRD
89
+ three-letter user ID, e.g. JAS
84
90
  -g GRANT_CODE, --grant_code GRANT_CODE
85
91
  grant code, e.g. R12345
86
92
  -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis'
87
93
  -p PROJECT_ID, --project_id PROJECT_ID
88
- full project ID, e.g. P2024-ABC-DEFG, if already generated
94
+ full project ID, e.g. P2024-JAS-ABCD, if already generated
95
+ --enable-logging enable logging output for the papi library
96
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
97
+ set the logging level (default: INFO)
98
+ --log-file LOG_FILE path to a file where logs should be written
89
99
  ```
90
100
 
91
101
  Ideally, a three-character user ID, grant code, and short project name will be provided, and PAPI will generate the project ID, e.g.
92
102
 
93
103
  ```
94
- create-toggl-project -u CRD -g R12345 -n 'Such project. Wow.'
104
+ create-toggl-project -u JAS -g R12345 -n 'Such project. Wow.'
95
105
  ```
96
106
 
97
107
  If a project ID has already been created, then it can be provided via the `-p` argument and the user ID is not necessary, e.g.
98
108
 
99
109
  ```
100
- create-toggl-project -p P2024-CRD-ABCD -g R12345 -n 'Such project. Wow.'
110
+ create-toggl-project -p P2024-JAS-ABCD -g R12345 -n 'Such project. Wow.'
101
111
  ```
102
112
 
103
113
  The grant code (`-g`) and name (`-n`) are not required, but either a project ID (`-p`) or user ID (`-u`) _is_ necessary.
104
114
 
105
- ## collate-toggl-hours
115
+ Logging can also be enabled at various levels of detail, and logs can be saved to a file.
116
+
117
+ ### collate-toggl-hours
106
118
 
107
119
  This script collates and returns your Toggl Track hours tracked over a specified time period:
108
120
 
@@ -130,11 +142,75 @@ To collate your hours worked in August 2024:
130
142
  collate-toggl-hours -s 2024-08-01 -e 2024-08-31 -o august-2024-hours.tsv
131
143
  ```
132
144
 
145
+ ### create-notion-project
146
+
147
+ This script creates a project ID if necessary, and adds the project to the Notion projects database:
148
+
149
+ ```
150
+ usage: create-notion-project [-h] [-u USER_ID] [-v USER_NAME] [-n NAME] [-p PROJECT_ID] [--enable-logging] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
151
+ [--log-file LOG_FILE]
152
+
153
+ options:
154
+ -h, --help show this help message and exit
155
+ -u USER_ID, --user_id USER_ID
156
+ three-letter user (client) ID, e.g. JAS
157
+ -v USER_NAME, --user_name USER_NAME
158
+ user (client) name, e.g. John Andrew Smith
159
+ -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated
160
+ -p PROJECT_ID, --project_id PROJECT_ID
161
+ full project ID, e.g. P2024-JAS-ABCD, if already generated
162
+ --enable-logging enable logging output for the papi library
163
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
164
+ set the logging level (default: INFO)
165
+ --log-file LOG_FILE path to a file where logs should be written
166
+ ```
167
+
168
+ Similar to the `create-toggl-project` script, you can simply provide a three-character user ID and a short project name, and PAPI will generate the project ID, e.g.
169
+
170
+ ```
171
+ create-notion-project -u JAS -n 'Such project. Wow.'
172
+ ```
173
+
174
+ If a project ID has already been created, then it can be provided via the `-p` argument and the user ID is not necessary, e.g.
175
+
176
+ ```
177
+ create-notion-project -p P2024-JAS-ABCD -n 'Such project. Wow.'
178
+ ```
179
+
180
+ Logging can also be enabled at various levels of detail, and logs can be saved to a file.
181
+
182
+ ### create-project
183
+
184
+ This script can create a project on Toggl Track or Notion, or both:
185
+
186
+ ```
187
+ usage: create-project [-h] [-u USER_ID] [-v USER_NAME] [-n NAME] [-p PROJECT_ID] [--enable-toggl] [--enable-notion] [--enable-logging]
188
+ [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--log-file LOG_FILE]
189
+
190
+ options:
191
+ -h, --help show this help message and exit
192
+ -u USER_ID, --user_id USER_ID
193
+ three-letter user (client) ID, e.g. JAS
194
+ -v USER_NAME, --user_name USER_NAME
195
+ user (client) name, e.g. John Andrew Smith
196
+ -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated
197
+ -p PROJECT_ID, --project_id PROJECT_ID
198
+ full project ID, e.g. P2024-JAS-DEFG, if already generated
199
+ --enable-toggl create Toggl Track project
200
+ --enable-notion create Notion project
201
+ --enable-logging enable logging output for the papi library
202
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
203
+ set the logging level (default: INFO)
204
+ --log-file LOG_FILE path to a file where logs should be written
205
+ ```
206
+
207
+ If no arguments are given to the script, i.e. just running `create-project`, then interactive prompts are shown to enter the necessary arguments.
208
+
133
209
  ## API reference
134
210
 
135
- ## project module
211
+ ### project module
136
212
 
137
- ## Project class
213
+ ### Project class
138
214
 
139
215
  The `Project` class is central to the whole library. A `Project` instance can be created in a few different ways.
140
216
 
@@ -143,7 +219,7 @@ At the most basic level, a valid `user_id` (either three letter initials or two
143
219
  ```
144
220
  from papi.project import Project
145
221
 
146
- proj = Project(user_id="CRD")
222
+ proj = Project(user_id="JAS")
147
223
  ```
148
224
 
149
225
  This will generate the project ID, `id` attribute using the current year, and a random four-letter suffix.
@@ -155,15 +231,15 @@ print(proj.suffix)
155
231
  ```
156
232
 
157
233
  ```
158
- P2024-CRD-FZLL
234
+ P2024-JAS-ABCD
159
235
  2024
160
- FZLL
236
+ ABCD
161
237
  ```
162
238
 
163
239
  If a valid project ID has already been created, then a `Project` instance can be instantiated with the `id` attribute, and the `year`, `user_id`, and `suffix` attributes will be pulled out and set on the instance.
164
240
 
165
241
  ```
166
- proj = Project(id="P2024-CRD-FZLL")
242
+ proj = Project(id="P2024-JAS-ABCD")
167
243
 
168
244
  print(proj.year)
169
245
  print(proj.user_id)
@@ -172,20 +248,20 @@ print(proj.suffix)
172
248
 
173
249
  ```
174
250
  2024
175
- CRD
176
- FZLL
251
+ JAS
252
+ ABCD
177
253
  ```
178
254
 
179
255
  If a grant code and/or project name are available, then these can be passed in when instantiating the class.
180
256
 
181
257
  ```
182
- proj = Project(user_id="CRD", grant_code="R12345", name="RNA-seq analysis")
258
+ proj = Project(user_id="JAS", grant_code="R12345", name="RNA-seq analysis")
183
259
  ```
184
260
 
185
261
  A version 4 UUID is also generated for the project when instantiated.
186
262
 
187
263
  ```
188
- proj = Project(user_id="CRD")
264
+ proj = Project(user_id="JAS")
189
265
 
190
266
  print(proj.p_uuid)
191
267
  ```
@@ -197,10 +273,10 @@ print(proj.p_uuid)
197
273
  Or if a version 4 UUID has been generated separately then it can be provided when instantiating.
198
274
 
199
275
  ```
200
- proj = Project(user_id="CRD", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
276
+ proj = Project(user_id="JAS", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
201
277
  ```
202
278
 
203
- ## project functions
279
+ ### project functions
204
280
 
205
281
  A couple of functions are provided to check the validity of a project ID, to check the validity of a suffix, and to check for a valid version 4 UUID.
206
282
 
@@ -209,8 +285,8 @@ You can check the validity of a project ID as follows:
209
285
  ```
210
286
  from papi.project import check_project_id
211
287
 
212
- print(check_project_id("P2024-CRD-FZLL"))
213
- print(check_project_id("P2024-CRD-1234"))
288
+ print(check_project_id("P2024-JAS-ABCD"))
289
+ print(check_project_id("P2024-JAS-1234"))
214
290
  ```
215
291
 
216
292
  ```
@@ -223,7 +299,7 @@ You can check the validity of a project suffix as follows:
223
299
  ```
224
300
  from papi.project import check_suffix
225
301
 
226
- print(check_suffix("FZLL"))
302
+ print(check_suffix("ABCD"))
227
303
  print(check_suffix("1234"))
228
304
  ```
229
305
 
@@ -232,9 +308,9 @@ True
232
308
  False
233
309
  ```
234
310
 
235
- ## user module
311
+ ### user module
236
312
 
237
- ## User class
313
+ ### User class
238
314
 
239
315
  The `User` class stores attributes of a user: their name, a three-letter initial (or two-letter initial and integer number from 1 to 9), and an optional email address.
240
316
 
@@ -243,15 +319,15 @@ The most basic way of instantiating a `User` instance is as follows:
243
319
  ```
244
320
  from papi.user import User
245
321
 
246
- usr = User("Charles Robert Darwin")
322
+ usr = User("John Andrew Smith")
247
323
 
248
324
  print(usr.user_id)
249
325
  print(usr.user_name)
250
326
  ```
251
327
 
252
328
  ```
253
- CRD
254
- Charles Robert Darwin
329
+ JAS
330
+ John Andrew Smith
255
331
  ```
256
332
 
257
333
  The first initials are converted into the `user_id` attribute.
@@ -261,20 +337,20 @@ If an email address is available, then this can be provided when instantiating:
261
337
  ```
262
338
  from papi.user import User
263
339
 
264
- usr = User("Charles Robert Darwin", email="cdarwin@beaglemail.com")
340
+ usr = User("John Andrew Smith", email="jasmith@email.com")
265
341
 
266
342
  print(usr.email)
267
343
  ```
268
344
 
269
345
  ```
270
- cdarwin@beaglemail.com
346
+ jasmith@email.com
271
347
  ```
272
348
 
273
349
  Because our user ID naming scheme enforces that a user ID must be unique, the `user_id` attribute should not really be set directly, although it can in theory:
274
350
 
275
351
  ```
276
- usr = User("Charles Darwin")
277
- usr.user_id = "CD1"
352
+ usr = User("John Smith")
353
+ usr.user_id = "JS1"
278
354
  ```
279
355
 
280
356
  Setting the `user_id` attribute creates the possibility of a clash in user IDs, therefore the `user` module provides a means to create a basic user database with the TinyDB library. This avoids the possibility of a clash and appends and increments integer numbers to the end of the user ID if a matching one is already in the database.
@@ -2,7 +2,7 @@ PAPI is an API for managing projects.
2
2
 
3
3
  <img src="https://imgur.com/lprJ3mP.jpg" alt="HAHA BUSINESS meme" height="250">
4
4
 
5
- It has functionality for creating User and Project instances, storing users in a TinyDB database, and generating project IDs in the format we use in the Data Science group (at the Bioscience Technology Facility at the University of York). It also has wrappers for Asana and Toggl Track, two tools we use for project management and time tracking, respectively.
5
+ It has functionality for creating User and Project instances, storing users in a TinyDB database, and generating project IDs in the format we use in the Data Science group (at the Bioscience Technology Facility at the University of York). It also has wrappers for Asana and Notion, and Toggl Track, tools we use for project management and time tracking, respectively.
6
6
 
7
7
  Much of the functionality is tailor-made to the way we manage projects in our group, but make of it what you will!
8
8
 
@@ -40,9 +40,14 @@ ASANA_TEAM="My Team Name"
40
40
  TOGGL_TRACK_API_KEY="YOURAPIKEY"
41
41
  TOGGL_TRACK_PASSWORD="api_token"
42
42
  TOGGL_TRACK_WORKSPACE="My Workspace Name"
43
+
44
+ # Notion config
45
+ NOTION_API_SECRET = "YOURAPISECRET"
46
+ NOTION_CLIENTS_DB = "notionclientsdbid"
47
+ NOTION_PROJECTS_DB = "notionprojectsdbid"
43
48
  ```
44
49
 
45
- The `ASANA_PASSWORD` and `TOGGL_TRACK_PASSWORD` values can be left as above, the remaining ones should be replaced with the correct values from your Asana and Toggl Track accounts.
50
+ The `ASANA_PASSWORD` and `TOGGL_TRACK_PASSWORD` values can be left as above, the remaining ones should be replaced with the correct values from your Notion, Asana, and Toggl Track accounts.
46
51
 
47
52
  This .env file can either be put in your working directory or in the top-level papi module folder wherever it is installed.
48
53
 
@@ -50,41 +55,48 @@ Alternatively, these values can be hard-coded in your scripts, but this is not a
50
55
 
51
56
  ## CLI scripts
52
57
 
53
- Two convenience CLI scripts are provided for common Toggl Track tasks. They are:
58
+ Convenience CLI scripts are provided for some common tasks. They are:
54
59
 
55
- ## create-toggl-project
60
+ ### create-toggl-project
56
61
 
57
62
  This script creates a project ID if necessary, and adds the project to your Toggl Track:
58
63
 
59
64
  ```
60
- usage: create-toggl-project [-h] [-u USER_ID] [-g GRANT_CODE] [-n NAME] [-p PROJECT_ID]
65
+ usage: create-toggl-project [-h] [-u USER_ID] [-g GRANT_CODE] [-n NAME] [-p PROJECT_ID] [--enable-logging] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
66
+ [--log-file LOG_FILE]
61
67
 
62
68
  options:
63
69
  -h, --help show this help message and exit
64
70
  -u USER_ID, --user_id USER_ID
65
- three-letter user ID, e.g. CRD
71
+ three-letter user ID, e.g. JAS
66
72
  -g GRANT_CODE, --grant_code GRANT_CODE
67
73
  grant code, e.g. R12345
68
74
  -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis'
69
75
  -p PROJECT_ID, --project_id PROJECT_ID
70
- full project ID, e.g. P2024-ABC-DEFG, if already generated
76
+ full project ID, e.g. P2024-JAS-ABCD, if already generated
77
+ --enable-logging enable logging output for the papi library
78
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
79
+ set the logging level (default: INFO)
80
+ --log-file LOG_FILE path to a file where logs should be written
71
81
  ```
72
82
 
73
83
  Ideally, a three-character user ID, grant code, and short project name will be provided, and PAPI will generate the project ID, e.g.
74
84
 
75
85
  ```
76
- create-toggl-project -u CRD -g R12345 -n 'Such project. Wow.'
86
+ create-toggl-project -u JAS -g R12345 -n 'Such project. Wow.'
77
87
  ```
78
88
 
79
89
  If a project ID has already been created, then it can be provided via the `-p` argument and the user ID is not necessary, e.g.
80
90
 
81
91
  ```
82
- create-toggl-project -p P2024-CRD-ABCD -g R12345 -n 'Such project. Wow.'
92
+ create-toggl-project -p P2024-JAS-ABCD -g R12345 -n 'Such project. Wow.'
83
93
  ```
84
94
 
85
95
  The grant code (`-g`) and name (`-n`) are not required, but either a project ID (`-p`) or user ID (`-u`) _is_ necessary.
86
96
 
87
- ## collate-toggl-hours
97
+ Logging can also be enabled at various levels of detail, and logs can be saved to a file.
98
+
99
+ ### collate-toggl-hours
88
100
 
89
101
  This script collates and returns your Toggl Track hours tracked over a specified time period:
90
102
 
@@ -112,11 +124,75 @@ To collate your hours worked in August 2024:
112
124
  collate-toggl-hours -s 2024-08-01 -e 2024-08-31 -o august-2024-hours.tsv
113
125
  ```
114
126
 
127
+ ### create-notion-project
128
+
129
+ This script creates a project ID if necessary, and adds the project to the Notion projects database:
130
+
131
+ ```
132
+ usage: create-notion-project [-h] [-u USER_ID] [-v USER_NAME] [-n NAME] [-p PROJECT_ID] [--enable-logging] [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}]
133
+ [--log-file LOG_FILE]
134
+
135
+ options:
136
+ -h, --help show this help message and exit
137
+ -u USER_ID, --user_id USER_ID
138
+ three-letter user (client) ID, e.g. JAS
139
+ -v USER_NAME, --user_name USER_NAME
140
+ user (client) name, e.g. John Andrew Smith
141
+ -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated
142
+ -p PROJECT_ID, --project_id PROJECT_ID
143
+ full project ID, e.g. P2024-JAS-ABCD, if already generated
144
+ --enable-logging enable logging output for the papi library
145
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
146
+ set the logging level (default: INFO)
147
+ --log-file LOG_FILE path to a file where logs should be written
148
+ ```
149
+
150
+ Similar to the `create-toggl-project` script, you can simply provide a three-character user ID and a short project name, and PAPI will generate the project ID, e.g.
151
+
152
+ ```
153
+ create-notion-project -u JAS -n 'Such project. Wow.'
154
+ ```
155
+
156
+ If a project ID has already been created, then it can be provided via the `-p` argument and the user ID is not necessary, e.g.
157
+
158
+ ```
159
+ create-notion-project -p P2024-JAS-ABCD -n 'Such project. Wow.'
160
+ ```
161
+
162
+ Logging can also be enabled at various levels of detail, and logs can be saved to a file.
163
+
164
+ ### create-project
165
+
166
+ This script can create a project on Toggl Track or Notion, or both:
167
+
168
+ ```
169
+ usage: create-project [-h] [-u USER_ID] [-v USER_NAME] [-n NAME] [-p PROJECT_ID] [--enable-toggl] [--enable-notion] [--enable-logging]
170
+ [--log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [--log-file LOG_FILE]
171
+
172
+ options:
173
+ -h, --help show this help message and exit
174
+ -u USER_ID, --user_id USER_ID
175
+ three-letter user (client) ID, e.g. JAS
176
+ -v USER_NAME, --user_name USER_NAME
177
+ user (client) name, e.g. John Andrew Smith
178
+ -n NAME, --name NAME short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated
179
+ -p PROJECT_ID, --project_id PROJECT_ID
180
+ full project ID, e.g. P2024-JAS-DEFG, if already generated
181
+ --enable-toggl create Toggl Track project
182
+ --enable-notion create Notion project
183
+ --enable-logging enable logging output for the papi library
184
+ --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
185
+ set the logging level (default: INFO)
186
+ --log-file LOG_FILE path to a file where logs should be written
187
+ ```
188
+
189
+ If no arguments are given to the script, i.e. just running `create-project`, then interactive prompts are shown to enter the necessary arguments.
190
+
115
191
  ## API reference
116
192
 
117
- ## project module
193
+ ### project module
118
194
 
119
- ## Project class
195
+ ### Project class
120
196
 
121
197
  The `Project` class is central to the whole library. A `Project` instance can be created in a few different ways.
122
198
 
@@ -125,7 +201,7 @@ At the most basic level, a valid `user_id` (either three letter initials or two
125
201
  ```
126
202
  from papi.project import Project
127
203
 
128
- proj = Project(user_id="CRD")
204
+ proj = Project(user_id="JAS")
129
205
  ```
130
206
 
131
207
  This will generate the project ID, `id` attribute using the current year, and a random four-letter suffix.
@@ -137,15 +213,15 @@ print(proj.suffix)
137
213
  ```
138
214
 
139
215
  ```
140
- P2024-CRD-FZLL
216
+ P2024-JAS-ABCD
141
217
  2024
142
- FZLL
218
+ ABCD
143
219
  ```
144
220
 
145
221
  If a valid project ID has already been created, then a `Project` instance can be instantiated with the `id` attribute, and the `year`, `user_id`, and `suffix` attributes will be pulled out and set on the instance.
146
222
 
147
223
  ```
148
- proj = Project(id="P2024-CRD-FZLL")
224
+ proj = Project(id="P2024-JAS-ABCD")
149
225
 
150
226
  print(proj.year)
151
227
  print(proj.user_id)
@@ -154,20 +230,20 @@ print(proj.suffix)
154
230
 
155
231
  ```
156
232
  2024
157
- CRD
158
- FZLL
233
+ JAS
234
+ ABCD
159
235
  ```
160
236
 
161
237
  If a grant code and/or project name are available, then these can be passed in when instantiating the class.
162
238
 
163
239
  ```
164
- proj = Project(user_id="CRD", grant_code="R12345", name="RNA-seq analysis")
240
+ proj = Project(user_id="JAS", grant_code="R12345", name="RNA-seq analysis")
165
241
  ```
166
242
 
167
243
  A version 4 UUID is also generated for the project when instantiated.
168
244
 
169
245
  ```
170
- proj = Project(user_id="CRD")
246
+ proj = Project(user_id="JAS")
171
247
 
172
248
  print(proj.p_uuid)
173
249
  ```
@@ -179,10 +255,10 @@ print(proj.p_uuid)
179
255
  Or if a version 4 UUID has been generated separately then it can be provided when instantiating.
180
256
 
181
257
  ```
182
- proj = Project(user_id="CRD", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
258
+ proj = Project(user_id="JAS", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
183
259
  ```
184
260
 
185
- ## project functions
261
+ ### project functions
186
262
 
187
263
  A couple of functions are provided to check the validity of a project ID, to check the validity of a suffix, and to check for a valid version 4 UUID.
188
264
 
@@ -191,8 +267,8 @@ You can check the validity of a project ID as follows:
191
267
  ```
192
268
  from papi.project import check_project_id
193
269
 
194
- print(check_project_id("P2024-CRD-FZLL"))
195
- print(check_project_id("P2024-CRD-1234"))
270
+ print(check_project_id("P2024-JAS-ABCD"))
271
+ print(check_project_id("P2024-JAS-1234"))
196
272
  ```
197
273
 
198
274
  ```
@@ -205,7 +281,7 @@ You can check the validity of a project suffix as follows:
205
281
  ```
206
282
  from papi.project import check_suffix
207
283
 
208
- print(check_suffix("FZLL"))
284
+ print(check_suffix("ABCD"))
209
285
  print(check_suffix("1234"))
210
286
  ```
211
287
 
@@ -214,9 +290,9 @@ True
214
290
  False
215
291
  ```
216
292
 
217
- ## user module
293
+ ### user module
218
294
 
219
- ## User class
295
+ ### User class
220
296
 
221
297
  The `User` class stores attributes of a user: their name, a three-letter initial (or two-letter initial and integer number from 1 to 9), and an optional email address.
222
298
 
@@ -225,15 +301,15 @@ The most basic way of instantiating a `User` instance is as follows:
225
301
  ```
226
302
  from papi.user import User
227
303
 
228
- usr = User("Charles Robert Darwin")
304
+ usr = User("John Andrew Smith")
229
305
 
230
306
  print(usr.user_id)
231
307
  print(usr.user_name)
232
308
  ```
233
309
 
234
310
  ```
235
- CRD
236
- Charles Robert Darwin
311
+ JAS
312
+ John Andrew Smith
237
313
  ```
238
314
 
239
315
  The first initials are converted into the `user_id` attribute.
@@ -243,20 +319,20 @@ If an email address is available, then this can be provided when instantiating:
243
319
  ```
244
320
  from papi.user import User
245
321
 
246
- usr = User("Charles Robert Darwin", email="cdarwin@beaglemail.com")
322
+ usr = User("John Andrew Smith", email="jasmith@email.com")
247
323
 
248
324
  print(usr.email)
249
325
  ```
250
326
 
251
327
  ```
252
- cdarwin@beaglemail.com
328
+ jasmith@email.com
253
329
  ```
254
330
 
255
331
  Because our user ID naming scheme enforces that a user ID must be unique, the `user_id` attribute should not really be set directly, although it can in theory:
256
332
 
257
333
  ```
258
- usr = User("Charles Darwin")
259
- usr.user_id = "CD1"
334
+ usr = User("John Smith")
335
+ usr.user_id = "JS1"
260
336
  ```
261
337
 
262
338
  Setting the `user_id` attribute creates the possibility of a clash in user IDs, therefore the `user` module provides a means to create a basic user database with the TinyDB library. This avoids the possibility of a clash and appends and increments integer numbers to the end of the user ID if a matching one is already in the database.
@@ -30,6 +30,16 @@ def check_project_id(id: str) -> bool:
30
30
  logger.info(f"Project ID '{id}' is not valid")
31
31
  return valid
32
32
 
33
+ def user_id_from_project_id(id: str) -> str:
34
+ """Extracts a three-letter user ID from a project ID.
35
+
36
+ :param id: Project ID to use.
37
+ :type id: str
38
+ :return: Three-letter user ID.
39
+ :rtype: str
40
+ """
41
+ logger.debug("Calling user_id_from_project_id function")
42
+ return id.split("-")[1]
33
43
 
34
44
  def check_suffix(suffix: str) -> bool:
35
45
  """Checks whether a project suffix is correctly formed.
@@ -710,7 +710,7 @@ class NotionWrapper(Protocol):
710
710
  logger.info(f"Notion user found with page ID {user_page_id}")
711
711
  return user_page_id
712
712
  else:
713
- logger.warning("Notion user not found")
713
+ logger.info("Notion user not found")
714
714
  return None
715
715
 
716
716
  def get_users(self, clients_db_id: str) -> list:
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "papi-projects"
3
- version = "0.1.6"
3
+ version = "0.1.8"
4
4
  description = "PAPI is an API for managing projects"
5
5
  authors = ["sandyjmacdonald <sandyjmacdonald@gmail.com>"]
6
6
  license = "MIT"
@@ -10,25 +10,25 @@ def main():
10
10
  # Set up argparse
11
11
  parser = argparse.ArgumentParser()
12
12
  parser.add_argument(
13
- "-u", "--user_id", type=str, help="three-letter user (client) ID, e.g. JS1", required=False
13
+ "-u", "--user_id", type=str, help="three-letter user (client) ID, e.g. JAS", required=False
14
14
  )
15
15
  parser.add_argument(
16
- "-v", "--user_name", type=str, help="user (client) name, e.g. John Smith", required=False
16
+ "-v", "--user_name", type=str, help="user (client) name, e.g. John Andrew Smith", required=False
17
17
  )
18
18
  parser.add_argument(
19
19
  "-n", "--name", type=str, help="short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated", required=False
20
20
  )
21
21
  parser.add_argument(
22
- "-p", "--project_id", type=str, help="full project ID, e.g. P2024-JS1-DEFG, if already generated", required=False
22
+ "-p", "--project_id", type=str, help="full project ID, e.g. P2024-JAS-ABCD, if already generated", required=False
23
23
  )
24
24
  parser.add_argument(
25
- '--enable-logging', action='store_true', help='Enable logging output for the papi library.'
25
+ '--enable-logging', action='store_true', help='enable logging output for the papi librar.'
26
26
  )
27
27
  parser.add_argument(
28
- '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='Set the logging level (default: INFO).'
28
+ '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='set the logging level (default: INFO)'
29
29
  )
30
30
  parser.add_argument(
31
- '--log-file', type=str, help='Path to a file where logs should be written.'
31
+ '--log-file', type=str, help='path to a file where logs should be written'
32
32
  )
33
33
  args = parser.parse_args()
34
34
 
@@ -0,0 +1,171 @@
1
+ import sys
2
+ import argparse
3
+ from papi.wrappers import NotionWrapper, TogglTrackWrapper
4
+ from papi import config, setup_logger
5
+ from papi.user import User
6
+ from papi.project import Project, check_project_id, user_id_from_project_id
7
+
8
+ def prompt_for_args():
9
+ """Prompt the user for input interactively."""
10
+ print("No command-line arguments provided. Enter the required information below:")
11
+ print()
12
+
13
+ user_id = input("Enter project PI three-letter ID (e.g., JAS): ").strip()
14
+ if not user_id:
15
+ user_name = input("Enter project PI name (e.g., John Andrew Smith): ").strip()
16
+ else:
17
+ user_name = None
18
+ name = input("Enter project name (e.g., 'RNA-seq analysis'): ").strip()
19
+ if not user_id and not user_name:
20
+ project_id = input("Enter project ID (e.g., P2024-JAS-DEFG): ").strip()
21
+ if check_project_id(project_id):
22
+ user_id = user_id_from_project_id(project_id)
23
+ else:
24
+ project_id = None
25
+
26
+ enable_logging_input = input("Enable logging? (y/n) [n]: ").strip().lower()
27
+ enable_logging = enable_logging_input in ('y', 'yes')
28
+
29
+ if enable_logging:
30
+ log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
31
+ log_level = input(f"Set log level {log_level_choices} [INFO]: ").strip().upper()
32
+ log_level = log_level if log_level else None
33
+ if log_level is not None and log_level not in log_level_choices:
34
+ print("Invalid log level. Defaulting to 'INFO'.")
35
+ log_level = 'INFO'
36
+
37
+ log_file = input("Path to log file (leave blank for none): ").strip()
38
+ log_file = log_file if log_file else None
39
+ else:
40
+ log_level = None
41
+ log_file = None
42
+
43
+ enable_toggl_input = input("Create Toggl Track project? (y/n) [n]: ").strip().lower()
44
+ enable_toggl = enable_toggl_input in ('y', 'yes')
45
+
46
+ enable_notion_input = input("Create Notion project? (y/n) [n]: ").strip().lower()
47
+ enable_notion = enable_notion_input in ('y', 'yes')
48
+
49
+ # Create a Namespace object similar to argparse's
50
+ return argparse.Namespace(
51
+ user_id=user_id or None,
52
+ user_name=user_name or None,
53
+ name=name or None,
54
+ project_id=project_id or None,
55
+ enable_logging=enable_logging,
56
+ log_level=log_level,
57
+ log_file=log_file,
58
+ enable_toggl=enable_toggl,
59
+ enable_notion=enable_notion
60
+ )
61
+
62
+ def main():
63
+ """Main function of create-project script"""
64
+
65
+ # Set up argparse
66
+ parser = argparse.ArgumentParser()
67
+ parser.add_argument(
68
+ "-u", "--user_id", type=str, help="three-letter user (client) ID, e.g. JAS", required=False
69
+ )
70
+ parser.add_argument(
71
+ "-v", "--user_name", type=str, help="user (client) name, e.g. John Andrew Smith", required=False
72
+ )
73
+ parser.add_argument(
74
+ "-n", "--name", type=str, help="short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated", required=False
75
+ )
76
+ parser.add_argument(
77
+ "-p", "--project_id", type=str, help="full project ID, e.g. P2024-JAS-DEFG, if already generated", required=False
78
+ )
79
+ parser.add_argument(
80
+ '--enable-toggl', action='store_true', help='create Toggl Track project'
81
+ )
82
+ parser.add_argument(
83
+ '--enable-notion', action='store_true', help='create Notion project'
84
+ )
85
+ parser.add_argument(
86
+ '--enable-logging', action='store_true', help='enable logging output for the papi library'
87
+ )
88
+ parser.add_argument(
89
+ '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='set the logging level (default: INFO)'
90
+ )
91
+ parser.add_argument(
92
+ '--log-file', type=str, help='path to a file where logs should be written'
93
+ )
94
+ args = parser.parse_args()
95
+
96
+ # Check if any arguments were provided
97
+ if len(sys.argv) == 1:
98
+ args = prompt_for_args()
99
+ else:
100
+ args = parser.parse_args()
101
+
102
+ logger = setup_logger(args.enable_logging, args.log_level, args.log_file)
103
+
104
+ user_id = args.user_id
105
+ user_name = args.user_name
106
+ project_name = args.name
107
+ project_id = args.project_id
108
+ enable_toggl = args.enable_toggl
109
+ enable_notion = args.enable_notion
110
+
111
+ if user_id and not user_name:
112
+ user = User(user_id=user_id)
113
+ elif user_name and not user_id:
114
+ user = User(user_name)
115
+ elif user_id and user_name:
116
+ user = User(user_name, user_id=user_id)
117
+ else:
118
+ logger.warning("Please provide either a three-letter user ID and/or user name")
119
+ return
120
+
121
+ if project_id and not project_name:
122
+ project = Project(id=project_id)
123
+ elif project_name and not project_id:
124
+ project = Project(name=project_name, user_id=user.user_id)
125
+ elif project_id and project_name:
126
+ project = Project(name=project_name, id=project_id)
127
+ else:
128
+ logger.warning("Please provide either a valid project ID and/or project name")
129
+ return
130
+
131
+ if enable_toggl:
132
+ # Set up Toggl Track API wrapper
133
+ #
134
+ # NOTE: you must have added Toggl Track API key and password, with
135
+ # variable names below to .env file in this directory
136
+ if "TOGGL_TRACK_API_KEY" not in config and "TOGGL_TRACK_PASSWORD" not in config:
137
+ logger.warning("Please create a .env file with TOGGL_TRACK_API_KEY and TOGGL_TRACK_PASSWORD set!")
138
+ return
139
+ toggl_api_key = config["TOGGL_TRACK_API_KEY"]
140
+ toggl_api_password = config["TOGGL_TRACK_PASSWORD"]
141
+ toggl = TogglTrackWrapper(toggl_api_key, toggl_api_password)
142
+
143
+ # Tell wrapper which workspace to set as default
144
+ toggl_workspace = config["TOGGL_TRACK_WORKSPACE"]
145
+ toggl.set_default_workspace(toggl_workspace)
146
+
147
+ # Create project on Toggl Track
148
+ toggl_proj_id = toggl.create_project(project, toggl.default_workspace_id)
149
+
150
+ if enable_notion:
151
+ # Set up Notion API wrapper
152
+ #
153
+ # NOTE: you must have added your Notion API credentials and user and projects
154
+ # database IDs with variable names below to .env file in this directory
155
+ if "NOTION_API_SECRET"not in config and "NOTION_CLIENTS_DB" not in config and "NOTION_PROJECTS_DB" not in config:
156
+ logger.warning("Please create a .env file with NOTION_API_SECRET and NOTION_CLIENTS_DB and NOTION_PROJECTS_DB set!")
157
+ return
158
+ notion_api_secret = config["NOTION_API_SECRET"]
159
+ notion_clients_db = config["NOTION_CLIENTS_DB"]
160
+ notion_projects_db = config["NOTION_PROJECTS_DB"]
161
+ notion = NotionWrapper(notion_api_secret)
162
+
163
+ # Create project on Notion
164
+ user_page_id = notion.get_user_page_id(notion_clients_db, user)
165
+ if user_page_id is not None:
166
+ notion_proj_id = notion.create_project(project, user, notion_projects_db, user_page_id=user_page_id)
167
+ else:
168
+ notion_proj_id = notion.create_project(project, user, notion_projects_db)
169
+
170
+ if __name__ == "__main__":
171
+ main()
@@ -10,7 +10,7 @@ def main():
10
10
  # Set up argparse
11
11
  parser = argparse.ArgumentParser()
12
12
  parser.add_argument(
13
- "-u", "--user_id", type=str, help="three-letter user ID, e.g. CRD", required=False
13
+ "-u", "--user_id", type=str, help="three-letter user ID, e.g. JAS", required=False
14
14
  )
15
15
  parser.add_argument(
16
16
  "-g", "--grant_code", type=str, help="grant code, e.g. R12345", required=False
@@ -19,16 +19,16 @@ def main():
19
19
  "-n", "--name", type=str, help="short project name, e.g. 'RNA-seq analysis'", required=False
20
20
  )
21
21
  parser.add_argument(
22
- "-p", "--project_id", type=str, help="full project ID, e.g. P2024-ABC-DEFG, if already generated", required=False
22
+ "-p", "--project_id", type=str, help="full project ID, e.g. P2024-JAS-ABCD, if already generated", required=False
23
23
  )
24
24
  parser.add_argument(
25
- '--enable-logging', action='store_true', help='Enable logging output for the papi library.'
25
+ '--enable-logging', action='store_true', help='enable logging output for the papi library'
26
26
  )
27
27
  parser.add_argument(
28
- '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='Set the logging level (default: INFO).'
28
+ '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='set the logging level (default: INFO)'
29
29
  )
30
30
  parser.add_argument(
31
- '--log-file', type=str, help='Path to a file where logs should be written.'
31
+ '--log-file', type=str, help='path to a file where logs should be written'
32
32
  )
33
33
  args = parser.parse_args()
34
34
 
@@ -81,7 +81,7 @@ def main():
81
81
  # Create project on Toggl Track
82
82
  #
83
83
  # If name and grant code were provided, then project name will
84
- # look like P2024-ABC-WXYZ - RNA-seq analysis (R12345),
84
+ # look like P2024-JAS-ABCD - RNA-seq analysis (R12345),
85
85
  # otherwise it will just be the project ID
86
86
  toggl_proj_id = toggl.create_project(project, toggl.default_workspace_id)
87
87
 
@@ -1,143 +0,0 @@
1
- import sys
2
- import argparse
3
- from papi.wrappers import NotionWrapper, TogglTrackWrapper
4
- from papi import config, setup_logger
5
- from papi.user import User
6
- from papi.project import Project
7
-
8
- def prompt_for_args():
9
- """Prompt the user for input interactively."""
10
- print("No command-line arguments provided. Enter the required information below:")
11
-
12
- user_id = input("Enter user ID (e.g., JS1): ").strip()
13
- user_name = input("Enter user name (e.g., John Smith): ").strip()
14
- name = input("Enter project name (e.g., 'RNA-seq analysis'): ").strip()
15
- project_id = input("Enter project ID (e.g., P2024-JS1-DEFG): ").strip()
16
-
17
- enable_logging_input = input("Enable logging? (y/n) [n]: ").strip().lower()
18
- enable_logging = enable_logging_input in ('y', 'yes')
19
-
20
- log_level_choices = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
21
- log_level = input(f"Set log level {log_level_choices} [INFO]: ").strip().upper()
22
- if log_level not in log_level_choices:
23
- print("Invalid log level. Defaulting to 'INFO'.")
24
- log_level = 'INFO'
25
-
26
- log_file = input("Path to log file (leave blank for none): ").strip()
27
- log_file = log_file if log_file else None
28
-
29
- # Create a Namespace object similar to argparse's
30
- return argparse.Namespace(
31
- user_id=user_id or None,
32
- user_name=user_name or None,
33
- name=name or None,
34
- project_id=project_id or None,
35
- enable_logging=enable_logging,
36
- log_level=log_level,
37
- log_file=log_file
38
- )
39
-
40
- def main():
41
- """Main function of create-project script"""
42
-
43
- # Set up argparse
44
- parser = argparse.ArgumentParser()
45
- parser.add_argument(
46
- "-u", "--user_id", type=str, help="three-letter user (client) ID, e.g. JS1", required=False
47
- )
48
- parser.add_argument(
49
- "-v", "--user_name", type=str, help="user (client) name, e.g. John Smith", required=False
50
- )
51
- parser.add_argument(
52
- "-n", "--name", type=str, help="short project name, e.g. 'RNA-seq analysis', project ID will be auto-generated", required=False
53
- )
54
- parser.add_argument(
55
- "-p", "--project_id", type=str, help="full project ID, e.g. P2024-JS1-DEFG, if already generated", required=False
56
- )
57
- parser.add_argument(
58
- '--enable-logging', action='store_true', help='Enable logging output for the papi library.'
59
- )
60
- parser.add_argument(
61
- '--log-level', type=str, choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='INFO', help='Set the logging level (default: INFO).'
62
- )
63
- parser.add_argument(
64
- '--log-file', type=str, help='Path to a file where logs should be written.'
65
- )
66
- args = parser.parse_args()
67
-
68
- # Check if any arguments were provided
69
- if len(sys.argv) == 1:
70
- args = prompt_for_args()
71
- else:
72
- args = parser.parse_args()
73
-
74
- logger = setup_logger(args.enable_logging, args.log_level, args.log_file)
75
-
76
- # Set up Notion API wrapper
77
- #
78
- # NOTE: you must have added your Notion API credentials and user and projects
79
- # database IDs with variable names below to .env file in this directory
80
- if "NOTION_API_SECRET"not in config and "NOTION_CLIENTS_DB" not in config and "NOTION_PROJECTS_DB" not in config:
81
- logger.warning("Please create a .env file with NOTION_API_SECRET and NOTION_CLIENTS_DB and NOTION_PROJECTS_DB set!")
82
- return
83
- notion_api_secret = config["NOTION_API_SECRET"]
84
- notion_clients_db = config["NOTION_CLIENTS_DB"]
85
- notion_projects_db = config["NOTION_PROJECTS_DB"]
86
- notion = NotionWrapper(notion_api_secret)
87
-
88
- # Set up Toggl Track API wrapper
89
- #
90
- # NOTE: you must have added Toggl Track API key and password, with
91
- # variable names below to .env file in this directory
92
- if "TOGGL_TRACK_API_KEY" not in config and "TOGGL_TRACK_PASSWORD" not in config:
93
- logger.warning("Please create a .env file with TOGGL_TRACK_API_KEY and TOGGL_TRACK_PASSWORD set!")
94
- return
95
- toggl_api_key = config["TOGGL_TRACK_API_KEY"]
96
- toggl_api_password = config["TOGGL_TRACK_PASSWORD"]
97
- toggl = TogglTrackWrapper(toggl_api_key, toggl_api_password)
98
-
99
- # Tell wrapper which workspace to set as default
100
- toggl_workspace = config["TOGGL_TRACK_WORKSPACE"]
101
- toggl.set_default_workspace(toggl_workspace)
102
-
103
- user_id = args.user_id
104
- user_name = args.user_name
105
- project_name = args.name
106
- project_id = args.project_id
107
-
108
- if user_id and not user_name:
109
- user = User(user_id=user_id)
110
- elif user_name and not user_id:
111
- user = User(user_name)
112
- elif user_id and user_name:
113
- user = User(user_name, user_id=user_id)
114
- else:
115
- logger.warning("Please provide either a three-letter user ID and/or user name")
116
- return
117
-
118
- if project_id and not project_name:
119
- project = Project(id=project_id)
120
- elif project_name and not project_id:
121
- project = Project(name=project_name, user_id=user.user_id)
122
- elif project_id and project_name:
123
- project = Project(name=project_name, id=project_id)
124
- else:
125
- logger.warning("Please provide either a valid project ID and/or project name")
126
- return
127
-
128
- # Create project on Notion
129
- user_page_id = notion.get_user_page_id(notion_clients_db, user)
130
- if user_page_id is not None:
131
- notion_proj_id = notion.create_project(project, user, notion_projects_db, user_page_id=user_page_id)
132
- else:
133
- notion_proj_id = notion.create_project(project, user, notion_projects_db)
134
-
135
- # Create project on Toggl Track
136
- #
137
- # If name and grant code were provided, then project name will
138
- # look like P2024-ABC-WXYZ - RNA-seq analysis (R12345),
139
- # otherwise it will just be the project ID
140
- toggl_proj_id = toggl.create_project(project, toggl.default_workspace_id)
141
-
142
- if __name__ == "__main__":
143
- main()