fotolab 0.14.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.
- {fotolab-0.14.0 → fotolab-0.16.0}/.pre-commit-config.yaml +1 -1
- fotolab-0.16.0/.python-version +5 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/CHANGELOG.md +25 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/PKG-INFO +23 -8
- {fotolab-0.14.0 → fotolab-0.16.0}/Pipfile +1 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/Pipfile.lock +109 -84
- {fotolab-0.14.0 → fotolab-0.16.0}/README.md +22 -7
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/__init__.py +3 -3
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/cli.py +14 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/resize.py +39 -5
- fotolab-0.16.0/fotolab/rotate.py +61 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/sharpen.py +3 -3
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/watermark.py +46 -7
- fotolab-0.16.0/noxfile.py +24 -0
- fotolab-0.14.0/.python-version +0 -5
- {fotolab-0.14.0 → fotolab-0.16.0}/.coveragerc +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/.gitignore +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/CONTRIBUTING.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/LICENSE.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/Makefile +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/make.bat +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/CHANGELOG.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/CONTRIBUTING.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/LICENSE.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/README.md +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/_static/logo.jpg +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/conf.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/docs/source/index.rst +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/__main__.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/animate.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/auto.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/border.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/contrast.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/env.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/info.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/fotolab/montage.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/pyproject.toml +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tests/__init__.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tests/conftest.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tests/test_env.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tests/test_help_flag.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tests/test_quiet_flag.py +0 -0
- {fotolab-0.14.0 → fotolab-0.16.0}/tox.ini +0 -0
@@ -7,6 +7,31 @@ 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
|
+
|
21
|
+
## v0.15.0 (2024-05-05)
|
22
|
+
|
23
|
+
### Added
|
24
|
+
|
25
|
+
- Add `-v` or `--verbose` flag to toggle the debug logs of PIL
|
26
|
+
|
27
|
+
### Changed
|
28
|
+
|
29
|
+
- Bump deps and `pre-commit` hooks
|
30
|
+
- Resize image to the right aspect ratio based on image's dimension
|
31
|
+
- Resize watermark font based on the image's dimension
|
32
|
+
- Remove empty lines in help message
|
33
|
+
- Show absolute image path in logs
|
34
|
+
|
10
35
|
## v0.14.0 (2024-04-28)
|
11
36
|
|
12
37
|
### Added
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fotolab
|
3
|
-
Version: 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>
|
@@ -57,9 +57,8 @@ fotolab -h
|
|
57
57
|
```
|
58
58
|
|
59
59
|
```console
|
60
|
-
|
61
|
-
|
62
|
-
{animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
60
|
+
usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
|
61
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
63
62
|
...
|
64
63
|
|
65
64
|
A console program to manipulate photos.
|
@@ -69,7 +68,7 @@ A console program to manipulate photos.
|
|
69
68
|
issues: https://github.com/kianmeng/fotolab/issues
|
70
69
|
|
71
70
|
positional arguments:
|
72
|
-
{animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
71
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
73
72
|
sub-command help
|
74
73
|
animate animate an image
|
75
74
|
auto auto adjust (resize, contrast, and watermark) a photo
|
@@ -77,6 +76,7 @@ positional arguments:
|
|
77
76
|
contrast contrast an image
|
78
77
|
info info an image
|
79
78
|
resize resize an image
|
79
|
+
rotate rotate an image
|
80
80
|
montage montage a list of image
|
81
81
|
sharpen sharpen an image
|
82
82
|
watermark watermark an image
|
@@ -89,6 +89,7 @@ optional arguments:
|
|
89
89
|
-od OUTPUT_DIR, --output-dir OUTPUT_DIR
|
90
90
|
set default output folder (default: 'output')
|
91
91
|
-q, --quiet suppress all logging
|
92
|
+
-v, --verbose show verbosity of debugging log, use -vv, -vvv for more details
|
92
93
|
-d, --debug show debugging log and stacktrace
|
93
94
|
-V, --version show program's version number and exit
|
94
95
|
```
|
@@ -100,7 +101,6 @@ fotolab animate -h
|
|
100
101
|
```
|
101
102
|
|
102
103
|
```console
|
103
|
-
|
104
104
|
usage: fotolab animate [-h] [-f FORMAT] [-d DURATION] [-l LOOP]
|
105
105
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
106
106
|
|
@@ -197,6 +197,22 @@ optional arguments:
|
|
197
197
|
-h, --help show this help message and exit
|
198
198
|
```
|
199
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
|
+
|
200
216
|
### fotolab montage
|
201
217
|
|
202
218
|
```console
|
@@ -204,7 +220,6 @@ fotolab montage -h
|
|
204
220
|
```
|
205
221
|
|
206
222
|
```console
|
207
|
-
|
208
223
|
usage: fotolab montage [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
209
224
|
|
210
225
|
positional arguments:
|
@@ -221,7 +236,7 @@ fotolab resize -h
|
|
221
236
|
```
|
222
237
|
|
223
238
|
```console
|
224
|
-
usage: fotolab resize [-h] [-wh WIDTH
|
239
|
+
usage: fotolab resize [-h] [-wh WIDTH | -ht HEIGHT]
|
225
240
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
226
241
|
|
227
242
|
positional arguments:
|
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"_meta": {
|
3
3
|
"hash": {
|
4
|
-
"sha256": "
|
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:
|
119
|
-
"sha256:
|
120
|
-
"sha256:
|
121
|
-
"sha256:
|
122
|
-
"sha256:
|
123
|
-
"sha256:
|
124
|
-
"sha256:
|
125
|
-
"sha256:
|
126
|
-
"sha256:
|
127
|
-
"sha256:
|
128
|
-
"sha256:
|
129
|
-
"sha256:
|
130
|
-
"sha256:
|
131
|
-
"sha256:
|
132
|
-
"sha256:
|
133
|
-
"sha256:
|
134
|
-
"sha256:
|
135
|
-
"sha256:
|
136
|
-
"sha256:
|
137
|
-
"sha256:
|
138
|
-
"sha256:
|
139
|
-
"sha256:
|
140
|
-
"sha256:
|
141
|
-
"sha256:
|
142
|
-
"sha256:
|
143
|
-
"sha256:
|
144
|
-
"sha256:
|
145
|
-
"sha256:
|
146
|
-
"sha256:
|
147
|
-
"sha256:
|
148
|
-
"sha256:
|
149
|
-
"sha256:
|
150
|
-
"sha256:
|
151
|
-
"sha256:
|
152
|
-
"sha256:
|
153
|
-
"sha256:
|
154
|
-
"sha256:
|
155
|
-
"sha256:
|
156
|
-
"sha256:
|
157
|
-
"sha256:
|
158
|
-
"sha256:
|
159
|
-
"sha256:
|
160
|
-
"sha256:
|
161
|
-
"sha256:
|
162
|
-
"sha256:
|
163
|
-
"sha256:
|
164
|
-
"sha256:
|
165
|
-
"sha256:
|
166
|
-
"sha256:
|
167
|
-
"sha256:
|
168
|
-
"sha256:
|
169
|
-
"sha256:
|
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.
|
188
|
+
"version": "==7.5.1"
|
173
189
|
},
|
174
190
|
"distlib": {
|
175
191
|
"hashes": [
|
@@ -197,11 +213,11 @@
|
|
197
213
|
},
|
198
214
|
"filelock": {
|
199
215
|
"hashes": [
|
200
|
-
"sha256:
|
201
|
-
"sha256:
|
216
|
+
"sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f",
|
217
|
+
"sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"
|
202
218
|
],
|
203
219
|
"markers": "python_version >= '3.8'",
|
204
|
-
"version": "==3.
|
220
|
+
"version": "==3.14.0"
|
205
221
|
},
|
206
222
|
"flake8": {
|
207
223
|
"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",
|
@@ -386,11 +411,11 @@
|
|
386
411
|
},
|
387
412
|
"platformdirs": {
|
388
413
|
"hashes": [
|
389
|
-
"sha256:
|
390
|
-
"sha256:
|
414
|
+
"sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf",
|
415
|
+
"sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"
|
391
416
|
],
|
392
417
|
"markers": "python_version >= '3.8'",
|
393
|
-
"version": "==4.2.
|
418
|
+
"version": "==4.2.1"
|
394
419
|
},
|
395
420
|
"pluggy": {
|
396
421
|
"hashes": [
|
@@ -443,12 +468,12 @@
|
|
443
468
|
},
|
444
469
|
"pytest": {
|
445
470
|
"hashes": [
|
446
|
-
"sha256:
|
447
|
-
"sha256:
|
471
|
+
"sha256:1733f0620f6cda4095bbf0d9ff8022486e91892245bb9e7d5542c018f612f233",
|
472
|
+
"sha256:d507d4482197eac0ba2bae2e9babf0672eb333017bcedaa5fb1a3d42c1174b3f"
|
448
473
|
],
|
449
474
|
"index": "pypi",
|
450
475
|
"markers": "python_version >= '3.8'",
|
451
|
-
"version": "==8.
|
476
|
+
"version": "==8.2.0"
|
452
477
|
},
|
453
478
|
"pytest-cov": {
|
454
479
|
"hashes": [
|
@@ -470,12 +495,12 @@
|
|
470
495
|
},
|
471
496
|
"pytest-xdist": {
|
472
497
|
"hashes": [
|
473
|
-
"sha256:
|
474
|
-
"sha256:
|
498
|
+
"sha256:9ed4adfb68a016610848639bb7e02c9352d5d9f03d04809919e2dafc3be4cca7",
|
499
|
+
"sha256:ead156a4db231eec769737f57668ef58a2084a34b2e55c4a8fa20d861107300d"
|
475
500
|
],
|
476
501
|
"index": "pypi",
|
477
|
-
"markers": "python_version >= '3.
|
478
|
-
"version": "==3.
|
502
|
+
"markers": "python_version >= '3.8'",
|
503
|
+
"version": "==3.6.1"
|
479
504
|
},
|
480
505
|
"pyyaml": {
|
481
506
|
"hashes": [
|
@@ -592,11 +617,11 @@
|
|
592
617
|
},
|
593
618
|
"virtualenv": {
|
594
619
|
"hashes": [
|
595
|
-
"sha256:
|
596
|
-
"sha256:
|
620
|
+
"sha256:604bfdceaeece392802e6ae48e69cec49168b9c5f4a44e483963f9242eb0e78b",
|
621
|
+
"sha256:7aa9982a728ae5892558bff6a2839c00b9ed145523ece2274fad6f414690ae75"
|
597
622
|
],
|
598
623
|
"markers": "python_version >= '3.7'",
|
599
|
-
"version": "==20.
|
624
|
+
"version": "==20.26.1"
|
600
625
|
},
|
601
626
|
"zipp": {
|
602
627
|
"hashes": [
|
@@ -618,11 +643,11 @@
|
|
618
643
|
},
|
619
644
|
"babel": {
|
620
645
|
"hashes": [
|
621
|
-
"sha256:
|
622
|
-
"sha256:
|
646
|
+
"sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb",
|
647
|
+
"sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"
|
623
648
|
],
|
624
|
-
"markers": "python_version >= '3.
|
625
|
-
"version": "==2.
|
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:
|
766
|
-
"sha256:
|
790
|
+
"sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369",
|
791
|
+
"sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"
|
767
792
|
],
|
768
793
|
"markers": "python_version >= '3.7'",
|
769
|
-
"version": "==3.1.
|
794
|
+
"version": "==3.1.4"
|
770
795
|
},
|
771
796
|
"markdown-it-py": {
|
772
797
|
"hashes": [
|
@@ -860,12 +885,12 @@
|
|
860
885
|
},
|
861
886
|
"myst-parser": {
|
862
887
|
"hashes": [
|
863
|
-
"sha256:
|
864
|
-
"sha256:
|
888
|
+
"sha256:6457aaa33a5d474aca678b8ead9b3dc298e89c68e67012e73146ea6fd54babf1",
|
889
|
+
"sha256:88f0cb406cb363b077d176b51c476f62d60604d68a8dcdf4832e080441301a87"
|
865
890
|
],
|
866
891
|
"index": "pypi",
|
867
892
|
"markers": "python_version >= '3.8'",
|
868
|
-
"version": "==3.0.
|
893
|
+
"version": "==3.0.1"
|
869
894
|
},
|
870
895
|
"packaging": {
|
871
896
|
"hashes": [
|
@@ -877,11 +902,11 @@
|
|
877
902
|
},
|
878
903
|
"pygments": {
|
879
904
|
"hashes": [
|
880
|
-
"sha256:
|
881
|
-
"sha256:
|
905
|
+
"sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199",
|
906
|
+
"sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"
|
882
907
|
],
|
883
|
-
"markers": "python_version >= '3.
|
884
|
-
"version": "==2.
|
908
|
+
"markers": "python_version >= '3.8'",
|
909
|
+
"version": "==2.18.0"
|
885
910
|
},
|
886
911
|
"pytz": {
|
887
912
|
"hashes": [
|
@@ -35,9 +35,8 @@ fotolab -h
|
|
35
35
|
```
|
36
36
|
|
37
37
|
```console
|
38
|
-
|
39
|
-
|
40
|
-
{animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
38
|
+
usage: fotolab [-h] [-o] [-op] [-od OUTPUT_DIR] [-q] [-v] [-d] [-V]
|
39
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
41
40
|
...
|
42
41
|
|
43
42
|
A console program to manipulate photos.
|
@@ -47,7 +46,7 @@ A console program to manipulate photos.
|
|
47
46
|
issues: https://github.com/kianmeng/fotolab/issues
|
48
47
|
|
49
48
|
positional arguments:
|
50
|
-
{animate,auto,border,contrast,info,resize,montage,sharpen,watermark,env}
|
49
|
+
{animate,auto,border,contrast,info,resize,rotate,montage,sharpen,watermark,env}
|
51
50
|
sub-command help
|
52
51
|
animate animate an image
|
53
52
|
auto auto adjust (resize, contrast, and watermark) a photo
|
@@ -55,6 +54,7 @@ positional arguments:
|
|
55
54
|
contrast contrast an image
|
56
55
|
info info an image
|
57
56
|
resize resize an image
|
57
|
+
rotate rotate an image
|
58
58
|
montage montage a list of image
|
59
59
|
sharpen sharpen an image
|
60
60
|
watermark watermark an image
|
@@ -67,6 +67,7 @@ optional arguments:
|
|
67
67
|
-od OUTPUT_DIR, --output-dir OUTPUT_DIR
|
68
68
|
set default output folder (default: 'output')
|
69
69
|
-q, --quiet suppress all logging
|
70
|
+
-v, --verbose show verbosity of debugging log, use -vv, -vvv for more details
|
70
71
|
-d, --debug show debugging log and stacktrace
|
71
72
|
-V, --version show program's version number and exit
|
72
73
|
```
|
@@ -78,7 +79,6 @@ fotolab animate -h
|
|
78
79
|
```
|
79
80
|
|
80
81
|
```console
|
81
|
-
|
82
82
|
usage: fotolab animate [-h] [-f FORMAT] [-d DURATION] [-l LOOP]
|
83
83
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
84
84
|
|
@@ -175,6 +175,22 @@ optional arguments:
|
|
175
175
|
-h, --help show this help message and exit
|
176
176
|
```
|
177
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
|
+
|
178
194
|
### fotolab montage
|
179
195
|
|
180
196
|
```console
|
@@ -182,7 +198,6 @@ fotolab montage -h
|
|
182
198
|
```
|
183
199
|
|
184
200
|
```console
|
185
|
-
|
186
201
|
usage: fotolab montage [-h] IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
187
202
|
|
188
203
|
positional arguments:
|
@@ -199,7 +214,7 @@ fotolab resize -h
|
|
199
214
|
```
|
200
215
|
|
201
216
|
```console
|
202
|
-
usage: fotolab resize [-h] [-wh WIDTH
|
217
|
+
usage: fotolab resize [-h] [-wh WIDTH | -ht HEIGHT]
|
203
218
|
IMAGE_FILENAMES [IMAGE_FILENAMES ...]
|
204
219
|
|
205
220
|
positional arguments:
|
@@ -21,7 +21,7 @@ import subprocess
|
|
21
21
|
import sys
|
22
22
|
from pathlib import Path
|
23
23
|
|
24
|
-
__version__ = "0.
|
24
|
+
__version__ = "0.16.0"
|
25
25
|
|
26
26
|
log = logging.getLogger(__name__)
|
27
27
|
|
@@ -48,7 +48,7 @@ def save_image(args, new_image, output_filename, subcommand):
|
|
48
48
|
)
|
49
49
|
new_filename.parent.mkdir(parents=True, exist_ok=True)
|
50
50
|
|
51
|
-
log.info("%s image: %s", subcommand, new_filename)
|
51
|
+
log.info("%s image: %s", subcommand, new_filename.resolve())
|
52
52
|
new_image.save(new_filename)
|
53
53
|
|
54
54
|
if args.open:
|
@@ -64,4 +64,4 @@ def _open_image(filename):
|
|
64
64
|
elif sys.platform == "windows":
|
65
65
|
os.startfile(filename)
|
66
66
|
|
67
|
-
log.info("open image: %s
|
67
|
+
log.info("open image: %s", filename.resolve())
|
@@ -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__
|
@@ -42,6 +43,9 @@ log = logging.getLogger(__name__)
|
|
42
43
|
|
43
44
|
def setup_logging(args: argparse.Namespace) -> None:
|
44
45
|
"""Set up logging by level."""
|
46
|
+
if args.verbose == 0:
|
47
|
+
logging.getLogger("PIL").setLevel(logging.ERROR)
|
48
|
+
|
45
49
|
if args.quiet:
|
46
50
|
logging.disable(logging.NOTSET)
|
47
51
|
else:
|
@@ -105,6 +109,15 @@ def build_parser() -> argparse.ArgumentParser:
|
|
105
109
|
help="suppress all logging",
|
106
110
|
)
|
107
111
|
|
112
|
+
parser.add_argument(
|
113
|
+
"-v",
|
114
|
+
"--verbose",
|
115
|
+
default=0,
|
116
|
+
action="count",
|
117
|
+
dest="verbose",
|
118
|
+
help="show verbosity of debugging log, use -vv, -vvv for more details",
|
119
|
+
)
|
120
|
+
|
108
121
|
parser.add_argument(
|
109
122
|
"-d",
|
110
123
|
"--debug",
|
@@ -128,6 +141,7 @@ def build_parser() -> argparse.ArgumentParser:
|
|
128
141
|
fotolab.contrast.build_subparser(subparsers)
|
129
142
|
fotolab.info.build_subparser(subparsers)
|
130
143
|
fotolab.resize.build_subparser(subparsers)
|
144
|
+
fotolab.rotate.build_subparser(subparsers)
|
131
145
|
fotolab.montage.build_subparser(subparsers)
|
132
146
|
fotolab.sharpen.build_subparser(subparsers)
|
133
147
|
fotolab.watermark.build_subparser(subparsers)
|
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
|
+
import math
|
20
21
|
|
21
22
|
from PIL import Image
|
22
23
|
|
@@ -24,6 +25,9 @@ from fotolab import save_image
|
|
24
25
|
|
25
26
|
log = logging.getLogger(__name__)
|
26
27
|
|
28
|
+
DEFAULT_WIDTH = 600
|
29
|
+
DEFAULT_HEIGHT = 277
|
30
|
+
|
27
31
|
|
28
32
|
def build_subparser(subparsers) -> None:
|
29
33
|
"""Build the subparser."""
|
@@ -40,23 +44,25 @@ def build_subparser(subparsers) -> None:
|
|
40
44
|
metavar="IMAGE_FILENAMES",
|
41
45
|
)
|
42
46
|
|
43
|
-
resize_parser.
|
47
|
+
group = resize_parser.add_mutually_exclusive_group(required=False)
|
48
|
+
|
49
|
+
group.add_argument(
|
44
50
|
"-wh",
|
45
51
|
"--width",
|
46
52
|
dest="width",
|
47
53
|
help="set the width of the image (default: '%(default)s')",
|
48
54
|
type=int,
|
49
|
-
default=
|
55
|
+
default=DEFAULT_WIDTH,
|
50
56
|
metavar="WIDTH",
|
51
57
|
)
|
52
58
|
|
53
|
-
|
59
|
+
group.add_argument(
|
54
60
|
"-ht",
|
55
61
|
"--height",
|
56
62
|
dest="height",
|
57
63
|
help="set the height of the image (default: '%(default)s')",
|
58
64
|
type=int,
|
59
|
-
default=
|
65
|
+
default=DEFAULT_HEIGHT,
|
60
66
|
metavar="HEIGHT",
|
61
67
|
)
|
62
68
|
|
@@ -74,9 +80,37 @@ def run(args: argparse.Namespace) -> None:
|
|
74
80
|
|
75
81
|
for image_filename in args.image_filenames:
|
76
82
|
original_image = Image.open(image_filename)
|
83
|
+
|
84
|
+
new_width, new_height = _calc_new_image_dimension(original_image, args)
|
77
85
|
resized_image = original_image.copy()
|
78
86
|
resized_image = resized_image.resize(
|
79
|
-
(
|
87
|
+
(new_width, new_height), Image.Resampling.LANCZOS
|
80
88
|
)
|
81
89
|
|
82
90
|
save_image(args, resized_image, image_filename, "resize")
|
91
|
+
|
92
|
+
|
93
|
+
def _calc_new_image_dimension(image, args) -> tuple:
|
94
|
+
new_width = args.width
|
95
|
+
new_height = args.height
|
96
|
+
|
97
|
+
old_width, old_height = image.size
|
98
|
+
log.debug("old image dimension: %d x %d", old_width, old_height)
|
99
|
+
|
100
|
+
if args.width != DEFAULT_WIDTH:
|
101
|
+
aspect_ratio = old_height / old_width
|
102
|
+
log.debug("aspect ratio: %f", aspect_ratio)
|
103
|
+
|
104
|
+
new_height = math.ceil(args.width * aspect_ratio)
|
105
|
+
log.debug("new height: %d", new_height)
|
106
|
+
|
107
|
+
if args.height != DEFAULT_HEIGHT:
|
108
|
+
aspect_ratio = old_width / old_height
|
109
|
+
log.debug("aspect ratio: %f", aspect_ratio)
|
110
|
+
|
111
|
+
new_width = math.floor(args.height * aspect_ratio)
|
112
|
+
log.debug("new width: %d", new_width)
|
113
|
+
|
114
|
+
log.debug("new image dimension: %d x %d", new_width, new_height)
|
115
|
+
|
116
|
+
return (new_width, new_height)
|
@@ -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")
|
@@ -44,7 +44,7 @@ def build_subparser(subparsers) -> None:
|
|
44
44
|
"-r",
|
45
45
|
"--radius",
|
46
46
|
dest="radius",
|
47
|
-
type=
|
47
|
+
type=int,
|
48
48
|
default=1,
|
49
49
|
help="set the radius or size of edges (default: '%(default)s')",
|
50
50
|
metavar="RADIUS",
|
@@ -54,7 +54,7 @@ def build_subparser(subparsers) -> None:
|
|
54
54
|
"-p",
|
55
55
|
"--percent",
|
56
56
|
dest="percent",
|
57
|
-
type=
|
57
|
+
type=int,
|
58
58
|
default=100,
|
59
59
|
help=(
|
60
60
|
"set the amount of overall strength of sharpening effect "
|
@@ -67,7 +67,7 @@ def build_subparser(subparsers) -> None:
|
|
67
67
|
"-t",
|
68
68
|
"--threshold",
|
69
69
|
dest="threshold",
|
70
|
-
type=
|
70
|
+
type=int,
|
71
71
|
default=3,
|
72
72
|
help=(
|
73
73
|
"set the minimum brightness changed to be sharpened "
|
@@ -17,6 +17,7 @@
|
|
17
17
|
|
18
18
|
import argparse
|
19
19
|
import logging
|
20
|
+
import math
|
20
21
|
|
21
22
|
from PIL import Image, ImageColor, ImageDraw, ImageFont
|
22
23
|
|
@@ -24,6 +25,9 @@ from fotolab import save_image
|
|
24
25
|
|
25
26
|
log = logging.getLogger(__name__)
|
26
27
|
|
28
|
+
FONT_SIZE_ASPECT_RATIO = 12 / 600
|
29
|
+
FONT_PADDING_ASPECT_RATIO = 15 / 600
|
30
|
+
FONT_OUTLINE_WIDTH_ASPECT_RATIO = 2 / 600
|
27
31
|
POSITIONS = ["top-left", "top-right", "bottom-left", "bottom-right"]
|
28
32
|
|
29
33
|
|
@@ -140,19 +144,21 @@ def run(args: argparse.Namespace) -> None:
|
|
140
144
|
|
141
145
|
draw = ImageDraw.Draw(watermarked_image)
|
142
146
|
|
143
|
-
font = ImageFont.truetype(
|
147
|
+
font = ImageFont.truetype(
|
148
|
+
"arial.ttf", calc_font_size(original_image, args)
|
149
|
+
)
|
144
150
|
|
145
151
|
(left, top, right, bottom) = draw.textbbox(
|
146
152
|
xy=(0, 0), text=args.text, font=font
|
147
153
|
)
|
148
154
|
text_width = right - left
|
149
155
|
text_height = bottom - top
|
150
|
-
(position_x, position_y) =
|
156
|
+
(position_x, position_y) = calc_position(
|
151
157
|
watermarked_image,
|
152
158
|
text_width,
|
153
159
|
text_height,
|
154
160
|
args.position,
|
155
|
-
args
|
161
|
+
calc_padding(original_image, args),
|
156
162
|
)
|
157
163
|
|
158
164
|
draw.text(
|
@@ -160,16 +166,49 @@ def run(args: argparse.Namespace) -> None:
|
|
160
166
|
args.text,
|
161
167
|
font=font,
|
162
168
|
fill=(*ImageColor.getrgb(args.font_color), 128),
|
163
|
-
stroke_width=args
|
169
|
+
stroke_width=calc_font_outline_width(original_image, args),
|
164
170
|
stroke_fill=(*ImageColor.getrgb(args.outline_color), 128),
|
165
171
|
)
|
166
172
|
|
167
173
|
save_image(args, watermarked_image, image_filename, "watermark")
|
168
174
|
|
169
175
|
|
170
|
-
def
|
171
|
-
|
172
|
-
|
176
|
+
def calc_font_size(image, args) -> int:
|
177
|
+
"""Calculate the font size based on the width of the image."""
|
178
|
+
width, _height = image.size
|
179
|
+
new_font_size = args.font_size
|
180
|
+
if width > 600:
|
181
|
+
new_font_size = math.floor(FONT_SIZE_ASPECT_RATIO * width)
|
182
|
+
|
183
|
+
log.debug("new font size: %d", new_font_size)
|
184
|
+
return new_font_size
|
185
|
+
|
186
|
+
|
187
|
+
def calc_font_outline_width(image, args) -> int:
|
188
|
+
"""Calculate the font padding based on the width of the image."""
|
189
|
+
width, _height = image.size
|
190
|
+
new_font_outline_width = args.outline_width
|
191
|
+
if width > 600:
|
192
|
+
new_font_outline_width = math.floor(
|
193
|
+
FONT_OUTLINE_WIDTH_ASPECT_RATIO * width
|
194
|
+
)
|
195
|
+
|
196
|
+
log.debug("new font outline width: %d", new_font_outline_width)
|
197
|
+
return new_font_outline_width
|
198
|
+
|
199
|
+
|
200
|
+
def calc_padding(image, args) -> int:
|
201
|
+
"""Calculate the font padding based on the width of the image."""
|
202
|
+
width, _height = image.size
|
203
|
+
new_padding = args.padding
|
204
|
+
if width > 600:
|
205
|
+
new_padding = math.floor(FONT_PADDING_ASPECT_RATIO * width)
|
206
|
+
|
207
|
+
log.debug("new padding: %d", new_padding)
|
208
|
+
return new_padding
|
209
|
+
|
210
|
+
|
211
|
+
def calc_position(image, text_width, text_height, position, padding) -> tuple:
|
173
212
|
"""Calculate the boundary coordinates of the watermark text."""
|
174
213
|
if position == "top-left":
|
175
214
|
position_x = 0 + padding
|
@@ -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)
|
fotolab-0.14.0/.python-version
DELETED
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
|
File without changes
|
File without changes
|
File without changes
|