Skip to content

Commit 11b0f95

Browse files
committed
Merge branch 'poetry' into decompat
2 parents 3b9b407 + 5760eec commit 11b0f95

34 files changed

+811
-866
lines changed

.editorconfig

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
indent_style = space
7+
indent_size = 2
8+
end_of_line = lf
9+
charset = utf-8
10+
trim_trailing_whitespace = true
11+
insert_final_newline = true
12+
13+
[*.py]
14+
indent_size = 4
15+
max_line_length = 88
16+
17+
[*.{rst,md}]
18+
indent_size = 4

.git-blame-ignore-revs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Ruff format the entire project
2+
5d60da17455607e9c8b7e7fef9940d20027894f2

.github/workflows/linting.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: Code Quality Checks
2+
3+
on:
4+
push:
5+
6+
jobs:
7+
linting:
8+
name: Code Quality Checks
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout Code
12+
uses: actions/checkout@v4
13+
14+
- name: Install Dependencies
15+
run: pip install ruff
16+
17+
- name: Code Linting
18+
if: always()
19+
run: ruff check qrcode
20+
21+
- name: Code Formatting
22+
if: always()
23+
run: ruff format --check qrcode

.github/workflows/push.yml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
name: Testsuite Run
2+
3+
on: [push]
4+
5+
jobs:
6+
build:
7+
runs-on: ubuntu-latest
8+
strategy:
9+
max-parallel: 4
10+
matrix:
11+
python-version: ["3.9", "3.10", "3.11", "3.12"]
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Set up Python ${{ matrix.python-version }}
17+
uses: actions/setup-python@v5
18+
with:
19+
python-version: ${{ matrix.python-version }}
20+
21+
- name: Install dependencies
22+
run: |
23+
pip install --disable-pip-version-check tox tox-gh-actions
24+
- name: Test with tox
25+
run: tox

.gitignore

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
*.pyc
2-
.tox
3-
dist/
42
.coverage
53
.coverage.*
6-
htmlcov/
7-
build/
8-
qrcode.egg-info/
9-
.pytest_cache/
104
.idea/
5+
.pytest_cache/
6+
.tox
7+
build/
118
cov.xml
9+
dist/
10+
htmlcov/
11+
poetry.lock
12+
qrcode.egg-info/

CHANGES.rst

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,28 @@ Change log
55
7.5 (unreleased)
66
================
77

8-
- Nothing changed yet.
8+
- Added support for Python 3.11 and 3.12.
9+
10+
- Drop support for Python <=3.8.
11+
12+
- Change local development setup to use Poetry_.
13+
14+
- Testsuite and code quality checks are done through Github Actions.
15+
16+
- Code quality and formatting utilises ruff_.
17+
18+
- Removed ``typing_extensions`` as a dependency, as it's no longer required with
19+
having Python 3.9+ as a requirement.
20+
21+
.. _Poetry: https://python-poetry.org
22+
.. _ruff: https://astral.sh/ruff
923

1024

1125
7.4.2 (6 February 2023)
1226
=======================
1327

1428
- Allow ``pypng`` factory to allow for saving to a string (like
15-
``qr.save("some_file.png")``) in addition to file-like objects.
29+
``qr.save("some_file.png")``) in addition to file-like objects.
1630

1731

1832
7.4.1 (3 February 2023)

MANIFEST.in

Lines changed: 0 additions & 7 deletions
This file was deleted.

PACKAGING.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ Packaging quick reminder
33

44
Make sure maintainer dependencies are installed::
55

6-
pip install -e .[maintainer,dev]
6+
poetry install
77

88
Run release command and follow prompt instructions::
99

10-
fullrelease
10+
poetry run fullrelease

TESTING.rst

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Testing
22
=======
33

4-
First, install tox into your virtualenv::
4+
First, install dev dependencies::
55

6-
pip install --upgrade tox
6+
poetry install --with dev
77

88
To run all tests, you'll need to install multiple Python interpreters. On a
99
modern Ubuntu distribution you can use ``add-apt-repository
@@ -15,5 +15,17 @@ the libraries to build PIL, too. Here's the Ubuntu commands::
1515
sudo apt-get install build-essential python-dev python3-dev
1616
sudo apt-get install libjpeg8-dev zlib1g-dev
1717

18+
Here's the OSX Homebrew command:
19+
20+
brew install libjpeg libtiff little-cms2 openjpeg webp
21+
1822
Finally, just run ``tox``!
19-
If you want, you can test against a specific version like this: ``tox -e py36``
23+
If you want, you can test against a specific version like this: ``tox -e py312-pil``
24+
25+
26+
Linting
27+
-------
28+
29+
Run `ruff` to check formatting::
30+
31+
ruff format qrcode

pyproject.toml

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,69 @@
11
[build-system]
2-
requires = ["setuptools >= 48"]
3-
build-backend = "setuptools.build_meta"
2+
requires = ["poetry-core"]
3+
build-backend = "poetry.core.masonry.api"
4+
5+
[tool.poetry]
6+
name = "qrcode"
7+
version = "8.0.dev0"
8+
packages = [{include = "qrcode"}]
9+
description = "QR Code image generator"
10+
authors = ["Lincoln Loop <[email protected]>"]
11+
license = "BSD"
12+
readme = ["README.rst", "CHANGES.rst"]
13+
homepage = "https://github.com/lincolnloop/python-qrcode"
14+
keywords = ["qr", "denso-wave", "IEC18004"]
15+
classifiers = [
16+
"Development Status :: 5 - Production/Stable",
17+
"License :: OSI Approved :: BSD License",
18+
"Operating System :: OS Independent",
19+
"Intended Audience :: Developers",
20+
"Programming Language :: Python",
21+
"Programming Language :: Python :: 3",
22+
"Programming Language :: Python :: 3.9",
23+
"Programming Language :: Python :: 3.10",
24+
"Programming Language :: Python :: 3.11",
25+
"Programming Language :: Python :: 3.12",
26+
"Programming Language :: Python :: 3 :: Only",
27+
"Topic :: Multimedia :: Graphics",
28+
"Topic :: Software Development :: Libraries :: Python Modules",
29+
]
30+
31+
# There is no support for data files yet.
32+
# https://github.com/python-poetry/poetry/issues/9519
33+
#
34+
# data_files = [
35+
# { destination = "share/man/man1", from = [ "doc/qr.1" ] },
36+
# ]
37+
38+
[tool.poetry.scripts]
39+
qr = 'qrcode.console_scripts:main'
40+
41+
42+
[tool.poetry.dependencies]
43+
python = "^3.9"
44+
colorama = {version = "*", platform = "win32"}
45+
pypng = {version = "*", optional = true}
46+
pillow = {version = ">=9.1.0", optional = true}
47+
48+
[tool.poetry.extras]
49+
pil = ["pillow"]
50+
png = ["pypng"]
51+
52+
[tool.poetry.group.dev.dependencies]
53+
pytest = {version = "*"}
54+
pytest-cov = {version = "*"}
55+
tox = {version = "*"}
56+
ruff = {version = "*"}
57+
docutils = "^0.21.2"
58+
zest-releaser = {extras = ["recommended"], version = "^9.2.0"}
59+
60+
[tool.zest-releaser]
61+
less-zeros = "yes"
62+
version-levels = 2
63+
tag-format = "v{version}"
64+
tag-message = "Version {version}"
65+
tag-signing = "yes"
66+
date-format =" %%-d %%B %%Y"
67+
prereleaser.middle = [
68+
"qrcode.release.update_manpage"
69+
]

qrcode/compat/png.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Try to import png library.
2+
PngWriter = None
3+
4+
try:
5+
from png import Writer as PngWriter # type: ignore # noqa: F401
6+
except ImportError: # pragma: no cover
7+
pass

qrcode/console_scripts.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@
55
When stdout is a tty the QR Code is printed to the terminal and when stdout is
66
a pipe to a file an image is written. The default image format is PNG.
77
"""
8+
89
import optparse
910
import os
1011
import sys
1112
from typing import Dict, Iterable, NoReturn, Optional, Set, Type
13+
from importlib import metadata
1214

1315
import qrcode
1416
from qrcode.image.base import BaseImage, DrawerAliases
@@ -40,9 +42,8 @@
4042
def main(args=None):
4143
if args is None:
4244
args = sys.argv[1:]
43-
from pkg_resources import get_distribution
4445

45-
version = get_distribution("qrcode").version
46+
version = metadata.version("qrcode")
4647
parser = optparse.OptionParser(usage=(__doc__ or "").strip(), version=version)
4748

4849
# Wrap parser.error in a typed NoReturn method for better typing.

qrcode/image/pil.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ class PilImage(qrcode.image.base.BaseImage):
1010
kind = "PNG"
1111

1212
def new_image(self, **kwargs):
13+
if not Image:
14+
raise ImportError("PIL library not found.")
15+
1316
back_color = kwargs.get("back_color", "white")
1417
fill_color = kwargs.get("fill_color", "black")
1518

qrcode/image/pure.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
from itertools import chain
22

3-
import png
3+
from qrcode.compat.png import PngWriter
4+
from qrcode.image.base import BaseImage
45

5-
import qrcode.image.base
66

7-
8-
class PyPNGImage(qrcode.image.base.BaseImage):
7+
class PyPNGImage(BaseImage):
98
"""
109
pyPNG image builder.
1110
"""
@@ -15,7 +14,10 @@ class PyPNGImage(qrcode.image.base.BaseImage):
1514
needs_drawrect = False
1615

1716
def new_image(self, **kwargs):
18-
return png.Writer(self.pixel_size, self.pixel_size, greyscale=True, bitdepth=1)
17+
if not PngWriter:
18+
raise ImportError("PyPNG library not installed.")
19+
20+
return PngWriter(self.pixel_size, self.pixel_size, greyscale=True, bitdepth=1)
1921

2022
def drawrect(self, row, col):
2123
"""

qrcode/image/styledpil.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ class StyledPilImage(qrcode.image.base.BaseImageWithDrawer):
2929
data integrity A resampling filter can be specified (defaulting to
3030
PIL.Image.Resampling.LANCZOS) for resizing; see PIL.Image.resize() for possible
3131
options for this parameter.
32+
The image size can be controlled by `embeded_image_ratio` which is a ratio
33+
between 0 and 1 that's set in relation to the overall width of the QR code.
3234
"""
3335

3436
kind = "PNG"
@@ -41,6 +43,7 @@ def __init__(self, *args, **kwargs):
4143
self.color_mask = kwargs.get("color_mask", SolidFillColorMask())
4244
embeded_image_path = kwargs.get("embeded_image_path", None)
4345
self.embeded_image = kwargs.get("embeded_image", None)
46+
self.embeded_image_ratio = kwargs.get("embeded_image_ratio", 0.25)
4447
self.embeded_image_resample = kwargs.get(
4548
"embeded_image_resample", Image.Resampling.LANCZOS
4649
)
@@ -84,7 +87,7 @@ def draw_embeded_image(self):
8487
return
8588
total_width, _ = self._img.size
8689
total_width = int(total_width)
87-
logo_width_ish = int(total_width / 4)
90+
logo_width_ish = int(total_width * self.embeded_image_ratio)
8891
logo_offset = (
8992
int((int(total_width / 2) - int(logo_width_ish / 2)) / self.box_size)
9093
* self.box_size

qrcode/image/styles/moduledrawers/base.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,5 +30,4 @@ def initialize(self, img: "BaseImage") -> None:
3030
self.img = img
3131

3232
@abc.abstractmethod
33-
def drawrect(self, box, is_active) -> None:
34-
...
33+
def drawrect(self, box, is_active) -> None: ...

qrcode/image/styles/moduledrawers/pil.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,9 @@ def setup_edges(self):
246246
base_draw = ImageDraw.Draw(base)
247247
base_draw.ellipse((0, 0, fake_width * 2, fake_height), fill=front_color)
248248

249-
self.ROUND_LEFT = base.resize((width, shrunken_height), Image.Resampling.LANCZOS)
249+
self.ROUND_LEFT = base.resize(
250+
(width, shrunken_height), Image.Resampling.LANCZOS
251+
)
250252
self.ROUND_RIGHT = self.ROUND_LEFT.transpose(Image.Transpose.FLIP_LEFT_RIGHT)
251253

252254
def drawrect(self, box, is_active: "ActiveWithNeighbors"):

qrcode/image/styles/moduledrawers/svg.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,7 @@ def drawrect(self, box, is_active: bool):
6060
self.img._img.append(self.el(box))
6161

6262
@abc.abstractmethod
63-
def el(self, box):
64-
...
63+
def el(self, box): ...
6564

6665

6766
class SvgSquareDrawer(SvgQRModuleDrawer):
@@ -106,8 +105,7 @@ def drawrect(self, box, is_active: bool):
106105
self.img._subpaths.append(self.subpath(box))
107106

108107
@abc.abstractmethod
109-
def subpath(self, box) -> str:
110-
...
108+
def subpath(self, box) -> str: ...
111109

112110

113111
class SvgPathSquareDrawer(SvgPathQRModuleDrawer):

0 commit comments

Comments
 (0)