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.
- {papi_projects-0.1.6 → papi_projects-0.1.8}/PKG-INFO +111 -35
- {papi_projects-0.1.6 → papi_projects-0.1.8}/README.md +110 -34
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/project.py +10 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/wrappers.py +1 -1
- {papi_projects-0.1.6 → papi_projects-0.1.8}/pyproject.toml +1 -1
- {papi_projects-0.1.6 → papi_projects-0.1.8}/scripts/create_notion_project.py +6 -6
- papi_projects-0.1.8/scripts/create_project.py +171 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/scripts/create_toggl_project.py +6 -6
- papi_projects-0.1.6/scripts/create_project.py +0 -143
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/__init__.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/mocks.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/tests/__init__.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/tests/test_project.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/tests/test_user.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/tests/test_userdb.json +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/tests/test_wrappers.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/papi/user.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/scripts/__init__.py +0 -0
- {papi_projects-0.1.6 → papi_projects-0.1.8}/scripts/collate_toggl_hours.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: papi-projects
|
|
3
|
-
Version: 0.1.
|
|
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,
|
|
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
|
-
|
|
76
|
+
Convenience CLI scripts are provided for some common tasks. They are:
|
|
72
77
|
|
|
73
|
-
|
|
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.
|
|
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-
|
|
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
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
211
|
+
### project module
|
|
136
212
|
|
|
137
|
-
|
|
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="
|
|
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-
|
|
234
|
+
P2024-JAS-ABCD
|
|
159
235
|
2024
|
|
160
|
-
|
|
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-
|
|
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
|
-
|
|
176
|
-
|
|
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="
|
|
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="
|
|
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="
|
|
276
|
+
proj = Project(user_id="JAS", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
|
|
201
277
|
```
|
|
202
278
|
|
|
203
|
-
|
|
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-
|
|
213
|
-
print(check_project_id("P2024-
|
|
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("
|
|
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
|
-
|
|
311
|
+
### user module
|
|
236
312
|
|
|
237
|
-
|
|
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("
|
|
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
|
-
|
|
254
|
-
|
|
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("
|
|
340
|
+
usr = User("John Andrew Smith", email="jasmith@email.com")
|
|
265
341
|
|
|
266
342
|
print(usr.email)
|
|
267
343
|
```
|
|
268
344
|
|
|
269
345
|
```
|
|
270
|
-
|
|
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("
|
|
277
|
-
usr.user_id = "
|
|
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,
|
|
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
|
-
|
|
58
|
+
Convenience CLI scripts are provided for some common tasks. They are:
|
|
54
59
|
|
|
55
|
-
|
|
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.
|
|
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-
|
|
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
|
|
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-
|
|
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
|
-
|
|
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
|
-
|
|
193
|
+
### project module
|
|
118
194
|
|
|
119
|
-
|
|
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="
|
|
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-
|
|
216
|
+
P2024-JAS-ABCD
|
|
141
217
|
2024
|
|
142
|
-
|
|
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-
|
|
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
|
-
|
|
158
|
-
|
|
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="
|
|
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="
|
|
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="
|
|
258
|
+
proj = Project(user_id="JAS", p_uuid="6697e457-9785-4668-b78b-72616b27aede")
|
|
183
259
|
```
|
|
184
260
|
|
|
185
|
-
|
|
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-
|
|
195
|
-
print(check_project_id("P2024-
|
|
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("
|
|
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
|
-
|
|
293
|
+
### user module
|
|
218
294
|
|
|
219
|
-
|
|
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("
|
|
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
|
-
|
|
236
|
-
|
|
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("
|
|
322
|
+
usr = User("John Andrew Smith", email="jasmith@email.com")
|
|
247
323
|
|
|
248
324
|
print(usr.email)
|
|
249
325
|
```
|
|
250
326
|
|
|
251
327
|
```
|
|
252
|
-
|
|
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("
|
|
259
|
-
usr.user_id = "
|
|
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.
|
|
713
|
+
logger.info("Notion user not found")
|
|
714
714
|
return None
|
|
715
715
|
|
|
716
716
|
def get_users(self, clients_db_id: str) -> list:
|
|
@@ -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.
|
|
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-
|
|
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='
|
|
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='
|
|
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='
|
|
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.
|
|
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-
|
|
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='
|
|
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='
|
|
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='
|
|
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-
|
|
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()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|