Showing posts with label python. Show all posts
Showing posts with label python. Show all posts
Wednesday, February 06, 2013
Friday, January 11, 2013
National Geographic Photo of the Day using Python
A small snippet of code to get the National Geographic Photo of the Day.
It uses mechanize and beautiful soup 4 to help with the scraping.
It also has a function to allow walking backwards to pickup previous photos.
# -*- coding: utf-8 -*- import os import re import sys import mechanize from bs4 import BeautifulSoup MASTER_URL = "http://photography.nationalgeographic.com/photography/photo-of-the-day/?source=NavPhoPOD" class POD_Browser(mechanize.Browser): """ A browser for pod, with our configuration settings. """ def __init__(self, *args, **kwargs): mechanize.Browser.__init__(self, *args, **kwargs) self.set_handle_robots(False) self.set_debug_redirects(False) self.set_debug_http(False) self.set_handle_equiv(True) self.set_handle_gzip(True) self.set_handle_redirect(True) self.open(MASTER_URL) class Session(object): """ A Session. """ def __init__(self): self.browser = POD_Browser() def downloadPhotoOfTheDay(self): """ Search the page looking for a Wallpaper link. Not all pages have Wallpaper link, and we (politely) don't download the image in that case. """ page = self.browser.response().read() soup = BeautifulSoup(page) tags = soup.find_all('a', text = re.compile ('Download Wallpaper')) for t in tags: filename = t['href'].split('/')[-1] # If we've already downloaded the file, don't download it again. if not os.path.exists(filename): filename, _headers = self.browser.retrieve(t['href'], filename ) print filename sys.stdout.flush() def goPrevious(self): """ Find the previous link and go back a day """ link = self.browser.find_link(text_regex = re.compile('Previous')) self.browser.follow_link(link) def downloadPriorPhotos(self, start = 1, num = 10): """ Download some prior photos. You can start 7 days back and get 14 days of photos with start = 7, num = 14 :param start: How many days to go back before starting :param num: How many days to look at. """ for x in xrange(start): self.goPrevious() for x in xrange(num): self.downloadPhotoOfTheDay() self.goPrevious() if __name__ == '__main__': s = Session() s.downloadPhotoOfTheDay() # If you want to get the last week's worth uncomment this instead. #s.downloadPriorPhotos(num = 7)
Wednesday, April 11, 2012
pyWallpaper Updated
I have committed a much more comprehensive version of pyWallpaper to the subversion repository.
It is multi-threaded to speed up the wallpaper construction (most of the threads end up being I/O bound, so this is a win in terms of elapsed time).
Also supports walking subfolders by prefixing paths with a +
The code is still available at http://code.google.com/p/pywallpaper/
It is multi-threaded to speed up the wallpaper construction (most of the threads end up being I/O bound, so this is a win in terms of elapsed time).
Also supports walking subfolders by prefixing paths with a +
The code is still available at http://code.google.com/p/pywallpaper/
Labels:
multiple monitors,
PIL,
python,
wallpaper,
windows
Monday, July 26, 2010
Google Code Repo for windows wallpaper code
I've setup a google code repository for the pywallpaper code.
You can download it from there , and get any updates as I make them, or contribute patches.
pywallpaper project
You can download it from there , and get any updates as I make them, or contribute patches.
pywallpaper project
Labels:
python,
source code,
subversion,
wallpaper
Tuesday, July 20, 2010
Set windows wallpaper from python for multiple monitors
This code will allow you to set a different image per monitor for any combination of monitors. Monitors don't have to be the same size, or setup to be square on for it to work. You can have your third monitor straddling the other two, and the wallpaper will be built to accommodate it.
You can now specify per-monitor directory lists if you want.
There are blending and resizing options available too, see the comments.
I've added a setup.py to make a .exe so that the dos window doesn't pop-up.
You can now specify per-monitor directory lists if you want.
There are blending and resizing options available too, see the comments.
I've added a setup.py to make a .exe so that the dos window doesn't pop-up.
#!C:/python25/python.exe # Code to rotate or set wallpaper under windows # Copyright (C) Andrew K. Milton 2007 - 2010 # Released under a 2-clause BSD License # See: http://www.opensource.org/licenses/bsd-license.php # Multi monitor detection based on http://code.activestate.com/recipes/460509/ # This will handle any configuration of an arbitrary number of monitors, # including offset boundaries. import os import sys import time import random from optparse import OptionParser from ConfigParser import SafeConfigParser import ctypes from ctypes import windll from win32con import * import win32gui import win32api import win32con from PIL import Image, ImageDraw, ImageChops, ImageOps, ImageFilter # I recommend you create a pywallpaper.conf file that looks something # like this to store the directories in rather than specifying -d # multiple times on the command line. # # NB you can specify paths per monitor. Any monitor number without its # own paths will get the global paths. Monitors start at 0 which is always # the primary monitor. # # Some options don't play nicely together. """ [global] Blending = True BlendRatio = 0.40 Crop = False Fill = True Gradient = False PreRotate = True [directories] paths = C:\Documents and Settings\akm\My Documents\My Pictures\gb C:\Documents and Settings\akm\My Documents\My Pictures\Ralph [monitor_0] paths = C:\Documents and Settings\akm\My Documents\My Pictures\Wide Screen [monitor_1] paths = C:\Documents and Settings\akm\My Documents\My Pictures\Landscapes """ # If you don't like the little dos window that pops you can use the # following as setup.py to create a .exe that won't display the window, # makes it a little easier to use as a startup item too. """ from distutils.core import setup import py2exe options = { "bundle_files": 2, "ascii": 1, # to make a smaller executable, don't include the encodings "compressed": 1, # compress the library archive "excludes": ['w9xpopen.exe',] } setup( windows = ['pyWallpaper.py'], options = {'py2exe': options}, ) """ class RECT(ctypes.Structure): _fields_ = [ ('left', ctypes.c_long), ('top', ctypes.c_long), ('right', ctypes.c_long), ('bottom', ctypes.c_long) ] def dump(self): f = (self.left, self.top, self.right, self.bottom) return [int(i) for i in f] class MONITORINFO(ctypes.Structure): _fields_ = [ ('cbSize', ctypes.c_ulong), ('rcMonitor', RECT), ('rcWork', RECT), ('dwFlags', ctypes.c_ulong) ] class Monitor(object): def __init__(self, monitor, physical, working, flags): self.monitor = monitor self.physical = physical self.working = working self.size = self.getSize(*self.physical) self.width, self.height = self.size self.left, self.top, self.right, self.bottom = self.physical self._left, self._top, self._right, self._bottom = self.physical self.isPrimary = (flags != 0) self.cTop = self.top if self.cTop < 0: self.cTop = 20000 + self.cTop self.cLeft = self.left if self.cLeft < 0: self.cLeft = 20000 + self.cLeft self.wLeft = int(self.left) self.wTop = int(self.top) self.needsSplit = ( (self.left < 0 and self.right > 0) or (self.top < 0 and self.bottom > 0) ) if self.needsSplit: self.needVSplit = self.top < 0 and self.bottom > 0 self.needHSplit = self.left < 0 and self.right > 0 def addWallpaper(self, bgImage, wallpaper): if not self.needsSplit: bgImage.paste(wallpaper, (self.wLeft, self.wTop)) return if self.needVSplit: height = -self.top bottom = wallpaper.crop((0, 0, self.width, height)) bottom.load() top = wallpaper.crop((0, height, self.width, self.height)) top.load() bgImage.paste(top, (self.wLeft, 0)) bgImage.paste(bottom, (self.wLeft, bgImage.size[1] - height)) else: width = -self.left right = wallpaper.crop((0, 0, width, self.height)) right.load() left = wallpaper.crop((width, 0, self.width, self.height)) left.load() bgImage.paste(left, (0, self.wTop)) bgImage.paste(right, (bgImage.size[0] - width, self.wTop)) def getSize(self, left, top, right, bottom): return [abs(right - left), abs(bottom - top)] def __repr__(self): return 'extent: ' + str(self.physical) + ' :: size: ' + str(self.size) + ' :: primary: ' + str(self.isPrimary) + ' :: needsSplit ' + str(self.needsSplit) + ':: ' + hex(self.monitor) def __cmp__(self, other): if not cmp(self.cTop, other.cTop): return cmp(self.cLeft, other.cLeft) return cmp(self.top, other.top) class Desktop(object): def __init__(self): self.setMonitorExtents() # Merge with the desktop background colour # Handy to tint your background to your theme. self.Blending = True # Amount of picture to bg colour ratio # This works well for black... self.BlendRatio = 0.40 # Render a gradient under the image.. # I'm not overly happy with the results. self.Gradient = False # Crop black/white borders before zooming # This doesn't work well with Fill.. self.Crop = False # Don't just maxpect the image... blow it up so there's no bg colour # showing so this will crop parts. self.Fill = True # If the aspect ratio is "wrong" for the monitor, rotate it for a # better fit first. So portraits rotate for landscape monitors. # With per-monitor dirs you can sort your pictures based on aspect # ratio if you want. self.PreRotate = True self.createEmptyWallpaper() def createEmptyWallpaper(self): c = (0, 0, 0) if self.Blending: # Alpha blend the image with the current desktop colour # Or black if something goes wrong with getting the desktop colour try: dc = windll.user32.GetSysColor(1) c = ((dc & 0xFF ), (dc & 0xFF00) >> 8, (dc & 0xFF0000) >> 16) except: pass self.bgColour = c bgImage = Image.new('RGB', self.wSize, c) if self.Gradient: r, g, b = c width, height = bgImage.size fh = float(height) if (r + g + b) / 3 < 64: r1, g1, b1 = (128, 128, 128) else: r1, g1, b1 = c r, g, b = (64, 64, 64) rd = r1 - r gd = g1 - g bd = b1 - b rs = float(rd) / fh gs = float(gd) / fh bs = float(bd) / fh draw = ImageDraw.Draw(bgImage) for h in range(0, height): draw.line((0, h, width, h), fill = (int(r1), int(g1), int(b1))) r1 -= rs b1 -= bs g1 -= gs self.bgImage = bgImage def findMonitors(self): retval = [] CBFUNC = ctypes.WINFUNCTYPE(ctypes.c_int, ctypes.c_ulong, ctypes.c_ulong, ctypes.POINTER(RECT), ctypes.c_double) def cb(hMonitor, hdcMonitor, lprcMonitor, dwData): r = lprcMonitor.contents data = [hMonitor] data.append(r.dump()) retval.append(data) return 1 cbfunc = CBFUNC(cb) temp = windll.user32.EnumDisplayMonitors(0, 0, cbfunc, 0) return retval def calcWallSize(self): # Also sets the relative offsets for building the wallpaper... ms = self.monitors primaryMonitor = [m for m in ms if m.isPrimary][0] leftMonitors = [m for m in ms if m.left < 0] rightMonitors = [m for m in ms if m.left >= primaryMonitor.right] topMonitors = [m for m in ms if m.top < 0] bottomMonitors = [m for m in ms if m.top >= primaryMonitor.bottom] leftMonitors.sort() rightMonitors.sort() topMonitors.sort() bottomMonitors.sort() hMonitors = [primaryMonitor,] + rightMonitors + leftMonitors vMonitors = [primaryMonitor,] + bottomMonitors + topMonitors width = max([m.right for m in ms]) height = max([m.bottom for m in ms]) extraWidth = -min([m.left for m in ms]) extraHeight = -min([m.top for m in ms]) width += extraWidth height += extraHeight hOff = width redo = [] for m in leftMonitors: m.wLeft = width + m.left if m in bottomMonitors: continue m.right = width for m in topMonitors: m.wTop = height + m.top if m in rightMonitors: continue m.bottom = height return (width, height) def getMonitors(self): retval = [] for hMonitor, extents in self.findMonitors(): # data = [hMonitor] mi = MONITORINFO() mi.cbSize = ctypes.sizeof(MONITORINFO) mi.rcMonitor = RECT() mi.rcWork = RECT() res = windll.user32.GetMonitorInfoA(hMonitor, ctypes.byref(mi)) data = Monitor(hMonitor, mi.rcMonitor.dump(), mi.rcWork.dump(), mi.dwFlags) retval.append(data) return retval def setMonitorExtents(self): self.monitors = self.getMonitors() self.wSize = self.calcWallSize() def getDefaultDirs(self): return [r'C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures',] def setWallPaperFromBmp(self, pathToBmp): """ Given a path to a bmp, set it as the wallpaper """ # Set it and make sure windows remembers the wallpaper we set. result = windll.user32.SystemParametersInfoA( SPI_SETDESKWALLPAPER, 0, pathToBmp, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE) if not result: raise Exception("Unable to set wallpaper.") def autoCrop(self, im, bgcolor = (0, 0, 0)): if im.mode != "RGB": im = im.convert("RGB") im2 = ImageOps.autocontrast(im, 5) bg = Image.new("RGB", im.size, bgcolor) diff = ImageChops.difference(im2, bg) bbox = diff.getbbox() if bbox: return im.crop(bbox) return im # no contents def maxAspectWallPaper_fill(self, image, width, height): # Blow up the image making sure that the smallest image aspect # fills the monitor. rsFilter = Image.BICUBIC scale = 2.0 imWidth, imHeight = image.size hScale = float(height) / float(imHeight) wScale = float(width) / float(imWidth) scale = max(hScale, wScale) if scale < 1: rsFilter = Image.ANTIALIAS newSize = (int(imWidth * scale), int(imHeight * scale)) newImage = image.resize(newSize, rsFilter) if scale > 2: newImage = newImage.filter(ImageFilter.BLUR) imWidth, imHeight = newSize x = int((imWidth - width) / 2.0) y = int((imHeight - height) / 2.0) bbox = (x, 0, width + x, height + y) return newImage.crop(bbox) def maxAspectWallPaper(self, image, width, height): # Blow the image up as much as possible without exceeding the monitor # bounds. rsFilter = Image.BICUBIC scale = 2.0 imWidth, imHeight = image.size hScale = float(height) / float(imHeight) wScale = float(width) / float(imWidth) if self.Fill: scale = max(hScale, wScale) else: scale = min(hScale, wScale) if scale < 1: rsFilter = Image.ANTIALIAS newSize = (int(imWidth * scale), int(imHeight * scale)) newImage = image.resize(newSize, rsFilter) if self.Fill: imWidth, imHeight = newSize x = int((imWidth - width) / 2.0) y = int((imHeight - height) / 2.0) bbox = (x, 0, width + x, height + y) newImage = newImage.crop(bbox) return newImage def preRotateImage(self,image): # Rotate 90 degrees. im = image.rotate(-90, resample = True, expand = True) return im def createWallPaperFromFile(self, pathToImage, monitor): # Given a path to an image, convert it to bmp format and set it as # the wallpaper bmpImage = Image.open(pathToImage) if self.PreRotate: if bmpImage.size[0] < bmpImage.size[1]: bmpImage = self.preRotateImage(bmpImage) if self.Crop: bmpImage = self.autoCrop(bmpImage, (0,0,0)) bmpImage = self.autoCrop(bmpImage, (255,255,255)) bmpImage = self.maxAspectWallPaper(bmpImage, *monitor.size) bmpSize = bmpImage.size xOffset = int((monitor.size[0] - bmpImage.size[0]) / 2) yOffset = int((monitor.size[1] - bmpImage.size[1]) / 2) if bmpImage.size != monitor.size: img1 = Image.new("RGB", monitor.size, (0, 0, 0)) img1.paste(bmpImage, (xOffset, yOffset)) if self.Blending: img2 = Image.new("RGB", monitor.size, self.bgColour) return Image.blend(img2, img1, self.BlendRatio) return img1 def setWallpaperStyleSingle(self): # 0x80000001 == HKEY_CURRENT_USER k = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER,"Control Panel\\Desktop",0,win32con.KEY_SET_VALUE) win32api.RegSetValueEx(k, "WallpaperStyle", 0, win32con.REG_SZ, "0") win32api.RegSetValueEx(k, "TileWallpaper", 0, win32con.REG_SZ, "0") def setWallpaperStyleMulti(self): # To set a multi-monitor wallpaper, we need to tile it... # 0x80000001 == HKEY_CURRENT_USER k = win32api.RegOpenKeyEx(win32con.HKEY_CURRENT_USER,"Control Panel\\Desktop",0,win32con.KEY_SET_VALUE) win32api.RegSetValueEx(k, "WallpaperStyle", 0, win32con.REG_SZ, "0") win32api.RegSetValueEx(k, "TileWallpaper", 0, win32con.REG_SZ, "1") def setWallpaperStyle(self): if len(self.monitors) > 1: self.setWallpaperStyleMulti() else: self.setWallpaperStyleSingle() def setWallpaper(self): self.setWallpaperStyle() # Save the new wallpaper in our current directory. newPath = os.getcwd() newPath = os.path.join(newPath, 'pywallpaper.bmp') self.bgImage.save(newPath, "BMP") self.setWallPaperFromBmp(newPath) def setWallpaperFromFile(self, pathToImage): for monitor in self.monitors: img = self.createWallPaperFromFile(filename, monitor) monitor.addWallpaper(self.bgImage, img) self.setWallpaper() def setWallPaperFromFileList(self, pathToDir, monitor): """ Given a directory choose an image from it and set it as a wallpaper """ # Image directories often contain Thumbs.db or other non-image # files or directories, try a few times to set a wallpaper, and then just give up. tries = 0 done = False filenames = [] files = os.listdir(pathToDir) try: # Priorwalls.txt is used so that we don't repeat an image # until every other image in that directory has been seen # The file is rewritten when necessary. prevList = open('priorWalls.txt', 'rb') filenames = [l.strip() for l in prevList.readlines()] prevList.close() except: pass files = [os.path.join(pathToDir, f) for f in files if not f.endswith('.db')] availChoices = [f for f in files if not f in filenames and not f.endswith('.db')] if not availChoices: # This entire directory has been "done" remove them # from the previously seen wallpapers and rewrite # the cache file without any of these entries. filenames = [f for f in filenames if not f in files] availChoices = files p = open('priorWalls.txt', 'wb') for f in filenames: p.write("%s\n"%(f)) p.close() files = availChoices while (not done) and tries < 3: # Thumbs.db and other stuff can live in the same Folder # So try three times to set a wallpaper before giving up. try: image = random.choice(files) filename = image img = self.createWallPaperFromFile(filename, monitor) monitor.addWallpaper(self.bgImage, img) prevList = open('priorWalls.txt', 'ab') prevList.write("%s\n"%(filename)) done = True except: import traceback; traceback.print_exc() print >> sys.stderr, filename, "failed" tries += 1 return done def getMonitorDirs(self, monIndex): section = 'monitor_%d'%(monIndex) # Check for [monitor_0] if self.config.has_section(section): # check for its own paths section if self.config.has_option(section, 'paths'): dirs = self.config.get(section, 'paths').split('\n') else: dirs = self.dirs return dirs def setWallPaperFromDirList(self): """ Given a list of directories choose a directory """ for monNum, monitor in enumerate(self.monitors): imageDir = random.choice(self.getMonitorDirs(monNum)) status = self.setWallPaperFromFileList(imageDir, monitor) self.setWallpaper() def getImageDirectories(self): # Set global image directories. dirs = [] try: dirs = self.config.get('directories', 'paths').split('\n') except: pass if not dirs: dirs = self.getDefaultDirs() return dirs def setWallPaperFromConfigDirs(self): self.setWallPaperFromDirList() def getConfigFileOptions(self, options): configFile = 'pywallpaper.conf' if options.configFile: configFile = options.configFile dirs = options.directories self.config = SafeConfigParser() self.config.readfp(open(configFile)) if self.config.has_section('global'): self.Blending = self.config.getboolean('global', 'Blending') self.BlendRatio = self.config.getfloat('global', 'BlendRatio') self.Crop = self.config.getboolean('global', 'Crop') self.Fill = self.config.getboolean('global', 'Fill') self.Gradient = self.config.getboolean('global', 'Gradient') self.PreRotate = self.config.getboolean('global', 'PreRotate') def getCommandLineOptions(self): parser = OptionParser() parser.add_option("-t", "--time", dest="change_time", help = "Change wallpaper time in minutes (0 = change once and exit [default])", default = 0, type = "int") parser.add_option("-i", "--image", dest="singleImage", default = None, help = "Set wallpaper to this image and exit (overrides -d)") parser.add_option("-d", "--directory", dest="directories", default = [], action="append", type="string", help = "Add an image directory") parser.add_option("-c", "--config", dest="configFile", default = None, help = "path to alternate config file (default <working dir>/pywallpaper.conf)") parser.add_option("-w", "--workingdir", dest="cwd", default=".", help = "Working Directory (default .)") (options, args) = parser.parse_args() return (options, args) def go(self): options, args = self.getCommandLineOptions() self.getConfigFileOptions(options) self.dirs = self.getImageDirectories() if options.cwd and options.cwd != '.': os.cwd(cwd) if options.singleImage: self.setWallPaper(options.singleImage) elif not options.change_time: self.setWallPaperFromConfigDirs() else: sleepTime = options.change_time * 60.0 while True: self.setWallPaperFromDirList() time.sleep(sleepTime) if __name__ == '__main__': d = Desktop() d.go()
Saturday, February 20, 2010
Decode Encrypted CueCat Output With Ugly Python
import sys; from string import maketrans as m; from binascii import a2b_uu as d q = lambda x,y: ''.join([chr(c) for c in range(ord(x), ord(y) + 1)]) t = m(q('a','z') + q('A','Z') + q('0','9') + '+-', q(' ','_')) def u(st): return ''.join([chr(ord(c) ^ 67) for c in d(chr(32 + 3 * len(st) / 4) + st)]) print "ID: %s, Type: %s, Barcode: %s"%(tuple([u(b.translate(t)) for b in sys.stdin.read().split('.')[1:-1]]))
Monday, March 19, 2007
Sendfile Patch for Zope2
I've put together a patch for Zope that allows code to use the sendfile system call to transfer data out of Zope.
As this requires a file object, it's only available for use from trusted code, so that means inside a Product or an External method.
The good news is, that it's fairly easy to write an External method that does something useful like serve contents from a directory.
Here's an example external method that serves files from '/shared/images'
It gives you a speed up of 2-3 times serving content out of Zope from the filesystem.
I also have a patch for ExternalFile to let this use the sendfile patch.
You can get the code and the patch from zope.org
As this requires a file object, it's only available for use from trusted code, so that means inside a Product or an External method.
The good news is, that it's fairly easy to write an External method that does something useful like serve contents from a directory.
Here's an example external method that serves files from '/shared/images'
It uses the sendfile wrapper module from here.
import os
directory = '/shared/images'
def Image(self, filename):
newPath = os.path.join(directory, filename)
if not os.access(newPath, os.F_OK|os.R_OK):
self.REQUEST.RESPONSE.setStatus(404)
return ''
f = open(newPath, 'rb')
self.REQUEST.RESPONSE.sendfile(f, content_type='image/jpeg', other_headers = {'Content-Disposition', 'inline;filename=%s'%(filename))
f.close()
return ''
It gives you a speed up of 2-3 times serving content out of Zope from the filesystem.
I also have a patch for ExternalFile to let this use the sendfile patch.
You can get the code and the patch from zope.org
Labels:
ExternalFile,
python,
sendfile,
zope
Saturday, February 17, 2007
ZopeTrac Updated
I have updated ZopeTrac to 0.10.3, which makes it work with Trac 0.10.3.
You can get it from here; here.
I will try to mimic the Trac release numbers so you can tell what version of Trac it last worked with.
You can get it from here; here.
I will try to mimic the Trac release numbers so you can tell what version of Trac it last worked with.
Monday, February 05, 2007
Set Windows Wallpaper from Python
*** For multiple monitors see this post instead Set windows wallpaper from python for multiple monitors ***
Here's some code to set a random wallpaper from a list of images, or a list of directories or a single image. It doesn't recurse subdirectories, but, that's just as simple to add if you really require that functionality. It requires PIL.
You can set it to change the wallpaper to rotate to a new one at a specified number of minutes.
It can use any image that PIL can read (it converts it to a BMP).
Here's some code to set a random wallpaper from a list of images, or a list of directories or a single image. It doesn't recurse subdirectories, but, that's just as simple to add if you really require that functionality. It requires PIL.
You can set it to change the wallpaper to rotate to a new one at a specified number of minutes.
It can use any image that PIL can read (it converts it to a BMP).
# Code to rotate or set wallpaper under windows # Copyright (C) Andrew K. Milton 2007 # Released under a 2-clause BSD License # See: http://www.opensource.org/licenses/bsd-license.php import os import time import random from optparse import OptionParser from ConfigParser import SafeConfigParser from ctypes import windll from win32con import * from PIL import Image """ I recommend you create a pywallpaper.conf file that looks something like this; [directories] paths = C:\Documents and Settings\akm\My Documents\My Pictures\gb C:\Documents and Settings\akm\My Documents\My Pictures\Ralph to store the directories in rather than specifying -d multiple times on the command line""" def getDefaultDirs(): return [r'C:\Documents and Settings\All Users\Documents\My Pictures\Sample Pictures',] def setWallPaperFromBmp(pathToBmp): """ Given a path to a bmp, set it as the wallpaper """ result = windll.user32.SystemParametersInfoA(SPI_SETDESKWALLPAPER, 0, pathToBmp, SPIF_UPDATEINIFILE | SPIF_SENDWININICHANGE) if not result: raise Exception("Unable to set wallpaper.") def setWallPaper(pathToImage): """ Given a path to an image, convert it to bmp format and set it as the wallpaper""" bmpImage = Image.open(pathToImage) newPath = os.getcwd() newPath = os.path.join(newPath, 'pywallpaper.bmp') bmpImage.save(newPath, "BMP") setWallPaperFromBmp(newPath) def setWallPaperFromFileList(pathToDir): """ Given a directory choose an image from it and set it as a wallpaper """ # Image directories often contain Thumbs.db or other non-image # files or directories, try a few times to set a wallpaper, and then just give up. tries = 0 done = False while (not done) and tries < 3: try: files = os.listdir(pathToDir) image = random.choice(files) setWallPaper(os.path.join(pathToDir, image)) done = True except: tries += 1 return done def setWallPaperFromDirList(pathList): """ Given a list of directories choose a directory """ imageDir = random.choice(pathList) status = setWallPaperFromFileList(imageDir) # Don't really need to say anything if we couldn't set the # wallpaper, I think the user will notice def getImageDirectories(options): configFile = 'pywallpaper.conf' if options.configFile: configFile = options.configFile dirs = options.directories try: config = SafeConfigParser() config.readfp(open(configFile)) dirs += config.get('directories', 'paths').split('\n') except: pass if not dirs: # raise Exception("No directories defined") dirs = getDefaultDirs() return dirs def setWallPaperFromConfigDirs(options): setWallPaperFromDirList(getImageDirectories(options)) def getCommandLineOptions(): parser = OptionParser() parser.add_option("-t", "--time", dest="change_time", help = "Change wallpaper time in minutes (0 = change once and exit [default])", default = 0, type = "int") parser.add_option("-i", "--image", dest="singleImage", default = None, help = "Set wallpaper to this image and exit (overrides -d)") parser.add_option("-d", "--directory", dest="directories", default = [], action="append", type="string", help = "Add an image directory") parser.add_option("-c", "--config", dest="configFile", default = None, help = "path to alternate config file (default <working dir>/pywallpaper.conf)") parser.add_option("-w", "--workingdir", dest="cwd", default=".", help = "Working Directory (default .)") (options, args) = parser.parse_args() return (options, args) if __name__ == '__main__': options, args = getCommandLineOptions() if options.cwd and options.cwd != '.': os.cwd(cwd) if options.singleImage: setWallPaper(options.singleImage) elif not options.change_time: setWallPaperFromConfigDirs(options) else: dirs = getImageDirectories(options) sleepTime = options.change_time * 60.0 while True: setWallPaperFromDirList(dirs) time.sleep(sleepTime)
Friday, May 12, 2006
Zope and Trac
I've put together a Zope frontend for Trac.
It seems to work fine (at least for me).
You can find it here
It seems to work fine (at least for me).
You can find it here
Thursday, April 13, 2006
Australian Eastern Timezones in Zope
Zope has had a well known bug with detecting Eastern Australian Timezones for a long long long time. Well today I got sick of detailing the workaround and created a Monkey Patch product for Zope 2 to fix it.
The problem is that Zope thinks that the EST and EDT timezones should be AEST and AEDT, well that's not what they're called, so most of the AU Zope servers run in US/Eastern time, which is very very very annoying.
So if you're in an Eastern AU state and you'd like your logs and times to be local without jumping through hoops, try downloading; ZAUTZ
The problem is that Zope thinks that the EST and EDT timezones should be AEST and AEDT, well that's not what they're called, so most of the AU Zope servers run in US/Eastern time, which is very very very annoying.
So if you're in an Eastern AU state and you'd like your logs and times to be local without jumping through hoops, try downloading; ZAUTZ
Monday, March 27, 2006
More side projects, and (small) Javascript grid rant.
I'm letting Compiled Page Templates settle for a little bit, I got some pretty quick feedback about some bugs, but, nothing for a little while, I'm sure there will be more. I'm hoping it gets a hammering by some people. I converted ZWiki to use it, but, the underlying framework is a little too obfuscated to really get a decent speed up out of it (I could only manage 10%).
Meanwhile I'm working on Javascript parser in python. I'm not sure where this will end up, but, I can see that it would be very useful to be able to run javascript inside python.
I've been trying to find a 'nice' looking template so I can actually build a 'proper' website. I've spent a few hours playing around building static pages, and I just can't be bothered. So I guess I'll being doing something in Zope for that too. Actually once I get that up and running, I think I might consolidate all of my various projects there. As always it's finding the time, and since we're being evicted, I don't think I'll make any headway on that until after we find a new place and move in.
I played a little with jsolait and Zope the other day. The jsolait xmlrpc lib is like python's so it's nice to use (even though I'm not a Javascript guy really), but, it's going to help out on my current paying gig, so it was worth investigating. I'm not really a front-end guy at all, but, it's irritating that even the 'nice' javascript grid widgets suck. I guess that's a byproduct of living inside a webpage. I really want to be able to create a grid that grows and shrinks dynamically. All of the ones I've seen so far, can grow, but, never get any smaller. That's great if you want to browse a fixed dataset, but, rotten if, for example, you want to display an active queue of items.
On the grid thing, the LiveGrid people suggested we no longer needed paging, and we could just use scrolling to navigate through datasets. Well that's great if your dataset is really small, but, it's sucks if you want to get to something in the middle of the dataset. Something that will stay in the middle of the dataset regardless of how you sort it. I often find myself binary searching results from various searches trying to find the set I want (I'm not talking google searches here). I don't want to go back to linear search.
Meanwhile I'm working on Javascript parser in python. I'm not sure where this will end up, but, I can see that it would be very useful to be able to run javascript inside python.
I've been trying to find a 'nice' looking template so I can actually build a 'proper' website. I've spent a few hours playing around building static pages, and I just can't be bothered. So I guess I'll being doing something in Zope for that too. Actually once I get that up and running, I think I might consolidate all of my various projects there. As always it's finding the time, and since we're being evicted, I don't think I'll make any headway on that until after we find a new place and move in.
I played a little with jsolait and Zope the other day. The jsolait xmlrpc lib is like python's so it's nice to use (even though I'm not a Javascript guy really), but, it's going to help out on my current paying gig, so it was worth investigating. I'm not really a front-end guy at all, but, it's irritating that even the 'nice' javascript grid widgets suck. I guess that's a byproduct of living inside a webpage. I really want to be able to create a grid that grows and shrinks dynamically. All of the ones I've seen so far, can grow, but, never get any smaller. That's great if you want to browse a fixed dataset, but, rotten if, for example, you want to display an active queue of items.
On the grid thing, the LiveGrid people suggested we no longer needed paging, and we could just use scrolling to navigate through datasets. Well that's great if your dataset is really small, but, it's sucks if you want to get to something in the middle of the dataset. Something that will stay in the middle of the dataset regardless of how you sort it. I often find myself binary searching results from various searches trying to find the set I want (I'm not talking google searches here). I don't want to go back to linear search.
Labels:
Javascript,
python,
zope,
ZPT
Subscribe to:
Posts (Atom)