timedctl 3.3.0__tar.gz → 3.5.0__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: timedctl
3
- Version: 3.3.0
3
+ Version: 3.5.0
4
4
  Summary: CLI for timed
5
5
  License: AGPL-3.0-only
6
6
  Author: Arthur Deierlein
@@ -12,7 +12,7 @@ Classifier: Programming Language :: Python :: 3.10
12
12
  Classifier: Programming Language :: Python :: 3.11
13
13
  Requires-Dist: click (>=8.1.3,<9.0.0)
14
14
  Requires-Dist: click-aliases (>=1.0.1,<2.0.0)
15
- Requires-Dist: libtimed (>=0.2.1,<0.3.0)
15
+ Requires-Dist: libtimed (>=0.3.0,<0.4.0)
16
16
  Requires-Dist: pyfzf (>=0.3.1,<0.4.0)
17
17
  Requires-Dist: rich (>=13.4.2,<14.0.0)
18
18
  Requires-Dist: terminaltables (>=3.1.10,<4.0.0)
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "timedctl"
3
- version = "3.3.0"
3
+ version = "3.5.0"
4
4
  description = "CLI for timed"
5
5
  authors = ["Arthur Deierlein <arthur.deierlein@adfinis.com>", "Gian Klug <gian.klug@adfinis.com>"]
6
6
  readme = "README.md"
@@ -11,7 +11,7 @@ python = "^3.10"
11
11
  click = "^8.1.3"
12
12
  pyfzf = "^0.3.1"
13
13
  rich = "^13.4.2"
14
- libtimed = "^0.2.1"
14
+ libtimed = "^0.3.0"
15
15
  terminaltables = "^3.1.10"
16
16
  tomlkit = "^0.11.8"
17
17
  click-aliases = "^1.0.1"
@@ -2,7 +2,6 @@
2
2
  """CLI application for libtimed."""
3
3
 
4
4
  import datetime
5
- import tomllib
6
5
  import os
7
6
  import re
8
7
  import sys
@@ -11,10 +10,11 @@ import click
11
10
  import pyfzf
12
11
  import rich
13
12
  import terminaltables
13
+ import tomllib
14
14
  from click_aliases import ClickAliasedGroup
15
- from tomlkit import dump
16
15
  from libtimed import TimedAPIClient
17
16
  from libtimed.oidc import OIDCClient
17
+ from tomlkit import dump
18
18
 
19
19
 
20
20
  def load_config():
@@ -204,11 +204,12 @@ def get_reports(date):
204
204
  task_obj = report["relationships"]["task"]
205
205
  task = task_obj["attributes"]["name"]
206
206
 
207
- project_obj = timed.projects.get(id=task_obj["relationships"]["project"]["id"])
207
+ project_obj = timed.projects.get(id=task_obj["relationships"]["project"]["id"], cached=True)
208
208
  project = project_obj["attributes"]["name"]
209
209
 
210
210
  customer_obj = timed.customers.get(
211
- id=project_obj["relationships"]["customer"]["data"]["id"]
211
+ id=project_obj["relationships"]["customer"]["data"]["id"],
212
+ cached=True
212
213
  )
213
214
  customer = customer_obj["attributes"]["name"]
214
215
 
@@ -232,28 +233,30 @@ def get_reports(date):
232
233
  def get_activities(date):
233
234
  """Get activities."""
234
235
  activities = timed.activities.get(
235
- {"day": date}, include="task,task.project,task.project.customer",
236
+ {"day": date},
237
+ include="task,task.project,task.project.customer",
236
238
  )
237
239
  table = [["Activity", "Comment", "Start", "End"]]
238
- for activity in activities:
239
- task_obj = activity["relationships"]["task"]
240
+ for activity_obj in activities:
241
+ task_obj = activity_obj["relationships"]["task"]
240
242
  task = task_obj["attributes"]["name"]
241
243
 
242
- project_obj = timed.projects.get(id=task_obj["relationships"]["project"]["id"])
244
+ project_obj = timed.projects.get(id=task_obj["relationships"]["project"]["id"], cached=True)
243
245
  project = project_obj["attributes"]["name"]
244
246
 
245
247
  customer_obj = timed.customers.get(
246
- id=project_obj["relationships"]["customer"]["data"]["id"]
248
+ id=project_obj["relationships"]["customer"]["data"]["id"],
249
+ cached=True
247
250
  )
248
251
  customer = customer_obj["attributes"]["name"]
249
252
 
250
253
  table.append(
251
254
  [
252
255
  f"{customer} > {project} > {task}",
253
- activity["attributes"]["comment"],
254
- activity["attributes"]["from-time"].strftime("%H:%M:%S"),
255
- activity["attributes"]["to-time"].strftime("%H:%M:%S")
256
- if activity["attributes"]["to-time"] is not None
256
+ activity_obj["attributes"]["comment"],
257
+ activity_obj["attributes"]["from-time"].strftime("%H:%M:%S"),
258
+ activity_obj["attributes"]["to-time"].strftime("%H:%M:%S")
259
+ if activity_obj["attributes"]["to-time"] is not None
257
260
  else "active",
258
261
  ]
259
262
  )
@@ -315,9 +318,9 @@ def add():
315
318
  @click.option("--task", default=None)
316
319
  @click.option("--description", default=None)
317
320
  @click.option("--duration", default=None)
318
- def add_report(customer, project, task, description, duration):
321
+ def add_report(customer, project, task, description, duration): # pylint: disable=R0912
319
322
  """Add report(s)."""
320
- customers = timed.customers.get()
323
+ customers = timed.customers.get(cached=True)
321
324
  # ask the user to select a customer
322
325
  msg("Select a customer")
323
326
  # select a customer
@@ -329,7 +332,7 @@ def add_report(customer, project, task, description, duration):
329
332
  else:
330
333
  customer = fzf_wrapper(customers, ["attributes", "name"], "Select a customer: ")
331
334
  # get projects
332
- projects = timed.projects.get({"customer": customer["id"]})
335
+ projects = timed.projects.get({"customer": customer["id"]}, cached=True)
333
336
  # select a project
334
337
  if project:
335
338
  project = [p for p in projects if p["attributes"]["name"] == project]
@@ -339,7 +342,7 @@ def add_report(customer, project, task, description, duration):
339
342
  else:
340
343
  project = fzf_wrapper(projects, ["attributes", "name"], "Select a project: ")
341
344
  # get tasks
342
- tasks = timed.tasks.get({"project": project["id"]})
345
+ tasks = timed.tasks.get({"project": project["id"]}, cached=True)
343
346
  # select a task
344
347
  if task:
345
348
  task = [t for t in tasks if t["attributes"]["name"] == task]
@@ -439,7 +442,7 @@ def activity():
439
442
  @click.option("--task", default=None)
440
443
  def start(comment, customer, project, task):
441
444
  """Start recording activity."""
442
- customers = timed.customers.get()
445
+ customers = timed.customers.get(cached=True)
443
446
  # ask the user to select a customer
444
447
  msg("Select a customer")
445
448
  # select a customer
@@ -451,7 +454,7 @@ def start(comment, customer, project, task):
451
454
  else:
452
455
  customer = fzf_wrapper(customers, ["attributes", "name"], "Select a customer: ")
453
456
  # get projects
454
- projects = timed.projects.get({"customer": customer["id"]})
457
+ projects = timed.projects.get({"customer": customer["id"]}, cached=True)
455
458
  # select a project
456
459
  if project:
457
460
  project = [p for p in projects if p["attributes"]["name"] == project]
@@ -461,7 +464,7 @@ def start(comment, customer, project, task):
461
464
  else:
462
465
  project = fzf_wrapper(projects, ["attributes", "name"], "Select a project: ")
463
466
  # get tasks
464
- tasks = timed.tasks.get({"project": project["id"]})
467
+ tasks = timed.tasks.get({"project": project["id"]}, cached=True)
465
468
  # select a task
466
469
  if task:
467
470
  task = [t for t in tasks if t["attributes"]["name"] == task]
@@ -482,19 +485,24 @@ def start(comment, customer, project, task):
482
485
  error_handler("ERR_ACTIVITY_START_FAILED")
483
486
 
484
487
 
485
- @activity.command()
486
- def stop(aliases=["end", "finish"]):
488
+ @activity.command(aliases=["end", "finish"])
489
+ def stop():
487
490
  """Stop current activity."""
491
+ if not timed.activities.current:
492
+ error_handler("ERR_NO_CURRENT_ACTIVITY")
493
+ else:
494
+ timed.activities.stop()
488
495
  msg("Activity stopped successfully.")
489
496
 
490
497
 
491
- @activity.command()
492
- def show(aliases=["s", "get", "info"]):
498
+ @activity.command(aliases=["s", "get", "info"])
499
+ def show():
493
500
  """Show current activity."""
494
501
  current_activity = timed.activities.current
495
502
  if current_activity:
496
503
  msg(
497
- f"Current activity: {current_activity['attributes']['comment']} (Since {current_activity['attributes']['from-time'].strftime('%H:%M:%S')})"
504
+ f"Current activity: {current_activity['attributes']['comment']} (Since "
505
+ + f"{current_activity['attributes']['from-time'].strftime('%H:%M:%S')})"
498
506
  )
499
507
  else:
500
508
  error_handler("ERR_NO_CURRENT_ACTIVITY")
@@ -505,23 +513,23 @@ def generate_timesheet():
505
513
  """Generate the timesheet of the current activities."""
506
514
  activities = timed.activities.get()
507
515
  if activities:
508
- for activity in activities:
509
- if not activity["attributes"]["transferred"]:
510
- if not activity["attributes"]["to-time"]:
511
- activity["attributes"]["to-time"] = datetime.now()
512
- from_time = activity["attributes"]["from-time"]
513
- to_time = activity["attributes"]["to-time"]
516
+ for activity_obj in activities:
517
+ if not activity_obj["attributes"]["transferred"]:
518
+ if not activity_obj["attributes"]["to-time"]:
519
+ activity_obj["attributes"]["to-time"] = datetime.datetime.now()
520
+ from_time = activity_obj["attributes"]["from-time"]
521
+ to_time = activity_obj["attributes"]["to-time"]
514
522
  duration = to_time - from_time
515
- task = activity["relationships"]["task"]["data"]["id"]
523
+ task = activity_obj["relationships"]["task"]["data"]["id"]
516
524
  timed.reports.post(
517
525
  {
518
526
  "duration": duration,
519
- "comment": activity["attributes"]["comment"],
527
+ "comment": activity_obj["attributes"]["comment"],
520
528
  },
521
529
  {"task": task},
522
530
  )
523
531
  timed.activities.patch(
524
- activity["id"], {"transferred": True}, {"task": task}
532
+ activity_obj["id"], {"transferred": True}, {"task": task}
525
533
  )
526
534
  msg("Timesheet generated successfully.")
527
535
  else:
File without changes
File without changes
File without changes