qrcode-6.1/0000755000175000017500000000000013416752765013117 5ustar chrischris00000000000000qrcode-6.1/setup.cfg0000644000175000017500000000277513416752765014753 0ustar chrischris00000000000000[metadata] name = qrcode version = 6.1 description = QR Code image generator long_description = file: README.rst, CHANGES.rst author = Lincoln Loop author_email = info@lincolnloop.com url = https://github.com/lincolnloop/python-qrcode keywords = qr denso-wave IEC18004 license = BSD 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.7 Programming Language :: Python :: 3.4 Programming Language :: Python :: 3.5 Programming Language :: Python :: 3.6 Topic :: Multimedia :: Graphics Topic :: Software Development :: Libraries :: Python Modules [options] zip_safe = False include_package_data = True packages = find: install_requires = six colorama;platform_system=="Windows" [options.extras_require] maintainer = zest.releaser[recommended] dev = tox pytest mock;python_version<"3" test = pytest pytest-cov mock;python_version<"3" pil = pillow [options.entry_points] console-scripts = qr = qrcode.console_scripts:main [bdist_wheel] universal = 1 [flake8] exclude = .tox .git __pycache__ build dist [coverage:run] source = qrcode [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 [tool:pytest] filterwarnings = module [egg_info] tag_build = tag_date = 0 qrcode-6.1/PACKAGING.rst0000644000175000017500000000067513416752764015144 0ustar chrischris00000000000000Packaging 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/* qrcode-6.1/setup.py0000644000175000017500000000022313416752764014625 0ustar chrischris00000000000000#!/usr/bin/env python from setuptools import setup # See setup.cfg for configuration. setup( data_files=[('share/man/man1', ['doc/qr.1'])], ) qrcode-6.1/README.rst0000644000175000017500000001014213416752764014603 0ustar chrischris00000000000000============================= Pure python QR Code generator ============================= Generate QR codes. For a standard install (which will include pillow_ for generating images), run:: pip install qrcode[pil] .. _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: .. code:: python import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example: .. code:: python 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(fill_color="black", back_color="white") 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. ``fill_color`` and ``back_color`` can change the background and the painting color of the QR, when using the default image factory. 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 --- 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: .. code:: 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: .. code:: python import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) qrcode-6.1/TESTING.rst0000644000175000017500000000114413416752764014765 0ustar chrischris00000000000000Testing ======= First, install tox into your virtualenv:: pip install --upgrade tox To run all tests, you'll need to install multiple Python interpreters. On a modern Ubuntu distribution you can use ``add-apt-repository ppa:deadsnakes/ppa``. Depending on if you can install the wheels directly for your OS, you may need 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 Finally, just run ``tox``! If you want, you can test against a specific version like this: ``tox -e py36`` qrcode-6.1/qrcode.egg-info/0000755000175000017500000000000013416752765016066 5ustar chrischris00000000000000qrcode-6.1/qrcode.egg-info/dependency_links.txt0000644000175000017500000000000113416752764022133 0ustar chrischris00000000000000 qrcode-6.1/qrcode.egg-info/entry_points.txt0000644000175000017500000000006413416752764021363 0ustar chrischris00000000000000[console_scripts] qr = qrcode.console_scripts:main qrcode-6.1/qrcode.egg-info/not-zip-safe0000644000175000017500000000000113416752764020313 0ustar chrischris00000000000000 qrcode-6.1/qrcode.egg-info/PKG-INFO0000644000175000017500000003320613416752764017166 0ustar chrischris00000000000000Metadata-Version: 2.1 Name: qrcode Version: 6.1 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 ============================= Generate QR codes. For a standard install (which will include pillow_ for generating images), run:: pip install qrcode[pil] .. _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: .. code:: python import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example: .. code:: python 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(fill_color="black", back_color="white") 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. ``fill_color`` and ``back_color`` can change the background and the painting color of the QR, when using the default image factory. 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 --- 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: .. code:: 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: .. code:: python import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) ========== Change log ========== 6.1 (14 January 2019) ===================== - Fix short chunks of data not being optimized to the correct mode. - Tests fixed for Python 3 6.0 (23 March 2018) =================== - Fix optimize length being ignored in ``QRCode.add_data``. - Better calculation of the best mask pattern and related optimizations. Big thanks to cryptogun! 5.3 (18 May 2016) ================= * 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. 5.2 (25 Jan 2016) ================= * 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. 5.2.1 ----- * Small fix to terminal output in Python 3 (and fix tests) 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. 5.1 (22 Oct 2014) ================= * 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+) 5.0 (17 Jun 2014) ================= * 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``. 5.0.1 ----- * Update version numbers correctly. 4.0 (4 Sep 2013) ================ * 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. 4.0.1 ----- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! 4.0.2 ----- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. 4.0.3 ----- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. 4.0.4 ----- * Bad version number for previous hotfix release. 3.1 (12 Aug 2013) ================= * 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. 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. 3.0 (25 Jun 2013) ================= * 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. 2.7 (5 Mar 2013) ================ * Fix incorrect termination padding. 2.6 (2 Apr 2013) ================ * 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. 2.5 (12 Mar 2013) ================= * 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. 2.5.1 ----- * Fix installation error on Windows. 2.4 (23 Apr 2012) ================= * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. 2.4.1 ----- * Fix a packaging issue 2.4.2 ----- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. 2.3 (29 Jan 2012) ================= * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). 2.3.1 ----- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. 2.2 (18 Jan 2012) ================= * 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 2.1 (17 Jan 2012) ================= * 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. Keywords: qr denso-wave IEC18004 Platform: UNKNOWN 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.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Multimedia :: Graphics Classifier: Topic :: Software Development :: Libraries :: Python Modules Provides-Extra: test Provides-Extra: dev Provides-Extra: pil Provides-Extra: maintainer qrcode-6.1/qrcode.egg-info/top_level.txt0000644000175000017500000000000713416752764020614 0ustar chrischris00000000000000qrcode qrcode-6.1/qrcode.egg-info/requires.txt0000644000175000017500000000032413416752764020464 0ustar chrischris00000000000000six [:platform_system == "Windows"] colorama [dev] tox pytest [dev:python_version < "3"] mock [maintainer] zest.releaser[recommended] [pil] pillow [test] pytest pytest-cov [test:python_version < "3"] mock qrcode-6.1/qrcode.egg-info/SOURCES.txt0000644000175000017500000000137013416752765017753 0ustar chrischris00000000000000CHANGES.rst LICENSE MANIFEST.in PACKAGING.rst README.rst TESTING.rst setup.cfg setup.py signing-key.asc tox.ini doc/qr.1 qrcode/LUT.py qrcode/__init__.py qrcode/base.py qrcode/console_scripts.py qrcode/constants.py qrcode/exceptions.py qrcode/main.py qrcode/release.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/not-zip-safe 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_release.py qrcode/tests/test_script.pyqrcode-6.1/LICENSE0000644000175000017500000000413713416752764014130 0ustar chrischris00000000000000Copyright (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-6.1/doc/0000755000175000017500000000000013416752765013664 5ustar chrischris00000000000000qrcode-6.1/doc/qr.10000644000175000017500000000245113416752764014371 0ustar chrischris00000000000000.\" Manpage for qr .TH QR 1 "14 Jan 2019" "6.1" "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-6.1/CHANGES.rst0000644000175000017500000001305613416752764014725 0ustar chrischris00000000000000========== Change log ========== 6.1 (14 January 2019) ===================== - Fix short chunks of data not being optimized to the correct mode. - Tests fixed for Python 3 6.0 (23 March 2018) =================== - Fix optimize length being ignored in ``QRCode.add_data``. - Better calculation of the best mask pattern and related optimizations. Big thanks to cryptogun! 5.3 (18 May 2016) ================= * 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. 5.2 (25 Jan 2016) ================= * 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. 5.2.1 ----- * Small fix to terminal output in Python 3 (and fix tests) 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. 5.1 (22 Oct 2014) ================= * 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+) 5.0 (17 Jun 2014) ================= * 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``. 5.0.1 ----- * Update version numbers correctly. 4.0 (4 Sep 2013) ================ * 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. 4.0.1 ----- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! 4.0.2 ----- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. 4.0.3 ----- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. 4.0.4 ----- * Bad version number for previous hotfix release. 3.1 (12 Aug 2013) ================= * 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. 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. 3.0 (25 Jun 2013) ================= * 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. 2.7 (5 Mar 2013) ================ * Fix incorrect termination padding. 2.6 (2 Apr 2013) ================ * 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. 2.5 (12 Mar 2013) ================= * 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. 2.5.1 ----- * Fix installation error on Windows. 2.4 (23 Apr 2012) ================= * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. 2.4.1 ----- * Fix a packaging issue 2.4.2 ----- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. 2.3 (29 Jan 2012) ================= * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). 2.3.1 ----- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. 2.2 (18 Jan 2012) ================= * 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 2.1 (17 Jan 2012) ================= * 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-6.1/PKG-INFO0000644000175000017500000003320613416752765014220 0ustar chrischris00000000000000Metadata-Version: 2.1 Name: qrcode Version: 6.1 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 ============================= Generate QR codes. For a standard install (which will include pillow_ for generating images), run:: pip install qrcode[pil] .. _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: .. code:: python import qrcode img = qrcode.make('Some data here') Advanced Usage -------------- For more control, use the ``QRCode`` class. For example: .. code:: python 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(fill_color="black", back_color="white") 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. ``fill_color`` and ``back_color`` can change the background and the painting color of the QR, when using the default image factory. 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 --- 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: .. code:: 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: .. code:: python import qrcode from qrcode.image.pure import PymagingImage img = qrcode.make('Some data here', image_factory=PymagingImage) ========== Change log ========== 6.1 (14 January 2019) ===================== - Fix short chunks of data not being optimized to the correct mode. - Tests fixed for Python 3 6.0 (23 March 2018) =================== - Fix optimize length being ignored in ``QRCode.add_data``. - Better calculation of the best mask pattern and related optimizations. Big thanks to cryptogun! 5.3 (18 May 2016) ================= * 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. 5.2 (25 Jan 2016) ================= * 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. 5.2.1 ----- * Small fix to terminal output in Python 3 (and fix tests) 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. 5.1 (22 Oct 2014) ================= * 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+) 5.0 (17 Jun 2014) ================= * 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``. 5.0.1 ----- * Update version numbers correctly. 4.0 (4 Sep 2013) ================ * 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. 4.0.1 ----- * Fix the pymaging backend not able to save the image to a buffer. Thanks ilj! 4.0.2 ----- * Fix incorrect regex causing a comma to be considered part of the alphanumeric set. * Switch to using setuptools for setup.py. 4.0.3 ----- * Fix bad QR code generation due to the regex comma fix in version 4.0.2. 4.0.4 ----- * Bad version number for previous hotfix release. 3.1 (12 Aug 2013) ================= * 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. 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. 3.0 (25 Jun 2013) ================= * 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. 2.7 (5 Mar 2013) ================ * Fix incorrect termination padding. 2.6 (2 Apr 2013) ================ * 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. 2.5 (12 Mar 2013) ================= * 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. 2.5.1 ----- * Fix installation error on Windows. 2.4 (23 Apr 2012) ================= * Use a pluggable backend system for generating images, thanks to Branko Čibej! Comes with PIL and SVG backends built in. 2.4.1 ----- * Fix a packaging issue 2.4.2 ----- * Added a ``show`` method to the PIL image wrapper so the ``run_example`` function actually works. 2.3 (29 Jan 2012) ================= * When adding data, auto-select the more efficient encoding methods for numbers and alphanumeric data (KANJI still not supported). 2.3.1 ----- * Encode unicode to utf-8 bytestrings when adding data to a QRCode. 2.2 (18 Jan 2012) ================= * 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 2.1 (17 Jan 2012) ================= * 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. Keywords: qr denso-wave IEC18004 Platform: UNKNOWN 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.7 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Topic :: Multimedia :: Graphics Classifier: Topic :: Software Development :: Libraries :: Python Modules Provides-Extra: test Provides-Extra: dev Provides-Extra: pil Provides-Extra: maintainer qrcode-6.1/qrcode/0000755000175000017500000000000013416752765014374 5ustar chrischris00000000000000qrcode-6.1/qrcode/tests/0000755000175000017500000000000013416752765015536 5ustar chrischris00000000000000qrcode-6.1/qrcode/tests/test_script.py0000644000175000017500000000440713416752764020457 0ustar chrischris00000000000000import 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): # sys.stdin.read() will raise an error... self.assertRaises(UnicodeDecodeError, sys.stdin.read) # ... but it won't be used now. 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-6.1/qrcode/tests/svg.py0000644000175000017500000000014013416752764016701 0ustar chrischris00000000000000from qrcode.image.svg import SvgImage class SvgImageWhite(SvgImage): background = 'white' qrcode-6.1/qrcode/tests/test_release.py0000644000175000017500000000314513416752764020571 0ustar chrischris00000000000000import sys import re import datetime import unittest try: from unittest import mock except ImportError: import mock import six from qrcode.release import update_manpage OPEN = '{}.open'.format(six.moves.builtins.__name__) DATA = 'test\n.TH "date" "version" "description"\nthis' @unittest.skipIf( sys.version_info[0] == 3 and sys.version_info[1] < 6, "mock_file not working on Python 3 when less than 3.6") class UpdateManpageTests(unittest.TestCase): @mock.patch(OPEN, new_callable=mock.mock_open, read_data='.TH invalid') def test_invalid_data(self, mock_file): update_manpage({'name': 'qrcode', 'new_version': '1.23'}) mock_file.assert_called() mock_file().write.assert_not_called() @mock.patch(OPEN, new_callable=mock.mock_open, read_data=DATA) def test_not_qrcode(self, mock_file): update_manpage({'name': 'not-qrcode'}) mock_file.assert_not_called() @mock.patch(OPEN, new_callable=mock.mock_open, read_data=DATA) def test_no_change(self, mock_file): update_manpage({'name': 'qrcode', 'new_version': 'version'}) mock_file.assert_called() mock_file().write.assert_not_called() @mock.patch(OPEN, new_callable=mock.mock_open, read_data=DATA) def test_change(self, mock_file): update_manpage({'name': 'qrcode', 'new_version': '3.11'}) expected = re.split(r'([^\n]*(?:\n|$))', DATA)[1::2] expected[1] = expected[1].replace('version', '3.11').replace( 'date', datetime.datetime.now().strftime('%-d %b %Y')) mock_file().write.has_calls([mock.call(line) for line in expected]) qrcode-6.1/qrcode/tests/test_qrcode.py0000644000175000017500000002167113416752764020432 0ustar chrischris00000000000000import 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( [d.mode for d in qr.data_list], [ MODE_8BIT_BYTE, MODE_NUMBER, MODE_8BIT_BYTE, MODE_ALPHA_NUM, MODE_8BIT_BYTE ] ) self.assertEqual(qr.version, 2) def test_optimize_short(self): qr = qrcode.QRCode() text = 'A1abc1234567def1HELLOa' qr.add_data(text, optimize=7) qr.make() self.assertEqual(len(qr.data_list), 3) self.assertEqual( [d.mode for d in qr.data_list], [MODE_8BIT_BYTE, MODE_NUMBER, MODE_8BIT_BYTE] ) self.assertEqual(qr.version, 2) def test_optimize_longer_than_data(self): qr = qrcode.QRCode() text = 'ABCDEFGHIJK' qr.add_data(text, optimize=12) self.assertEqual(len(qr.data_list), 1) self.assertEqual(qr.data_list[0].mode, MODE_ALPHA_NUM) 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-6.1/qrcode/tests/test_example.py0000644000175000017500000000054513416752764020605 0ustar chrischris00000000000000try: 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-6.1/qrcode/tests/__init__.py0000644000175000017500000000000013416752764017634 0ustar chrischris00000000000000qrcode-6.1/qrcode/main.py0000644000175000017500000003344013416752764015675 0ustar chrischris00000000000000from 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) def _check_mask_pattern(mask_pattern): if mask_pattern is None: return if not isinstance(mask_pattern, int): raise TypeError( "Invalid mask pattern (was %s, expected int)" % type(mask_pattern)) if mask_pattern < 0 or mask_pattern > 7: raise ValueError( "Mask pattern should be in range(8) (got %s)" % mask_pattern) class QRCode: def __init__(self, version=None, error_correction=constants.ERROR_CORRECT_M, box_size=10, border=4, image_factory=None, mask_pattern=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) _check_mask_pattern(mask_pattern) self.mask_pattern = mask_pattern 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, minimum=optimize)) 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) if self.mask_pattern is None: self.makeImpl(False, self.best_mask_pattern()) else: self.makeImpl(False, self.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-6.1/qrcode/image/0000755000175000017500000000000013416752765015456 5ustar chrischris00000000000000qrcode-6.1/qrcode/image/pil.py0000644000175000017500000000317213416752764016616 0ustar chrischris00000000000000# 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("back_color", "white") fill_color = kwargs.get("fill_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" # L mode (1 mode) color = (r*299 + g*587 + b*114)//1000 if fill_color.lower() == "black": fill_color = 0 if back_color.lower() == "white": back_color = 255 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-6.1/qrcode/image/pure.py0000644000175000017500000000265413416752764017011 0ustar chrischris00000000000000from 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-6.1/qrcode/image/svg.py0000644000175000017500000001122213416752764016624 0ustar chrischris00000000000000from 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-6.1/qrcode/image/base.py0000644000175000017500000000352713416752764016750 0ustar chrischris00000000000000class 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-6.1/qrcode/image/__init__.py0000644000175000017500000000000013416752764017554 0ustar chrischris00000000000000qrcode-6.1/qrcode/LUT.py0000644000175000017500000000427413416752764015420 0ustar chrischris00000000000000# Store all kinds of lookup table. # # generate rsPoly lookup table. # from qrcode import base # def create_bytes(rs_blocks): # for r in range(len(rs_blocks)): # dcCount = rs_blocks[r].data_count # ecCount = rs_blocks[r].total_count - dcCount # rsPoly = base.Polynomial([1], 0) # for i in range(ecCount): # rsPoly = rsPoly * base.Polynomial([1, base.gexp(i)], 0) # return ecCount, rsPoly # rsPoly_LUT = {} # for version in range(1,41): # for error_correction in range(4): # rs_blocks_list = base.rs_blocks(version, error_correction) # ecCount, rsPoly = create_bytes(rs_blocks_list) # rsPoly_LUT[ecCount]=rsPoly.num # print(rsPoly_LUT) # Result. Usage: input: ecCount, output: Polynomial.num # e.g. rsPoly = base.Polynomial(LUT.rsPoly_LUT[ecCount], 0) rsPoly_LUT = { 7: [1, 127, 122, 154, 164, 11, 68, 117], 10: [1, 216, 194, 159, 111, 199, 94, 95, 113, 157, 193], 13: [1, 137, 73, 227, 17, 177, 17, 52, 13, 46, 43, 83, 132, 120], 15: [1, 29, 196, 111, 163, 112, 74, 10, 105, 105, 139, 132, 151, 32, 134, 26], 16: [1, 59, 13, 104, 189, 68, 209, 30, 8, 163, 65, 41, 229, 98, 50, 36, 59], 17: [1, 119, 66, 83, 120, 119, 22, 197, 83, 249, 41, 143, 134, 85, 53, 125, 99, 79], 18: [1, 239, 251, 183, 113, 149, 175, 199, 215, 240, 220, 73, 82, 173, 75, 32, 67, 217, 146], 20: [1, 152, 185, 240, 5, 111, 99, 6, 220, 112, 150, 69, 36, 187, 22, 228, 198, 121, 121, 165, 174], 22: [1, 89, 179, 131, 176, 182, 244, 19, 189, 69, 40, 28, 137, 29, 123, 67, 253, 86, 218, 230, 26, 145, 245], 24: [1, 122, 118, 169, 70, 178, 237, 216, 102, 115, 150, 229, 73, 130, 72, 61, 43, 206, 1, 237, 247, 127, 217, 144, 117], 26: [1, 246, 51, 183, 4, 136, 98, 199, 152, 77, 56, 206, 24, 145, 40, 209, 117, 233, 42, 135, 68, 70, 144, 146, 77, 43, 94], 28: [1, 252, 9, 28, 13, 18, 251, 208, 150, 103, 174, 100, 41, 167, 12, 247, 56, 117, 119, 233, 127, 181, 100, 121, 147, 176, 74, 58, 197], 30: [1, 212, 246, 77, 73, 195, 192, 75, 98, 5, 70, 103, 177, 22, 217, 138, 51, 181, 246, 72, 25, 18, 46, 228, 74, 216, 195, 11, 106, 130, 150] } qrcode-6.1/qrcode/exceptions.py0000644000175000017500000000005513416752764017126 0ustar chrischris00000000000000class DataOverflowError(Exception): pass qrcode-6.1/qrcode/release.py0000644000175000017500000000207413416752764016370 0ustar chrischris00000000000000""" This file provides zest.releaser entrypoints using when releasing new qrcode versions. """ import os import re import datetime def update_manpage(data): """ Update the version in the manpage document. """ if data['name'] != 'qrcode': return base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) filename = os.path.join(base_dir, 'doc', 'qr.1') with open(filename, 'r') as f: lines = f.readlines() changed = False for i, line in enumerate(lines): if not line.startswith('.TH '): continue parts = re.split(r'"([^"]*)"', line) if len(parts) < 5: continue changed = parts[3] != data['new_version'] if changed: # Update version parts[3] = data['new_version'] # Update date parts[1] = datetime.datetime.now().strftime('%-d %b %Y') lines[i] = '"'.join(parts) break if changed: with open(filename, 'w') as f: for line in lines: f.write(line) qrcode-6.1/qrcode/console_scripts.py0000755000175000017500000000645213416752764020170 0ustar chrischris00000000000000#!/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=None): if args is None: args = sys.argv[1:] from pkg_resources import get_distribution version = get_distribution('qrcode').version parser = optparse.OptionParser(usage=__doc__.strip(), version=version) 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-6.1/qrcode/util.py0000644000175000017500000004260213416752764015726 0ustar chrischris00000000000000import re import math import six from six.moves import xrange from qrcode import base, exceptions, LUT # 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(r']*\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) container = [0] * (modules_count + 1) for row in modules_range: this_row = modules[row] previous_color = this_row[0] length = 0 for col in modules_range: if this_row[col] == previous_color: length += 1 else: if length >= 5: container[length] += 1 length = 1 previous_color = this_row[col] if length >= 5: container[length] += 1 for col in modules_range: previous_color = modules[0][col] length = 0 for row in modules_range: if modules[row][col] == previous_color: length += 1 else: if length >= 5: container[length] += 1 length = 1 previous_color = modules[row][col] if length >= 5: container[length] += 1 lost_point += sum(container[each_length] * (each_length - 2) for each_length in xrange(5, modules_count + 1)) 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] # use iter() and next() to skip next four-block. e.g. # d a f if top-right a != b botton-right, # c b e then both abcd and abef won't lost any point. modules_range_iter = iter(modules_range) for col in modules_range_iter: top_right = this_row[col + 1] if top_right != next_row[col + 1]: # reduce 33.3% of runtime via next(). # None: raise nothing if there is no next item. next(modules_range_iter, None) elif top_right != this_row[col]: continue elif top_right != next_row[col]: continue else: lost_point += 3 return lost_point def _lost_point_level3(modules, modules_count): # 1 : 1 : 3 : 1 : 1 ratio (dark:light:dark:light:dark) pattern in # row/column, preceded or followed by light area 4 modules wide. From ISOIEC. # pattern1: 10111010000 # pattern2: 00001011101 modules_range = xrange(modules_count) modules_range_short = xrange(modules_count-10) lost_point = 0 for row in modules_range: this_row = modules[row] modules_range_short_iter = iter(modules_range_short) col = 0 for col in modules_range_short_iter: if ( not this_row[col + 1] and this_row[col + 4] and not this_row[col + 5] and this_row[col + 6] and not this_row[col + 9] and ( this_row[col + 0] and this_row[col + 2] and this_row[col + 3] and not this_row[col + 7] and not this_row[col + 8] and not this_row[col + 10] or not this_row[col + 0] and not this_row[col + 2] and not this_row[col + 3] and this_row[col + 7] and this_row[col + 8] and this_row[col + 10] ) ): lost_point += 40 # horspool algorithm. # if this_row[col + 10] == True, pattern1 shift 4, pattern2 shift 2. So min=2. # if this_row[col + 10] == False, pattern1 shift 1, pattern2 shift 1. So min=1. if this_row[col + 10]: next(modules_range_short_iter, None) for col in modules_range: modules_range_short_iter = iter(modules_range_short) row = 0 for row in modules_range_short_iter: if ( not modules[row + 1][col] and modules[row + 4][col] and not modules[row + 5][col] and modules[row + 6][col] and not modules[row + 9][col] and ( modules[row + 0][col] and modules[row + 2][col] and modules[row + 3][col] and not modules[row + 7][col] and not modules[row + 8][col] and not modules[row + 10][col] or not modules[row + 0][col] and not modules[row + 2][col] and not modules[row + 3][col] and modules[row + 7][col] and modules[row + 8][col] and modules[row + 10][col] ) ): lost_point += 40 if modules[row + 10][col]: next(modules_range_short_iter, None) return lost_point def _lost_point_level4(modules, modules_count): dark_count = sum(map(sum, modules)) percent = float(dark_count) / (modules_count**2) # Every 5% departure from 50%, rating++ rating = int(abs(percent * 100 - 50) / 5) return rating * 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) num_pattern = six.b(r'\d') alpha_pattern = six.b('[') + re.escape(ALPHA_NUM) + six.b(']') if len(data) <= minimum: num_pattern = re.compile(six.b('^') + num_pattern + six.b('+$')) alpha_pattern = re.compile(six.b('^') + alpha_pattern + six.b('+$')) else: re_repeat = ( six.b('{') + six.text_type(minimum).encode('ascii') + six.b(',}')) num_pattern = re.compile(num_pattern + re_repeat) alpha_pattern = re.compile(alpha_pattern + re_repeat) num_bits = _optimal_split(data, num_pattern) 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. if ecCount in LUT.rsPoly_LUT: rsPoly = base.Polynomial(LUT.rsPoly_LUT[ecCount], 0) else: 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-6.1/qrcode/constants.py0000644000175000017500000000015213416752764016757 0ustar chrischris00000000000000# QR error correct levels ERROR_CORRECT_L = 1 ERROR_CORRECT_M = 0 ERROR_CORRECT_Q = 3 ERROR_CORRECT_H = 2 qrcode-6.1/qrcode/base.py0000644000175000017500000001632713416752764015670 0ustar chrischris00000000000000from 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)) for offset in range(len(num)): if num[offset] != 0: break else: offset += 1 self.num = num[offset:] + [0] * shift 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 = [ 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-6.1/qrcode/__init__.py0000644000175000017500000000116613416752764016510 0ustar chrischris00000000000000from 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-6.1/tox.ini0000644000175000017500000000162213416752764014432 0ustar chrischris00000000000000[tox] distribute = False envlist = coverage_setup py{27,34,35,36} readme coverage_report skip_missing_interpreters = True [testenv] usedevelop = True extras = test pil deps = git+git://github.com/ojii/pymaging.git#egg=pymaging git+git://github.com/ojii/pymaging-png.git#egg=pymaging-png commands = pytest --cov --cov-append --cov-report= [testenv:readme] skip_install = True deps = docutils Pygments commands = {envbindir}/rst2html.py --report=info --halt=warning README.rst /dev/null {envbindir}/rst2html.py --report=info --halt=warning CHANGES.rst /dev/null [testenv:coverage_setup] skip_install = True deps = coverage commands = coverage erase [testenv:coverage_report] skip_install = True deps = coverage commands = coverage html coverage report --include="qrcode/tests/*" --fail-under=100 -m coverage report --omit="qrcode/tests/*" --fail-under=90 -m qrcode-6.1/MANIFEST.in0000644000175000017500000000012713416752764014654 0ustar chrischris00000000000000include *.rst include LICENSE include signing-key.asc include tox.ini include doc/qr.1 qrcode-6.1/signing-key.asc0000644000175000017500000000424713416752764016041 0ustar chrischris00000000000000-----BEGIN PGP PUBLIC KEY BLOCK----- Version: GnuPG v1 mQENBFDTudIBCACagG1d2hP80O3aNi+9S4rgpd1Lfa7To11XI1HsGI74jkshSxCU dRPc/OmPAgLjjr+iEpEZeI/h8XyCem0QOgmr2mr1nu58dJ6UvCG0yX4DvXX9SDfh ZeAHRzFi9tUEN4BbBf79EYfma9iqNpQPXKurvxLeHGDW48rMbT5dJd8WSN96rNEo OrS7EMHy3tvrU5lX4JURwHQUYmO+wXYbX5aZdvZRVG5onD1ettP3Ie87Mc/bRJ91 6NIGXX3vlk9Gou0EpJbs6zhjvTxmjU4trjmnhUNf7+dDZpHpId5eU2sMl959qjsO zdQWtSgyjZ4rN8kw8MuaFqaMaBbbWnrECBAJABEBAAG0JENocmlzIEJlYXZlbiA8 c21pbGV5Y2hyaXNAZ21haWwuY29tPokBPgQTAQIAKAIbAwYLCQgHAwIGFQgCCQoL BBYCAwECHgECF4AFAlc+K5MFCQwdXW4ACgkQ1vRASXANOvCRMAgAjHOqeoBYZi6h OKPFcyshl+qiDkpHNEAZnxMvCX5gqfc+aLQA4FmmjwkbIBKYYgT/SmnAB/txpTgN QByOw+LzWFjhsqKGEUlpva/o6N80Y7EH7HE9PldEandEZEAb4XXqQHItrDkY80/P WznO66TmmsNYa4cbb21+Q9bRZDZyaGPc/ZukL8rzFpXsQWwVf41fVAp0gWrnXwwC GqGIAC8WcmKLK0K62LmSJ5HnO+PSC0K6UFAcBg8XwCWaI+BqGw81Bi/Dho2GxkDv RyF8JK+HrNm1AJgn3kILhQKDxRb9HamCrAbZ5leB7NNX855MyXCoIsZMJkDksHxW PcF+l39thbQvQ2hyaXMgQmVhdmVuICgyMDEyIGtleSkgPHNtaWxleWNocmlzQGdt YWlsLmNvbT6JATgEEwECACIFAlDTudICGwMGCwkIBwMCBhUIAgkKCwQWAgMBAh4B AheAAAoJENb0QElwDTrwhPAH/RAD40WAqHErF47yoJhrurTUDESRqcz1CSEFYEyJ vx4a3ZOAoCe7okw/DWz934vRggToTNfhEpGFqDjwM1rrnYvlT577ay095ZZveDw+ zU4SzseamBHO07uDugBF2XDXiW7iAWLgvRRp+9fFuHdJxAy0OcYceIsKVm9O7QOG EyZSm/rugXQzx62yZkMMWVRDBkClRP2AmubqXhZWMYll2jnqo7dSFUKSHikt/Dpw 8BG4vFZiOurFoThgkQt0yxbXNjKa1Q3RfVQO3f0WtKwIiE8zg7abFdK1LlMybfde Jf2l5H1d17wfdXnnzGnwzJ06Ss/1NOdI8Pd+/Gnh+mlm/Ou5AQ0EUNO50gEIAPmL jErCZsDkBsijy6LAvC1C9uiye5nRAPxB85H58u/IyRaPwoReBcMQMTeT92f3A+uV F7yvNm598L9dY/+QK5L6JOwvpOMEBBInSbJNXxnSlSSeyaEN2jbRbkkTrxWz93xQ lLAjU8ROjTLojzW5LqC4A8XebuH9XKp7rX9XMb4yKkxmDyqPaJLWUtMig6XZStwG odILFURHPLfsreWx7spYhA3NiC6OIrPmN4kORt6GT7g6umBjellsG/h+XZZW3jQV v768BhOsTeTdZZxbPApwrWqO/Y2fswVC+rsrd0sRXUnNFv8o4EVWdIsgQ/cdG4cM S79fczQVxLL+UGYLswEAEQEAAYkBJQQYAQIADwIbDAUCVz4rgwUJCFr2bgAKCRDW 9EBJcA068AB2B/9LGmNceTLY3ckKqtxTaTc9OqSbu/B9kbuOSaOO1KB4A7a1F6Ay I5z3r50x88GqAIr3FigDlGNLfgWQAdeAzeaOV8CX/J7MHwAvZDg4qLPIfiVeq9r1 ztXi9wITBLrn2TUugj9lK3x1uUzwmFhmyrnLl8wvqw74m6b3iY5zvSY24mpTBupD ZjuYt/fCrdAtjyGIKXkQBQzmLqrOFX2jq3tOBE+qGPECiUVdDYH2X/NrJFqMgu0/ IjsGMlA46GlzypOXDNrgPX3EJ7w59H3Fn9cQgH8C2OIE40Nr6AF7oAR+/vxwG/Er yCUbp4StCe9l6Jv7I6XTqofSZaQVkWNLwbOi =OWh8 -----END PGP PUBLIC KEY BLOCK-----