mnooner256 / pyqrcode

Python 3 module to generate QR Codes
BSD 3-Clause "New" or "Revised" License
408 stars 75 forks source link

Too much data for this code version. #3

Closed tvfeed closed 9 years ago

tvfeed commented 9 years ago

Im using pythong 2.7.8 and django 1.6.5 (dont care about django) I need to dynamically create 2 QR-files (png and svg):

url = 'http://test.com/test/myproject/name/etc/1/'  # tried with %s' % pk  , does not matter
data = QRCode(url)

hello exceptions:

if current_byte < len(data):
    raise ValueError('Too much data for this code version.')

but.. if i change code like this

data = QRCode('http://test.com/test/myproject/name/etc/1/')

all works fine, but looks the same, right? what problem with string variable ?

then i changed builder.py like this:

# if current_byte < len(data):
#    raise ValueError('Too much data for this code version.')

and all works fine with 1st version.

where I was wrong?

mnooner256 commented 9 years ago

Sorry it has taken me forever to get to this. I have finals coming up and a bunch of projects due, so my time is really limited.

I have tried the given code using Python 2.7.6 which comes with my linux distro. It works fine. I know the "could not replicate" answer is really frustrating to hear.

The ValueError, is really just a sanity check that should never be thrown unless the user tries to force something wrong. The idea of the check is that more data is being offered than what the QR code can handle with a given version, mode, and error level. Obviously that is not happening in this case. In this case current_byte and len(data) should be the same number.

I am not giving up though. If you will help me out, I think we might be able to narrow down what is causing the problem.

Lets try getting more information. Just before the if statement in the builder, put the following two print statements. This should tell me what the builder thinks is going on at the moment just before the error is raised. Please reply with the output of the print statements.

print("current_byte=%d, len(data)=%d" % (current_byte,len(data)))
print("version={s.version}, mode={s.mode}, error={s.error}\ndata=\"{s.data}\"".format(s=self))

Also, double check that your the example code actually breaks for you, and you did not make any other changes, i.e. forcing too small of a version. Below is the example program I used to try and replicate the error.

from pyqrcode import QRCode

url = 'http://test.com/test/myproject/name/etc/1/'
data = QRCode(url)

Thanks for using my library!

tvfeed commented 9 years ago

Thanks for library !

in python shell all works fine. This exceptions in django (1.6.5). But in other project i use library on django 1.6.5 and python 2.7.5 and all works fine =|

Test in shell

test.py

from pyqrcode import QRCode

def create_qr(obj):
    url = 'http://test.com/qrcode/%s/' % obj
    data = QRCode(url)

and in shell

from test import create_qr
create_qr(3)
current_byte=26, len(data)=27
version=3, mode=2, error=H
mnooner256 commented 9 years ago

I have an idea. Please check to see if django is using unicode, regular, or byte strings. It could be something is not converting properly.

tvfeed commented 9 years ago

In prev post i used only python (shell). current_byte and len(data) dont match.

in django

# -*- coding: utf-8 -*-

rly this problem in py 1.7.8 and comment exception works for me )

mnooner256 commented 9 years ago

I really have no idea what is going on. Your len(data) is one too large.

I even went and downloaded 2.7.8 and django. I tried them together and separately, it works fine for me.

I am not giving up yet. Lets try getting more information, again.

Add this print statement to the two already there.

print("{}".format(self.buffer.getvalue()));

This will tell me the exact bits that will be fed into the QR code. I should then be able to replicate the process or compare your values to mine.

tvfeed commented 9 years ago

this is funny ) look.. with test.py (from 3rd post)

if url with real url

    url = 'http://mealplace.ru/place/%s/review/' % obj

i saw that

001000010001101100011010101001100101111110011111110100101010100000000111100101001110111011010001010101110111110110101110001100011110100011100111001010100001000101100101001100110110110000101010100101101010110000000000
current_byte=26, len(data)=27
version=3, mode=2, error=H
data="HTTP://MEALPLACE.RU/PLACE/3/REVIEW/"

if i change url on something like this

    url = 'http://testresource.com/place/%s/review/' % obj

all works fine xD

001000010011101100011010101001100101111110011111110101100010100100101010011010001010010010100010101101001100101101010100000010001101001000000100110001111010001110011100101010000100010110010100110011011011000010101010010110101011000011101100000100011110110000010001111011000001000111101100
current_byte=36, len(data)=36
version=4, mode=2, error=H
data="HTTP://TESTRESOURCE.COM/PLACE/3/REVIEW/"
mnooner256 commented 9 years ago

Finally Success!!!!

I figured out what is causing the problem.

I was adding terminal bits as part of the encoding. As per the standard, terminating bits are only supposed to be added after the bit stream is complete. I took that to mean after the encoding portion (due to how and where it is written). Actually it supposed to be done after the entire data bit stream has been constructed.

Thank god for sanity checks. I would have never found this except you discovered the "perfect storm" of a example. When the process was said and done, Your example added one entire extra byte of data. As soon as I saw your bits, I knew that it was wrong. 2 hours later, and multiple readings of the standard, I finally tracked down the problem.

Thank you

Thanks for your patience with the back and forth. I really appreciate it. I know it can be painful to help someone you have never met help debug their code.

I have uploaded the fix to git hub. Please download the fix from git hub and try it. I only had to change the builder.py file, so that is the only one you should need.

I have a pull request to process. After that is done, I will push it and the added feature to Pypi as a new version of the library (so you can do pip update).

Please tell me if works now

If it does, then I will close the issue.

tvfeed commented 9 years ago

All works fine (for me).

current_byte=26, len(data)=26

I think the problem is solved. Ty for fix and Ty for this module. I'm glad I could help you :)

mnooner256 commented 9 years ago

FYI. I updated the PyPi package version. It now includes this fix.