Skip to content

Commit

Permalink
Merge branch 'poetry' into test-improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
maribedran committed Sep 26, 2024
2 parents 423579b + 12b7393 commit 5405643
Show file tree
Hide file tree
Showing 28 changed files with 240 additions and 231 deletions.
18 changes: 18 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# editorconfig.org

root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[*.py]
indent_size = 4
max_line_length = 88

[*.{rst,md}]
indent_size = 4
2 changes: 2 additions & 0 deletions .git-blame-ignore-revs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ruff format the entire project
5d60da17455607e9c8b7e7fef9940d20027894f2
23 changes: 23 additions & 0 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Code Quality Checks

on:
push:

jobs:
linting:
name: Code Quality Checks
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Install Dependencies
run: pip install ruff

- name: Code Linting
if: always()
run: ruff check qrcode

- name: Code Formatting
if: always()
run: ruff format --check qrcode
25 changes: 25 additions & 0 deletions .github/workflows/push.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Testsuite Run

on: [push]

jobs:
build:
runs-on: ubuntu-latest
strategy:
max-parallel: 4
matrix:
python-version: ["3.9", "3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}

- name: Install dependencies
run: |
pip install --disable-pip-version-check tox tox-gh-actions
- name: Test with tox
run: tox
13 changes: 7 additions & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
*.pyc
.tox
dist/
.coverage
.coverage.*
htmlcov/
build/
qrcode.egg-info/
.pytest_cache/
.idea/
.pytest_cache/
.tox
build/
cov.xml
dist/
htmlcov/
poetry.lock
qrcode.egg-info/
18 changes: 16 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,28 @@ Change log
7.5 (unreleased)
================

- Nothing changed yet.
- Added support for Python 3.11 and 3.12.

- Drop support for Python <=3.8.

- Change local development setup to use Poetry_.

- Testsuite and code quality checks are done through Github Actions.

- Code quality and formatting utilises ruff_.

- Removed ``typing_extensions`` as a dependency, as it's no longer required with
having Python 3.9+ as a requirement.

.. _Poetry: https://python-poetry.org
.. _ruff: https://astral.sh/ruff


7.4.2 (6 February 2023)
=======================

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


7.4.1 (3 February 2023)
Expand Down
7 changes: 0 additions & 7 deletions MANIFEST.in

This file was deleted.

4 changes: 2 additions & 2 deletions PACKAGING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Packaging quick reminder

Make sure maintainer dependencies are installed::

pip install -e .[maintainer,dev]
poetry install

Run release command and follow prompt instructions::

fullrelease
poetry run fullrelease
18 changes: 15 additions & 3 deletions TESTING.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
Testing
=======

First, install tox into your virtualenv::
First, install dev dependencies::

pip install --upgrade tox
poetry install --with dev

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

Here's the OSX Homebrew command:

brew install libjpeg libtiff little-cms2 openjpeg webp

Finally, just run ``tox``!
If you want, you can test against a specific version like this: ``tox -e py36``
If you want, you can test against a specific version like this: ``tox -e py312-pil``


Linting
-------

Run `ruff` to check linting::

ruff check
70 changes: 68 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,69 @@
[build-system]
requires = ["setuptools >= 48"]
build-backend = "setuptools.build_meta"
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.poetry]
name = "qrcode"
version = "8.0.dev0"
packages = [{include = "qrcode"}]
description = "QR Code image generator"
authors = ["Lincoln Loop <info@lincolnloop.com>"]
license = "BSD"
readme = ["README.rst", "CHANGES.rst"]
homepage = "https://github.com/lincolnloop/python-qrcode"
keywords = ["qr", "denso-wave", "IEC18004"]
classifiers = [
"Development Status :: 5 - Production/Stable",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Intended Audience :: Developers",
"Programming Language :: Python",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3 :: Only",
"Topic :: Multimedia :: Graphics",
"Topic :: Software Development :: Libraries :: Python Modules",
]

# There is no support for data files yet.
# https://github.com/python-poetry/poetry/issues/9519
#
# data_files = [
# { destination = "share/man/man1", from = [ "doc/qr.1" ] },
# ]

[tool.poetry.scripts]
qr = 'qrcode.console_scripts:main'


[tool.poetry.dependencies]
python = "^3.9"
colorama = {version = "*", platform = "win32"}
pypng = {version = "*", optional = true}
pillow = {version = ">=9.1.0", optional = true}

[tool.poetry.extras]
pil = ["pillow"]
png = ["pypng"]

[tool.poetry.group.dev.dependencies]
pytest = {version = "*"}
pytest-cov = {version = "*"}
tox = {version = "*"}
ruff = {version = "*"}
docutils = "^0.21.2"
zest-releaser = {extras = ["recommended"], version = "^9.2.0"}

[tool.zest-releaser]
less-zeros = "yes"
version-levels = 2
tag-format = "v{version}"
tag-message = "Version {version}"
tag-signing = "yes"
date-format =" %%-d %%B %%Y"
prereleaser.middle = [
"qrcode.release.update_manpage"
]
7 changes: 7 additions & 0 deletions qrcode/compat/png.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Try to import png library.
PngWriter = None

try:
from png import Writer as PngWriter # type: ignore # noqa: F401
except ImportError: # pragma: no cover
pass
5 changes: 3 additions & 2 deletions qrcode/console_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
When stdout is a tty the QR Code is printed to the terminal and when stdout is
a pipe to a file an image is written. The default image format is PNG.
"""

import optparse
import os
import sys
from typing import Dict, Iterable, NoReturn, Optional, Set, Type
from importlib import metadata

import qrcode
from qrcode.image.base import BaseImage, DrawerAliases
Expand Down Expand Up @@ -40,9 +42,8 @@
def main(args=None):
if args is None:
args = sys.argv[1:]
from pkg_resources import get_distribution

version = get_distribution("qrcode").version
version = metadata.version("qrcode")
parser = optparse.OptionParser(usage=(__doc__ or "").strip(), version=version)

# Wrap parser.error in a typed NoReturn method for better typing.
Expand Down
3 changes: 3 additions & 0 deletions qrcode/image/pil.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ class PilImage(qrcode.image.base.BaseImage):
kind = "PNG"

def new_image(self, **kwargs):
if not Image:
raise ImportError("PIL library not found.")

back_color = kwargs.get("back_color", "white")
fill_color = kwargs.get("fill_color", "black")

Expand Down
12 changes: 7 additions & 5 deletions qrcode/image/pure.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from itertools import chain

import png
from qrcode.compat.png import PngWriter
from qrcode.image.base import BaseImage

import qrcode.image.base


class PyPNGImage(qrcode.image.base.BaseImage):
class PyPNGImage(BaseImage):
"""
pyPNG image builder.
"""
Expand All @@ -15,7 +14,10 @@ class PyPNGImage(qrcode.image.base.BaseImage):
needs_drawrect = False

def new_image(self, **kwargs):
return png.Writer(self.pixel_size, self.pixel_size, greyscale=True, bitdepth=1)
if not PngWriter:
raise ImportError("PyPNG library not installed.")

return PngWriter(self.pixel_size, self.pixel_size, greyscale=True, bitdepth=1)

def drawrect(self, row, col):
"""
Expand Down
5 changes: 4 additions & 1 deletion qrcode/image/styledpil.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ class StyledPilImage(qrcode.image.base.BaseImageWithDrawer):
data integrity A resampling filter can be specified (defaulting to
PIL.Image.Resampling.LANCZOS) for resizing; see PIL.Image.resize() for possible
options for this parameter.
The image size can be controlled by `embeded_image_ratio` which is a ratio
between 0 and 1 that's set in relation to the overall width of the QR code.
"""

kind = "PNG"
Expand All @@ -44,6 +46,7 @@ def __init__(self, *args, **kwargs):
self.color_mask = kwargs.get("color_mask", SolidFillColorMask())
embeded_image_path = kwargs.get("embeded_image_path", None)
self.embeded_image = kwargs.get("embeded_image", None)
self.embeded_image_ratio = kwargs.get("embeded_image_ratio", 0.25)
self.embeded_image_resample = kwargs.get(
"embeded_image_resample", Image.Resampling.LANCZOS
)
Expand Down Expand Up @@ -87,7 +90,7 @@ def draw_embeded_image(self):
return
total_width, _ = self._img.size
total_width = int(total_width)
logo_width_ish = int(total_width / 4)
logo_width_ish = int(total_width * self.embeded_image_ratio)
logo_offset = (
int((int(total_width / 2) - int(logo_width_ish / 2)) / self.box_size)
* self.box_size
Expand Down
3 changes: 1 addition & 2 deletions qrcode/image/styles/moduledrawers/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,4 @@ def initialize(self, img: "BaseImage") -> None:
self.img = img

@abc.abstractmethod
def drawrect(self, box, is_active) -> None:
...
def drawrect(self, box, is_active) -> None: ...
4 changes: 3 additions & 1 deletion qrcode/image/styles/moduledrawers/pil.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,9 @@ def setup_edges(self):
base_draw = ImageDraw.Draw(base)
base_draw.ellipse((0, 0, fake_width * 2, fake_height), fill=front_color)

self.ROUND_LEFT = base.resize((width, shrunken_height), Image.Resampling.LANCZOS)
self.ROUND_LEFT = base.resize(
(width, shrunken_height), Image.Resampling.LANCZOS
)
self.ROUND_RIGHT = self.ROUND_LEFT.transpose(Image.Transpose.FLIP_LEFT_RIGHT)

def drawrect(self, box, is_active: "ActiveWithNeighbors"):
Expand Down
6 changes: 2 additions & 4 deletions qrcode/image/styles/moduledrawers/svg.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,7 @@ def drawrect(self, box, is_active: bool):
self.img._img.append(self.el(box))

@abc.abstractmethod
def el(self, box):
...
def el(self, box): ...


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

@abc.abstractmethod
def subpath(self, box) -> str:
...
def subpath(self, box) -> str: ...


class SvgPathSquareDrawer(SvgPathQRModuleDrawer):
Expand Down
Loading

0 comments on commit 5405643

Please sign in to comment.