fotolab 0.31.2__tar.gz → 0.31.4__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.
Files changed (56) hide show
  1. {fotolab-0.31.2 → fotolab-0.31.4}/CHANGELOG.md +8 -0
  2. {fotolab-0.31.2 → fotolab-0.31.4}/CONTRIBUTING.md +3 -3
  3. {fotolab-0.31.2 → fotolab-0.31.4}/PKG-INFO +7 -12
  4. {fotolab-0.31.2 → fotolab-0.31.4}/README.md +4 -10
  5. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/__init__.py +2 -1
  6. {fotolab-0.31.2 → fotolab-0.31.4}/noxfile.py +61 -68
  7. {fotolab-0.31.2 → fotolab-0.31.4}/pyproject.toml +26 -1
  8. fotolab-0.31.4/uv.lock +1377 -0
  9. fotolab-0.31.2/Pipfile +0 -33
  10. fotolab-0.31.2/Pipfile.lock +0 -1103
  11. {fotolab-0.31.2 → fotolab-0.31.4}/.coveragerc +0 -0
  12. {fotolab-0.31.2 → fotolab-0.31.4}/.gitignore +0 -0
  13. {fotolab-0.31.2 → fotolab-0.31.4}/.pre-commit-config.yaml +0 -0
  14. {fotolab-0.31.2 → fotolab-0.31.4}/.python-version +0 -0
  15. {fotolab-0.31.2 → fotolab-0.31.4}/LICENSE.md +0 -0
  16. {fotolab-0.31.2 → fotolab-0.31.4}/docs/Makefile +0 -0
  17. {fotolab-0.31.2 → fotolab-0.31.4}/docs/make.bat +0 -0
  18. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/CHANGELOG.md +0 -0
  19. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/CONTRIBUTING.md +0 -0
  20. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/LICENSE.md +0 -0
  21. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/README.md +0 -0
  22. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/_static/logo.jpg +0 -0
  23. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/conf.py +0 -0
  24. {fotolab-0.31.2 → fotolab-0.31.4}/docs/source/index.rst +0 -0
  25. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/__main__.py +0 -0
  26. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/cli.py +0 -0
  27. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/__init__.py +0 -0
  28. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/animate.py +0 -0
  29. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/auto.py +0 -0
  30. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/border.py +0 -0
  31. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/contrast.py +0 -0
  32. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/env.py +0 -0
  33. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/halftone.py +0 -0
  34. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/info.py +0 -0
  35. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/montage.py +0 -0
  36. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/resize.py +0 -0
  37. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/rotate.py +0 -0
  38. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/sharpen.py +0 -0
  39. {fotolab-0.31.2 → fotolab-0.31.4}/fotolab/subcommands/watermark.py +0 -0
  40. {fotolab-0.31.2 → fotolab-0.31.4}/generate +0 -0
  41. {fotolab-0.31.2 → fotolab-0.31.4}/tests/__init__.py +0 -0
  42. {fotolab-0.31.2 → fotolab-0.31.4}/tests/conftest.py +0 -0
  43. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_animate_subcommand.py +0 -0
  44. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_auto_subcommand.py +0 -0
  45. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_border_subcommand.py +0 -0
  46. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_contrast_subcommand.py +0 -0
  47. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_env_subcommand.py +0 -0
  48. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_halftone_subcommand.py +0 -0
  49. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_help_flag.py +0 -0
  50. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_info_subcommand.py +0 -0
  51. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_montage_subcommand.py +0 -0
  52. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_quiet_flag.py +0 -0
  53. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_resize_subcommand.py +0 -0
  54. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_rotate_subcommand.py +0 -0
  55. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_sharpen_subcommand.py +0 -0
  56. {fotolab-0.31.2 → fotolab-0.31.4}/tests/test_watermark_subcommand.py +0 -0
@@ -7,6 +7,14 @@ and this project adheres to [0-based versioning](https://0ver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## v0.31.4 (2025-06-15)
11
+
12
+ - Fix `deps` job in `nox` session due to migration to `uv`
13
+ - Fix `pre-commit` not available in `lint` session
14
+ - Initial migration from `pipenv` to `uv`
15
+ - Refactor release `nox` job to use uv version
16
+ - Resolve `uv` not using nox's `venv` warning
17
+
10
18
  ## v0.31.2 (2025-06-08)
11
19
 
12
20
  - Add `ruff` to dev deps
@@ -31,14 +31,14 @@ pyenv install $(cat .python-version)
31
31
  Install necessary packages:
32
32
 
33
33
  ```console
34
- python -m pip install --upgrade pip pipenv nox
35
- pipenv install --dev
34
+ python -m pip install --upgrade pip uv nox
35
+ uv pip install -e .[dev]
36
36
  ```
37
37
 
38
38
  Spawn a shell in virtual environment for your development:
39
39
 
40
40
  ```console
41
- pipenv shell
41
+ uv shell
42
42
  ```
43
43
 
44
44
  Show all available `nox` sessions:
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: fotolab
3
- Version: 0.31.2
3
+ Version: 0.31.4
4
4
  Summary: A console program that manipulate images.
5
5
  Keywords: photography,photo
6
6
  Author-email: Kian-Meng Ang <kianmeng@cpan.org>
@@ -16,6 +16,7 @@ Classifier: Programming Language :: Python :: 3.11
16
16
  Classifier: Programming Language :: Python :: 3.12
17
17
  Classifier: Programming Language :: Python :: 3.13
18
18
  Classifier: Programming Language :: Python
19
+ License-File: LICENSE.md
19
20
  Requires-Dist: pillow
20
21
  Project-URL: Changelog, https://github.com/kianmeng/fotolab/blob/master/CHANGELOG.md
21
22
  Project-URL: Issues, https://github.com/kianmeng/fotolab/issues
@@ -27,28 +28,22 @@ A console program to manipulate photos.
27
28
 
28
29
  ## Installation
29
30
 
30
- Stable version From PyPI using `pipx`:
31
+ Stable version From PyPI using `uv`:
31
32
 
32
33
  ```console
33
- pipx install fotolab
34
- ```
35
-
36
- Stable version From PyPI using `pip`:
37
-
38
- ```console
39
- python -m pip install fotolab
34
+ uv pip install fotolab
40
35
  ```
41
36
 
42
37
  Upgrade to latest stable version:
43
38
 
44
39
  ```console
45
- python3 -m pip install fotolab --upgrade
40
+ uv pip install fotolab --upgrade
46
41
  ```
47
42
 
48
43
  Latest development version from GitHub:
49
44
 
50
45
  ```console
51
- python -m pip install -e git+https://github.com/kianmeng/fotolab.git
46
+ uv pip install -e git+https://github.com/kianmeng/fotolab.git
52
47
  ```
53
48
 
54
49
  ## Usage
@@ -4,28 +4,22 @@ A console program to manipulate photos.
4
4
 
5
5
  ## Installation
6
6
 
7
- Stable version From PyPI using `pipx`:
7
+ Stable version From PyPI using `uv`:
8
8
 
9
9
  ```console
10
- pipx install fotolab
11
- ```
12
-
13
- Stable version From PyPI using `pip`:
14
-
15
- ```console
16
- python -m pip install fotolab
10
+ uv pip install fotolab
17
11
  ```
18
12
 
19
13
  Upgrade to latest stable version:
20
14
 
21
15
  ```console
22
- python3 -m pip install fotolab --upgrade
16
+ uv pip install fotolab --upgrade
23
17
  ```
24
18
 
25
19
  Latest development version from GitHub:
26
20
 
27
21
  ```console
28
- python -m pip install -e git+https://github.com/kianmeng/fotolab.git
22
+ uv pip install -e git+https://github.com/kianmeng/fotolab.git
29
23
  ```
30
24
 
31
25
  ## Usage
@@ -20,11 +20,12 @@ import logging
20
20
  import os
21
21
  import subprocess
22
22
  import sys
23
+ from importlib import metadata
23
24
  from pathlib import Path
24
25
 
25
26
  from PIL import Image
26
27
 
27
- __version__ = "0.31.2"
28
+ __version__ = metadata.version("fotolab")
28
29
 
29
30
  log = logging.getLogger(__name__)
30
31
 
@@ -17,19 +17,17 @@
17
17
 
18
18
  """Nox configuration."""
19
19
 
20
- import ast
20
+ import argparse
21
21
  import datetime
22
22
 
23
23
  import nox
24
- from packaging.version import Version
25
24
 
26
25
 
27
26
  @nox.session(python="3.9")
28
27
  def deps(session: nox.Session) -> None:
29
28
  """Update pre-commit hooks and deps."""
30
- session.install("pipenv")
29
+ _uv_install(session)
31
30
  session.run("pre-commit", "autoupdate", *session.posargs)
32
- session.run("pipenv", "update", env={"PIPENV_VERBOSITY": "-1"})
33
31
 
34
32
 
35
33
  @nox.session(python="3.13")
@@ -40,22 +38,23 @@ def lint(session: nox.Session) -> None:
40
38
 
41
39
  nox -s lint -- pylint
42
40
  """
41
+ _uv_install(session)
43
42
  session.run("pre-commit", "run", "--all-files", *session.posargs)
44
43
 
45
44
 
46
45
  @nox.session(python=["3.9", "3.10", "3.11", "3.12", "3.13"])
47
46
  def test(session: nox.Session) -> None:
48
47
  """Run test."""
49
- _pipenv_install(session)
50
- session.run("pipenv", "run", "pytest", "--numprocesses", "auto", *session.posargs)
48
+ _uv_install(session)
49
+ session.run("uv", "run", "pytest", "--numprocesses", "auto", *session.posargs)
51
50
 
52
51
 
53
52
  @nox.session(python="3.13")
54
53
  def cov(session: nox.Session) -> None:
55
54
  """Run test coverage."""
56
- _pipenv_install(session)
55
+ _uv_install(session)
57
56
  session.run(
58
- "pipenv",
57
+ "uv",
59
58
  "run",
60
59
  "pytest",
61
60
  "--numprocesses",
@@ -70,16 +69,16 @@ def cov(session: nox.Session) -> None:
70
69
  @nox.session(python="3.13")
71
70
  def doc(session: nox.Session) -> None:
72
71
  """Build doc with sphinx."""
73
- _pipenv_install(session)
72
+ _uv_install(session)
74
73
  session.run("sphinx-build", "docs/source/", "docs/build/html", *session.posargs)
75
74
 
76
75
 
77
76
  @nox.session(python="3.13")
78
77
  def readme(session: nox.Session) -> None:
79
78
  """Update console help menu to readme."""
80
- _pipenv_install(session)
79
+ _uv_install(session)
81
80
  with open("README.md", "r+", encoding="utf8") as f:
82
- help_message = session.run("fotolab", "-h", silent=True)
81
+ help_message = session.run("uv", "run", "fotolab", "-h", silent=True)
83
82
  help_codeblock = f"\n\n```console\n{help_message}```\n\n"
84
83
 
85
84
  content = f.read()
@@ -99,7 +98,9 @@ def readme(session: nox.Session) -> None:
99
98
  "watermark",
100
99
  "env",
101
100
  ]:
102
- help_message = session.run("fotolab", subcommand, "-h", silent=True)
101
+ help_message = session.run(
102
+ "uv", "run", "fotolab", subcommand, "-h", silent=True
103
+ )
103
104
  help_codeblock = f"\n\n```console\n{help_message}```\n\n"
104
105
 
105
106
  marker = readme_md.split(f"<!--help-{subcommand} !-->")[1]
@@ -120,66 +121,39 @@ def release(session: nox.Session) -> None:
120
121
  nox -s release -- minor
121
122
  nox -s release -- micro (default)
122
123
  """
123
- with open("fotolab/__init__.py", "r", encoding="utf8") as f:
124
- tree = ast.parse(f.read())
125
- current_version = None
126
- for node in ast.walk(tree):
127
- if isinstance(node, ast.Assign) and len(node.targets) == 1:
128
- target, value = node.targets[0], node.value
129
- if target.id == "__version__" and isinstance(value, ast.Constant):
130
- current_version = value.s
131
- break
132
-
133
- if current_version is None:
134
- raise ValueError("Missing __version__ variable in __init__.py")
135
-
136
- before_version = Version(current_version)
137
-
138
- (major, minor, micro) = (
139
- before_version.major,
140
- before_version.minor,
141
- before_version.micro,
142
- )
143
- if "major" in session.posargs:
144
- major = major + 1
145
- minor = 0
146
- micro = 0
147
-
148
- if "minor" in session.posargs:
149
- minor = minor + 1
150
- micro = 0
151
-
152
- if "micro" in session.posargs or session.posargs == []:
153
- micro = micro + 1
154
-
155
- after_version = f"{major}.{minor}.{micro}"
156
-
157
- _search_and_replace("fotolab/__init__.py", str(before_version), after_version)
158
-
159
- session.log(f"Bumping version from {before_version} to {after_version}")
160
-
161
- date = datetime.date.today().strftime("%Y-%m-%d")
162
- before_header = "## [Unreleased]\n\n"
163
- after_header = f"## [Unreleased]\n\n## v{after_version} ({date})\n\n"
164
- _search_and_replace("CHANGELOG.md", before_header, after_header)
124
+ _uv_install(session)
125
+
126
+ parser = argparse.ArgumentParser(description="Release a semver version.")
127
+ parser.add_argument(
128
+ "semver",
129
+ type=str,
130
+ nargs="?",
131
+ help="The type of semver release to make.",
132
+ default="patch",
133
+ choices={"major", "minor", "patch"},
134
+ )
135
+ args = parser.parse_args(args=session.posargs)
165
136
 
166
- session.run(
167
- "git",
168
- "commit",
169
- "--no-verify",
170
- "-am",
171
- f"Bump {after_version} release",
172
- external=True,
173
- )
137
+ session.run("uv", "version", "--bump", args.semver)
138
+ after_version = session.run("uv", "version", "--short", silent=True).strip()
174
139
 
175
- if input("Publish package to pypi? (y/n): ").lower() in ["y", "yes"]:
176
- session.run("flit", "build")
177
- session.run("flit", "publish")
140
+ date = datetime.date.today().strftime("%Y-%m-%d")
141
+ before_header = "## [Unreleased]\n\n"
142
+ after_header = f"## [Unreleased]\n\n## v{after_version} ({date})\n\n"
143
+ _search_and_replace("CHANGELOG.md", before_header, after_header)
178
144
 
145
+ session.run(
146
+ "git",
147
+ "commit",
148
+ "--no-verify",
149
+ "-am",
150
+ f"Bump {after_version} release",
151
+ external=True,
152
+ )
179
153
 
180
- def _pipenv_install(session: nox.Session) -> None:
181
- session.install("pipenv")
182
- session.run("pipenv", "install", "--dev", env={"PIPENV_VERBOSITY": "-1"})
154
+ if input("Publish package to pypi? (y/n): ").lower() in ["y", "yes"]:
155
+ session.run("flit", "build")
156
+ session.run("flit", "publish")
183
157
 
184
158
 
185
159
  def _search_and_replace(file, search, replace) -> None:
@@ -189,3 +163,22 @@ def _search_and_replace(file, search, replace) -> None:
189
163
  f.seek(0)
190
164
  f.write(content)
191
165
  f.truncate()
166
+
167
+
168
+ def _uv_install(session: nox.Session) -> None:
169
+ """Install the project and its development dependencies using uv.
170
+
171
+ This also resolves the following error:
172
+ warning: `VIRTUAL_ENV=.nox/lint` does not match the project environment
173
+ path `.venv` and will be ignored
174
+
175
+ See https://nox.thea.codes/en/stable/cookbook.html#using-a-lockfile
176
+ """
177
+ session.run_install(
178
+ "uv",
179
+ "sync",
180
+ "--upgrade",
181
+ "--all-packages",
182
+ f"--python={session.virtualenv.location}",
183
+ env={"UV_PROJECT_ENVIRONMENT": session.virtualenv.location},
184
+ )
@@ -20,7 +20,8 @@ classifiers = [
20
20
  "Programming Language :: Python :: 3.13",
21
21
  "Programming Language :: Python",
22
22
  ]
23
- dynamic = ["version", "description"]
23
+ version = "0.31.4"
24
+ dynamic = ["description"]
24
25
  keywords = ["photography", "photo"]
25
26
  dependencies = [
26
27
  "pillow",
@@ -33,3 +34,27 @@ Source = "https://github.com/kianmeng/fotolab"
33
34
 
34
35
  [project.scripts]
35
36
  fotolab = "fotolab.cli:main"
37
+
38
+ [dependency-groups]
39
+ dev = [
40
+ "exceptiongroup",
41
+ "flake8-docstrings",
42
+ "flake8-print",
43
+ "flake8-pytest-style",
44
+ "flake8-simplify",
45
+ "flit",
46
+ "importlib-metadata",
47
+ "myst-parser",
48
+ "nox",
49
+ "pre-commit",
50
+ "pytest",
51
+ "pytest-cov",
52
+ "pytest-randomly",
53
+ "pytest-xdist",
54
+ "ruff",
55
+ "scripttest",
56
+ "sphinx",
57
+ "sphinx-autodoc-typehints",
58
+ "sphinx-copybutton",
59
+ "tomli",
60
+ ]