worklogs 0.3.0__tar.gz → 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: worklogs
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: Local markdown worklog helpers for developer workflows.
5
5
  Project-URL: Homepage, https://github.com/alik-git/worklogs
6
6
  Project-URL: Repository, https://github.com/alik-git/worklogs
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Typing :: Typed
19
19
  Requires-Python: >=3.11
20
+ Requires-Dist: colorlog>=6.10
20
21
  Provides-Extra: dev
21
22
  Requires-Dist: build>=1.2; extra == 'dev'
22
23
  Requires-Dist: mypy>=1.15; extra == 'dev'
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "worklogs"
7
- version = "0.3.0"
7
+ version = "0.3.2"
8
8
  description = "Local markdown worklog helpers for developer workflows."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.11"
@@ -25,7 +25,9 @@ classifiers = [
25
25
  "Programming Language :: Python :: 3.13",
26
26
  "Typing :: Typed",
27
27
  ]
28
- dependencies = []
28
+ dependencies = [
29
+ "colorlog>=6.10",
30
+ ]
29
31
 
30
32
  [project.optional-dependencies]
31
33
  dev = [
@@ -2,6 +2,6 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- __version__ = "0.3.0"
5
+ __version__ = "0.3.2"
6
6
 
7
7
  __all__ = ["__version__"]
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import argparse
6
+ import logging
6
7
  import os
7
8
  import re
8
9
  import subprocess
@@ -20,6 +21,15 @@ if TYPE_CHECKING:
20
21
  from collections.abc import Mapping, Sequence
21
22
 
22
23
  VALID_KINDS = frozenset({"plan", "note", "investigation", "codereview"})
24
+ _LOG_FORMAT = "[%(levelname)s] %(message)s"
25
+ _COLOR_FORMAT = "%(log_color)s[%(levelname)s]%(reset)s %(message)s"
26
+ _LOG_COLORS = {
27
+ "DEBUG": "cyan",
28
+ "INFO": "bold_white",
29
+ "WARNING": "yellow",
30
+ "ERROR": "red",
31
+ }
32
+ LOGGER = logging.getLogger(__name__)
23
33
  NAME_PATTERN = re.compile(r"^[a-z0-9][a-z0-9._-]*$")
24
34
  CONFIG_PATH = Path("~/.config/worklogs/config.toml")
25
35
 
@@ -123,8 +133,26 @@ def build_parser() -> argparse.ArgumentParser:
123
133
  return parser
124
134
 
125
135
 
136
+ def _configure_logging() -> None:
137
+ """Configure color console logging for the worklogs CLI."""
138
+ use_color = not os.environ.get("NO_COLOR") and sys.stderr.isatty()
139
+ handler = logging.StreamHandler()
140
+ if use_color:
141
+ try:
142
+ import colorlog
143
+ handler.setFormatter(
144
+ colorlog.ColoredFormatter(_COLOR_FORMAT, log_colors=_LOG_COLORS)
145
+ )
146
+ except ImportError:
147
+ handler.setFormatter(logging.Formatter(_LOG_FORMAT))
148
+ else:
149
+ handler.setFormatter(logging.Formatter(_LOG_FORMAT))
150
+ logging.basicConfig(level=logging.INFO, handlers=[handler], force=True)
151
+
152
+
126
153
  def main(argv: Sequence[str] | None = None) -> int:
127
154
  """Run the worklogs command-line interface."""
155
+ _configure_logging()
128
156
  parser = build_parser()
129
157
  args = parser.parse_args(argv)
130
158
 
@@ -201,13 +229,16 @@ def _run_workset(args: argparse.Namespace) -> int:
201
229
  year, month, day = day_dir.parts[-3], day_dir.parts[-2], day_dir.parts[-1]
202
230
  dest = worksets_root / year / month / day / args.name
203
231
 
204
- result = create_workset(
205
- slug=args.name,
206
- repo_specs=args.repo_specs,
207
- dest=dest,
208
- no_env=args.no_env,
209
- no_smoke=args.no_smoke,
210
- )
232
+ try:
233
+ result = create_workset(
234
+ slug=args.name,
235
+ repo_specs=args.repo_specs,
236
+ dest=dest,
237
+ no_env=args.no_env,
238
+ no_smoke=args.no_smoke,
239
+ )
240
+ except Exception as exc:
241
+ raise WorklogsError(str(exc)) from exc
211
242
  _print_workset_result(result)
212
243
  return 0 if result.ok else 1
213
244
 
@@ -279,23 +310,22 @@ def _create_workset_for_plan(
279
310
  from workset import create_workset
280
311
 
281
312
  if config.worksets_root is None:
282
- print(
283
- "worklogs: warning: --workset given but worksets_root not configured; "
284
- "skipping workset creation",
285
- file=sys.stderr,
286
- )
313
+ LOGGER.warning("--workset given but worksets_root not configured; skipping")
287
314
  return
288
315
 
289
316
  day_dir = plan_path.parent
290
317
  year, month, day = day_dir.parts[-3], day_dir.parts[-2], day_dir.parts[-1]
291
318
  dest = config.worksets_root / year / month / day / identity.name
292
- result = create_workset(slug=identity.name, repo_specs=repo_specs, dest=dest)
319
+ try:
320
+ result = create_workset(slug=identity.name, repo_specs=repo_specs, dest=dest)
321
+ except Exception as exc:
322
+ raise WorklogsError(str(exc)) from exc
293
323
  _print_workset_result(result)
294
324
 
295
325
 
296
326
  def _print_workset_result(result: object) -> None:
297
- """Print workset creation summary."""
298
- print(f"\nworkset ready: {result.path}") # type: ignore[attr-defined]
327
+ """Log workset creation summary."""
328
+ LOGGER.info("workset ready: %s", result.path) # type: ignore[attr-defined]
299
329
  for repo in result.repos: # type: ignore[attr-defined]
300
330
  smoke = (
301
331
  "✓"
@@ -303,9 +333,9 @@ def _print_workset_result(result: object) -> None:
303
333
  else ("✗" if repo.smoke_passed is False else "~")
304
334
  )
305
335
  label = f"[{repo.env_backend}]" if repo.env_backend != "none" else "[no env]"
306
- print(f" {smoke} {repo.name} {label} {repo.branch}")
336
+ LOGGER.info(" %s %s %s %s", smoke, repo.name, label, repo.branch)
307
337
  if not repo.env_ok:
308
- print(f" ! {repo.env_message}")
338
+ LOGGER.warning(" %s", repo.env_message)
309
339
 
310
340
 
311
341
  def _require_workset_package() -> None:
@@ -724,7 +754,4 @@ def _unlink_created_file(path: Path) -> None:
724
754
  except FileNotFoundError:
725
755
  return
726
756
  except OSError as error:
727
- print(
728
- f"worklogs: warning: could not clean up partial file {path}: {error}",
729
- file=sys.stderr,
730
- )
757
+ LOGGER.warning("could not clean up partial file %s: %s", path, error)
@@ -28,7 +28,7 @@ if TYPE_CHECKING:
28
28
 
29
29
  def test_version_is_exposed() -> None:
30
30
  """Package exposes its current version."""
31
- assert worklogs.__version__ == "0.3.0"
31
+ assert worklogs.__version__ == "0.3.2"
32
32
 
33
33
 
34
34
  def test_cli_accepts_no_arguments() -> None:
@@ -38,6 +38,18 @@ wheels = [
38
38
  { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
39
39
  ]
40
40
 
41
+ [[package]]
42
+ name = "colorlog"
43
+ version = "6.10.1"
44
+ source = { registry = "https://pypi.org/simple" }
45
+ dependencies = [
46
+ { name = "colorama", marker = "sys_platform == 'win32'" },
47
+ ]
48
+ sdist = { url = "https://files.pythonhosted.org/packages/a2/61/f083b5ac52e505dfc1c624eafbf8c7589a0d7f32daa398d2e7590efa5fda/colorlog-6.10.1.tar.gz", hash = "sha256:eb4ae5cb65fe7fec7773c2306061a8e63e02efc2c72eba9d27b0fa23c94f1321", size = 17162, upload-time = "2025-10-16T16:14:11.978Z" }
49
+ wheels = [
50
+ { url = "https://files.pythonhosted.org/packages/6d/c1/e419ef3723a074172b68aaa89c9f3de486ed4c2399e2dbd8113a4fdcaf9e/colorlog-6.10.1-py3-none-any.whl", hash = "sha256:2d7e8348291948af66122cff006c9f8da6255d224e7cf8e37d8de2df3bad8c9c", size = 11743, upload-time = "2025-10-16T16:14:10.512Z" },
51
+ ]
52
+
41
53
  [[package]]
42
54
  name = "distlib"
43
55
  version = "0.4.0"
@@ -420,8 +432,11 @@ wheels = [
420
432
 
421
433
  [[package]]
422
434
  name = "worklogs"
423
- version = "0.3.0"
435
+ version = "0.3.2"
424
436
  source = { editable = "." }
437
+ dependencies = [
438
+ { name = "colorlog" },
439
+ ]
425
440
 
426
441
  [package.optional-dependencies]
427
442
  dev = [
@@ -435,6 +450,7 @@ dev = [
435
450
  [package.metadata]
436
451
  requires-dist = [
437
452
  { name = "build", marker = "extra == 'dev'", specifier = ">=1.2" },
453
+ { name = "colorlog", specifier = ">=6.10" },
438
454
  { name = "mypy", marker = "extra == 'dev'", specifier = ">=1.15" },
439
455
  { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=4.0" },
440
456
  { name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" },
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes