Django + solr.thumbnail: get_thumbnail() fails in test environment - python

I'm trying to find a way how to test thumbnail generation when using Django and sorl-thumbnail's get_thumbnail() method.
Environment:
Django==1.5.5
Pillow==2.1.0
sorl-thumbnail==11.12
Simplified code under test (ran in test environment):
from StringIO import StringIO
from PIL import Image
from django.conf import settings
from django.core.files.uploadedfile import InMemoryUploadedFile
from django.db import models
from sorl.thumbnail import get_thumbnail
# simple class with ImageField
class User(models.Model):
avatar = models.ImageField(upload_to='avatars', default=None, null=True, blank=True)
def get_thumbnail_uri(self):
avatar_thumbnail = get_thumbnail(self.avatar, '100x100')
return avatar_thumbnail.url
# make sure we're using in-memory test env.
assert settings.THUMBNAIL_STORAGE == 'inmemorystorage.InMemoryStorage'
assert settings.DEFAULT_FILE_STORAGE == 'inmemorystorage.InMemoryStorage'
# prepare image
fake_file = StringIO()
picture = Image.new(mode='RGBA', size=(500, 500), color=(255, 0, 0, 0))
picture.save(fake_file, 'JPEG')
fake_file.name = 'test.jpg'
fake_file.seek(0)
uploaded_image = InMemoryUploadedFile(fake_file, field_name=None, name='test.jpg',
content_type='image/jpeg', size=fake_file.len,
charset=None)
# add image to user
u = User()
u.avatar = uploaded_image
assert u.get_thumbnail_uri() is not None
The above always fails on the last line:
Traceback (most recent call last):
File "/vagrant/path/to/file.py", line 1440, in test_stackprep
assert u.get_thumbnail_uri() is not None
File "/vagrant/path/to/file.py", line 1413, in get_thumbnail_uri
avatar_thumbnail = get_thumbnail(self.avatar, '100x100')
File "/home/vagrant/.virtualenv/appname/local/lib/python2.7/site-packages/sorl/thumbnail/shortcuts.py", line 8, in get_thumbnail
return default.backend.get_thumbnail(file_, geometry_string, **options)
File "/home/vagrant/.virtualenv/appname/local/lib/python2.7/site-packages/sorl/thumbnail/base.py", line 56, in get_thumbnail
source_image = default.engine.get_image(source)
File "/home/vagrant/.virtualenv/appname/local/lib/python2.7/site-packages/sorl/thumbnail/engines/pil_engine.py", line 13, in get_image
return Image.open(buf)
File "/home/vagrant/.virtualenv/appname/local/lib/python2.7/site-packages/PIL/Image.py", line 2008, in open
raise IOError("cannot identify image file")
IOError: cannot identify image file
I assume that either Django or sorl-thumbnail gets out of inmemorystorage while running the test. I've been at it for a long time, but I failed to find any configuration that works, with the exception of testing stuff directly on the filesystem (which I'd like to avoid).
Did anyone manage to get sorl's get_thumbnail() method working in tests, please?
Thanks.

Version 11.12, which is the latest one on PyPI today, is 2 years old. There's version 12.0 available in repo, which should work. It's not on PyPI, because there was change of maintainers and I guess they hadn't chance to do it yet.
I've tried master version and it works ok with your example.

Related

Taking Screenshot's using python using the Virtualbox API

I'm trying to take screenshots from my guest Virtualbox session using a python script running in the host. From the research I did the best way of doing this is accessing the VirtualBox API and using COM constants in order to make a screenshot. However, every time I try to run the script I get an attribute error:
Traceback (most recent call last):
File "D:\computer_vision_scripts\take_screenshot.py", line 29, in <module>
take_screenshot('Windows 10 Pro')
File "D:\computer_vision_scripts\take_screenshot.py", line 16, in take_screenshot
machine.LockMachine(session, constants.LockType_Shared)
File "C:\Users\me\AppData\Roaming\Python\Python39\site-packages\win32com\client\__init__.py", line 180, in __getattr__
raise AttributeError(a)
AttributeError: LockType_Shared
The script I am using comes from https://floatingoctothorpe.uk/2018/automating-virtualbox-screenshots-with-python.html
And looks like this when seen in the file version:
import win32com.client
from win32com.client import constants
def take_screenshot(vm_name, screenshot_path='screenshot.png'):
"""Create a VM Screenshot for a given VM"""
vbox = win32com.client.Dispatch("VirtualBox.VirtualBox")
session = win32com.client.Dispatch("VirtualBox.Session")
machine = vbox.FindMachine(vm_name)
machine.LockMachine(session, constants.LockType_Shared)
display = session.Console.Display
width, height, _, _, _, _ = display.GetScreenResolution(0)
screenshot = display.TakeScreenShotToArray(0, width, height,
constants.BitmapFormat_PNG)
session.UnlockMachine()
with open(screenshot_path, 'wb') as output_png:
output_png.write(screenshot.tobytes())
if __name__ == '__main__':
take_screenshot('Windows 10 Pro')
Does anyone know what I should do in order to make it work?
I faced the same issue.
Solved it like this:
Add this:
import virtualbox
from virtualbox import library
Change
machine.LockMachine(session, constants.LockType_Shared)
by
machine.LockMachine(session, virtualbox.library.LockType.shared)
and
screenshot = display.TakeScreenShotToArray(0, width, height,constants.BitmapFormat_PNG)
by
screenshot = display.TakeScreenShotToArray(0, width, height, virtualbox.library.BitmapFormat.png)
Found this solution here:
https://github.com/sethmlarson/virtualbox-python/blob/master/tests/test_test_vm.py

Why is Django adding a typo when saving a file?

I am writing some test code for a project I am making with Django. The test code is such:
from django.test import TestCase, override_settings
from django.core.files import File
import sys
import os
from .models import Manual
#override_settings(MEDIA_ROOT=os.getcwd()+'/temp/django_test')
# Create your tests here.
class ManualModelTests(TestCase):
def tearDown(self):
try:
os.remove('/temp/django_test/test_image.jpg')
except FileNotFoundError:
pass
def test_normal_manual_upload(self):
in_image = open(os.path.join(os.path.dirname(__file__), 'test_image.jpg'), 'r+b')
in_file = open(os.path.join(os.path.dirname(__file__), 'test_manual.pdf'), 'r+b')
thumbnail = File(in_image)
in_manual = File(in_file)
new_manual = Manual.objects.create(
photo=thumbnail,
manual=in_manual,
make='yoshimura',
model='001',
year_min=2007,
year_max=2010
)
self.assertTrue(os.path.exists('/temp/django_test/photos/test_image.jpg'))
self.assertTrue(os.path.exists
('/temp/django_test/manuals/test_manual.pdf'))
self.tearDown()
The model code is such:
class Manual(models.Model):
photo = models.ImageField(upload_to="photos")
make = models.CharField(max_length=50)
model = models.CharField(max_length=100)
manual = models.FileField(upload_to="manuals")
year_min = models.PositiveIntegerField(default=0)
year_max = models.PositiveIntegerField(default=0)
The test code aims to create a Manual object (just testing to see if the model saves normally). Upon running the code however, after finishing the model constructor call, I get a crazy long error that comes after many calls of python's makdirs() function ends with
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: 'C:\\Users\\Jason\\Projects\\motomanuals\\temp\\django_test\\photos\\C:'
A full pastebin of the error can be found here
My guess is the problems stems from the path ending in '\\C:'?
My questions are:
Is my guess right. If not, then why am I getting this error?
Why is Django trying to add '\\C:\' to the file path and how do I fix this?

How do I store images in a python script using Tkinter?

I want to render an image in tkinter but I always end up with an error saying that the image (PieTalk.gif) could not be found even though the image is in the same directory as the python script (startupgui.py):
/Home/COMP3203/COMP30203-project/src/ptgui/
Here is the method where I want to render an image in a GUI. The following code is a class called startupgui.py. It consists of a constructor and a method to load the image
Constructor:
def __init__(self):
# String to decide whether to go to client or server
self.trigger = None
#-----------------------#
# Creating window frame #
#-----------------------#
self.root = Tk()
self.root.wm_title("PieTalk")
self.root.geometry('600x450')
# creating PieTalk image
self.createimage()
# creating buttons
self.createbuttons()
Method to load image:
def createimage(self):
# Creating image frame
self.imageframe = Frame(self.root, bg='light grey')
self.imageframe.place(relx=0.1, relwidth=0.8, rely=0.05, relheight=0.65)
# Creating PieTalk image
self.pietalkimage=PhotoImage(file="PieTalk.gif")
# Creating label
self.imagelabel = Label(self.imageframe, image=pietalkimage)
self.imagelabel.image = self.pietalkimage
self.imagelabel.pack()
I have used the file name only:
self.pietalkimage=PhotoImage(file="PieTalk.gif")
And I have also used the absolute path to the file:
self.pietalkimage=PhotoImage(file="/Home/COMP3203/COMP30203-project/src/ptgui/PieTalk.gif")
Unfortunately, I keep on getting the same error when I execute the script:
Traceback (most recent call last):
File "pietalk.py", line 361, in <module>
startview=sgui.startupgui()
File "/home/archit/COMP3203/COMP3203-project/src/ptgui/startupgui.py", line 66, in __init__
self.createimage()
File "/home/archit/COMP3203/COMP3203-project/src/ptgui/startupgui.py", line 33, in createimage
self.pietalkimage=PhotoImage(file="/Home/COMP3203/COMP30203-project/src/ptgui/PieTalk.gif")
File "/usr/lib/python3.4/tkinter/__init__.py", line 3387, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/usr/lib/python3.4/tkinter/__init__.py", line 3343, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "/Home/COMP3203/COMP30203-project/src/ptgui/PieTalk.gif": no such file or directory
Is there something else that I am doing wrong when I am loading the image? What else can I do to load an image?
first convert it to base64 python variable
>>> import base64
>>> with open("my_image.py","w") as f:
... f.write('my_image="""%s"""'%base64.b64encode(open("my_gif.gif","rb").read()))
...
>>> exit()
you should now have the my_image.py file there ... copy that to the same directory as your tkinter script... an now you can do
from my_image import my_image
image=PhotoImage(data = my_image)
since you are having some problems lets try and simplify it a little bit
img2base64.py
import base64,sys,os,re
assert len(sys.argv) > 2,"Error: Useage %s /path/to/image.gif outfile.py"
assert os.path.exists(sys.argv[1]),"Error Unable to find image passed in as first argument"
outfile = open(sys.argv[2],"w")
raw_binary_data = open(sys.argv[1],"rb").read()
b64_encoded_data = base64.b64encode(raw_binary_data)
varname = re.sub("[^W]","_",os.path.splitext(os.path.basename(sys.argv[1]))[0])
pyname = os.path.splitext(os.path.basename(sys.argv[2]))[0]
outfile.write("%s='''%s'''"%(varname,b64_encoded_data))
outfile.close()
print "all done please put %s in your script directory and use it as follows:"%sys.argv[2]
print "from %s import %s"%(pyname,varname)
print "image=PhotoImage(data = %s)"%(varname)
just save that and then call it
$ python img2base64.py /path/to/image.gif pyimage.py
I think at least I didnt try it ...
Inspired by previous answer:
import base64
from pathlib import Path
import sys
src = Path(sys.argv[1])
dst = src.with_suffix(".py")
with dst.open("w") as f:
data = base64.b64encode(src.read_bytes()).decode('utf-8')
f.write(f'image="{data}"')
exit()
and I tested it ;-)

Runtime error:App registry isn't ready yet

I am trying to create a script that populates a database with test users. I am new to Django and Python. I keep on getting:
Runtime error: App registry isn't ready yet.
Here is the output and error:
starting population script
Traceback (most recent call last):
File "populate.py", line 32, in <module>
populate()
File "populate.py", line 22, in populate
i.save()
File "c:\Python27\lib\site-packages\django-1.7a2-py2.7.egg\django\db\models\base.py", line 603, in save
force_update=force_update, update_fields=update_fields)
...
...
...
File "c:\Python27\lib\site-packages\django-1.7a2-py2.7.egg\django\apps\registry.py", line 156, in get_models
self.check_ready()
File "c:\Python27\lib\site-packages\django-1.7a2-py2.7.egg\django\apps\registry.py", line 119, in check_ready
raise RuntimeError("App registry isn't ready yet.")
RuntimeError: App registry isn't ready yet.
Here is the code:
import os
import datetime
def populate():
freer = User.objects.create_user( 'joyyie', 'lolcats#gmail.com', 'e')
cat = User.objects.create_user( 'steve', 'l2olcats#gmail.com', 'e')
dog = User.objects.create_user( 'aasd', 'lo3lcats#gmail.com', 'ad')
cow = User.objects.create_user( 'sadsfa', 'lol4cats#gmail.com', 't' )
pig = User.objects.create_user( 'regibald', 'lolc5ats#gmail.com', '0')
donkey = User.objects.create_user( 'turnip', 'lolca6ts#gmail.com', 'pop')
human = User.objects.create_user( 'tutu', 'lolcat7s#gmail.com', 'pa')
a = [freer,cat,dog,cow,pig,donkey,human]
for i in a:
i.first_name= 'jackee'
i.is_superuser=True
i.is_staff=False
i.date_joined=datetime.datetime.today()
i.last_login=datetime.datetime.today()
i.save()
if __name__=='__main__':
print "starting population script"
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'infosmos.settings')
from django.conf import settings
from django.db import models
from django.contrib.auth.models import User
populate()
Is there a way to force the user profile creation to wait for the registry app by using a signal or something?
[django 1.7] The Standalone script you wish to run, import django and settings like below
import os
import django
[...]
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
django.setup()
This is a known and intended behaviour according to Django's 1.7 release notes, under the "startup sequence" clause:
Another common culprit is django.contrib.auth.get_user_model(). Use the AUTH_USER_MODEL setting to reference the User model at import time.
and that should do the trick
for reference:
https://docs.djangoproject.com/en/dev/releases/1.7/#app-loading-changes
I found out that if I run populate through the manage.py shell with the execfile() command then it runs properly. Everything needed to be setup before I start modifying the database or run outside code. Thanks to lanzz for the hint.

django error ,about django-sphinx

from django.db import models
from djangosphinx.models import SphinxSearch
class MyModel(models.Model):
search = SphinxSearch() # optional: defaults to db_table
# If your index name does not match MyModel._meta.db_table
# Note: You can only generate automatic configurations from the ./manage.py script
# if your index name matches.
search = SphinxSearch('index_name')
# Or maybe we want to be more.. specific
searchdelta = SphinxSearch(
index='index_name delta_name',
weights={
'name': 100,
'description': 10,
'tags': 80,
},
mode='SPH_MATCH_ALL',
rankmode='SPH_RANK_NONE',
)
queryset = MyModel.search.query('query')
results1 = queryset.order_by('#weight', '#id', 'my_attribute')
results2 = queryset.filter(my_attribute=5)
results3 = queryset.filter(my_other_attribute=[5, 3,4])
results4 = queryset.exclude(my_attribute=5)[0:10]
results5 = queryset.count()
# as of 2.0 you can now access an attribute to get the weight and similar arguments
for result in results1:
print result, result._sphinx
# you can also access a similar set of meta data on the queryset itself (once it's been sliced or executed in any way)
print results1._sphinx
and
Traceback (most recent call last):
File "D:\zjm_code\sphinx_test\models.py", line 1, in <module>
from django.db import models
File "D:\Python25\Lib\site-packages\django\db\__init__.py", line 10, in <module>
if not settings.DATABASE_ENGINE:
File "D:\Python25\Lib\site-packages\django\utils\functional.py", line 269, in __getattr__
self._setup()
File "D:\Python25\Lib\site-packages\django\conf\__init__.py", line 38, in _setup
raise ImportError("Settings cannot be imported, because environment variable %s is undefined." % ENVIRONMENT_VARIABLE)
ImportError: Settings cannot be imported, because environment variable DJANGO_SETTINGS_MODULE is undefined.
I know what the problem is :)
You are trying to run this script as stand-alone. But since you use django models. all of them have to be imported in your namespace. This is what is the error. It clearly days ImportError.
To solve - go to your django-project directory & then type python manage.py shell. This imports all Django-env files. Now import your models & try out the search.
The error is about the environment. Django cannot find your settings file; Are you doing
python manage.py runserver
itself, or something else?

Categories

Resources