How to response with PIL image in Cherrypy dynamically (Python3)? - python-3.x

It seems the task is easy but...
I have simple PIL.Image object. How to make Cherrypy response with this image dynamically?
def get_image(self, data_id):
cherrypy.response.headers['Content-Type'] = 'image/png'
img = PIL.Image.frombytes(...)
buffer = io.StringIO()
img.save(buffer, 'PNG')
return buffer.getvalue()
This code gives me:
500 Internal Server Error
The server encountered an unexpected condition which prevented it from fulfilling the request.
Traceback (most recent call last):
File "C:\Users\Serge\AppData\Local\Programs\Python\Python36\lib\site-packages\cherrypy\_cprequest.py", line 631, in respond
self._do_respond(path_info)
File "C:\Users\Serge\AppData\Local\Programs\Python\Python36\lib\site-packages\cherrypy\_cprequest.py", line 690, in _do_respond
response.body = self.handler()
File "C:\Users\Serge\AppData\Local\Programs\Python\Python36\lib\site-packages\cherrypy\_cpdispatch.py", line 60, in __call__
return self.callable(*self.args, **self.kwargs)
File "D:\Dev\Bf\webapp\controllers\calculation.py", line 69, in get_image
img.save(buffer, 'PNG')
File "C:\Users\Serge\AppData\Local\Programs\Python\Python36\lib\site-packages\PIL\Image.py", line 1930, in save
save_handler(self, fp, filename)
File "C:\Users\Serge\AppData\Local\Programs\Python\Python36\lib\site-packages\PIL\PngImagePlugin.py", line 731, in _save
fp.write(_MAGIC)
TypeError: string argument expected, got 'bytes'
Can someone help me please?

Use io.BytesIO() instead of io.StringIO(). (From this answer.)

Related

Flask-Restful Object not serializable errors on return code 200

Im currently getting a strange error whenever I try to return a response with the code 200.
Here's the snippet of the code I'm using:
from pathlib import Path
from flask_restful import Resource
from app.models.user import User
from app.models.workspace import Workspace
from app.models.file import File
from app.controllers.filesystem import FileSystem
from flask import request
import os
class Signup(Resource):
def post(self):
if not request.is_json:
return {"msg": "Missing JSON in request"}, 400
email = request.json.get('email', None)
password = request.json.get('password', None)
if not email:
return {"msg": "Missing username parameter"}, 400
if not password:
return {"msg": "Missing password parameter"}, 400
# TODO- Find a more elegant way to do this
try:
user = User.objects.get(email=email)
except User.DoesNotExist:
user = None
if user:
return {"msg": "User already exists"}, 400
new_user = User(email=email, password=password)
new_user.hash_password()
# Create a new workspace called "Microfluidics Examples"
new_workspace = Workspace(name="Microfluidics Examples")
# Step 1 - Go through every file in the examples directory
# Step 2 - Upload these files to s3 and get the file_id
# Step 3 - Create a new file object for each of the file_ids and add it to the workspace
# Go through every file in the examples directory
examples_directory = Path("examples")
for file_name in examples_directory.iterdir():
# Upload the file to s3 and get the file_id
s3_object_id = FileSystem.upload_file(file_name)
# Create a new file object for the file_id and add it to the workspace
new_file = File(file_name=str(file_name.name), s3_path=s3_object_id)
new_file.save()
new_workspace.design_files.append(new_file)
# Save the workspace
new_workspace.save()
# Add the workspace to the user
new_user.workspaces.append(new_workspace)
# Save the user
new_user.save()
# Return success
return {"mes":, "id": str(new_user.id)}, 200
From the error trace, it looks like something originating from the cors package might be interfering with this. Here's the trace:
127.0.0.1 - - [19/Nov/2022 14:18:02] "GET /api/v2/user HTTP/1.1" 500 -
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2548, in __call__
return self.wsgi_app(environ, start_response)
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2528, in wsgi_app
response = self.handle_exception(e)
File "/usr/local/lib/python3.8/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python3.8/dist-packages/flask_cors/extension.py", line 165, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2525, in wsgi_app
response = self.full_dispatch_request()
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1822, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/usr/local/lib/python3.8/dist-packages/flask_restful/__init__.py", line 271, in error_router
return original_handler(e)
File "/usr/local/lib/python3.8/dist-packages/flask_cors/extension.py", line 165, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1820, in full_dispatch_request
rv = self.dispatch_request()
File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1796, in dispatch_request
return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
File "/usr/local/lib/python3.8/dist-packages/flask_restful/__init__.py", line 471, in wrapper
return self.make_response(data, code, headers=headers)
File "/usr/local/lib/python3.8/dist-packages/flask_restful/__init__.py", line 500, in make_response
resp = self.representations[mediatype](data, *args, **kwargs)
File "/usr/local/lib/python3.8/dist-packages/flask_restful/representations/json.py", line 21, in output_json
dumped = dumps(data, **settings) + "\n"
File "/usr/lib/python3.8/json/__init__.py", line 234, in dumps
return cls(
File "/usr/lib/python3.8/json/encoder.py", line 201, in encode
chunks = list(chunks)
File "/usr/lib/python3.8/json/encoder.py", line 438, in _iterencode
o = _default(o)
File "/usr/lib/python3.8/json/encoder.py", line 179, in default
raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type function is not JSON serializable
I can't figure out why this is happening; for instance, if I change the return code to 400, it just works fine. Can someone help me figure out what this error is?
Apologies to the community, I traced the error incorrectly. The error did not originate because of the given code snippet. I will update the question shortly to reflect the source of the error trace correctly and post the solution

Python convert SVGz to PDF: no response

I tried to convert a batch of .svgz into a single pdf file following the instructions of Generating PDFs from SVG input.
from svglib.svglib import svg2rlg
from reportlab.graphics import renderPDF
renderPDF.drawToFile(svg2rlg("images/p1.svgz"), "out.pdf")
Encounter the issue OSError: Not a gzipped file (b'<s'). The file is not compressed at all as I can read the file with cat.
I changed the filename extension to .svg with mv, run again the above codes renderPDF.drawToFile(svg2rlg("images_svg/p1.svg"), "out.pdf"), but got nothing response.
I terminated the process with Ctrl + c, and got this,
$ python3 img_to_pdf.py
^CTraceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/reportlab/lib/utils.py", line 658, in open_for_read
return open_for_read_by_name(name,mode)
File "/usr/local/lib/python3.7/site-packages/reportlab/lib/utils.py", line 602, in open_for_read_by_name
return open(name,mode)
FileNotFoundError: [Errno 2] No such file or directory: 'p2_g_d0_f57.ttf'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/reportlab/lib/utils.py", line 661, in open_for_read
return getBytesIO(datareader(name) if name[:5].lower()=='data:' else urlopen(name).read())
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 222, in urlopen
return opener.open(url, data, timeout)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 510, in open
req = Request(fullurl, data)
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 328, in __init__
self.full_url = url
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 354, in full_url
self._parse()
File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 383, in _parse
raise ValueError("unknown url type: %r" % self.full_url)
ValueError: unknown url type: 'p2_g_d0_f57.ttf'
During handling of the above exception, another exception occurred:
......
How do I make it work?

How to solve the error: TypeError: a bytes-like object is required, not 'str' with FLASK-MAIL?

In one of my FLASK projects, I use flask-mail to send emails. I tried to attach a log file to the mail but I receive an error: TypeError: a bytes-like object is required, not 'str'. Here is the complete error:
Exception in thread Thread-37:
Traceback (most recent call last):
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "/home/Tobin/Documents/PYTHON-PROJECTS/FLASK CHAOS V1/app/email.py", line 7, in send_async_email
mail.send(msg)
File "/home/Tobin/.local/lib/python3.7/site-packages/flask_mail.py", line 492, in send
message.send(connection)
File "/home/Tobin/.local/lib/python3.7/site-packages/flask_mail.py", line 427, in send
connection.send(self)
File "/home/Tobin/.local/lib/python3.7/site-packages/flask_mail.py", line 190, in send
message.as_bytes() if PY3 else message.as_string(),
File "/home/Tobin/.local/lib/python3.7/site-packages/flask_mail.py", line 385, in as_bytes
return self._message().as_bytes()
File "/home/Tobin/.local/lib/python3.7/site-packages/flask_mail.py", line 349, in _message
f = MIMEBase(*attachment.content_type.split('/'))
TypeError: a bytes-like object is required, not 'str'
Here is my code:
from threading import Thread
from flask_mail import Message
from app import app, mail
def send_async_email(app, msg):
with app.app_context():
mail.send(msg)
def send_email(subject, sender, recipients, text_body):
msg = Message(subject, sender=sender, recipients=recipients)
msg.body = text_body
with app.open_resource("../logs/chaos.log") as fp:
msg.attach(b'../logs/chaos.log', fp.read())
Thread(target=send_async_email, args=(app, msg)).start()
I read in a previous post that it was not possible to open a file in binary mode and treat it as str. One solution would be to use a byte object (msg.attach(b'../logs/chaos.log', fp.read())). but that does not seem to solve my problem. apparently there is an essential notion that escapes me, so how to solve this bug?
You are supplying wrong arguments to msg.attach(). See the API for the correct parameters. The first argument should be a filename, second a content type, third the data. So the call should read something like this:
with app.open_resource("../logs/chaos.log") as fp:
msg.attach('chaos.log', 'text/plain', fp.read())

Cannot run bind() with ldap3 in python3

Below is my code to try and query my ldap server. However, for some reason, I cannot seem to make the bind command work to progress in my code. I continue to get the following message and am not sure what it means or how to fix it. I apologize about the error message formatting. I tried my best to make it as readable as possible.
Any help would be greatly appreciated!
>>> from ldap3 import Server, Connection, SUBTREE
>>> server = Server('<server_name>')
>>> conn = Connection(server, user='<username>', password='<password>')
>>> conn.open()
>>> conn.bind()
Traceback (most recent call last):
File "", line 1, in
File "/usr/lib/python3.5/site-packages/ldap3/core/connection.py", line 427, in bind
response = self.post_send_single_response(self.send('bindRequest', request, controls))
File "/usr/lib/python3.5/site-packages/ldap3/strategy/sync.py", line 122, in post_send_single_response
responses, result = self.get_response(message_id)
File "/usr/lib/python3.5/site-packages/ldap3/strategy/base.py", line 298, in get_response
responses = self._get_response(message_id)
File "/usr/lib/python3.5/site-packages/ldap3/strategy/sync.py", line 168, in _get_response
dict_response = self.decode_response(ldap_resp)
File "/usr/lib/python3.5/site-packages/ldap3/strategy/base.py", line 403, in decode_response
result = bind_response_to_dict(component)
File "/usr/lib/python3.5/site-packages/ldap3/operation/bind.py", line 119, in bind_response_to_dict
'saslCreds': bytes(response['serverSaslCreds']) if response['serverSaslCreds'] is not None else None}
File "/usr/lib/python3.5/site-packages/pyasn1/type/univ.py", line 984, in bytes
return bytes(self._value)
File "/usr/lib/python3.5/site-packages/pyasn1/type/base.py", line 164, in plug
raise error.PyAsn1Error('Uninitialized ASN.1 value ("%s" attribute looked up)' % name)
pyasn1.error.PyAsn1Error: Uninitialized ASN.1 value ("len" attribute looked up)

ValueError: invalid literal for int() with base 10: urllib

I am not a python guru I am just writing a code to check my api authentication and URL access status. I just want to assure that my api and domain url is accessible to users.
For the above reason I am writing a python script which can check and a cron can send an alert to me.
Here is my Code:
def check(argv):
# I'm going to use argpase.It makes
# command-line args a breeze.
parser = argparse.ArgumentParser()
parser.add_argument('-H', '--hostname', dest='hostname', required=True)
parser.add_argument('-a', '--auth_id', dest='authenticationid')
parser.add_argument('-t', '--auth_token', dest='authenticationtoken')
parser.add_argument('-r', '--dest_url', dest='dest_url',help="""Path to report relative to root, like /v1/ OR /""", required=True)
parser.add_argument("-q", "--quiet", action="store_false", dest="verbose", default=True,
help="don't print status messages to stdout")
args = vars(parser.parse_args())
if args['authenticationid'] and args['authenticationtoken'] and not len(sys.argv) == 7:
authurl = urllib.request.Request('https://{%s}:{%s}#%s%s/%s/' %(args['authenticationid'],args['authenticationtoken'],args['hostname'], args['dest_url'],args['authenticationid']))
return (getAuthResponseCode(authurl))
else:
url = urllib.request.Request("https://%s%s" %(args['hostname'], args['dest_url']))
return(getResponseCode(url))
def getResponseCode(url):
try:
conn = urllib.request.urlopen(url,timeout=10)
code = conn.getcode()
return (status['OK'], code)
except timeout:
return (status['WARNING'], logging.error('socket timed out - URL %s', url))
except urllib.error.URLError as e:
return (status['CRITICAL'], e.reason)
else:
return (status['UNKNOWN'])
def getAuthResponseCode(authurl):
try:
authconn = urllib.request.urlopen(authurl, timeout=10)
authcode = authconn.getcode()
return (status['OK'], authcode)
except timeout:
return (status['WARNING'], logging.error('socket timed out - URL %s'))
except urllib.error.URLError as err:
return (status['CRITICAL'], err.reason)
else:
return (status['UNKNOWN'])
ERROR Message:
G:\Python>python check_http.py -H api.mydomain.com -r /API/Function/ -a 'MAMZMZZGVLMG
FMNTHIYTREETBESSS' -t 'DafniisfnsifnsifsbANBBDSDNBISDExODZlODAwMmZm'
Traceback (most recent call last):
File "C:\Python33\lib\http\client.py", line 770, in _set_hostport
port = int(host[i+1:])
ValueError: invalid literal for int() with base 10: "{'DafniisfnsifnsifsbANBBDSDNBISDExODZlODAw
MmZm'}#api.mydomain.com"
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "check_http.py", line 76, in <module>
print (check(sys.argv[1:]))
File "check_http.py", line 41, in check
return (getAuthResponseCode(authurl))
File "check_http.py", line 61, in getAuthResponseCode
authconn = urllib.request.urlopen(authurl, timeout=10)
File "C:\Python33\lib\urllib\request.py", line 156, in urlopen
return opener.open(url, data, timeout)
File "C:\Python33\lib\urllib\request.py", line 469, in open
response = self._open(req, data)
File "C:\Python33\lib\urllib\request.py", line 487, in _open
'_open', req)
File "C:\Python33\lib\urllib\request.py", line 447, in _call_chain
result = func(*args)
File "C:\Python33\lib\urllib\request.py", line 1283, in https_open
context=self._context, check_hostname=self._check_hostname)
File "C:\Python33\lib\urllib\request.py", line 1219, in do_open
h = http_class(host, timeout=req.timeout, **http_conn_args)
File "C:\Python33\lib\http\client.py", line 1172, in __init__
source_address)
File "C:\Python33\lib\http\client.py", line 749, in __init__
self._set_hostport(host, port)
File "C:\Python33\lib\http\client.py", line 775, in _set_hostport
raise InvalidURL("nonnumeric port: '%s'" % host[i+1:])
http.client.InvalidURL: nonnumeric port: '{'DafniisfnsifnsifsbANBBDSDNBISDExODZlODAw
MmZm'}#api.mydomain.com'
I know this is not write my code forum but I am helpless and looking for some help.If some one can tell where exactly I went wrong so that I can fix it.
I am using python3.
You're passing ʹhttps://user:pass#whateverʹ as the url.
Python doesn't understand you're trying to authenticate, and thinks you're passing ʹhttps://domain:port...ʹ
To do basic auth with urllib, you need to use a urllib.request.HTTPBasicAuthHandler
Sorry I'm not posting links and/or example code, but I'm typing this on my phone, and it makes those a pain.

Resources