qrcode-5.3/0000755000175000017500000000000012716767167010764 5ustar hlehleqrcode-5.3/setup.py0000644000175000017500000000351112716767107012470 0ustar hlehle#!/usr/bin/env python from __future__ import unicode_literals import io import os from setuptools import setup, find_packages import sys def long_description(): """ Build the long description from a README file located in the same directory as this module. """ base_path = os.path.dirname(os.path.realpath(__file__)) content = [] for name in ('README.rst', 'CHANGES.rst'): with io.open(os.path.join(base_path, name), encoding='utf-8') as f: content.append(f.read()) return '\n\n'.join(content) # Colorama is needed for proper terminal support on MS platforms if sys.platform.startswith(('win', 'cygwin')): dependencies = ['six', 'colorama'] else: dependencies = ['six'] setup( name='qrcode', version='5.3', url='https://github.com/lincolnloop/python-qrcode', description='QR Code image generator', license='BSD', long_description=long_description(), author='Lincoln Loop', author_email='info@lincolnloop.com', platforms=['any'], packages=find_packages(), entry_points={ 'console_scripts': [ 'qr = qrcode.console_scripts:main', ], }, install_requires=dependencies, data_files=[('share/man/man1', ['doc/qr.1'])], include_package_data=True, classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Intended Audience :: Developers', 'Programming Language :: Python', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Topic :: Multimedia :: Graphics', 'Topic :: Software Development :: Libraries :: Python Modules', ], ) qrcode-5.3/README.rst0000644000175000017500000001001212350137012012413 0ustar hlehle============================= Pure python QR Code generator ============================= This module uses image libraries, Python Imaging Library (PIL) by default, to generate QR Codes. It is recommended to use the pillow_ fork rather than PIL itself. .. _pillow: https://pypi.python.org/pypi/Pillow What is a QR Code? ================== A Quick Response code is a two-dimensional pictographic code used for its fast readability and comparatively large storage capacity. The code consists of black modules arranged in a square pattern on a white background. The information encoded can be made up of any kind of data (e.g., binary, alphanumeric, or Kanji symbols) Usage ===== From the command line, use the installed ``qr`` script:: qr "Some text" > test.png Or in Python, use the ``make`` shortcut function:: import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example:: import qrcode qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) qr.add_data('Some data') qr.make(fit=True) img = qr.make_image() The ``version`` parameter is an integer from 1 to 40 that controls the size of the QR Code (the smallest, version 1, is a 21x21 matrix). Set to ``None`` and use the ``fit`` parameter when making the code to determine this automatically. The ``error_correction`` parameter controls the error correction used for the QR Code. The following four constants are made available on the ``qrcode`` package: ``ERROR_CORRECT_L`` About 7% or less errors can be corrected. ``ERROR_CORRECT_M`` (default) About 15% or less errors can be corrected. ``ERROR_CORRECT_Q`` About 25% or less errors can be corrected. ``ERROR_CORRECT_H``. About 30% or less errors can be corrected. The ``box_size`` parameter controls how many pixels each "box" of the QR code is. The ``border`` parameter controls how many boxes thick the border should be (the default is 4, which is the minimum according to the specs). Other image factories ===================== You can encode as SVG, or use a new pure Python image processor to encode to PNG images. The Python examples below use the ``make`` shortcut. The same ``image_factory`` keyword argument is a valid option for the ``QRCode`` class for more advanced usage. SVG --- On Python 2.6 must install lxml since the older xml.etree.ElementTree version can not be used to create SVG images. You can create the entire SVG or an SVG fragment. When building an entire SVG image, you can use the factory that combines as a path (recommended, and default for the script) or a factory that creates a simple set of rectangles. From your command line:: qr --factory=svg-path "Some text" > test.svg qr --factory=svg "Some text" > test.svg qr --factory=svg-fragment "Some text" > test.svg Or in Python:: import qrcode import qrcode.image.svg if method == 'basic': # Simple factory, just a set of rects. factory = qrcode.image.svg.SvgImage elif method == 'fragment': # Fragment factory (also just a set of rects) factory = qrcode.image.svg.SvgFragmentImage else: # Combined path factory, fixes white space that may occur when zooming factory = qrcode.image.svg.SvgPathImage img = qrcode.make('Some data here', image_factory=factory) Two other related factories are available that work the same, but also fill the background of the SVG with white:: qrcode.image.svg.SvgFillImage qrcode.image.svg.SvgPathFillImage Pure Python PNG --------------- Install the following two packages:: pip install git+git://github.com/ojii/pymaging.git#egg=pymaging pip install git+git://github.com/ojii/pymaging-png.git#egg=pymaging-png From your command line:: qr --factory=pymaging "Some text" > test.png Or in Python:: import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) qrcode-5.3/qrcode/0000755000175000017500000000000012716767167012241 5ustar hlehleqrcode-5.3/qrcode/console_scripts.py0000755000175000017500000000622012716766375016027 0ustar hlehle#!/usr/bin/env python """ qr - Convert stdin (or the first argument) to a QR Code. 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 sys import optparse import os import qrcode # The next block is added to get the terminal to display properly on MS platforms if sys.platform.startswith(('win', 'cygwin')): import colorama colorama.init() default_factories = { 'pil': 'qrcode.image.pil.PilImage', 'pymaging': 'qrcode.image.pure.PymagingImage', 'svg': 'qrcode.image.svg.SvgImage', 'svg-fragment': 'qrcode.image.svg.SvgFragmentImage', 'svg-path': 'qrcode.image.svg.SvgPathImage', } error_correction = { 'L': qrcode.ERROR_CORRECT_L, 'M': qrcode.ERROR_CORRECT_M, 'Q': qrcode.ERROR_CORRECT_Q, 'H': qrcode.ERROR_CORRECT_H, } def main(args=sys.argv[1:]): parser = optparse.OptionParser(usage=__doc__.strip()) parser.add_option( "--factory", help="Full python path to the image factory class to " "create the image with. You can use the following shortcuts to the " "built-in image factory classes: {0}.".format( ", ".join(sorted(default_factories.keys())))) parser.add_option( "--optimize", type=int, help="Optimize the data by looking for chunks " "of at least this many characters that could use a more efficient " "encoding method. Use 0 to turn off chunk optimization.") parser.add_option( "--error-correction", type='choice', choices=sorted(error_correction.keys()), default='M', help="The error correction level to use. Choices are L (7%), " "M (15%, default), Q (25%), and H (30%).") opts, args = parser.parse_args(args) qr = qrcode.QRCode( error_correction=error_correction[opts.error_correction]) if opts.factory: module = default_factories.get(opts.factory, opts.factory) if '.' not in module: parser.error("The image factory is not a full python path") module, name = module.rsplit('.', 1) imp = __import__(module, {}, [], [name]) image_factory = getattr(imp, name) else: image_factory = None if args: data = args[0] else: # Use sys.stdin.buffer if available (Python 3) avoiding # UnicodeDecodeErrors. stdin_buffer = getattr(sys.stdin, 'buffer', sys.stdin) data = stdin_buffer.read() if opts.optimize is None: qr.add_data(data) else: qr.add_data(data, optimize=opts.optimize) if image_factory is None and os.isatty(sys.stdout.fileno()): qr.print_ascii(tty=True) return img = qr.make_image(image_factory=image_factory) sys.stdout.flush() # Use sys.stdout.buffer if available (Python 3), avoiding # UnicodeDecodeErrors. stdout_buffer = getattr(sys.stdout, 'buffer', None) if not stdout_buffer: if sys.platform == 'win32': # pragma: no cover import msvcrt msvcrt.setmode(sys.stdout.fileno(), os.O_BINARY) stdout_buffer = sys.stdout img.save(stdout_buffer) if __name__ == "__main__": main() qrcode-5.3/qrcode/tests/0000755000175000017500000000000012716767167013403 5ustar hlehleqrcode-5.3/qrcode/tests/test_qrcode.py0000644000175000017500000002071012672061145016251 0ustar hlehleimport warnings import six import sys import qrcode import qrcode.util import qrcode.image.svg try: import qrcode.image.pure import pymaging_png # ensure that PNG support is installed except ImportError: # pragma: no cover pymaging_png = None import qrcode from qrcode.image.base import BaseImage from qrcode.exceptions import DataOverflowError from qrcode.util import ( QRData, MODE_NUMBER, MODE_ALPHA_NUM, MODE_8BIT_BYTE) from qrcode.tests.svg import SvgImageWhite try: import unittest2 as unittest except ImportError: import unittest try: from unittest import mock except ImportError: import mock UNICODE_TEXT = u'\u03b1\u03b2\u03b3' class QRCodeTests(unittest.TestCase): def test_basic(self): qr = qrcode.QRCode(version=1) qr.add_data('a') qr.make(fit=False) def test_large(self): qr = qrcode.QRCode(version=27) qr.add_data('a') qr.make(fit=False) def test_invalid_version(self): qr = qrcode.QRCode(version=41) self.assertRaises(ValueError, qr.make, fit=False) def test_overflow(self): qr = qrcode.QRCode(version=1) qr.add_data('abcdefghijklmno') self.assertRaises(DataOverflowError, qr.make, fit=False) def test_add_qrdata(self): qr = qrcode.QRCode(version=1) data = QRData('a') qr.add_data(data) qr.make(fit=False) def test_fit(self): qr = qrcode.QRCode() qr.add_data('a') qr.make() self.assertEqual(qr.version, 1) qr.add_data('bcdefghijklmno') qr.make() self.assertEqual(qr.version, 2) def test_mode_number(self): qr = qrcode.QRCode() qr.add_data('1234567890123456789012345678901234', optimize=0) qr.make() self.assertEqual(qr.version, 1) self.assertEqual(qr.data_list[0].mode, MODE_NUMBER) def test_mode_alpha(self): qr = qrcode.QRCode() qr.add_data('ABCDEFGHIJ1234567890', optimize=0) qr.make() self.assertEqual(qr.version, 1) self.assertEqual(qr.data_list[0].mode, MODE_ALPHA_NUM) def test_regression_mode_comma(self): qr = qrcode.QRCode() qr.add_data(',', optimize=0) qr.make() self.assertEqual(qr.data_list[0].mode, MODE_8BIT_BYTE) def test_mode_8bit(self): qr = qrcode.QRCode() qr.add_data(u'abcABC' + UNICODE_TEXT, optimize=0) qr.make() self.assertEqual(qr.version, 1) self.assertEqual(qr.data_list[0].mode, MODE_8BIT_BYTE) def test_mode_8bit_newline(self): qr = qrcode.QRCode() qr.add_data('ABCDEFGHIJ1234567890\n', optimize=0) qr.make() self.assertEqual(qr.data_list[0].mode, MODE_8BIT_BYTE) def test_render_pil(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image() img.save(six.BytesIO()) def test_qrcode_bad_factory(self): self.assertRaises( TypeError, qrcode.QRCode, image_factory='not_BaseImage') self.assertRaises( AssertionError, qrcode.QRCode, image_factory=dict) def test_qrcode_factory(self): class MockFactory(BaseImage): drawrect = mock.Mock() qr = qrcode.QRCode(image_factory=MockFactory) qr.add_data(UNICODE_TEXT) qr.make_image() self.assertTrue(MockFactory.drawrect.called) def test_render_svg(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=qrcode.image.svg.SvgImage) img.save(six.BytesIO()) def test_render_svg_path(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=qrcode.image.svg.SvgPathImage) img.save(six.BytesIO()) def test_render_svg_fragment(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=qrcode.image.svg.SvgFragmentImage) img.save(six.BytesIO()) def test_render_svg_with_background(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=SvgImageWhite) img.save(six.BytesIO()) @unittest.skipIf(not pymaging_png, "Requires pymaging with PNG support") def test_render_pymaging_png(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=qrcode.image.pure.PymagingImage) with warnings.catch_warnings(): if six.PY3: warnings.simplefilter('ignore', DeprecationWarning) img.save(six.BytesIO()) @unittest.skipIf(not pymaging_png, "Requires pymaging") def test_render_pymaging_png_bad_kind(self): qr = qrcode.QRCode() qr.add_data(UNICODE_TEXT) img = qr.make_image(image_factory=qrcode.image.pure.PymagingImage) self.assertRaises(ValueError, img.save, six.BytesIO(), kind='FISH') def test_optimize(self): qr = qrcode.QRCode() text = 'A1abc12345def1HELLOa' qr.add_data(text, optimize=4) qr.make() self.assertEqual(len(qr.data_list), 5) self.assertEqual(qr.data_list[0].mode, MODE_8BIT_BYTE) self.assertEqual(qr.data_list[1].mode, MODE_NUMBER) self.assertEqual(qr.data_list[2].mode, MODE_8BIT_BYTE) self.assertEqual(qr.data_list[3].mode, MODE_ALPHA_NUM) self.assertEqual(qr.data_list[4].mode, MODE_8BIT_BYTE) self.assertEqual(qr.version, 2) def test_optimize_size(self): text = 'A1abc12345123451234512345def1HELLOHELLOHELLOHELLOa' * 5 qr = qrcode.QRCode() qr.add_data(text) qr.make() self.assertEqual(qr.version, 10) qr = qrcode.QRCode() qr.add_data(text, optimize=0) qr.make() self.assertEqual(qr.version, 11) def test_qrdata_repr(self): data = b'hello' data_obj = qrcode.util.QRData(data) self.assertEqual(repr(data_obj), repr(data)) def test_print_ascii_stdout(self): qr = qrcode.QRCode() stdout_encoding = sys.stdout.encoding with mock.patch('sys.stdout') as fake_stdout: # Python 2.6 needs sys.stdout.encoding to be a real string. sys.stdout.encoding = stdout_encoding fake_stdout.isatty.return_value = None self.assertRaises(OSError, qr.print_ascii, tty=True) self.assertTrue(fake_stdout.isatty.called) def test_print_ascii(self): qr = qrcode.QRCode(border=0) f = six.StringIO() qr.print_ascii(out=f) printed = f.getvalue() f.close() expected = u'\u2588\u2580\u2580\u2580\u2580\u2580\u2588' self.assertEqual(printed[:len(expected)], expected) f = six.StringIO() f.isatty = lambda: True qr.print_ascii(out=f, tty=True) printed = f.getvalue() f.close() expected = ( u'\x1b[48;5;232m\x1b[38;5;255m' + u'\xa0\u2584\u2584\u2584\u2584\u2584\xa0') self.assertEqual(printed[:len(expected)], expected) def test_print_tty_stdout(self): qr = qrcode.QRCode() with mock.patch('sys.stdout') as fake_stdout: fake_stdout.isatty.return_value = None self.assertRaises(OSError, qr.print_tty) self.assertTrue(fake_stdout.isatty.called) def test_print_tty(self): qr = qrcode.QRCode() f = six.StringIO() f.isatty = lambda: True qr.print_tty(out=f) printed = f.getvalue() f.close() BOLD_WHITE_BG = '\x1b[1;47m' BLACK_BG = '\x1b[40m' WHITE_BLOCK = BOLD_WHITE_BG + ' ' + BLACK_BG EOL = '\x1b[0m\n' expected = ( BOLD_WHITE_BG + ' '*23 + EOL + WHITE_BLOCK + ' '*7 + WHITE_BLOCK) self.assertEqual(printed[:len(expected)], expected) def test_get_matrix(self): qr = qrcode.QRCode(border=0) qr.add_data('1') self.assertEqual(qr.get_matrix(), qr.modules) def test_get_matrix_border(self): qr = qrcode.QRCode(border=1) qr.add_data('1') matrix = [row[1:-1] for row in qr.get_matrix()[1:-1]] self.assertEqual(matrix, qr.modules) def test_negative_size_at_construction(self): self.assertRaises(ValueError, qrcode.QRCode, box_size=-1) def test_negative_size_at_usage(self): qr = qrcode.QRCode() qr.box_size = -1 self.assertRaises(ValueError, qr.make_image) class ShortcutTest(unittest.TestCase): def runTest(self): qrcode.make('image') qrcode-5.3/qrcode/tests/test_example.py0000644000175000017500000000054512520274365016435 0ustar hlehletry: import unittest2 as unittest except ImportError: import unittest try: from unittest import mock except ImportError: import mock from qrcode import run_example class ExampleTest(unittest.TestCase): @mock.patch('PIL.Image.Image.show') def runTest(self, mock_show): run_example() mock_show.assert_called_with() qrcode-5.3/qrcode/tests/test_script.py0000644000175000017500000000414312651246027016303 0ustar hlehleimport sys try: import unittest2 as unittest except ImportError: import unittest try: from unittest import mock except ImportError: import mock from qrcode.console_scripts import main def bad_read(): raise UnicodeDecodeError('utf-8', b'0x80', 0, 1, 'invalid start byte') class ScriptTest(unittest.TestCase): @mock.patch('os.isatty', lambda *args: True) @mock.patch('qrcode.main.QRCode.print_ascii') def test_isatty(self, mock_print_ascii): main(['testtext']) mock_print_ascii.assert_called_with(tty=True) @mock.patch('os.isatty', lambda *args: False) @mock.patch('sys.stdout') def test_piped(self, mock_stdout): main(['testtext']) @mock.patch('os.isatty', lambda *args: True) @mock.patch('qrcode.main.QRCode.print_ascii') def test_stdin(self, mock_print_ascii): mock_stdin = mock.Mock(sys.stdin) stdin_buffer = getattr(mock_stdin, 'buffer', mock_stdin) stdin_buffer.read.return_value = 'testtext' with mock.patch('sys.stdin', mock_stdin): main([]) self.assertTrue(stdin_buffer.read.called) mock_print_ascii.assert_called_with(tty=True) @unittest.skipIf(sys.version_info[0] < 3, 'Python 3') @mock.patch('os.isatty', lambda *args: True) @mock.patch('qrcode.main.QRCode.print_ascii') def test_stdin_py3_unicodedecodeerror(self, mock_print_ascii): mock_stdin = mock.Mock(sys.stdin) mock_stdin.buffer.read.return_value = 'testtext' mock_stdin.read.side_effect = bad_read with mock.patch('sys.stdin', mock_stdin): main([]) mock_print_ascii.assert_called_with(tty=True) @mock.patch('os.isatty', lambda *args: True) @mock.patch('qrcode.main.QRCode.print_ascii') def test_optimize(self, mock_print_ascii): main('testtext --optimize 0'.split()) @mock.patch('sys.stdout') def test_factory(self, mock_stdout): main('testtext --factory svg'.split()) @mock.patch('sys.stderr') def test_bad_factory(self, mock_stderr): self.assertRaises(SystemExit, main, 'testtext --factory fish'.split()) qrcode-5.3/qrcode/tests/svg.py0000644000175000017500000000014012520274365014531 0ustar hlehlefrom qrcode.image.svg import SvgImage class SvgImageWhite(SvgImage): background = 'white' qrcode-5.3/qrcode/tests/__init__.py0000644000175000017500000000000012520274365015464 0ustar hlehleqrcode-5.3/qrcode/main.py0000644000175000017500000003223512672061145013524 0ustar hlehlefrom qrcode import constants, exceptions, util from qrcode.image.base import BaseImage import six from bisect import bisect_left def make(data=None, **kwargs): qr = QRCode(**kwargs) qr.add_data(data) return qr.make_image() def _check_version(version): if version < 1 or version > 40: raise ValueError( "Invalid version (was %s, expected 1 to 40)" % version) def _check_box_size(size): if int(size) <= 0: raise ValueError( "Invalid box size (was %s, expected larger than 0)" % size) class QRCode: def __init__(self, version=None, error_correction=constants.ERROR_CORRECT_M, box_size=10, border=4, image_factory=None): _check_box_size(box_size) self.version = version and int(version) self.error_correction = int(error_correction) self.box_size = int(box_size) # Spec says border should be at least four boxes wide, but allow for # any (e.g. for producing printable QR codes). self.border = int(border) self.image_factory = image_factory if image_factory is not None: assert issubclass(image_factory, BaseImage) self.clear() def clear(self): """ Reset the internal data. """ self.modules = None self.modules_count = 0 self.data_cache = None self.data_list = [] def add_data(self, data, optimize=20): """ Add data to this QR Code. :param optimize: Data will be split into multiple chunks to optimize the QR size by finding to more compressed modes of at least this length. Set to ``0`` to avoid optimizing at all. """ if isinstance(data, util.QRData): self.data_list.append(data) else: if optimize: self.data_list.extend(util.optimal_data_chunks(data)) else: self.data_list.append(util.QRData(data)) self.data_cache = None def make(self, fit=True): """ Compile the data into a QR Code array. :param fit: If ``True`` (or if a size has not been provided), find the best fit for the data to avoid data overflow errors. """ if fit or (self.version is None): self.best_fit(start=self.version) self.makeImpl(False, self.best_mask_pattern()) def makeImpl(self, test, mask_pattern): _check_version(self.version) self.modules_count = self.version * 4 + 17 self.modules = [None] * self.modules_count for row in range(self.modules_count): self.modules[row] = [None] * self.modules_count for col in range(self.modules_count): self.modules[row][col] = None # (col + row) % 3 self.setup_position_probe_pattern(0, 0) self.setup_position_probe_pattern(self.modules_count - 7, 0) self.setup_position_probe_pattern(0, self.modules_count - 7) self.setup_position_adjust_pattern() self.setup_timing_pattern() self.setup_type_info(test, mask_pattern) if self.version >= 7: self.setup_type_number(test) if self.data_cache is None: self.data_cache = util.create_data( self.version, self.error_correction, self.data_list) self.map_data(self.data_cache, mask_pattern) def setup_position_probe_pattern(self, row, col): for r in range(-1, 8): if row + r <= -1 or self.modules_count <= row + r: continue for c in range(-1, 8): if col + c <= -1 or self.modules_count <= col + c: continue if (0 <= r and r <= 6 and (c == 0 or c == 6) or (0 <= c and c <= 6 and (r == 0 or r == 6)) or (2 <= r and r <= 4 and 2 <= c and c <= 4)): self.modules[row + r][col + c] = True else: self.modules[row + r][col + c] = False def best_fit(self, start=None): """ Find the minimum size required to fit in the data. """ if start is None: start = 1 _check_version(start) # Corresponds to the code in util.create_data, except we don't yet know # version, so optimistically assume start and check later mode_sizes = util.mode_sizes_for_version(start) buffer = util.BitBuffer() for data in self.data_list: buffer.put(data.mode, 4) buffer.put(len(data), mode_sizes[data.mode]) data.write(buffer) needed_bits = len(buffer) self.version = bisect_left(util.BIT_LIMIT_TABLE[self.error_correction], needed_bits, start) if self.version == 41: raise exceptions.DataOverflowError() # Now check whether we need more bits for the mode sizes, recursing if # our guess was too low if mode_sizes is not util.mode_sizes_for_version(self.version): self.best_fit(start=self.version) return self.version def best_mask_pattern(self): """ Find the most efficient mask pattern. """ min_lost_point = 0 pattern = 0 for i in range(8): self.makeImpl(True, i) lost_point = util.lost_point(self.modules) if i == 0 or min_lost_point > lost_point: min_lost_point = lost_point pattern = i return pattern def print_tty(self, out=None): """ Output the QR Code only using TTY colors. If the data has not been compiled yet, make it first. """ if out is None: import sys out = sys.stdout if not out.isatty(): raise OSError("Not a tty") if self.data_cache is None: self.make() modcount = self.modules_count out.write("\x1b[1;47m" + (" " * (modcount * 2 + 4)) + "\x1b[0m\n") for r in range(modcount): out.write("\x1b[1;47m \x1b[40m") for c in range(modcount): if self.modules[r][c]: out.write(" ") else: out.write("\x1b[1;47m \x1b[40m") out.write("\x1b[1;47m \x1b[0m\n") out.write("\x1b[1;47m" + (" " * (modcount * 2 + 4)) + "\x1b[0m\n") out.flush() def print_ascii(self, out=None, tty=False, invert=False): """ Output the QR Code using ASCII characters. :param tty: use fixed TTY color codes (forces invert=True) :param invert: invert the ASCII characters (solid <-> transparent) """ if out is None: import sys if sys.version_info < (2, 7): # On Python versions 2.6 and earlier, stdout tries to encode # strings using ASCII rather than stdout.encoding, so use this # workaround. import codecs out = codecs.getwriter(sys.stdout.encoding)(sys.stdout) else: out = sys.stdout if tty and not out.isatty(): raise OSError("Not a tty") if self.data_cache is None: self.make() modcount = self.modules_count codes = [six.int2byte(code).decode('cp437') for code in (255, 223, 220, 219)] if tty: invert = True if invert: codes.reverse() def get_module(x, y): if (invert and self.border and max(x, y) >= modcount+self.border): return 1 if min(x, y) < 0 or max(x, y) >= modcount: return 0 return self.modules[x][y] for r in range(-self.border, modcount+self.border, 2): if tty: if not invert or r < modcount+self.border-1: out.write('\x1b[48;5;232m') # Background black out.write('\x1b[38;5;255m') # Foreground white for c in range(-self.border, modcount+self.border): pos = get_module(r, c) + (get_module(r+1, c) << 1) out.write(codes[pos]) if tty: out.write('\x1b[0m') out.write('\n') out.flush() def make_image(self, image_factory=None, **kwargs): """ Make an image from the QR Code data. If the data has not been compiled yet, make it first. """ _check_box_size(self.box_size) if self.data_cache is None: self.make() if image_factory is not None: assert issubclass(image_factory, BaseImage) else: image_factory = self.image_factory if image_factory is None: # Use PIL by default from qrcode.image.pil import PilImage image_factory = PilImage im = image_factory( self.border, self.modules_count, self.box_size, **kwargs) for r in range(self.modules_count): for c in range(self.modules_count): if self.modules[r][c]: im.drawrect(r, c) return im def setup_timing_pattern(self): for r in range(8, self.modules_count - 8): if self.modules[r][6] is not None: continue self.modules[r][6] = (r % 2 == 0) for c in range(8, self.modules_count - 8): if self.modules[6][c] is not None: continue self.modules[6][c] = (c % 2 == 0) def setup_position_adjust_pattern(self): pos = util.pattern_position(self.version) for i in range(len(pos)): for j in range(len(pos)): row = pos[i] col = pos[j] if self.modules[row][col] is not None: continue for r in range(-2, 3): for c in range(-2, 3): if (r == -2 or r == 2 or c == -2 or c == 2 or (r == 0 and c == 0)): self.modules[row + r][col + c] = True else: self.modules[row + r][col + c] = False def setup_type_number(self, test): bits = util.BCH_type_number(self.version) for i in range(18): mod = (not test and ((bits >> i) & 1) == 1) self.modules[i // 3][i % 3 + self.modules_count - 8 - 3] = mod for i in range(18): mod = (not test and ((bits >> i) & 1) == 1) self.modules[i % 3 + self.modules_count - 8 - 3][i // 3] = mod def setup_type_info(self, test, mask_pattern): data = (self.error_correction << 3) | mask_pattern bits = util.BCH_type_info(data) # vertical for i in range(15): mod = (not test and ((bits >> i) & 1) == 1) if i < 6: self.modules[i][8] = mod elif i < 8: self.modules[i + 1][8] = mod else: self.modules[self.modules_count - 15 + i][8] = mod # horizontal for i in range(15): mod = (not test and ((bits >> i) & 1) == 1) if i < 8: self.modules[8][self.modules_count - i - 1] = mod elif i < 9: self.modules[8][15 - i - 1 + 1] = mod else: self.modules[8][15 - i - 1] = mod # fixed module self.modules[self.modules_count - 8][8] = (not test) def map_data(self, data, mask_pattern): inc = -1 row = self.modules_count - 1 bitIndex = 7 byteIndex = 0 mask_func = util.mask_func(mask_pattern) data_len = len(data) for col in six.moves.xrange(self.modules_count - 1, 0, -2): if col <= 6: col -= 1 col_range = (col, col-1) while True: for c in col_range: if self.modules[row][c] is None: dark = False if byteIndex < data_len: dark = (((data[byteIndex] >> bitIndex) & 1) == 1) if mask_func(row, c): dark = not dark self.modules[row][c] = dark bitIndex -= 1 if bitIndex == -1: byteIndex += 1 bitIndex = 7 row += inc if row < 0 or self.modules_count <= row: row -= inc inc = -inc break def get_matrix(self): """ Return the QR Code as a multidimensonal array, including the border. To return the array without a border, set ``self.border`` to 0 first. """ if self.data_cache is None: self.make() if not self.border: return self.modules width = len(self.modules) + self.border*2 code = [[False]*width] * self.border x_border = [False]*self.border for module in self.modules: code.append(x_border + module + x_border) code += [[False]*width] * self.border return code qrcode-5.3/qrcode/util.py0000644000175000017500000003600012647555462013563 0ustar hlehleimport re import math import six from six.moves import xrange from qrcode import base, exceptions # QR encoding modes. MODE_NUMBER = 1 << 0 MODE_ALPHA_NUM = 1 << 1 MODE_8BIT_BYTE = 1 << 2 MODE_KANJI = 1 << 3 # Encoding mode sizes. MODE_SIZE_SMALL = { MODE_NUMBER: 10, MODE_ALPHA_NUM: 9, MODE_8BIT_BYTE: 8, MODE_KANJI: 8, } MODE_SIZE_MEDIUM = { MODE_NUMBER: 12, MODE_ALPHA_NUM: 11, MODE_8BIT_BYTE: 16, MODE_KANJI: 10, } MODE_SIZE_LARGE = { MODE_NUMBER: 14, MODE_ALPHA_NUM: 13, MODE_8BIT_BYTE: 16, MODE_KANJI: 12, } ALPHA_NUM = six.b('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ $%*+-./:') RE_ALPHA_NUM = re.compile(six.b('^[') + re.escape(ALPHA_NUM) + six.b(']*\Z')) # The number of bits for numeric delimited data lengths. NUMBER_LENGTH = {3: 10, 2: 7, 1: 4} PATTERN_POSITION_TABLE = [ [], [6, 18], [6, 22], [6, 26], [6, 30], [6, 34], [6, 22, 38], [6, 24, 42], [6, 26, 46], [6, 28, 50], [6, 30, 54], [6, 32, 58], [6, 34, 62], [6, 26, 46, 66], [6, 26, 48, 70], [6, 26, 50, 74], [6, 30, 54, 78], [6, 30, 56, 82], [6, 30, 58, 86], [6, 34, 62, 90], [6, 28, 50, 72, 94], [6, 26, 50, 74, 98], [6, 30, 54, 78, 102], [6, 28, 54, 80, 106], [6, 32, 58, 84, 110], [6, 30, 58, 86, 114], [6, 34, 62, 90, 118], [6, 26, 50, 74, 98, 122], [6, 30, 54, 78, 102, 126], [6, 26, 52, 78, 104, 130], [6, 30, 56, 82, 108, 134], [6, 34, 60, 86, 112, 138], [6, 30, 58, 86, 114, 142], [6, 34, 62, 90, 118, 146], [6, 30, 54, 78, 102, 126, 150], [6, 24, 50, 76, 102, 128, 154], [6, 28, 54, 80, 106, 132, 158], [6, 32, 58, 84, 110, 136, 162], [6, 26, 54, 82, 110, 138, 166], [6, 30, 58, 86, 114, 142, 170] ] G15 = ( (1 << 10) | (1 << 8) | (1 << 5) | (1 << 4) | (1 << 2) | (1 << 1) | (1 << 0)) G18 = ( (1 << 12) | (1 << 11) | (1 << 10) | (1 << 9) | (1 << 8) | (1 << 5) | (1 << 2) | (1 << 0)) G15_MASK = (1 << 14) | (1 << 12) | (1 << 10) | (1 << 4) | (1 << 1) PAD0 = 0xEC PAD1 = 0x11 # Precompute bit count limits, indexed by error correction level and code size _data_count = lambda block: block.data_count BIT_LIMIT_TABLE = [ [0] + [8*sum(map(_data_count, base.rs_blocks(version, error_correction))) for version in xrange(1, 41)] for error_correction in xrange(4) ] def BCH_type_info(data): d = data << 10 while BCH_digit(d) - BCH_digit(G15) >= 0: d ^= (G15 << (BCH_digit(d) - BCH_digit(G15))) return ((data << 10) | d) ^ G15_MASK def BCH_type_number(data): d = data << 12 while BCH_digit(d) - BCH_digit(G18) >= 0: d ^= (G18 << (BCH_digit(d) - BCH_digit(G18))) return (data << 12) | d def BCH_digit(data): digit = 0 while data != 0: digit += 1 data >>= 1 return digit def pattern_position(version): return PATTERN_POSITION_TABLE[version - 1] def mask_func(pattern): """ Return the mask function for the given mask pattern. """ if pattern == 0: # 000 return lambda i, j: (i + j) % 2 == 0 if pattern == 1: # 001 return lambda i, j: i % 2 == 0 if pattern == 2: # 010 return lambda i, j: j % 3 == 0 if pattern == 3: # 011 return lambda i, j: (i + j) % 3 == 0 if pattern == 4: # 100 return lambda i, j: (math.floor(i / 2) + math.floor(j / 3)) % 2 == 0 if pattern == 5: # 101 return lambda i, j: (i * j) % 2 + (i * j) % 3 == 0 if pattern == 6: # 110 return lambda i, j: ((i * j) % 2 + (i * j) % 3) % 2 == 0 if pattern == 7: # 111 return lambda i, j: ((i * j) % 3 + (i + j) % 2) % 2 == 0 raise TypeError("Bad mask pattern: " + pattern) # pragma: no cover def mode_sizes_for_version(version): if version < 10: return MODE_SIZE_SMALL elif version < 27: return MODE_SIZE_MEDIUM else: return MODE_SIZE_LARGE def length_in_bits(mode, version): if mode not in ( MODE_NUMBER, MODE_ALPHA_NUM, MODE_8BIT_BYTE, MODE_KANJI): raise TypeError("Invalid mode (%s)" % mode) # pragma: no cover if version < 1 or version > 40: # pragma: no cover raise ValueError( "Invalid version (was %s, expected 1 to 40)" % version) return mode_sizes_for_version(version)[mode] def lost_point(modules): modules_count = len(modules) lost_point = 0 lost_point = _lost_point_level1(modules, modules_count) lost_point += _lost_point_level2(modules, modules_count) lost_point += _lost_point_level3(modules, modules_count) lost_point += _lost_point_level4(modules, modules_count) return lost_point def _lost_point_level1(modules, modules_count): lost_point = 0 modules_range = xrange(modules_count) row_range_first = (0, 1) row_range_last = (-1, 0) row_range_standard = (-1, 0, 1) col_range_first = ((0, 1), (1,)) col_range_last = ((-1, 0), (-1,)) col_range_standard = ((-1, 0, 1), (-1, 1)) for row in modules_range: if row == 0: row_range = row_range_first elif row == modules_count-1: row_range = row_range_last else: row_range = row_range_standard for col in modules_range: sameCount = 0 dark = modules[row][col] if col == 0: col_range = col_range_first elif col == modules_count-1: col_range = col_range_last else: col_range = col_range_standard for r in row_range: row_offset = row + r if r != 0: col_idx = 0 else: col_idx = 1 for c in col_range[col_idx]: if dark == modules[row_offset][col + c]: sameCount += 1 if sameCount > 5: lost_point += (3 + sameCount - 5) return lost_point def _lost_point_level2(modules, modules_count): lost_point = 0 modules_range = xrange(modules_count - 1) for row in modules_range: this_row = modules[row] next_row = modules[row+1] for col in modules_range: count = 0 if this_row[col]: count += 1 if next_row[col]: count += 1 if this_row[col + 1]: count += 1 if next_row[col + 1]: count += 1 if count == 0 or count == 4: lost_point += 3 return lost_point def _lost_point_level3(modules, modules_count): modules_range_short = xrange(modules_count-6) lost_point = 0 for row in xrange(modules_count): this_row = modules[row] for col in modules_range_short: if (this_row[col] and not this_row[col + 1] and this_row[col + 2] and this_row[col + 3] and this_row[col + 4] and not this_row[col + 5] and this_row[col + 6]): lost_point += 40 for col in xrange(modules_count): for row in modules_range_short: if (modules[row][col] and not modules[row + 1][col] and modules[row + 2][col] and modules[row + 3][col] and modules[row + 4][col] and not modules[row + 5][col] and modules[row + 6][col]): lost_point += 40 return lost_point def _lost_point_level4(modules, modules_count): modules_range = xrange(modules_count) dark_count = 0 for row in modules_range: this_row = modules[row] for col in modules_range: if this_row[col]: dark_count += 1 ratio = abs(100 * dark_count / modules_count / modules_count - 50) / 5 return ratio * 10 def optimal_data_chunks(data, minimum=4): """ An iterator returning QRData chunks optimized to the data content. :param minimum: The minimum number of bytes in a row to split as a chunk. """ data = to_bytestring(data) re_repeat = ( six.b('{') + six.text_type(minimum).encode('ascii') + six.b(',}')) num_pattern = re.compile(six.b('\d') + re_repeat) num_bits = _optimal_split(data, num_pattern) alpha_pattern = re.compile( six.b('[') + re.escape(ALPHA_NUM) + six.b(']') + re_repeat) for is_num, chunk in num_bits: if is_num: yield QRData(chunk, mode=MODE_NUMBER, check_data=False) else: for is_alpha, sub_chunk in _optimal_split(chunk, alpha_pattern): if is_alpha: mode = MODE_ALPHA_NUM else: mode = MODE_8BIT_BYTE yield QRData(sub_chunk, mode=mode, check_data=False) def _optimal_split(data, pattern): while data: match = re.search(pattern, data) if not match: break start, end = match.start(), match.end() if start: yield False, data[:start] yield True, data[start:end] data = data[end:] if data: yield False, data def to_bytestring(data): """ Convert data to a (utf-8 encoded) byte-string if it isn't a byte-string already. """ if not isinstance(data, six.binary_type): data = six.text_type(data).encode('utf-8') return data def optimal_mode(data): """ Calculate the optimal mode for this chunk of data. """ if data.isdigit(): return MODE_NUMBER if RE_ALPHA_NUM.match(data): return MODE_ALPHA_NUM return MODE_8BIT_BYTE class QRData: """ Data held in a QR compatible format. Doesn't currently handle KANJI. """ def __init__(self, data, mode=None, check_data=True): """ If ``mode`` isn't provided, the most compact QR data type possible is chosen. """ if check_data: data = to_bytestring(data) if mode is None: self.mode = optimal_mode(data) else: self.mode = mode if mode not in (MODE_NUMBER, MODE_ALPHA_NUM, MODE_8BIT_BYTE): raise TypeError("Invalid mode (%s)" % mode) # pragma: no cover if check_data and mode < optimal_mode(data): # pragma: no cover raise ValueError( "Provided data can not be represented in mode " "{0}".format(mode)) self.data = data def __len__(self): return len(self.data) def write(self, buffer): if self.mode == MODE_NUMBER: for i in xrange(0, len(self.data), 3): chars = self.data[i:i + 3] bit_length = NUMBER_LENGTH[len(chars)] buffer.put(int(chars), bit_length) elif self.mode == MODE_ALPHA_NUM: for i in xrange(0, len(self.data), 2): chars = self.data[i:i + 2] if len(chars) > 1: buffer.put( ALPHA_NUM.find(chars[0]) * 45 + ALPHA_NUM.find(chars[1]), 11) else: buffer.put(ALPHA_NUM.find(chars), 6) else: if six.PY3: # Iterating a bytestring in Python 3 returns an integer, # no need to ord(). data = self.data else: data = [ord(c) for c in self.data] for c in data: buffer.put(c, 8) def __repr__(self): return repr(self.data) class BitBuffer: def __init__(self): self.buffer = [] self.length = 0 def __repr__(self): return ".".join([str(n) for n in self.buffer]) def get(self, index): buf_index = math.floor(index / 8) return ((self.buffer[buf_index] >> (7 - index % 8)) & 1) == 1 def put(self, num, length): for i in range(length): self.put_bit(((num >> (length - i - 1)) & 1) == 1) def __len__(self): return self.length def put_bit(self, bit): buf_index = self.length // 8 if len(self.buffer) <= buf_index: self.buffer.append(0) if bit: self.buffer[buf_index] |= (0x80 >> (self.length % 8)) self.length += 1 def create_bytes(buffer, rs_blocks): offset = 0 maxDcCount = 0 maxEcCount = 0 dcdata = [0] * len(rs_blocks) ecdata = [0] * len(rs_blocks) for r in range(len(rs_blocks)): dcCount = rs_blocks[r].data_count ecCount = rs_blocks[r].total_count - dcCount maxDcCount = max(maxDcCount, dcCount) maxEcCount = max(maxEcCount, ecCount) dcdata[r] = [0] * dcCount for i in range(len(dcdata[r])): dcdata[r][i] = 0xff & buffer.buffer[i + offset] offset += dcCount # Get error correction polynomial. rsPoly = base.Polynomial([1], 0) for i in range(ecCount): rsPoly = rsPoly * base.Polynomial([1, base.gexp(i)], 0) rawPoly = base.Polynomial(dcdata[r], len(rsPoly) - 1) modPoly = rawPoly % rsPoly ecdata[r] = [0] * (len(rsPoly) - 1) for i in range(len(ecdata[r])): modIndex = i + len(modPoly) - len(ecdata[r]) if (modIndex >= 0): ecdata[r][i] = modPoly[modIndex] else: ecdata[r][i] = 0 totalCodeCount = 0 for rs_block in rs_blocks: totalCodeCount += rs_block.total_count data = [None] * totalCodeCount index = 0 for i in range(maxDcCount): for r in range(len(rs_blocks)): if i < len(dcdata[r]): data[index] = dcdata[r][i] index += 1 for i in range(maxEcCount): for r in range(len(rs_blocks)): if i < len(ecdata[r]): data[index] = ecdata[r][i] index += 1 return data def create_data(version, error_correction, data_list): buffer = BitBuffer() for data in data_list: buffer.put(data.mode, 4) buffer.put(len(data), length_in_bits(data.mode, version)) data.write(buffer) # Calculate the maximum number of bits for the given version. rs_blocks = base.rs_blocks(version, error_correction) bit_limit = 0 for block in rs_blocks: bit_limit += block.data_count * 8 if len(buffer) > bit_limit: raise exceptions.DataOverflowError( "Code length overflow. Data size (%s) > size available (%s)" % (len(buffer), bit_limit)) # Terminate the bits (add up to four 0s). for i in range(min(bit_limit - len(buffer), 4)): buffer.put_bit(False) # Delimit the string into 8-bit words, padding with 0s if necessary. delimit = len(buffer) % 8 if delimit: for i in range(8 - delimit): buffer.put_bit(False) # Add special alternating padding bitstrings until buffer is full. bytes_to_fill = (bit_limit - len(buffer)) // 8 for i in range(bytes_to_fill): if i % 2 == 0: buffer.put(PAD0, 8) else: buffer.put(PAD1, 8) return create_bytes(buffer, rs_blocks) qrcode-5.3/qrcode/base.py0000644000175000017500000001647312716766375013540 0ustar hlehlefrom qrcode import constants EXP_TABLE = list(range(256)) LOG_TABLE = list(range(256)) for i in range(8): EXP_TABLE[i] = 1 << i for i in range(8, 256): EXP_TABLE[i] = ( EXP_TABLE[i - 4] ^ EXP_TABLE[i - 5] ^ EXP_TABLE[i - 6] ^ EXP_TABLE[i - 8]) for i in range(255): LOG_TABLE[EXP_TABLE[i]] = i RS_BLOCK_OFFSET = { constants.ERROR_CORRECT_L: 0, constants.ERROR_CORRECT_M: 1, constants.ERROR_CORRECT_Q: 2, constants.ERROR_CORRECT_H: 3, } RS_BLOCK_TABLE = [ # L # M # Q # H # 1 [1, 26, 19], [1, 26, 16], [1, 26, 13], [1, 26, 9], # 2 [1, 44, 34], [1, 44, 28], [1, 44, 22], [1, 44, 16], # 3 [1, 70, 55], [1, 70, 44], [2, 35, 17], [2, 35, 13], # 4 [1, 100, 80], [2, 50, 32], [2, 50, 24], [4, 25, 9], # 5 [1, 134, 108], [2, 67, 43], [2, 33, 15, 2, 34, 16], [2, 33, 11, 2, 34, 12], # 6 [2, 86, 68], [4, 43, 27], [4, 43, 19], [4, 43, 15], # 7 [2, 98, 78], [4, 49, 31], [2, 32, 14, 4, 33, 15], [4, 39, 13, 1, 40, 14], # 8 [2, 121, 97], [2, 60, 38, 2, 61, 39], [4, 40, 18, 2, 41, 19], [4, 40, 14, 2, 41, 15], # 9 [2, 146, 116], [3, 58, 36, 2, 59, 37], [4, 36, 16, 4, 37, 17], [4, 36, 12, 4, 37, 13], # 10 [2, 86, 68, 2, 87, 69], [4, 69, 43, 1, 70, 44], [6, 43, 19, 2, 44, 20], [6, 43, 15, 2, 44, 16], # 11 [4, 101, 81], [1, 80, 50, 4, 81, 51], [4, 50, 22, 4, 51, 23], [3, 36, 12, 8, 37, 13], # 12 [2, 116, 92, 2, 117, 93], [6, 58, 36, 2, 59, 37], [4, 46, 20, 6, 47, 21], [7, 42, 14, 4, 43, 15], # 13 [4, 133, 107], [8, 59, 37, 1, 60, 38], [8, 44, 20, 4, 45, 21], [12, 33, 11, 4, 34, 12], # 14 [3, 145, 115, 1, 146, 116], [4, 64, 40, 5, 65, 41], [11, 36, 16, 5, 37, 17], [11, 36, 12, 5, 37, 13], # 15 [5, 109, 87, 1, 110, 88], [5, 65, 41, 5, 66, 42], [5, 54, 24, 7, 55, 25], [11, 36, 12, 7, 37, 13], # 16 [5, 122, 98, 1, 123, 99], [7, 73, 45, 3, 74, 46], [15, 43, 19, 2, 44, 20], [3, 45, 15, 13, 46, 16], # 17 [1, 135, 107, 5, 136, 108], [10, 74, 46, 1, 75, 47], [1, 50, 22, 15, 51, 23], [2, 42, 14, 17, 43, 15], # 18 [5, 150, 120, 1, 151, 121], [9, 69, 43, 4, 70, 44], [17, 50, 22, 1, 51, 23], [2, 42, 14, 19, 43, 15], # 19 [3, 141, 113, 4, 142, 114], [3, 70, 44, 11, 71, 45], [17, 47, 21, 4, 48, 22], [9, 39, 13, 16, 40, 14], # 20 [3, 135, 107, 5, 136, 108], [3, 67, 41, 13, 68, 42], [15, 54, 24, 5, 55, 25], [15, 43, 15, 10, 44, 16], # 21 [4, 144, 116, 4, 145, 117], [17, 68, 42], [17, 50, 22, 6, 51, 23], [19, 46, 16, 6, 47, 17], # 22 [2, 139, 111, 7, 140, 112], [17, 74, 46], [7, 54, 24, 16, 55, 25], [34, 37, 13], # 23 [4, 151, 121, 5, 152, 122], [4, 75, 47, 14, 76, 48], [11, 54, 24, 14, 55, 25], [16, 45, 15, 14, 46, 16], # 24 [6, 147, 117, 4, 148, 118], [6, 73, 45, 14, 74, 46], [11, 54, 24, 16, 55, 25], [30, 46, 16, 2, 47, 17], # 25 [8, 132, 106, 4, 133, 107], [8, 75, 47, 13, 76, 48], [7, 54, 24, 22, 55, 25], [22, 45, 15, 13, 46, 16], # 26 [10, 142, 114, 2, 143, 115], [19, 74, 46, 4, 75, 47], [28, 50, 22, 6, 51, 23], [33, 46, 16, 4, 47, 17], # 27 [8, 152, 122, 4, 153, 123], [22, 73, 45, 3, 74, 46], [8, 53, 23, 26, 54, 24], [12, 45, 15, 28, 46, 16], # 28 [3, 147, 117, 10, 148, 118], [3, 73, 45, 23, 74, 46], [4, 54, 24, 31, 55, 25], [11, 45, 15, 31, 46, 16], # 29 [7, 146, 116, 7, 147, 117], [21, 73, 45, 7, 74, 46], [1, 53, 23, 37, 54, 24], [19, 45, 15, 26, 46, 16], # 30 [5, 145, 115, 10, 146, 116], [19, 75, 47, 10, 76, 48], [15, 54, 24, 25, 55, 25], [23, 45, 15, 25, 46, 16], # 31 [13, 145, 115, 3, 146, 116], [2, 74, 46, 29, 75, 47], [42, 54, 24, 1, 55, 25], [23, 45, 15, 28, 46, 16], # 32 [17, 145, 115], [10, 74, 46, 23, 75, 47], [10, 54, 24, 35, 55, 25], [19, 45, 15, 35, 46, 16], # 33 [17, 145, 115, 1, 146, 116], [14, 74, 46, 21, 75, 47], [29, 54, 24, 19, 55, 25], [11, 45, 15, 46, 46, 16], # 34 [13, 145, 115, 6, 146, 116], [14, 74, 46, 23, 75, 47], [44, 54, 24, 7, 55, 25], [59, 46, 16, 1, 47, 17], # 35 [12, 151, 121, 7, 152, 122], [12, 75, 47, 26, 76, 48], [39, 54, 24, 14, 55, 25], [22, 45, 15, 41, 46, 16], # 36 [6, 151, 121, 14, 152, 122], [6, 75, 47, 34, 76, 48], [46, 54, 24, 10, 55, 25], [2, 45, 15, 64, 46, 16], # 37 [17, 152, 122, 4, 153, 123], [29, 74, 46, 14, 75, 47], [49, 54, 24, 10, 55, 25], [24, 45, 15, 46, 46, 16], # 38 [4, 152, 122, 18, 153, 123], [13, 74, 46, 32, 75, 47], [48, 54, 24, 14, 55, 25], [42, 45, 15, 32, 46, 16], # 39 [20, 147, 117, 4, 148, 118], [40, 75, 47, 7, 76, 48], [43, 54, 24, 22, 55, 25], [10, 45, 15, 67, 46, 16], # 40 [19, 148, 118, 6, 149, 119], [18, 75, 47, 31, 76, 48], [34, 54, 24, 34, 55, 25], [20, 45, 15, 61, 46, 16] ] def glog(n): if n < 1: # pragma: no cover raise ValueError("glog(%s)" % n) return LOG_TABLE[n] def gexp(n): return EXP_TABLE[n % 255] class Polynomial: def __init__(self, num, shift): if not num: # pragma: no cover raise Exception("%s/%s" % (len(num), shift)) offset = 0 for item in num: if item != 0: break offset += 1 self.num = [0] * (len(num) - offset + shift) for i in range(len(num) - offset): self.num[i] = num[i + offset] def __getitem__(self, index): return self.num[index] def __iter__(self): return iter(self.num) def __len__(self): return len(self.num) def __mul__(self, other): num = [0] * (len(self) + len(other) - 1) for i, item in enumerate(self): for j, other_item in enumerate(other): num[i + j] ^= gexp(glog(item) + glog(other_item)) return Polynomial(num, 0) def __mod__(self, other): difference = len(self) - len(other) if difference < 0: return self ratio = glog(self[0]) - glog(other[0]) num = self[:] num = [ item ^ gexp(glog(other_item) + ratio) for item, other_item in zip(self, other)] if difference: num.extend(self[-difference:]) # recursive call return Polynomial(num, 0) % other class RSBlock: def __init__(self, total_count, data_count): self.total_count = total_count self.data_count = data_count def rs_blocks(version, error_correction): if error_correction not in RS_BLOCK_OFFSET: # pragma: no cover raise Exception( "bad rs block @ version: %s / error_correction: %s" % (version, error_correction)) offset = RS_BLOCK_OFFSET[error_correction] rs_block = RS_BLOCK_TABLE[(version - 1) * 4 + offset] blocks = [] for i in range(0, len(rs_block), 3): count, total_count, data_count = rs_block[i:i + 3] for j in range(count): blocks.append(RSBlock(total_count, data_count)) return blocks qrcode-5.3/qrcode/image/0000755000175000017500000000000012716767167013323 5ustar hlehleqrcode-5.3/qrcode/image/pil.py0000644000175000017500000000267212651240657014454 0ustar hlehle# Needed on case-insensitive filesystems from __future__ import absolute_import # Try to import PIL in either of the two ways it can be installed. try: from PIL import Image, ImageDraw except ImportError: # pragma: no cover import Image import ImageDraw import qrcode.image.base class PilImage(qrcode.image.base.BaseImage): """ PIL image builder, default format is PNG. """ kind = "PNG" def new_image(self, **kwargs): back_color = kwargs.get("fill_color", "white") fill_color = kwargs.get("back_color", "black") if fill_color.lower() != "black" or back_color.lower() != "white": if back_color.lower() == "transparent": mode = "RGBA" back_color = None else: mode = "RGB" else: mode = "1" img = Image.new(mode, (self.pixel_size, self.pixel_size), back_color) self.fill_color = fill_color self._idr = ImageDraw.Draw(img) return img def drawrect(self, row, col): box = self.pixel_box(row, col) self._idr.rectangle(box, fill=self.fill_color) def save(self, stream, format=None, **kwargs): if format is None: format = kwargs.get("kind", self.kind) if "kind" in kwargs: del kwargs["kind"] self._img.save(stream, format=format, **kwargs) def __getattr__(self, name): return getattr(self._img, name) qrcode-5.3/qrcode/image/pure.py0000644000175000017500000000265412350137012014625 0ustar hlehlefrom pymaging import Image from pymaging.colors import RGB from pymaging.formats import registry from pymaging.shapes import Line from pymaging.webcolors import Black, White from pymaging_png.png import PNG import qrcode.image.base class PymagingImage(qrcode.image.base.BaseImage): """ pymaging image builder, default format is PNG. """ kind = "PNG" allowed_kinds = ("PNG",) def __init__(self, *args, **kwargs): """ Register PNG with pymaging. """ registry.formats = [] registry.names = {} registry._populate() registry.register(PNG) super(PymagingImage, self).__init__(*args, **kwargs) def new_image(self, **kwargs): return Image.new(RGB, self.pixel_size, self.pixel_size, White) def drawrect(self, row, col): (x, y), (x2, y2) = self.pixel_box(row, col) for r in range(self.box_size): line_y = y + r line = Line(x, line_y, x2, line_y) self._img.draw(line, Black) def save(self, stream, kind=None): self._img.save(stream, self.check_kind(kind)) def check_kind(self, kind, transform=None, **kwargs): """ pymaging (pymaging_png at least) uses lower case for the type. """ if transform is None: transform = lambda x: x.lower() return super(PymagingImage, self).check_kind( kind, transform=transform, **kwargs) qrcode-5.3/qrcode/image/svg.py0000644000175000017500000001122212350137012014440 0ustar hlehlefrom decimal import Decimal # On Python 2.6 must install lxml since the older xml.etree.ElementTree # version can not be used to create SVG images. try: import lxml.etree as ET except ImportError: import xml.etree.ElementTree as ET import qrcode.image.base class SvgFragmentImage(qrcode.image.base.BaseImage): """ SVG image builder Creates a QR-code image as a SVG document fragment. """ _SVG_namespace = "http://www.w3.org/2000/svg" kind = "SVG" allowed_kinds = ("SVG",) def __init__(self, *args, **kwargs): ET.register_namespace("svg", self._SVG_namespace) super(SvgFragmentImage, self).__init__(*args, **kwargs) # Save the unit size, for example the default box_size of 10 is '1mm'. self.unit_size = self.units(self.box_size) def drawrect(self, row, col): self._img.append(self._rect(row, col)) def units(self, pixels, text=True): """ A box_size of 10 (default) equals 1mm. """ units = Decimal(pixels) / 10 if not text: return units return '%smm' % units def save(self, stream, kind=None): self.check_kind(kind=kind) self._write(stream) def new_image(self, **kwargs): return self._svg() def _svg(self, tag=None, version='1.1', **kwargs): if tag is None: tag = ET.QName(self._SVG_namespace, "svg") dimension = self.units(self.pixel_size) return ET.Element( tag, width=dimension, height=dimension, version=version, **kwargs) def _rect(self, row, col, tag=None): if tag is None: tag = ET.QName(self._SVG_namespace, "rect") x, y = self.pixel_box(row, col)[0] return ET.Element( tag, x=self.units(x), y=self.units(y), width=self.unit_size, height=self.unit_size) def _write(self, stream): ET.ElementTree(self._img).write(stream, xml_declaration=False) class SvgImage(SvgFragmentImage): """ Standalone SVG image builder Creates a QR-code image as a standalone SVG document. """ background = None def _svg(self, tag='svg', **kwargs): svg = super(SvgImage, self)._svg(tag=tag, **kwargs) svg.set("xmlns", self._SVG_namespace) if self.background: svg.append( ET.Element( 'rect', fill=self.background, x='0', y='0', width='100%', height='100%')) return svg def _rect(self, row, col): return super(SvgImage, self)._rect(row, col, tag="rect") def _write(self, stream): ET.ElementTree(self._img).write(stream, encoding="UTF-8", xml_declaration=True) class SvgPathImage(SvgImage): """ SVG image builder with one single element (removes white spaces between individual QR points). """ QR_PATH_STYLE = 'fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none' def __init__(self, *args, **kwargs): self._points = set() super(SvgPathImage, self).__init__(*args, **kwargs) def _svg(self, viewBox=None, **kwargs): if viewBox is None: dimension = self.units(self.pixel_size, text=False) viewBox = '0 0 %(d)s %(d)s' % {'d': dimension} return super(SvgPathImage, self)._svg(viewBox=viewBox, **kwargs) def drawrect(self, row, col): # (x, y) self._points.add((col, row)) def _generate_subpaths(self): """Generates individual QR points as subpaths""" rect_size = self.units(self.box_size, text=False) for point in self._points: x_base = self.units( (point[0]+self.border)*self.box_size, text=False) y_base = self.units( (point[1]+self.border)*self.box_size, text=False) yield ( 'M %(x0)s %(y0)s L %(x0)s %(y1)s L %(x1)s %(y1)s L %(x1)s ' '%(y0)s z' % dict( x0=x_base, y0=y_base, x1=x_base+rect_size, y1=y_base+rect_size, )) def make_path(self): subpaths = self._generate_subpaths() return ET.Element( ET.QName("path"), style=self.QR_PATH_STYLE, d=' '.join(subpaths), id="qr-path" ) def _write(self, stream): self._img.append(self.make_path()) super(SvgPathImage, self)._write(stream) class SvgFillImage(SvgImage): """ An SvgImage that fills the background to white. """ background = 'white' class SvgPathFillImage(SvgPathImage): """ An SvgPathImage that fills the background to white. """ background = 'white' qrcode-5.3/qrcode/image/base.py0000644000175000017500000000352712672061171014575 0ustar hlehleclass BaseImage(object): """ Base QRCode image output class. """ kind = None allowed_kinds = None def __init__(self, border, width, box_size, *args, **kwargs): self.border = border self.width = width self.box_size = box_size self.pixel_size = (self.width + self.border*2) * self.box_size self._img = self.new_image(**kwargs) def drawrect(self, row, col): """ Draw a single rectangle of the QR code. """ raise NotImplementedError("BaseImage.drawrect") def save(self, stream, kind=None): """ Save the image file. """ raise NotImplementedError("BaseImage.save") def pixel_box(self, row, col): """ A helper method for pixel-based image generators that specifies the four pixel coordinates for a single rect. """ x = (col + self.border) * self.box_size y = (row + self.border) * self.box_size return [(x, y), (x + self.box_size - 1, y + self.box_size - 1)] def new_image(self, **kwargs): # pragma: no cover """ Build the image class. Subclasses should return the class created. """ return None def get_image(self, **kwargs): """ Return the image class for further processing. """ return self._img def check_kind(self, kind, transform=None): """ Get the image type. """ if kind is None: kind = self.kind allowed = not self.allowed_kinds or kind in self.allowed_kinds if transform: kind = transform(kind) if not allowed: allowed = kind in self.allowed_kinds if not allowed: raise ValueError( "Cannot set %s type to %s" % (type(self).__name__, kind)) return kind qrcode-5.3/qrcode/image/__init__.py0000644000175000017500000000000012350137012015370 0ustar hlehleqrcode-5.3/qrcode/constants.py0000644000175000017500000000015212350137012014573 0ustar hlehle# QR error correct levels ERROR_CORRECT_L = 1 ERROR_CORRECT_M = 0 ERROR_CORRECT_Q = 3 ERROR_CORRECT_H = 2 qrcode-5.3/qrcode/__init__.py0000644000175000017500000000116612647555462014352 0ustar hlehlefrom qrcode.main import QRCode from qrcode.main import make # noqa from qrcode.constants import ( # noqa ERROR_CORRECT_L, ERROR_CORRECT_M, ERROR_CORRECT_Q, ERROR_CORRECT_H) from qrcode import image # noqa def run_example(data="http://www.lincolnloop.com", *args, **kwargs): """ Build an example QR Code and display it. There's an even easier way than the code here though: just use the ``make`` shortcut. """ qr = QRCode(*args, **kwargs) qr.add_data(data) im = qr.make_image() im.show() if __name__ == '__main__': # pragma: no cover import sys run_example(*sys.argv[1:]) qrcode-5.3/qrcode/exceptions.py0000644000175000017500000000005512350137012014742 0ustar hlehleclass DataOverflowError(Exception): pass qrcode-5.3/qrcode.egg-info/0000755000175000017500000000000012716767167013733 5ustar hlehleqrcode-5.3/qrcode.egg-info/requires.txt0000644000175000017500000000000412716767167016325 0ustar hlehlesix qrcode-5.3/qrcode.egg-info/entry_points.txt0000644000175000017500000000006412716767167017231 0ustar hlehle[console_scripts] qr = qrcode.console_scripts:main qrcode-5.3/qrcode.egg-info/pbr.json0000644000175000017500000000005712651245573015401 0ustar hlehle{"git_version": "a2e3516", "is_release": false}qrcode-5.3/qrcode.egg-info/dependency_links.txt0000644000175000017500000000000112716767167020001 0ustar hlehle qrcode-5.3/qrcode.egg-info/PKG-INFO0000644000175000017500000003164512716767167015041 0ustar hlehleMetadata-Version: 1.1 Name: qrcode Version: 5.3 Summary: QR Code image generator Home-page: https://github.com/lincolnloop/python-qrcode Author: Lincoln Loop Author-email: info@lincolnloop.com License: BSD Description: ============================= Pure python QR Code generator ============================= This module uses image libraries, Python Imaging Library (PIL) by default, to generate QR Codes. It is recommended to use the pillow_ fork rather than PIL itself. .. _pillow: https://pypi.python.org/pypi/Pillow What is a QR Code? ================== A Quick Response code is a two-dimensional pictographic code used for its fast readability and comparatively large storage capacity. The code consists of black modules arranged in a square pattern on a white background. The information encoded can be made up of any kind of data (e.g., binary, alphanumeric, or Kanji symbols) Usage ===== From the command line, use the installed ``qr`` script:: qr "Some text" > test.png Or in Python, use the ``make`` shortcut function:: import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example:: import qrcode qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) qr.add_data('Some data') qr.make(fit=True) img = qr.make_image() The ``version`` parameter is an integer from 1 to 40 that controls the size of the QR Code (the smallest, version 1, is a 21x21 matrix). Set to ``None`` and use the ``fit`` parameter when making the code to determine this automatically. The ``error_correction`` parameter controls the error correction used for the QR Code. The following four constants are made available on the ``qrcode`` package: ``ERROR_CORRECT_L`` About 7% or less errors can be corrected. ``ERROR_CORRECT_M`` (default) About 15% or less errors can be corrected. ``ERROR_CORRECT_Q`` About 25% or less errors can be corrected. ``ERROR_CORRECT_H``. About 30% or less errors can be corrected. The ``box_size`` parameter controls how many pixels each "box" of the QR code is. The ``border`` parameter controls how many boxes thick the border should be (the default is 4, which is the minimum according to the specs). Other image factories ===================== You can encode as SVG, or use a new pure Python image processor to encode to PNG images. The Python examples below use the ``make`` shortcut. The same ``image_factory`` keyword argument is a valid option for the ``QRCode`` class for more advanced usage. SVG --- On Python 2.6 must install lxml since the older xml.etree.ElementTree version can not be used to create SVG images. You can create the entire SVG or an SVG fragment. When building an entire SVG image, you can use the factory that combines as a path (recommended, and default for the script) or a factory that creates a simple set of rectangles. From your command line:: qr --factory=svg-path "Some text" > test.svg qr --factory=svg "Some text" > test.svg qr --factory=svg-fragment "Some text" > test.svg Or in Python:: import qrcode import qrcode.image.svg if method == 'basic': # Simple factory, just a set of rects. factory = qrcode.image.svg.SvgImage elif method == 'fragment': # Fragment factory (also just a set of rects) factory = qrcode.image.svg.SvgFragmentImage else: # Combined path factory, fixes white space that may occur when zooming factory = qrcode.image.svg.SvgPathImage img = qrcode.make('Some data here', image_factory=factory) Two other related factories are available that work the same, but also fill the background of the SVG with white:: qrcode.image.svg.SvgFillImage qrcode.image.svg.SvgPathFillImage Pure Python PNG --------------- Install the following two packages:: pip install git+git://github.com/ojii/pymaging.git#egg=pymaging pip install git+git://github.com/ojii/pymaging-png.git#egg=pymaging-png From your command line:: qr --factory=pymaging "Some text" > test.png Or in Python:: import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) ========== Change log ========== Version 5.3 =========== * Fix incomplete block table for QR version 15. Thanks Rodrigo Queiro for the report and Jacob Welsh for the investigation and fix. * Avoid unnecessary dependency for non MS platforms, thanks to Noah Vesely. * Make ``BaseImage.get_image()`` actually work. Version 5.2 =========== * Add ``--error-correction`` option to qr script. * Fix script piping to stdout in Python 3 and reading non-UTF-8 characters in Python 3. * Fix script piping in Windows. * Add some useful behind-the-curtain methods for tinkerers. * Fix terminal output when using Python 2.6 * Fix terminal output to display correctly on MS command line. Version 5.2.1 ------------- * Small fix to terminal output in Python 3 (and fix tests) Version 5.2.2 ------------- * Revert some terminal changes from 5.2 that broke Python 3's real life tty code generation and introduce a better way from Jacob Welsh. Version 5.1 =========== * Make ``qr`` script work in Windows. Thanks Ionel Cristian Mărieș * Fixed print_ascii function in Python 3. * Out-of-bounds code version numbers are handled more consistently with a ValueError. * Much better test coverage (now only officially supporting Python 2.6+) Version 5.0 =========== * Speed optimizations. * Change the output when using the ``qr`` script to use ASCII rather than just colors, better using the terminal real estate. * Fix a bug in passing bytecode data directly when in Python 3. * Substation speed optimizations to best-fit algorithm (thanks Jacob Welsh!). * Introduce a ``print_ascii`` method and use it as the default for the ``qr`` script rather than ``print_tty``. Version 5.0.1 ------------- * Update version numbers correctly. Version 4.0 =========== * Made qrcode work on Python 2.4 - Thanks tcely. Note: officially, qrcode only supports 2.5+. * Support pure-python PNG generation (via pymaging) for Python 2.6+ -- thanks Adam Wisniewski! * SVG image generation now supports alternate sizing (the default box size of 10 == 1mm per rectangle). * SVG path image generation allows cleaner SVG output by combining all QR rects into a single path. Thank you, Viktor Stískala. * Added some extra simple SVG factories that fill the background white. Version 4.0.1 ------------- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! Version 4.0.2 ------------- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. Version 4.0.3 ------------- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. Version 4.0.4 ------------- * Bad version number for previous hotfix release. Version 3.1 =========== * Important fixes for incorrect matches of the alpha-numeric encoding mode. Previously, the pattern would match if a single line was alpha-numeric only (even if others wern't). Also, the two characters ``{`` and ``}`` had snuck in as valid characters. Thanks to Eran Tromer for the report and fix. * Optimized chunking -- if the parts of the data stream can be encoded more efficiently, the data will be split into chunks of the most efficient modes. Version 3.1.1 ------------- * Update change log to contain version 3.1 changes. :P * Give the ``qr`` script an ``--optimize`` argument to control the chunk optimization setting. Version 3.0 =========== * Python 3 support. * Add QRCode.get_matrix, an easy way to get the matrix array of a QR code including the border. Thanks Hugh Rawlinson. * Add in a workaround so that Python 2.6 users can use SVG generation (they must install ``lxml``). * Some initial tests! And tox support (``pip install tox``) for testing across Python platforms. Version 2.7 =========== * Fix incorrect termination padding. Version 2.6 =========== * Fix the first four columns incorrectly shifted by one. Thanks to Josep Gómez-Suay for the report and fix. * Fix strings within 4 bits of the QR version limit being incorrectly terminated. Thanks to zhjie231 for the report. Version 2.5 =========== * The PilImage wrapper is more transparent - you can use any methods or attributes available to the underlying PIL Image instance. * Fixed the first column of the QR Code coming up empty! Thanks to BecoKo. Version 2.5.1 ------------- * Fix installation error on Windows. Version 2.4 =========== * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. Version 2.4.1 ------------- * Fix a packaging issue Version 2.4.2 ------------- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. Version 2.3 =========== * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). Version 2.3.1 ------------- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. Version 2.2 =========== * Fixed tty output to work on both white and black backgrounds. * Added `border` parameter to allow customizing of the number of boxes used to create the border of the QR code Version 2.1 =========== * Added a ``qr`` script which can be used to output a qr code to the tty using background colors, or to a file via a pipe. Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Topic :: Multimedia :: Graphics Classifier: Topic :: Software Development :: Libraries :: Python Modules qrcode-5.3/qrcode.egg-info/SOURCES.txt0000644000175000017500000000123712716767167015622 0ustar hlehleCHANGES.rst LICENSE MANIFEST.in PACKAGING.rst README.rst TESTING.rst setup.cfg setup.py doc/qr.1 qrcode/__init__.py qrcode/base.py qrcode/console_scripts.py qrcode/constants.py qrcode/exceptions.py qrcode/main.py qrcode/util.py qrcode.egg-info/PKG-INFO qrcode.egg-info/SOURCES.txt qrcode.egg-info/dependency_links.txt qrcode.egg-info/entry_points.txt qrcode.egg-info/pbr.json qrcode.egg-info/requires.txt qrcode.egg-info/top_level.txt qrcode/image/__init__.py qrcode/image/base.py qrcode/image/pil.py qrcode/image/pure.py qrcode/image/svg.py qrcode/tests/__init__.py qrcode/tests/svg.py qrcode/tests/test_example.py qrcode/tests/test_qrcode.py qrcode/tests/test_script.pyqrcode-5.3/qrcode.egg-info/top_level.txt0000644000175000017500000000000712716767167016462 0ustar hlehleqrcode qrcode-5.3/setup.cfg0000644000175000017500000000013012716767167012577 0ustar hlehle[bdist_wheel] universal = 1 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 qrcode-5.3/doc/0000755000175000017500000000000012716767167011531 5ustar hlehleqrcode-5.3/doc/qr.10000644000175000017500000000245112716767130012225 0ustar hlehle.\" Manpage for qr .TH QR 1 "25 Jun 2013" "5.3" "Python QR tool" .SH NAME qr \- script to create QR codes at the command line .SH SYNOPSIS qr [\-\-help] [\-\-factory=FACTORY] [\-\-optimize=OPTIMIZE] [\-\-error\-correction=LEVEL] [data] .SH DESCRIPTION This script uses the python qrcode module. It can take data from stdin or from the commandline and generate a QR code. Normally it will output the QR code as ascii art to the terminal. If the output is piped to a file, it will output the image (default type of PNG). .SH OPTIONS .PP \fB\ \-h, \-\-help\fR .RS 4 Show a help message. .RE .PP \fB\ \-\-factory=FACTORY\fR .RS 4 Full python path to the image factory class to create the image with. You can use the following shortcuts to the built-in image factory classes: pil (default), pymaging, svg, svg-fragment, svg-path. .RE .PP \fB\ \-\-optimize=OPTIMIZE\fR .RS 4 Optimize the data by looking for chunks of at least this many characters that could use a more efficient encoding method. Use 0 to turn off chunk optimization. .RE .PP \fB\ \-\-error\-correction=LEVEL\fR .RS 4 The error correction level to use. Choices are L (7%), M (15%, default), Q (25%), and H (30%). .RE .PP \fB\ data\fR .RS 4 The data from which the QR code will be generated. .RE .SH SEE ALSO https://github.com/lincolnloop/python-qrcode/ qrcode-5.3/CHANGES.rst0000644000175000017500000001236112716767044012563 0ustar hlehle========== Change log ========== Version 5.3 =========== * Fix incomplete block table for QR version 15. Thanks Rodrigo Queiro for the report and Jacob Welsh for the investigation and fix. * Avoid unnecessary dependency for non MS platforms, thanks to Noah Vesely. * Make ``BaseImage.get_image()`` actually work. Version 5.2 =========== * Add ``--error-correction`` option to qr script. * Fix script piping to stdout in Python 3 and reading non-UTF-8 characters in Python 3. * Fix script piping in Windows. * Add some useful behind-the-curtain methods for tinkerers. * Fix terminal output when using Python 2.6 * Fix terminal output to display correctly on MS command line. Version 5.2.1 ------------- * Small fix to terminal output in Python 3 (and fix tests) Version 5.2.2 ------------- * Revert some terminal changes from 5.2 that broke Python 3's real life tty code generation and introduce a better way from Jacob Welsh. Version 5.1 =========== * Make ``qr`` script work in Windows. Thanks Ionel Cristian Mărieș * Fixed print_ascii function in Python 3. * Out-of-bounds code version numbers are handled more consistently with a ValueError. * Much better test coverage (now only officially supporting Python 2.6+) Version 5.0 =========== * Speed optimizations. * Change the output when using the ``qr`` script to use ASCII rather than just colors, better using the terminal real estate. * Fix a bug in passing bytecode data directly when in Python 3. * Substation speed optimizations to best-fit algorithm (thanks Jacob Welsh!). * Introduce a ``print_ascii`` method and use it as the default for the ``qr`` script rather than ``print_tty``. Version 5.0.1 ------------- * Update version numbers correctly. Version 4.0 =========== * Made qrcode work on Python 2.4 - Thanks tcely. Note: officially, qrcode only supports 2.5+. * Support pure-python PNG generation (via pymaging) for Python 2.6+ -- thanks Adam Wisniewski! * SVG image generation now supports alternate sizing (the default box size of 10 == 1mm per rectangle). * SVG path image generation allows cleaner SVG output by combining all QR rects into a single path. Thank you, Viktor Stískala. * Added some extra simple SVG factories that fill the background white. Version 4.0.1 ------------- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! Version 4.0.2 ------------- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. Version 4.0.3 ------------- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. Version 4.0.4 ------------- * Bad version number for previous hotfix release. Version 3.1 =========== * Important fixes for incorrect matches of the alpha-numeric encoding mode. Previously, the pattern would match if a single line was alpha-numeric only (even if others wern't). Also, the two characters ``{`` and ``}`` had snuck in as valid characters. Thanks to Eran Tromer for the report and fix. * Optimized chunking -- if the parts of the data stream can be encoded more efficiently, the data will be split into chunks of the most efficient modes. Version 3.1.1 ------------- * Update change log to contain version 3.1 changes. :P * Give the ``qr`` script an ``--optimize`` argument to control the chunk optimization setting. Version 3.0 =========== * Python 3 support. * Add QRCode.get_matrix, an easy way to get the matrix array of a QR code including the border. Thanks Hugh Rawlinson. * Add in a workaround so that Python 2.6 users can use SVG generation (they must install ``lxml``). * Some initial tests! And tox support (``pip install tox``) for testing across Python platforms. Version 2.7 =========== * Fix incorrect termination padding. Version 2.6 =========== * Fix the first four columns incorrectly shifted by one. Thanks to Josep Gómez-Suay for the report and fix. * Fix strings within 4 bits of the QR version limit being incorrectly terminated. Thanks to zhjie231 for the report. Version 2.5 =========== * The PilImage wrapper is more transparent - you can use any methods or attributes available to the underlying PIL Image instance. * Fixed the first column of the QR Code coming up empty! Thanks to BecoKo. Version 2.5.1 ------------- * Fix installation error on Windows. Version 2.4 =========== * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. Version 2.4.1 ------------- * Fix a packaging issue Version 2.4.2 ------------- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. Version 2.3 =========== * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). Version 2.3.1 ------------- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. Version 2.2 =========== * Fixed tty output to work on both white and black backgrounds. * Added `border` parameter to allow customizing of the number of boxes used to create the border of the QR code Version 2.1 =========== * Added a ``qr`` script which can be used to output a qr code to the tty using background colors, or to a file via a pipe. qrcode-5.3/PKG-INFO0000644000175000017500000003164512716767167012072 0ustar hlehleMetadata-Version: 1.1 Name: qrcode Version: 5.3 Summary: QR Code image generator Home-page: https://github.com/lincolnloop/python-qrcode Author: Lincoln Loop Author-email: info@lincolnloop.com License: BSD Description: ============================= Pure python QR Code generator ============================= This module uses image libraries, Python Imaging Library (PIL) by default, to generate QR Codes. It is recommended to use the pillow_ fork rather than PIL itself. .. _pillow: https://pypi.python.org/pypi/Pillow What is a QR Code? ================== A Quick Response code is a two-dimensional pictographic code used for its fast readability and comparatively large storage capacity. The code consists of black modules arranged in a square pattern on a white background. The information encoded can be made up of any kind of data (e.g., binary, alphanumeric, or Kanji symbols) Usage ===== From the command line, use the installed ``qr`` script:: qr "Some text" > test.png Or in Python, use the ``make`` shortcut function:: import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example:: import qrcode qr = qrcode.QRCode( version=1, error_correction=qrcode.constants.ERROR_CORRECT_L, box_size=10, border=4, ) qr.add_data('Some data') qr.make(fit=True) img = qr.make_image() The ``version`` parameter is an integer from 1 to 40 that controls the size of the QR Code (the smallest, version 1, is a 21x21 matrix). Set to ``None`` and use the ``fit`` parameter when making the code to determine this automatically. The ``error_correction`` parameter controls the error correction used for the QR Code. The following four constants are made available on the ``qrcode`` package: ``ERROR_CORRECT_L`` About 7% or less errors can be corrected. ``ERROR_CORRECT_M`` (default) About 15% or less errors can be corrected. ``ERROR_CORRECT_Q`` About 25% or less errors can be corrected. ``ERROR_CORRECT_H``. About 30% or less errors can be corrected. The ``box_size`` parameter controls how many pixels each "box" of the QR code is. The ``border`` parameter controls how many boxes thick the border should be (the default is 4, which is the minimum according to the specs). Other image factories ===================== You can encode as SVG, or use a new pure Python image processor to encode to PNG images. The Python examples below use the ``make`` shortcut. The same ``image_factory`` keyword argument is a valid option for the ``QRCode`` class for more advanced usage. SVG --- On Python 2.6 must install lxml since the older xml.etree.ElementTree version can not be used to create SVG images. You can create the entire SVG or an SVG fragment. When building an entire SVG image, you can use the factory that combines as a path (recommended, and default for the script) or a factory that creates a simple set of rectangles. From your command line:: qr --factory=svg-path "Some text" > test.svg qr --factory=svg "Some text" > test.svg qr --factory=svg-fragment "Some text" > test.svg Or in Python:: import qrcode import qrcode.image.svg if method == 'basic': # Simple factory, just a set of rects. factory = qrcode.image.svg.SvgImage elif method == 'fragment': # Fragment factory (also just a set of rects) factory = qrcode.image.svg.SvgFragmentImage else: # Combined path factory, fixes white space that may occur when zooming factory = qrcode.image.svg.SvgPathImage img = qrcode.make('Some data here', image_factory=factory) Two other related factories are available that work the same, but also fill the background of the SVG with white:: qrcode.image.svg.SvgFillImage qrcode.image.svg.SvgPathFillImage Pure Python PNG --------------- Install the following two packages:: pip install git+git://github.com/ojii/pymaging.git#egg=pymaging pip install git+git://github.com/ojii/pymaging-png.git#egg=pymaging-png From your command line:: qr --factory=pymaging "Some text" > test.png Or in Python:: import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) ========== Change log ========== Version 5.3 =========== * Fix incomplete block table for QR version 15. Thanks Rodrigo Queiro for the report and Jacob Welsh for the investigation and fix. * Avoid unnecessary dependency for non MS platforms, thanks to Noah Vesely. * Make ``BaseImage.get_image()`` actually work. Version 5.2 =========== * Add ``--error-correction`` option to qr script. * Fix script piping to stdout in Python 3 and reading non-UTF-8 characters in Python 3. * Fix script piping in Windows. * Add some useful behind-the-curtain methods for tinkerers. * Fix terminal output when using Python 2.6 * Fix terminal output to display correctly on MS command line. Version 5.2.1 ------------- * Small fix to terminal output in Python 3 (and fix tests) Version 5.2.2 ------------- * Revert some terminal changes from 5.2 that broke Python 3's real life tty code generation and introduce a better way from Jacob Welsh. Version 5.1 =========== * Make ``qr`` script work in Windows. Thanks Ionel Cristian Mărieș * Fixed print_ascii function in Python 3. * Out-of-bounds code version numbers are handled more consistently with a ValueError. * Much better test coverage (now only officially supporting Python 2.6+) Version 5.0 =========== * Speed optimizations. * Change the output when using the ``qr`` script to use ASCII rather than just colors, better using the terminal real estate. * Fix a bug in passing bytecode data directly when in Python 3. * Substation speed optimizations to best-fit algorithm (thanks Jacob Welsh!). * Introduce a ``print_ascii`` method and use it as the default for the ``qr`` script rather than ``print_tty``. Version 5.0.1 ------------- * Update version numbers correctly. Version 4.0 =========== * Made qrcode work on Python 2.4 - Thanks tcely. Note: officially, qrcode only supports 2.5+. * Support pure-python PNG generation (via pymaging) for Python 2.6+ -- thanks Adam Wisniewski! * SVG image generation now supports alternate sizing (the default box size of 10 == 1mm per rectangle). * SVG path image generation allows cleaner SVG output by combining all QR rects into a single path. Thank you, Viktor Stískala. * Added some extra simple SVG factories that fill the background white. Version 4.0.1 ------------- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! Version 4.0.2 ------------- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. Version 4.0.3 ------------- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. Version 4.0.4 ------------- * Bad version number for previous hotfix release. Version 3.1 =========== * Important fixes for incorrect matches of the alpha-numeric encoding mode. Previously, the pattern would match if a single line was alpha-numeric only (even if others wern't). Also, the two characters ``{`` and ``}`` had snuck in as valid characters. Thanks to Eran Tromer for the report and fix. * Optimized chunking -- if the parts of the data stream can be encoded more efficiently, the data will be split into chunks of the most efficient modes. Version 3.1.1 ------------- * Update change log to contain version 3.1 changes. :P * Give the ``qr`` script an ``--optimize`` argument to control the chunk optimization setting. Version 3.0 =========== * Python 3 support. * Add QRCode.get_matrix, an easy way to get the matrix array of a QR code including the border. Thanks Hugh Rawlinson. * Add in a workaround so that Python 2.6 users can use SVG generation (they must install ``lxml``). * Some initial tests! And tox support (``pip install tox``) for testing across Python platforms. Version 2.7 =========== * Fix incorrect termination padding. Version 2.6 =========== * Fix the first four columns incorrectly shifted by one. Thanks to Josep Gómez-Suay for the report and fix. * Fix strings within 4 bits of the QR version limit being incorrectly terminated. Thanks to zhjie231 for the report. Version 2.5 =========== * The PilImage wrapper is more transparent - you can use any methods or attributes available to the underlying PIL Image instance. * Fixed the first column of the QR Code coming up empty! Thanks to BecoKo. Version 2.5.1 ------------- * Fix installation error on Windows. Version 2.4 =========== * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. Version 2.4.1 ------------- * Fix a packaging issue Version 2.4.2 ------------- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. Version 2.3 =========== * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). Version 2.3.1 ------------- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. Version 2.2 =========== * Fixed tty output to work on both white and black backgrounds. * Added `border` parameter to allow customizing of the number of boxes used to create the border of the QR code Version 2.1 =========== * Added a ``qr`` script which can be used to output a qr code to the tty using background colors, or to a file via a pipe. Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Intended Audience :: Developers Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Topic :: Multimedia :: Graphics Classifier: Topic :: Software Development :: Libraries :: Python Modules qrcode-5.3/LICENSE0000644000175000017500000000413712350137012011744 0ustar hlehleCopyright (c) 2011, Lincoln Loop All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the package name nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- Original text and license from the pyqrnative package where this was forked from (http://code.google.com/p/pyqrnative): #Ported from the Javascript library by Sam Curren # #QRCode for Javascript #http://d-project.googlecode.com/svn/trunk/misc/qrcode/js/qrcode.js # #Copyright (c) 2009 Kazuhiko Arase # #URL: http://www.d-project.com/ # #Licensed under the MIT license: # http://www.opensource.org/licenses/mit-license.php # # The word "QR Code" is registered trademark of # DENSO WAVE INCORPORATED # http://www.denso-wave.com/qrcode/faqpatent-e.html qrcode-5.3/MANIFEST.in0000644000175000017500000000003712350137012012470 0ustar hlehleinclude LICENSE *.rst doc/qr.1 qrcode-5.3/TESTING.rst0000644000175000017500000000116312350137012012602 0ustar hlehleTesting ======= First, install tox into your virtualenv:: pip install -U tox To run all the qrcode tests, you'll need to install the older Python interpreters. Here's how you'll do it on a modern Ubuntu distribution:: sudo add-apt-repository ppa:fkrull/deadsnakes sudo apt-get update sudo apt-get install python2.4-dev python2.6-dev Ensure you have the libraries to build PIL, too:: sudo apt-get install build-essential python-dev python3-dev sudo apt-get install libjpeg8-dev zlib1g-dev Finally, just run ``tox``! If you want, you can test against a specific version like this: ``tox -e py33`` qrcode-5.3/PACKAGING.rst0000644000175000017500000000067512651252506012772 0ustar hlehlePackaging quick reminder ======================== Ensure version numbers in ``setup.py`` and ``doc/qr.1`` have been updated. 1. Check twine and wheel are up to date:: pip install --upgrade twine wheel 2. Delete contents of ``dist/``:: rm -r dist 3. Package it up:: python setup.py sdist bdist_wheel 4. Sign it:: gpg --detach-sign -a dist/*.gz gpg --detach-sign -a dist/*.whl 5. Upload it:: twine upload dist/*