Skip to content

Consider adding a setter to the mask_pattern attribute #191

@pricebenjamin

Description

@pricebenjamin

Modifying the mask_pattern of a previously instantiated QRCode object works as expected, so long as the user knows which values to assign.

>>> qr = qrcode.QRCode(version=1)
>>> for i in range(8):
...     qr.mask_pattern = i
...     qr.make()
...     qr.print_tty()
...     # Works as expected

However, assigning incorrect values can lead to strange issues.

Here's a case where we break an error message. Instead of raising the TypeError we wanted, a separate TypeError is raised (because pattern is an int, not a str).

>>> import qrcode
>>> qr = qrcode.QRCode(version=1)
>>> qr.mask_pattern = 8
>>> qr.make()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 97, in make
    self.makeImpl(False, self.mask_pattern)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 124, in makeImpl
    self.map_data(self.data_cache, mask_pattern)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 382, in map_data
    mask_func = util.mask_func(mask_pattern)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/util.py", line 151, in mask_func
    raise TypeError("Bad mask pattern: " + pattern)  # pragma: no cover
TypeError: can only concatenate str (not "int") to str

Worse than that, we can hang the program:

>>> qr = qrcode.QRCode(version=1)
>>> qr.mask_pattern = -1
>>> qr.make()
^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 97, in make
    self.makeImpl(False, self.mask_pattern)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 116, in makeImpl
    self.setup_type_info(test, mask_pattern)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/main.py", line 347, in setup_type_info
    bits = util.BCH_type_info(data)
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/util.py", line 106, in BCH_type_info
    while BCH_digit(d) - BCH_digit(G15) >= 0:
  File "/home/ben/miniconda3/envs/qr/lib/python3.7/site-packages/qrcode/util.py", line 121, in BCH_digit
    while data != 0:
KeyboardInterrupt

It's clear that parts of this library were written under the assumption that this value would not change after instantiation. If that's the case, perhaps this attribute could be made read-only. Otherwise, a simple setter could be used to verify the value before assignment. (Bonus: the _check_mask_pattern function already exists!)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions