fotolab 0.15.0__tar.gz → 0.16.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.
Files changed (43) hide show
  1. {fotolab-0.15.0 → fotolab-0.16.0}/.pre-commit-config.yaml +1 -1
  2. fotolab-0.16.0/.python-version +5 -0
  3. {fotolab-0.15.0 → fotolab-0.16.0}/CHANGELOG.md +11 -0
  4. {fotolab-0.15.0 → fotolab-0.16.0}/PKG-INFO +20 -3
  5. {fotolab-0.15.0 → fotolab-0.16.0}/Pipfile +1 -0
  6. {fotolab-0.15.0 → fotolab-0.16.0}/Pipfile.lock +90 -65
  7. {fotolab-0.15.0 → fotolab-0.16.0}/README.md +19 -2
  8. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/__init__.py +1 -1
  9. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/cli.py +2 -0
  10. fotolab-0.16.0/fotolab/rotate.py +61 -0
  11. fotolab-0.16.0/noxfile.py +24 -0
  12. fotolab-0.15.0/.python-version +0 -5
  13. {fotolab-0.15.0 → fotolab-0.16.0}/.coveragerc +0 -0
  14. {fotolab-0.15.0 → fotolab-0.16.0}/.gitignore +0 -0
  15. {fotolab-0.15.0 → fotolab-0.16.0}/CONTRIBUTING.md +0 -0
  16. {fotolab-0.15.0 → fotolab-0.16.0}/LICENSE.md +0 -0
  17. {fotolab-0.15.0 → fotolab-0.16.0}/docs/Makefile +0 -0
  18. {fotolab-0.15.0 → fotolab-0.16.0}/docs/make.bat +0 -0
  19. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/CHANGELOG.md +0 -0
  20. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/CONTRIBUTING.md +0 -0
  21. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/LICENSE.md +0 -0
  22. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/README.md +0 -0
  23. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/_static/logo.jpg +0 -0
  24. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/conf.py +0 -0
  25. {fotolab-0.15.0 → fotolab-0.16.0}/docs/source/index.rst +0 -0
  26. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/__main__.py +0 -0
  27. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/animate.py +0 -0
  28. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/auto.py +0 -0
  29. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/border.py +0 -0
  30. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/contrast.py +0 -0
  31. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/env.py +0 -0
  32. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/info.py +0 -0
  33. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/montage.py +0 -0
  34. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/resize.py +0 -0
  35. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/sharpen.py +0 -0
  36. {fotolab-0.15.0 → fotolab-0.16.0}/fotolab/watermark.py +0 -0
  37. {fotolab-0.15.0 → fotolab-0.16.0}/pyproject.toml +0 -0
  38. {fotolab-0.15.0 → fotolab-0.16.0}/tests/__init__.py +0 -0
  39. {fotolab-0.15.0 → fotolab-0.16.0}/tests/conftest.py +0 -0
  40. {fotolab-0.15.0 → fotolab-0.16.0}/tests/test_env.py +0 -0
  41. {fotolab-0.15.0 → fotolab-0.16.0}/tests/test_help_flag.py +0 -0
  42. {fotolab-0.15.0 → fotolab-0.16.0}/tests/test_quiet_flag.py +0 -0
  43. {fotolab-0.15.0 → fotolab-0.16.0}/tox.ini +0 -0
@@ -15,7 +15,7 @@ repos:
15
15
  - id: trailing-whitespace
16
16
 
17
17
  - repo: https://github.com/abravalheri/validate-pyproject
18
- rev: v0.16
18
+ rev: v0.17
19
19
  hooks:
20
20
  - id: validate-pyproject
21
21
  name: validate-pyproject
@@ -0,0 +1,5 @@
1
+ 3.8.19
2
+ 3.9.19
3
+ 3.10.14
4
+ 3.11.9
5
+ 3.12.3
@@ -7,6 +7,17 @@ and this project adheres to [0-based versioning](https://0ver.org/).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## v0.16.0 (2024-05-12)
11
+
12
+ ### Added
13
+
14
+ - Add `rotate` subcommand to rotate an image
15
+ - Add initial `lint` session for `nox`
16
+
17
+ ### Changed
18
+
19
+ - Bump deps, `pre-commit` hooks, and Python versions in `pyenv`
20
+
10
21
  ## v0.15.0 (2024-05-05)
11
22
 
12
23
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fotolab
3
- Version: 0.15.0
3
+ Version: 0.16.0
4
4
  Summary: A console program that manipulate images.
5
5
  Keywords: photography,photo
6
6
  Author-email: Kian-Meng Ang <kianmeng@cpan.org>
@@ -58,7 +58,7 @@ fotolab -h
58
58
 
59
59
  ```console
60
60
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
61
- {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
61
+ {animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
62
62
  ...
63
63
 
64
64
  A console program to manipulate photos.
@@ -68,7 +68,7 @@ A console program to manipulate photos.
68
68
  issues: https://github.com/kianmeng/fotolab/issues
69
69
 
70
70
  positional arguments:
71
- {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
71
+ {animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
72
72
  sub-command help
73
73
  animate animate an image
74
74
  auto auto adjust (resize, contrast, and watermark) a photo
@@ -76,6 +76,7 @@ positional arguments:
76
76
  contrast contrast an image
77
77
  info info an image
78
78
  resize resize an image
79
+ rotate rotate an image
79
80
  montage montage a list of image
80
81
  sharpen sharpen an image
81
82
  watermark watermark an image
@@ -196,6 +197,22 @@ optional arguments:
196
197
  -h, --help show this help message and exit
197
198
  ```
198
199
 
200
+ ### fotolab rotate
201
+
202
+ ```console
203
+ fotolab rotate -h
204
+ ```
205
+
206
+ ```console
207
+ usage: fotolab rotate [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
208
+
209
+ positional arguments:
210
+ IMAGE_FILENAMES set the image filenames
211
+
212
+ optional arguments:
213
+ -h, --help show this help message and exit
214
+ ```
215
+
199
216
  ### fotolab montage
200
217
 
201
218
  ```console
@@ -23,6 +23,7 @@ scripttest = "*"
23
23
  tomli = "*"
24
24
  tox = "<4"
25
25
  tox-pyenv = "*"
26
+ nox = "*"
26
27
 
27
28
  [requires]
28
29
  python_version = "3.8"
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "_meta": {
3
3
  "hash": {
4
- "sha256": "771b8d253ef37cf5b47ebdfb6ec968ac0c2287ac70f9b4590691debfa8c42af0"
4
+ "sha256": "2802f82088933ceafb9dbd46875d8cdfd808d188201db87fb804aeb1746f1095"
5
5
  },
6
6
  "pipfile-spec": 6,
7
7
  "requires": {
@@ -94,6 +94,14 @@
94
94
  }
95
95
  },
96
96
  "develop": {
97
+ "argcomplete": {
98
+ "hashes": [
99
+ "sha256:c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54",
100
+ "sha256:fd03ff4a5b9e6580569d34b273f741e85cd9e072f3feeeee3eba4891c70eda62"
101
+ ],
102
+ "markers": "python_version >= '3.8'",
103
+ "version": "==3.3.0"
104
+ },
97
105
  "astor": {
98
106
  "hashes": [
99
107
  "sha256:070a54e890cefb5b3739d19f30f5a5ec840ffc9c50ffa7d23cc9fc1a38ebbfc5",
@@ -110,66 +118,74 @@
110
118
  "markers": "python_version >= '3.8'",
111
119
  "version": "==3.4.0"
112
120
  },
121
+ "colorlog": {
122
+ "hashes": [
123
+ "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44",
124
+ "sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33"
125
+ ],
126
+ "markers": "python_version >= '3.6'",
127
+ "version": "==6.8.2"
128
+ },
113
129
  "coverage": {
114
130
  "extras": [
115
131
  "toml"
116
132
  ],
117
133
  "hashes": [
118
- "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0",
119
- "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7",
120
- "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631",
121
- "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b",
122
- "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25",
123
- "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7",
124
- "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067",
125
- "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b",
126
- "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46",
127
- "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5",
128
- "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a",
129
- "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3",
130
- "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4",
131
- "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1",
132
- "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475",
133
- "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c",
134
- "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1",
135
- "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be",
136
- "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58",
137
- "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de",
138
- "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a",
139
- "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb",
140
- "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95",
141
- "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb",
142
- "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517",
143
- "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656",
144
- "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e",
145
- "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880",
146
- "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9",
147
- "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f",
148
- "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2",
149
- "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af",
150
- "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2",
151
- "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932",
152
- "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc",
153
- "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d",
154
- "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d",
155
- "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493",
156
- "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64",
157
- "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4",
158
- "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff",
159
- "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8",
160
- "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1",
161
- "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4",
162
- "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e",
163
- "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375",
164
- "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88",
165
- "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a",
166
- "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb",
167
- "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4",
168
- "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743",
169
- "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"
134
+ "sha256:0646599e9b139988b63704d704af8e8df7fa4cbc4a1f33df69d97f36cb0a38de",
135
+ "sha256:0cdcbc320b14c3e5877ee79e649677cb7d89ef588852e9583e6b24c2e5072661",
136
+ "sha256:0d0a0f5e06881ecedfe6f3dd2f56dcb057b6dbeb3327fd32d4b12854df36bf26",
137
+ "sha256:1434e088b41594baa71188a17533083eabf5609e8e72f16ce8c186001e6b8c41",
138
+ "sha256:16db7f26000a07efcf6aea00316f6ac57e7d9a96501e990a36f40c965ec7a95d",
139
+ "sha256:1cc0fe9b0b3a8364093c53b0b4c0c2dd4bb23acbec4c9240b5f284095ccf7981",
140
+ "sha256:1fc81d5878cd6274ce971e0a3a18a8803c3fe25457165314271cf78e3aae3aa2",
141
+ "sha256:2ec92012fefebee89a6b9c79bc39051a6cb3891d562b9270ab10ecfdadbc0c34",
142
+ "sha256:39afcd3d4339329c5f58de48a52f6e4e50f6578dd6099961cf22228feb25f38f",
143
+ "sha256:4a7b0ceee8147444347da6a66be737c9d78f3353b0681715b668b72e79203e4a",
144
+ "sha256:4a9ca3f2fae0088c3c71d743d85404cec8df9be818a005ea065495bedc33da35",
145
+ "sha256:4bf0655ab60d754491004a5efd7f9cccefcc1081a74c9ef2da4735d6ee4a6223",
146
+ "sha256:4cc37def103a2725bc672f84bd939a6fe4522310503207aae4d56351644682f1",
147
+ "sha256:4fc84a37bfd98db31beae3c2748811a3fa72bf2007ff7902f68746d9757f3746",
148
+ "sha256:5037f8fcc2a95b1f0e80585bd9d1ec31068a9bcb157d9750a172836e98bc7a90",
149
+ "sha256:54de9ef3a9da981f7af93eafde4ede199e0846cd819eb27c88e2b712aae9708c",
150
+ "sha256:556cf1a7cbc8028cb60e1ff0be806be2eded2daf8129b8811c63e2b9a6c43bca",
151
+ "sha256:57e0204b5b745594e5bc14b9b50006da722827f0b8c776949f1135677e88d0b8",
152
+ "sha256:5a5740d1fb60ddf268a3811bcd353de34eb56dc24e8f52a7f05ee513b2d4f596",
153
+ "sha256:5c3721c2c9e4c4953a41a26c14f4cef64330392a6d2d675c8b1db3b645e31f0e",
154
+ "sha256:5fa567e99765fe98f4e7d7394ce623e794d7cabb170f2ca2ac5a4174437e90dd",
155
+ "sha256:5fd215c0c7d7aab005221608a3c2b46f58c0285a819565887ee0b718c052aa4e",
156
+ "sha256:6175d1a0559986c6ee3f7fccfc4a90ecd12ba0a383dcc2da30c2b9918d67d8a3",
157
+ "sha256:61c4bf1ba021817de12b813338c9be9f0ad5b1e781b9b340a6d29fc13e7c1b5e",
158
+ "sha256:6537e7c10cc47c595828b8a8be04c72144725c383c4702703ff4e42e44577312",
159
+ "sha256:68f962d9b72ce69ea8621f57551b2fa9c70509af757ee3b8105d4f51b92b41a7",
160
+ "sha256:7352b9161b33fd0b643ccd1f21f3a3908daaddf414f1c6cb9d3a2fd618bf2572",
161
+ "sha256:796a79f63eca8814ca3317a1ea443645c9ff0d18b188de470ed7ccd45ae79428",
162
+ "sha256:79afb6197e2f7f60c4824dd4b2d4c2ec5801ceb6ba9ce5d2c3080e5660d51a4f",
163
+ "sha256:7a588d39e0925f6a2bff87154752481273cdb1736270642aeb3635cb9b4cad07",
164
+ "sha256:8748731ad392d736cc9ccac03c9845b13bb07d020a33423fa5b3a36521ac6e4e",
165
+ "sha256:8fe7502616b67b234482c3ce276ff26f39ffe88adca2acf0261df4b8454668b4",
166
+ "sha256:9314d5678dcc665330df5b69c1e726a0e49b27df0461c08ca12674bcc19ef136",
167
+ "sha256:9735317685ba6ec7e3754798c8871c2f49aa5e687cc794a0b1d284b2389d1bd5",
168
+ "sha256:9981706d300c18d8b220995ad22627647be11a4276721c10911e0e9fa44c83e8",
169
+ "sha256:9e78295f4144f9dacfed4f92935fbe1780021247c2fabf73a819b17f0ccfff8d",
170
+ "sha256:b016ea6b959d3b9556cb401c55a37547135a587db0115635a443b2ce8f1c7228",
171
+ "sha256:b6cf3764c030e5338e7f61f95bd21147963cf6aa16e09d2f74f1fa52013c1206",
172
+ "sha256:beccf7b8a10b09c4ae543582c1319c6df47d78fd732f854ac68d518ee1fb97fa",
173
+ "sha256:c0884920835a033b78d1c73b6d3bbcda8161a900f38a488829a83982925f6c2e",
174
+ "sha256:c3e757949f268364b96ca894b4c342b41dc6f8f8b66c37878aacef5930db61be",
175
+ "sha256:ca498687ca46a62ae590253fba634a1fe9836bc56f626852fb2720f334c9e4e5",
176
+ "sha256:d1d0d98d95dd18fe29dc66808e1accf59f037d5716f86a501fc0256455219668",
177
+ "sha256:d21918e9ef11edf36764b93101e2ae8cc82aa5efdc7c5a4e9c6c35a48496d601",
178
+ "sha256:d7fed867ee50edf1a0b4a11e8e5d0895150e572af1cd6d315d557758bfa9c057",
179
+ "sha256:db66fc317a046556a96b453a58eced5024af4582a8dbdc0c23ca4dbc0d5b3146",
180
+ "sha256:dde0070c40ea8bb3641e811c1cfbf18e265d024deff6de52c5950677a8fb1e0f",
181
+ "sha256:df4e745a81c110e7446b1cc8131bf986157770fa405fe90e15e850aaf7619bc8",
182
+ "sha256:e2213def81a50519d7cc56ed643c9e93e0247f5bbe0d1247d15fa520814a7cd7",
183
+ "sha256:ef48e2707fb320c8f139424a596f5b69955a85b178f15af261bab871873bb987",
184
+ "sha256:f152cbf5b88aaeb836127d920dd0f5e7edff5a66f10c079157306c4343d86c19",
185
+ "sha256:fc0b4d8bfeabd25ea75e94632f5b6e047eef8adaed0c2161ada1e922e7f7cece"
170
186
  ],
171
187
  "markers": "python_version >= '3.8'",
172
- "version": "==7.5.0"
188
+ "version": "==7.5.1"
173
189
  },
174
190
  "distlib": {
175
191
  "hashes": [
@@ -300,6 +316,15 @@
300
316
  "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5, 3.6'",
301
317
  "version": "==1.8.0"
302
318
  },
319
+ "nox": {
320
+ "hashes": [
321
+ "sha256:6492236efa15a460ecb98e7b67562a28b70da006ab0be164e8821177577c0565",
322
+ "sha256:ecf6700199cdfa9e5ea0a41ff5e6ef4641d09508eda6edb89d9987864115817f"
323
+ ],
324
+ "index": "pypi",
325
+ "markers": "python_version >= '3.7'",
326
+ "version": "==2024.4.15"
327
+ },
303
328
  "packaging": {
304
329
  "hashes": [
305
330
  "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5",
@@ -618,11 +643,11 @@
618
643
  },
619
644
  "babel": {
620
645
  "hashes": [
621
- "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363",
622
- "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"
646
+ "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb",
647
+ "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"
623
648
  ],
624
- "markers": "python_version >= '3.7'",
625
- "version": "==2.14.0"
649
+ "markers": "python_version >= '3.8'",
650
+ "version": "==2.15.0"
626
651
  },
627
652
  "certifi": {
628
653
  "hashes": [
@@ -762,11 +787,11 @@
762
787
  },
763
788
  "jinja2": {
764
789
  "hashes": [
765
- "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa",
766
- "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"
790
+ "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
791
+ "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
767
792
  ],
768
793
  "markers": "python_version >= '3.7'",
769
- "version": "==3.1.3"
794
+ "version": "==3.1.4"
770
795
  },
771
796
  "markdown-it-py": {
772
797
  "hashes": [
@@ -877,11 +902,11 @@
877
902
  },
878
903
  "pygments": {
879
904
  "hashes": [
880
- "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c",
881
- "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"
905
+ "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
906
+ "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"
882
907
  ],
883
- "markers": "python_version >= '3.7'",
884
- "version": "==2.17.2"
908
+ "markers": "python_version >= '3.8'",
909
+ "version": "==2.18.0"
885
910
  },
886
911
  "pytz": {
887
912
  "hashes": [
@@ -36,7 +36,7 @@ fotolab -h
36
36
 
37
37
  ```console
38
38
  usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
39
- {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
39
+ {animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
40
40
  ...
41
41
 
42
42
  A console program to manipulate photos.
@@ -46,7 +46,7 @@ A console program to manipulate photos.
46
46
  issues: https://github.com/kianmeng/fotolab/issues
47
47
 
48
48
  positional arguments:
49
- {animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
49
+ {animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
50
50
  sub-command help
51
51
  animate animate an image
52
52
  auto auto adjust (resize, contrast, and watermark) a photo
@@ -54,6 +54,7 @@ positional arguments:
54
54
  contrast contrast an image
55
55
  info info an image
56
56
  resize resize an image
57
+ rotate rotate an image
57
58
  montage montage a list of image
58
59
  sharpen sharpen an image
59
60
  watermark watermark an image
@@ -174,6 +175,22 @@ optional arguments:
174
175
  -h, --help show this help message and exit
175
176
  ```
176
177
 
178
+ ### fotolab rotate
179
+
180
+ ```console
181
+ fotolab rotate -h
182
+ ```
183
+
184
+ ```console
185
+ usage: fotolab rotate [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
186
+
187
+ positional arguments:
188
+ IMAGE_FILENAMES set the image filenames
189
+
190
+ optional arguments:
191
+ -h, --help show this help message and exit
192
+ ```
193
+
177
194
  ### fotolab montage
178
195
 
179
196
  ```console
@@ -21,7 +21,7 @@ import subprocess
21
21
  import sys
22
22
  from pathlib import Path
23
23
 
24
- __version__ = "0.15.0"
24
+ __version__ = "0.16.0"
25
25
 
26
26
  log = logging.getLogger(__name__)
27
27
 
@@ -33,6 +33,7 @@ import fotolab.env
33
33
  import fotolab.info
34
34
  import fotolab.montage
35
35
  import fotolab.resize
36
+ import fotolab.rotate
36
37
  import fotolab.sharpen
37
38
  import fotolab.watermark
38
39
  from fotolab import __version__
@@ -140,6 +141,7 @@ def build_parser() -> argparse.ArgumentParser:
140
141
  fotolab.contrast.build_subparser(subparsers)
141
142
  fotolab.info.build_subparser(subparsers)
142
143
  fotolab.resize.build_subparser(subparsers)
144
+ fotolab.rotate.build_subparser(subparsers)
143
145
  fotolab.montage.build_subparser(subparsers)
144
146
  fotolab.sharpen.build_subparser(subparsers)
145
147
  fotolab.watermark.build_subparser(subparsers)
@@ -0,0 +1,61 @@
1
+ # Copyright (C) 2024 Kian-Meng Ang
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify it under
4
+ # the terms of the GNU Affero General Public License as published by the Free
5
+ # Software Foundation, either version 3 of the License, or (at your option) any
6
+ # later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful, but WITHOUT
9
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
+ # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
11
+ # details.
12
+ #
13
+ # You should have received a copy of the GNU Affero General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ """Rotate subcommand."""
17
+
18
+ import argparse
19
+ import logging
20
+
21
+ from PIL import Image
22
+
23
+ from fotolab import save_image
24
+
25
+ log = logging.getLogger(__name__)
26
+
27
+
28
+ def build_subparser(subparsers) -> None:
29
+ """Build the subparser."""
30
+ rotate_parser = subparsers.add_parser("rotate", help="rotate an image")
31
+
32
+ rotate_parser.set_defaults(func=run)
33
+
34
+ rotate_parser.add_argument(
35
+ dest="image_filenames",
36
+ help="set the image filenames",
37
+ nargs="+",
38
+ type=str,
39
+ default=None,
40
+ metavar="IMAGE_FILENAMES",
41
+ )
42
+
43
+
44
+ def run(args: argparse.Namespace) -> None:
45
+ """Run rotate subcommand.
46
+
47
+ Args:
48
+ config (argparse.Namespace): Config from command line arguments
49
+
50
+ Returns:
51
+ None
52
+ """
53
+ log.debug(args)
54
+
55
+ for image_filename in args.image_filenames:
56
+ original_image = Image.open(image_filename)
57
+ rotated_image = original_image.rotate(
58
+ 180,
59
+ expand=True,
60
+ )
61
+ save_image(args, rotated_image, image_filename, "rotate")
@@ -0,0 +1,24 @@
1
+ # Copyright (c) 2022,2023,2024 Kian-Meng Ang
2
+
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU Generals Public License for more details.
12
+
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
15
+
16
+ """Nox configuration."""
17
+ import nox
18
+
19
+
20
+ @nox.session()
21
+ def lint(session: nox.Session) -> None:
22
+ """Runs pre-commit linter."""
23
+ session.install("pre-commit")
24
+ session.run("pre-commit", "run", "--all-files", *session.posargs)
@@ -1,5 +0,0 @@
1
- 3.8.18
2
- 3.9.18
3
- 3.10.13
4
- 3.11.8
5
- 3.12.2
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
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
File without changes
File without changes
File without changes
File without changes
File without changes