I am trying to get Flask-openid working, but keep hitting this error when trying to log in
ValueError: Unicode strings with encoding declaration are not supported. Please use bytes input or XML fragments without declaration.
It happens when using this function
oid.try_login(openid, ask_for=['email', 'fullname', 'nickname'])
This is where the function is used:
#app.route('/login', methods=['GET', 'POST'])
#oid.loginhandler
def login():
"""Does the login via OpenID. Has to call into `oid.try_login`
to start the OpenID machinery.
"""
# if we are already logged in, go back to were we came from
if g.user is not None:
app.logger.info('logged-in: ' + oid.get_next_url())
return redirect(oid.get_next_url())
if request.method == 'POST':
openid = request.form.get('openid_identifier')
if openid:
app.logger.info(request.form)
app.logger.info('logging-in: ' + oid.get_next_url())
return oid.try_login(openid, ask_for=['email', 'fullname',
'nickname'])
app.logger.info('not-logged-in: ' + oid.get_next_url())
return render_template('login.html', next=oid.get_next_url(),
error=oid.fetch_error())
and actually seems to be an issue with lxml that Flask-openid uses:
File "C:\Python33\lib\site-packages\openid\yadis\etxrd.py", line 69, in parseXRDS
element = ElementTree.XML(text)
File "lxml.etree.pyx", line 3012, in lxml.etree.XML (src\lxml\lxml.etree.c:67876)
File "parser.pxi", line 1781, in lxml.etree._parseMemoryDocument (src\lxml\lxml.etree.c:102435)
I have tried a couple of example projects on github, but they all have the same issue. Is there some way I can get Flask-openid to work in Python 3?
I'm only just learning Flask myself, so I'm not of much help.
However take a look at http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins
The author mentions
Note that due to the differences in unicode handling between Python 2 and 3 we have to provide two alternative versions of this method.
He uses a str instead of unicode
def get_id(self):
try:
return unicode(self.id) # python 2
except NameError:
return str(self.id) # python 3
I might be completely wrong! In which case i'm sorry, worth a try though.
Its much more than just string. Its based on an older python-openid package That is not Python3 compatible. There is a new version of python-openid specifically for Python3.
https://pypi.python.org/pypi/python3-openid/3.0.1
Same blog mentioned earlier also detail this:
http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-v-user-logins
"Unfortunately version 1.2.1 of Flask-OpenID (the current official version) does not work well with Python 3. Check what version you have by running the following command:"
Related
I am working through the tutorial https://simpleisbetterthancomplex.com/series/beginners-guide/1.11/ from Vitor Freitas.
I am using Django 2.0.7 for this task. I know that the tutorial was written for 1.11 and I have been fixing any challenges that have come up during the process. Currently I am having issues with one test that is failing to run due to this error
====================================================================== ERROR: accounts.tests.test_view_password_change
(unittest.loader._FailedTest)
---------------------------------------------------------------------- ImportError: Failed to import test module:
accounts.tests.test_view_password_change Traceback (most recent call
last): File "/usr/lib/python3.5/unittest/loader.py", line 428, in
_find_test_path
module = self._get_module_from_name(name) File "/usr/lib/python3.5/unittest/loader.py", line 369, in
_get_module_from_name
import(name) File "/home/lance/dev/proj/accounts/tests/test_view_password_change.py",
line 44
self.assertRedirects(response, f'{login_url}?next={url}')
The test code is question looks like this
class PasswordChangeTests(TestCase):
def setUp(self):
username = 'john'
password = 'secret123'
user = User.objects.create_user(username=username, email='john#doe.com', password=password)
url = reverse('password_change')
self.client.login(username=username, password=password)
self.response = self.client.get(url)
class LoginRequiredPasswordChangeTests(TestCase):
def test_redirection(self):
url = reverse('password_change')
login_url = reverse('login')
response = self.client.get(url)
self.assertRedirects(response, f'{login_url}?next={url}')
The invalid syntax seems to come from the last line
self.assertRedirects(response, f'{login_url}?next={url}')
Can someone help me out as to why this is invalid?
As I understand it the test is looking for the pattern that is listed in the single quotes and I have tested that it is there.
I can't understand why the single quotes is incorrect.
f-strings were introduced in Python 3.6. They are a syntax error in earlier versions. Might that be your problem?
Since the F string literals is implemented Python 3.6 onwards. So make sure you are using Python 3.6+.
You can also use str.format() method as,
self.assertRedirects(response, '{}?next={}'.format(login_url, url))
I try to make connection with the Google Adwords API using Python 3.6. I managed to install the libraries, got a developer token, client_customer_id, user_agent, client_id, client_secret and requested succesfully a refresh_token.
My googleads.yaml file looks like this:
adwords:
developer_token: hta...
client_customer_id: 235-...-....
user_agent: mycompany
client_id: 25785...apps.googleusercontent.com
client_secret: J9Da...
refresh_token: 1/ckhGH6...
When running the first python script get_campaigns.py, I get the very generic response TypeError: cannot use a string pattern on a bytes-like object in ...\Anaconda3\lib\site-packages\googleads-10.0.0-py3.6.egg\googleads\util.py", line 302, in filter
Other functions like traffic_estimator_service.get(selector) produce the same error. Furthermore, when starting the Python script get_campaigns.py, I get the following warning, which might explains something:
WARNING:googleads.common:Your default encoding, cp1252, is not UTF-8. Please run this script with UTF-8 encoding to avoid errors.
INFO:oauth2client.client:Refreshing access_token
INFO:googleads.common:Request summary - {'methodName': get, 'clientCustomerId': xxx-xxx-xxxx}
I tried many things, but still can't find what causes my error. My settings seem to be right, and I use the examples as provided here. Help is highly appreciated!
There are two solutions for now:
One:
Use Python2.7, solved this error for me.
Two:
For python 3
def method_waraper(self, record):
def filter(self, record):
if record.args:
arg = record.args[0]
if isinstance(arg, suds.transport.Request):
new_arg = suds.transport.Request(arg.url)
sanitized_headers = arg.headers.copy()
if self._AUTHORIZATION_HEADER in sanitized_headers:
sanitized_headers[self._AUTHORIZATION_HEADER] = self._REDACTED
new_arg.headers = sanitized_headers
msg = arg.message
if sys.version_info.major < 3:
msg = msg.decode('utf-8')
new_arg.message = self._DEVELOPER_TOKEN_SUB.sub(
self._REDACTED, str(msg, encoding='utf-8'))
record.args = (new_arg,)
return filter(self, record)
googleads.util._SudsTransportFilter.filter = method_waraper
This solution changes code provided by google and add utf encoding for the binary string, which solves our problem.
I am trying to mess with the pygooglevoice api and am trying to run the example call program on the documentation website:
from googlevoice import Voice
from googlevoice.util import input
voice = Voice()
voice.login()
outgoingNumber = input('Number to call: ')
forwardingNumber = input('Number to call from [optional]: ') or None
voice.call(outgoingNumber, forwardingNumber)
if input('Calling now... cancel?[y/N] ').lower() == 'y':
voice.cancel(outgoingNumber, forwardingNumber)
I then get the following error when voice.login() tries to execute:
File "C:\Users\<USER>\AppData\Local\Programs\Python\Python35\lib\configparser.py", line 406, in _interpolate_some
rawval = parser.get(section, option, raw=True, fallback=rest)
TypeError: get() got an unexpected keyword argument 'raw'
I am currently using Python 3.5 on a Windows 10 machine. I am also 90% sure I configured my .gvoice file properly in my user home directory. I have the email, password, and forwardingnumber all written out in that file.
Has anyone else had this issue? Am I using a deprecated API?
I found a more recent version of the library here: https://github.com/pettazz/pygooglevoice
This did fix my configparser error but I am now encountering another problem of a different nature. However my primary problem is fixed.
I am trying to write a RESTful web service in python. But while trying out the tutorials given on Cherrypy Website I ended up with an error like
Traceback (most recent call last):
File "rest.py", line 35, in <module>
cherrypy.quickstart(StringGeneratorWebService(), '/', conf)
TypeError: expose_() takes exactly 1 argument (0 given)
Where rest.py is my file which contains the exact same code on the site and under subtitle "Give us a REST".
I am clear that, obviously from error message, I am missing a parameter that should be passed in. But I am not clear where exactly I should amend that code to make it work.
I tried out fixing something on line number 35, but nothing helped me, and I am stuck! Please help me to clear this or please give some code snippet to make a REST service in cherrypy. Thank you!
The CherryPy version that you're using (3.2.2) doesn't support the cherrypy.expose decorator on classes, that functionality was added in version 6.
You can use the old syntax of setting the exposed attribute to True(it is also compatible with the newer versions).
The class would end up like:
class StringGeneratorWebService(object):
exposed = True
#cherrypy.tools.accept(media='text/plain')
def GET(self):
return cherrypy.session['mystring']
def POST(self, length=8):
some_string = ''.join(random.sample(string.hexdigits, int(length)))
cherrypy.session['mystring'] = some_string
return some_string
def PUT(self, another_string):
cherrypy.session['mystring'] = another_string
def DELETE(self):
cherrypy.session.pop('mystring', None)
I am trying to implement a file upload solution using app engine and python. The thing which I am struggling with checking whether there is actually a file attached to the form or not. I am setting the enctype="multipart/form-data" and in principle it works. My python handler looks like this:
fileupload = self.request.POST["content"]
if not fileupload:
return self.error(400)
This works if there is no file attached. However if there is a file attached it gives the following error:
File "D:\eclipse_dev\workspace\test\src\handlers.py", line 351, in post
if not fileupload:
File "C:\Python25\lib\cgi.py", line 633, in __len__
return len(self.keys())
File "C:\Python25\lib\cgi.py", line 609, in keys
raise TypeError, "not indexable"
TypeError: not indexable
How can I safely check that an upload is present before doing anything else in the handler?
Thanks for any help.
Regards,
Robin
How about:
fileupload = self.request.POST["content"]
if fileupload is None:
return self.error(400)
Well, I've got this working using:
import cgi
.
.
fileupload = self.request.POST["content"]
if not isinstance(fileupload, cgi.FieldStorage):
return self.error(400)
Not sure if that's the best solution, but it seems to work.
App Engine's self.request.get() method handles POST data just fine:
"The request object provides a get() method that returns values for arguments parsed from the query and from POST data."
Try this instead:
def post(self):
fileupload = self.request.get('content')
if not fileupload:
self.error(400)
else:
# Proceed normally
I have a small tutorial about file upload to GAE.
http://verysimplescripts.blogspot.jp/
There is a completely working solution included as well.