Thursday, 16 December 2010
teethgrinder :: python spider using mechanize pullparser and beautiful soup
Tuesday, 7 December 2010
http://svn.python.org/projects/python/trunk/Demo/pdist/rcslib.py
"""RCS interface module.Defines the class RCS, which represents a directory with rcs versionfiles and (possibly) corresponding work files."""import fnmatchimport osimport reimport stringimport tempfileclass RCS: """RCS interface class (local filesystem version). An instance of this class represents a directory with rcs version files and (possible) corresponding work files. Methods provide access to most rcs operations such as checkin/checkout, access to the rcs metadata (revisions, logs, branches etc.) as well as some filesystem operations such as listing all rcs version files. XXX BUGS / PROBLEMS - The instance always represents the current directory so it's not very useful to have more than one instance around simultaneously """ # Characters allowed in work file names okchars = string.ascii_letters + string.digits + '-_=+' def __init__(self): """Constructor.""" pass def __del__(self): """Destructor.""" pass # --- Informational methods about a single file/revision --- def log(self, name_rev, otherflags = ''): """Return the full log text for NAME_REV as a string. Optional OTHERFLAGS are passed to rlog. """ f = self._open(name_rev, 'rlog ' + otherflags) data = f.read() status = self._closepipe(f) if status: data = data + "%s: %s" % status elif data[-1] == '\n': data = data[:-1] return data def head(self, name_rev): """Return the head revision for NAME_REV""" dict = self.info(name_rev) return dict['head'] def info(self, name_rev): """Return a dictionary of info (from rlog -h) for NAME_REV The dictionary's keys are the keywords that rlog prints (e.g. 'head' and its values are the corresponding data (e.g. '1.3'). XXX symbolic names and locks are not returned """ f = self._open(name_rev, 'rlog -h') dict = {} while 1: line = f.readline() if not line: break if line[0] == '\t': # XXX could be a lock or symbolic name # Anything else? continue i = string.find(line, ':') if i > 0: key, value = line[:i], string.strip(line[i+1:]) dict[key] = value status = self._closepipe(f) if status: raise IOError, status return dict # --- Methods that change files --- def lock(self, name_rev): """Set an rcs lock on NAME_REV.""" name, rev = self.checkfile(name_rev) cmd = "rcs -l%s %s" % (rev, name) return self._system(cmd) def unlock(self, name_rev): """Clear an rcs lock on NAME_REV.""" name, rev = self.checkfile(name_rev) cmd = "rcs -u%s %s" % (rev, name) return self._system(cmd) def checkout(self, name_rev, withlock=0, otherflags=""): """Check out NAME_REV to its work file. If optional WITHLOCK is set, check out locked, else unlocked. The optional OTHERFLAGS is passed to co without interpretation. Any output from co goes to directly to stdout. """ name, rev = self.checkfile(name_rev) if withlock: lockflag = "-l" else: lockflag = "-u" cmd = 'co %s%s %s %s' % (lockflag, rev, otherflags, name) return self._system(cmd) def checkin(self, name_rev, message=None, otherflags=""): """Check in NAME_REV from its work file. The optional MESSAGE argument becomes the checkin message (default "<none>" if None); or the file description if this is a new file. The optional OTHERFLAGS argument is passed to ci without interpretation. Any output from ci goes to directly to stdout. """ name, rev = self._unmangle(name_rev) new = not self.isvalid(name) if not message: message = "<none>" if message and message[-1] != '\n': message = message + '\n' lockflag = "-u" if new: f = tempfile.NamedTemporaryFile() f.write(message) f.flush() cmd = 'ci %s%s -t%s %s %s' % \ (lockflag, rev, f.name, otherflags, name) else: message = re.sub(r'([\"$`])', r'\\\1', message) cmd = 'ci %s%s -m"%s" %s %s' % \ (lockflag, rev, message, otherflags, name) return self._system(cmd) # --- Exported support methods --- def listfiles(self, pat = None): """Return a list of all version files matching optional PATTERN.""" files = os.listdir(os.curdir) files = filter(self._isrcs, files) if os.path.isdir('RCS'): files2 = os.listdir('RCS') files2 = filter(self._isrcs, files2) files = files + files2 files = map(self.realname, files) return self._filter(files, pat) def isvalid(self, name): """Test whether NAME has a version file associated.""" namev = self.rcsname(name) return (os.path.isfile(namev) or os.path.isfile(os.path.join('RCS', namev))) def rcsname(self, name): """Return the pathname of the version file for NAME. The argument can be a work file name or a version file name. If the version file does not exist, the name of the version file that would be created by "ci" is returned. """ if self._isrcs(name): namev = name else: namev = name + ',v' if os.path.isfile(namev): return namev namev = os.path.join('RCS', os.path.basename(namev)) if os.path.isfile(namev): return namev if os.path.isdir('RCS'): return os.path.join('RCS', namev) else: return namev def realname(self, namev): """Return the pathname of the work file for NAME. The argument can be a work file name or a version file name. If the work file does not exist, the name of the work file that would be created by "co" is returned. """ if self._isrcs(namev): name = namev[:-2] else: name = namev if os.path.isfile(name): return name name = os.path.basename(name) return name def islocked(self, name_rev): """Test whether FILE (which must have a version file) is locked. XXX This does not tell you which revision number is locked and ignores any revision you may pass in (by virtue of using rlog -L -R). """ f = self._open(name_rev, 'rlog -L -R') line = f.readline() status = self._closepipe(f) if status: raise IOError, status if not line: return None if line[-1] == '\n': line = line[:-1] return self.realname(name_rev) == self.realname(line) def checkfile(self, name_rev): """Normalize NAME_REV into a (NAME, REV) tuple. Raise an exception if there is no corresponding version file. """ name, rev = self._unmangle(name_rev) if not self.isvalid(name): raise os.error, 'not an rcs file %r' % (name,) return name, rev # --- Internal methods --- def _open(self, name_rev, cmd = 'co -p', rflag = '-r'): """INTERNAL: open a read pipe to NAME_REV using optional COMMAND. Optional FLAG is used to indicate the revision (default -r). Default COMMAND is "co -p". Return a file object connected by a pipe to the command's output. """ name, rev = self.checkfile(name_rev) namev = self.rcsname(name) if rev: cmd = cmd + ' ' + rflag + rev return os.popen("%s %r" % (cmd, namev)) def _unmangle(self, name_rev): """INTERNAL: Normalize NAME_REV argument to (NAME, REV) tuple. Raise an exception if NAME contains invalid characters. A NAME_REV argument is either NAME string (implying REV='') or a tuple of the form (NAME, REV). """ if type(name_rev) == type(''): name_rev = name, rev = name_rev, '' else: name, rev = name_rev for c in rev: if c not in self.okchars: raise ValueError, "bad char in rev" return name_rev def _closepipe(self, f): """INTERNAL: Close PIPE and print its exit status if nonzero.""" sts = f.close() if not sts: return None detail, reason = divmod(sts, 256) if reason == 0: return 'exit', detail # Exit status signal = reason&0x7F if signal == 0x7F: code = 'stopped' signal = detail else: code = 'killed' if reason&0x80: code = code + '(coredump)' return code, signal def _system(self, cmd): """INTERNAL: run COMMAND in a subshell. Standard input for the command is taken from /dev/null. Raise IOError when the exit status is not zero. Return whatever the calling method should return; normally None. A derived class may override this method and redefine it to capture stdout/stderr of the command and return it. """ cmd = cmd + " </dev/null" sts = os.system(cmd) if sts: raise IOError, "command exit status %d" % sts def _filter(self, files, pat = None): """INTERNAL: Return a sorted copy of the given list of FILES. If a second PATTERN argument is given, only files matching it are kept. No check for valid filenames is made. """ if pat: def keep(name, pat = pat): return fnmatch.fnmatch(name, pat) files = filter(keep, files) else: files = files[:] files.sort() return files def _remove(self, fn): """INTERNAL: remove FILE without complaints.""" try: os.unlink(fn) except os.error: pass def _isrcs(self, name): """INTERNAL: Test whether NAME ends in ',v'.""" return name[-2:] == ',v'
Wednesday, 1 December 2010
BBP formula in Python
See http://mathworld.wolfram.com/BBPFormula.html
Not the most efficient Python but it works.
def x(n):
return (4.0/(8*n+1)-2.0/(8*n+4) - 1.0/(8*n+5) -1.0/(8*n+6))*((1.0/16)**n)
s = 0
for i in range(n):
s+=x(i)
return s
>>> pi(1)
3.1333333333333333
>>> pi(2)
3.1414224664224664
>>> pi(4)
3.1415924575674357
>>> pi(10)
3.1415926535897913
>>> pi(20)
3.141592653589793
>>> pi(40)
3.141592653589793
Tuesday, 16 November 2010
Sunday, 14 November 2010
Get Twitter messages from your IMAP server:
http://flowingdata.com/2008/11/05/how-to-make-your-own-twitter-bot-python-imp...
Send Twitter message with Python, Tweepy:
http://jeffmiller.github.com/2010/05/31/twitter-from-the-command-line-in-pyth...
Send Twitter messages with python-twitter:
http://code.google.com/p/python-twitter/
Register application with Twitter:
http://jeffmiller.github.com/2010/05/31/twitter-from-the-command-line-in-pyth...
My app:
reader.novel
Monday, 1 November 2010
Deleted posts on Guardian Cif
kwhitefoot
31 October 2010 8:54PM
BeautifulBurnout
31 October 2010 9:13PM
kwhitefoot
I know! It is really annoying when you craft a response to a bunch of nonsense, only to find that cos the nonsense has been deleted, your own post is zapped into the ether as well!
At least it wasn't really long and difficult to do...
kwhitefoot
31 October 2010 9:54PM
As an antidote to the Guardian's occasional lapse into the covering up of Cif history I have installed a Firefox add-on called History Search that takes snapshots of every page you visit every time you visit so that you can search in the history of the page. So, if a comment unexpectedly disappears and you have a feeling that it said something important, relevant, or merely amusing, you can at least satisfy your own curiosity. Of course one could also repost the offending comment either on Cif or elsewhere. You can find it at https://addons.mozilla.org/en-US/firefox/addon/7028/
Perhaps Cif should consider disemvowelling as on Boing-Boing and ScienceBlogs instead of outright deletion.
This one hasn't been deleted yet:
kwhitefoot
1 November 2010 7:36AM
This is getting silly. The moderator has now removed my post that began:
31 October 2010 9:54PMAs an antidote to the Guardian's occasional lapse into the covering up of Cif history I have installed a Firefox add-on called History Search
Several of BeautifulBurnout's comments that referred to either me or Ostmark have also disappeared.
In a thread that is all about access to information and exercise of civil liberty it seems strange that the moderators should be both anonymous and arbitrary and that they do not have the courtesy to explain to the commenter even briefly why the comment has been deleted.
Tuesday, 26 October 2010
Sunday, 24 October 2010
The enemy of your enemy isn't your friend: He's just the next enemy in a long line of enemies who could have been your friend if it weren't for the fact that you keep seeing enemies everywhere.
From El Reg:
The enemy of my enemy #
Posted Saturday 23rd October 2010 12:47 GMT
OK the military might have a valid point about putting lives at risk, but you have to wonder how organisations like the Taliban have managed to garner enough support to warrant going after them with guns.
Well the reason why is - we gave them guns and ammo during the Cold War in an attempt to dislodge the Russians from Afghanistan and it all kinda snowballed from there. We weren't that bothered that this might be a problem at the time because they were keeping the Russians away from us. Unfortunately this attitude seems to have gotten us into a spot of bother.
So the question is, seeing as this "arm them and don't be too concerned with the consequences" would seem to be a repeated pattern of behaviour (at least as US foreign policy is concerned), who the hell are we arming right now? Because it will be them - whoever they are - that we have to deal with next. In fact if we are currently arming someone else in the next phase of whatever ideological battle we're supposed to be having maybe we should be learning from recent history and not repeating the same behaviour over and over again?
The enemy of your enemy isn't your friend: He's just the next enemy in a long line of enemies who could have been your friend if it weren't for the fact that you keep seeing enemies everywhere.
I hope AC doesn't mind my reposting this. The final sentence says it all so well.
The enemy of your enemy isn't your friend: He's just the next enemy in a long line of enemies who could have been your friend if it weren't for the fact that you keep seeing enemies everywhere.
From El Reg:
The enemy of my enemy #
Posted Saturday 23rd October 2010 12:47 GMT
OK the military might have a valid point about putting lives at risk, but you have to wonder how organisations like the Taliban have managed to garner enough support to warrant going after them with guns.
Well the reason why is - we gave them guns and ammo during the Cold War in an attempt to dislodge the Russians from Afghanistan and it all kinda snowballed from there. We weren't that bothered that this might be a problem at the time because they were keeping the Russians away from us. Unfortunately this attitude seems to have gotten us into a spot of bother.
So the question is, seeing as this "arm them and don't be too concerned with the consequences" would seem to be a repeated pattern of behaviour (at least as US foreign policy is concerned), who the hell are we arming right now? Because it will be them - whoever they are - that we have to deal with next. In fact if we are currently arming someone else in the next phase of whatever ideological battle we're supposed to be having maybe we should be learning from recent history and not repeating the same behaviour over and over again?
The enemy of your enemy isn't your friend: He's just the next enemy in a long line of enemies who could have been your friend if it weren't for the fact that you keep seeing enemies everywhere.
I hope AC doesn't mind my reposting this. The final sentence says it all so well.
Friday, 8 October 2010
TEACHINGS OF DIOGENES
Tuesday, 5 October 2010
Erlang Community - How to use ei to marshal binary terms in port programs - Trapexit
Saturday, 2 October 2010
Parallel port output in Linux with Python
Parallel port output
http://pyserial.sourceforge.net/pyparallel.html
http://www.hare.demon.co.uk/ioport/ioport.html
http://bigasterisk.com/projects/parallel
http://www.ladyada.net/make/spokepov/download.html
http://book.opensourceproject.org.cn/kernel/kernelpri/index.html?page=opensource/0131181637/ch05lev1sec4.html
pyParallel
On Ubuntu 10.04 pyParallel can be installed from Synaptic.
Then start python:
>>> import parallel
>>> p=parallel.Parallel()
but that won't work
unless you first make /dev/parpart0 writable
# sudo chmod o+wr /dev/parport0
and unload the lp module
# sudo rmmod lp
For permanent changes it is best to add the user to the lp group instead of changing the permissions. You still need to unload the lp module though. Presumably you can do this in the init scripts.
Friday, 1 October 2010
Tuesday, 28 September 2010
Fetch email from gmail by command
Well I don't really want to fetch email, I want to be able to get my backups back.
But getting the email is a start. Here are some pages that describe how:
- http://www.mattcutts.com/blog/backup-gmail-in-linux-with-getmail/. >
- http://pyropus.ca/software/getmail/
Send email from the command line to gmail
Just some notes about what works and what is simple.
Works and is simple
http://www.debianadmin.com/how-to-sendemail-from-the-command-line-using-a-gma...
You can install sendEmail via Synaptic in Ubuntu but you will need to also install
- libio-socket-ssl-perl
- libnet-ssleay-perl
- perl
You can, of course, just tell Synaptic to do that. You can also do it all from the command line:
$ sudo apt-get install sendemail libio-socket-ssl-perl libnet-ssleay-perl perl
Caveats and questions
sendEmail can use tls authentication but presumably this does not mean that the actual traffic is secure. Of course email is normally transmitted in the clear anyway so this might not be a problem; however, if you are using this to backup confidential files to your gmail account you should try to use secure sockets to secure the connection against eavesdroppers. And, especially in the light of recent reports of a Google employee snooping on email, you should encrypt the files themselves.
So the question: can sendEmail use SSL?
Wednesday, 22 September 2010
Buffered csp oscilloscope
Add a buffer process so that the oscilloscope gets a whole frame at once. the buffer process triggers on positive zero crossings.
traces.py
#!/usr/bin/env python
## Example oscilloscope traces.
#import sys
from csp.csp import *
from csp.builtins import Sin, Cos, GenerateFloats, Mux2, Delta2
from bscope import Oscilloscope
@forever
def Random(outchan):
"""Random process. Generates random data and writes it to outchan.
"""
import random
while True:
outchan.write(random.random())
yield
return
@forever
def Buffer(inchan, outchan):
"""Buffer one frame and send as a list. This version simply uses
a literal constant frame size which should mathc that used in
oscilloscope.py.
"""
a = []
while True:
y = inchan.read()
a.append(y)
if len(a) == 512:
outchan.write(a)
a = []
yield@forever
def TriggeredBuffer(inchan, outchan):
"""Buffer one frame and send as a list. This version simply uses
a literal constant frame size which should mathc that used in
oscilloscope.py. Waits for positive going zero crossing.
"""
a = []
armed = False
while True:
y = inchan.read()
if 0 < len(a):
a.append(y)
if len(a) == 512:
outchan.write(a)
a = []
armed = False
elif armed:
if yp < y and 0 <= y:
a.append(y);
elif y < 0:
armed = True
yp = y
yielddef trace_random():
"""Test the Oscilloscope with random data.
"""
channel = Channel()
par = Par(Random(channel), Oscilloscope(channel))
par.start()
return
def trace_sin():
"""Plot a sine wave on the oscilloscope.
"""
channels = Channel(), Channel()
par = Par(GenerateFloats(channels[0]),
Sin(channels[0], channels[1]),
Oscilloscope(channels[1]))
par.start()
return
def trace_cos():
"""Plot a cosine wave on the oscilloscope.
"""
channels = Channel(), Channel(), Channel()
par = Par(GenerateFloats(channels[0]),
Cos(channels[0], channels[1]),
TriggeredBuffer(channels[1],channels[2]),
Oscilloscope(channels[2]))
par.start()
return
def trace_mux():
"""Plot sine and cosine waves on the oscilloscope.
"""
channels = [Channel() for i in range(6)]
par = Par(GenerateFloats(channels[0]),
Delta2(channels[0], channels[1], channels[2]),
Cos(channels[1], channels[3]),
Sin(channels[2], channels[4]),
Mux2(channels[3], channels[4], channels[5]),
Oscilloscope(channels[5]))
par.start()
return EXAMPLES = {}
for name, func in globals().items():
if name.startswith('trace_'):
EXAMPLES[name[6:]] = funcif __name__ == '__main__':
if len(sys.argv) != 2:
print('Syntax: python {0} {1}'.format(sys.argv[0],
' | '.join(EXAMPLES.keys())))
for name, func in EXAMPLES.items():
print(' {0:<9} {1}'.format(name, func.func_doc.strip()))
elif sys.argv[1] not in EXAMPLES:
print('Unknown example {0}'.format(sys.argv[1]))
else:
print('Use cursor up/down for scaling, s for save and q for quit')
EXAMPLES[sys.argv[1]]()bscope.py
#!/usr/bin/env python
"""Simple oscilloscope traces for python-csp.
Requires Pygame.Features:
* Press 's' to save an oscilloscope trace as a PNG.
* Press UP and DOWN to scale the input more / less.Copyright (C) Sarah Mount, 2009.This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.Changes: (C) Kevin Whitefoot, 2010 Allow sender to send a complete frame instead of just a single new sample."""
from csp.csp import *import copy
import numpy
import pygame
__author__ = 'Sarah Mount <s.mount@wlv.ac.uk>'
__date__ = 'November 2009'
__version__ = '0.2'
@forever
def Oscilloscope(inchan, scale=80.0, _process=None):
# Constants
WIDTH, HEIGHT = 512, 256
TRACE, GREY = (80, 255, 100), (110, 110, 110)
caption = 'Oscilloscope'
filename = caption + '.png'
# Open window
pygame.init()
screen = pygame.display.set_mode((WIDTH, HEIGHT), 0)
pygame.display.set_caption(caption)
# Create a blank chart with vertical ticks, etc
blank = numpy.zeros((WIDTH, HEIGHT, 3), dtype=numpy.int8)
# Draw x-axis
xaxis = HEIGHT // 2
blank[::, xaxis] = GREY
# Draw vertical ticks
vticks = [-100, -50, +50, +100]
for vtick in vticks: blank[::5, xaxis + vtick] = GREY # Horizontals
blank[::50, ::5] = GREY # Verticals
# Draw the 'blank' screen.
pygame.surfarray.blit_array(screen, blank) # Blit the screen buffer
pygame.display.flip() # Flip the double buffer
# ydata stores data for the trace.
ydata = [0.0 for i in range(WIDTH)] # assert len(ydata) <= WIDTH QUIT = False
while not QUIT: pixels = copy.copy(blank)
indata = inchan.read()
if type(indata) == list:
# We have been sent a complete frame
ydata = map(lambda(x): x*scale, indata)
else:
# we only have one new point
ydata.append(inchan.read() * scale)
ydata.pop(0) for x in range(WIDTH):
try: pixels[x][xaxis - int(ydata[x])] = TRACE
except: pass
pygame.surfarray.blit_array(screen, pixels) # Blit the screen buffer
pygame.display.flip() # Flip the double buffer
#pygame.display.update(0, xaxis-100, WIDTH, 201) # Flip the double buffer
del pixels # Use constant space.
for event in pygame.event.get():
if event.type == pygame.QUIT \
or event.type == pygame.KEYDOWN and event.key == pygame.K_q:
QUIT = True
elif event.type == pygame.KEYDOWN and event.key == pygame.K_s:
pygame.image.save(screen, filename)
print('Saving oscope image in: ' + str ( filename ) )
elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP:
scale += 10.0
print('Oscilloscope scaling by %f' % scale)
elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN:
if scale - 10.0 > 0.0: scale -= 10.0
print('Oscilloscope scaling by %f' % scale)
yield
inchan.poison()
pygame.display.quit()
return
if __name__ == '__main__':
print('For this tutorial run traces.py')
CSP Oscilloscope
See http://python-csp.googlecode.com/hg/tutorial/part07/oscilloscope.py
#!/usr/bin/env python """ Simple oscilloscope traces for python-csp. Requires Pygame. Features: * Press 's' to save an oscilloscope trace as a PNG. * Press UP and DOWN to scale the input more / less. Copyright (C) Sarah Mount, 2009. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have rceeived a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. Changes: (C) Kevin Whitefoot, 2010 Allow for sender to send a complete frame instead of just a single new sample.""" from csp.csp import * import copy import numpy import pygame __author__ = 'Sarah Mount <s.mount@wlv.ac.uk>' __date__ = 'November 2009' __version__ = '0.2' @forever def Oscilloscope(inchan, scale=80.0, _process=None): # Constants WIDTH, HEIGHT = 512, 256 TRACE, GREY = (80, 255, 100), (110, 110, 110) caption = 'Oscilloscope' filename = caption + '.png' # Open window pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT), 0) pygame.display.set_caption(caption) # Create a blank chart with vertical ticks, etc blank = numpy.zeros((WIDTH, HEIGHT, 3), dtype=numpy.int8) # Draw x-axis xaxis = HEIGHT // 2 blank[::, xaxis] = GREY # Draw vertical ticks vticks = [-100, -50, +50, +100] for vtick in vticks: blank[::5, xaxis + vtick] = GREY # Horizontals blank[::50, ::5] = GREY # Verticals # Draw the 'blank' screen. pygame.surfarray.blit_array(screen, blank) # Blit the screen buffer pygame.display.flip() # Flip the double buffer # ydata stores data for the trace. ydata = [0.0 for i in range(WIDTH)] # assert len(ydata) <= WIDTH QUIT = False while not QUIT: pixels = copy.copy(blank) indata = inchan.read() if type(indata).name == 'list': # We have been sent a complete frame ydata = map(lambda(x) x*scale, indata) else: # we only have one new point ydata.append(inchan.read() * scale) ydata.pop(0) for x in range(WIDTH): try: pixels[x][xaxis - int(ydata[x])] = TRACE except: pass pygame.surfarray.blit_array(screen, pixels) # Blit the screen buffer pygame.display.flip() # Flip the double buffer #pygame.display.update(0, xaxis-100, WIDTH, 201) # Flip the double buffer del pixels # Use constant space. for event in pygame.event.get(): if event.type == pygame.QUIT \ or event.type == pygame.KEYDOWN and event.key == pygame.K_q: QUIT = True elif event.type == pygame.KEYDOWN and event.key == pygame.K_s: pygame.image.save(screen, filename) print('Saving oscope image in: ' + str ( filename ) ) elif event.type == pygame.KEYDOWN and event.key == pygame.K_UP: scale += 10.0 print('Oscilloscope scaling by %f' % scale) elif event.type == pygame.KEYDOWN and event.key == pygame.K_DOWN: if scale - 10.0 > 0.0: scale -= 10.0 print('Oscilloscope scaling by %f' % scale) yield inchan.poison() pygame.display.quit() return if __name__ == '__main__': print('For this tutorial run traces.py')
Monday, 20 September 2010
Electric.py
Electric.py
Queue size is one item to ensure that we catch underrun errors in the
consumer. Meter process will typically take 0.5 second samples.
Meter is a daemon process, it needs no input except for arguments to
construction.The queue used is a common queue so the item must be a tuple where the
first item is a tag saying what the second means. The queue is used
by the UI to send requests to the relay process. This means that the
relay process need only wait on one queue instead of repeatedly
polling several queues. Would be cleaner to use Occam's ALT function
but there appears to be no equivalent in Python (or Erlang for that
matter).How about python-csp?
Saturday, 18 September 2010
Python GUI
What is the easiest way to vreate a simple GUI in Python under Linux (Ubuntu >=10.04)?
Some sites:
Emacs
I hate the Winows/CUA binding for the Home and End keys. To make them go to the start and end of the document instead of the line add this to .emacs:
(global-set-key [kp-home] 'beginning-of-buffer) ; [Home]
(global-set-key [home] 'beginning-of-buffer) ; [Home]
(global-set-key [kp-end] 'end-of-buffer) ; [End]
(global-set-key [end] 'end-of-buffer) ; [End]
Many thanks to http://geosoft.no/development/emacs.html
Friday, 17 September 2010
Monday, 13 September 2010
Sunday, 12 September 2010
Audio recording, Linux, Python
Just some notes:
- Use Alsamixer and arecord to get the data: http://jordilin.wordpress.com/2006/07/28/howto-recording-audio-from-the-comma...
- See also http://www.acronymchile.com/sigproc.html for notes on mono recording and analysis.
- Pipewave command line tools: http://www.cf.ac.uk/psych/home2/CullingJ/pipewave.html
Wednesday, 8 September 2010
-inurl:(htm|html|php) intitle:"index of" "last modified" "parent directory" description size (wma|mp3|ogg) "subirana" - Google Search
-inurl:(htm|html|php) intitle:"index of" "last modified" "parent directory" description size (wma|mp3|ogg) "subirana" - Google Search
IP Catcher - Link Record Log
Sunday, 29 August 2010
Flashcards on Symbian with Python
This program lets you use sets of flashcards downloaded from flashcarddb.com (or made yourself). The cards must be lines withe front and back separated by @ signs.
'''
Copyright 2010, Kevin Whitefoot <kwhitefoot@hotmail.com> License: use as you will so long as you maintain the credits. Language: mshell <http://www.m-shell.net> Method: See http://flashcarddb.com/leitner
Simplified Leitner.
For use with decks from Flashcarddb.com exported with @ separators.
Notes:- My mobile has Python 2.2.2 so string formatting has to be done with
the % operator not string interpolation.
'''
''' Decide if we are running in a terminal or on the mobile. Note
that this probably only works for *nix not Windows.Adapted from
http://www.gossamer-threads.com/lists/python/python/379465'''
import sys
import time
import os
import os.path
def emitmobile(s):
# Must set the cursor position because the up arrow key is
# passed to the normal handler as well as ours so it moves the
# cursor.
text.set_pos(text.len())
text.add('\n' + s)
text.set_pos(text.len())
def emitterminal(s):
print s
try:
import tty, termios
runningOnMobile = False
emit = emitterminal
def getch():
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
except:
# '... choose Symbian stuff instead'
runningOnMobile = True
emit = emitmobile
CmdCorrect = 1
CmdWrong = 2
CmdQuit = 3
CmdAllDone = 4
'''
Return true if user is correct.
'''
def getcmd():
if runningOnMobile:
pass
else:
ch = getch()
if ord(ch) == 27: # escape
ch = getch()
c = ord(getch())
if c == 65:
return CmdCorrect
elif c in [53, 54]:
ch =getch()
return CmdWrong
else:
return CmdWrong
elif ch == 'q':
return CmdQuit
else:
return CmdWrong
""" Initialize some tables, etc.
See http:# flashcarddb.com/leitner
Deck
Number Time until next repetition
One None
Two 1 day
Three 3 days
Four 1 week
Five 1 month
"""
oneday = 24*60*60 # seconds in a day
expiry = [0, 0, 1 * oneday, 3 * oneday, 7 * oneday, 30 * oneday]lsLoaded=0
lsLoadedWithDuplicates = 1
lsZeroLength = 2
lsTooManyStates = 3
lsTooFewStates = 4""" debug
Set verbosity higher to generate more logging output.
"""
verbosity = 0def verbose(n, s):
if n < verbosity :
print s
# end
# end
class Card:
""" Cards are simple data structures that can be read from an open
text file. A card has a front and a back. They are never
modified by the program.
"""
# front
# back # f is an open file
def load(self, line):
i = line.index("@")
self.front = line[0:i].strip()
self.back = line[i+1:].strip()
# f is an open file
def save(self, file) :
file.writeline(front + u"@" + back)
# end
# f is an open file
def __init__(self, line):
self.load(line)
# end# end
class Cards:
"""Cards is a list of Card instances in the order they were found
in a file. The file name is generated from the set name by
appending .cards.
"""
# cards
# setname
def count(self):
return len(self.cards)
# end
def filename(self):
return os.path.join(pathname,self.setname) + u".cards"
# end
def get(self, i):
return self.cards[i]
# end
def add(self, c):
self.cards.append(c)
# end
# f is an open file
def load(self):
t = time.time()
f = open(self.filename())
for line in f :
c = Card(line)
self.add(c)
# end
d = time.time()-t
# emit(u"Cards.load: {0} cards in {1} seconds".format(len(self.cards), d))
emit(u"Cards.load: %s cards in %s seconds" % (len(self.cards), d))
# end
def __init__(self, setname):
self.setname = setname
self.cards = []
self.load()
# end
# f is an open file
def save(self, f):
c = null
for c in self.cards:
c.save(f)
# end
# end
# endclass CardState:
"""
The state of each card is stored in a card state object. These
objects are stored in a file that is updated every time a card
changes state. To save time the new stte is simply appended to the
end of the file. When reading the file back later entries for the
same card overwrite the newer ones. The state is : written out
again so that the file does not grow indefinitely.
""" # card # index into array of cards.
# deck # number of the deck to which this card belongs.
# expires # date at which the card should be reviewed expressed as
# seconds from the start of the epoch.
def getcard(self, cards):
return cards.get(self.card)
# end
def __init__(self, card, deck):
self.card = card
self.deck = deck
self.expires = 0
# end
def loadfromstr(self, s):
a = s.split()
self.card = int(a[0])
self.deck = int(a[1])
self.expires = float(a[2])
# end
# f is an open file
def load(self, file):
s = io.readln(file)
self.loadfromstr(s)
# end
# f is an open file
def save(self, file):
file.write("%s %s %s\n" % (self.card, self.deck, self.expires))
# end
def promote(self):
if self.deck < 5 :
self.deck += 1
# end
self.expires = time.time() + expiry[self.deck]
# end
def demote(self):
self.deck = 1
self.expires = 0
# end# end
""""""
class CardStates: # cards:Cards
# cardstates # array of CardState
# setname
def get(self, i):
return self.cardstates[i]
# end
def card(self, i):
cs = self.cardstates[i]
return cs.getcard(self.cards)
# end
def count(self):
return self.cards.count()
# end
def filename(self):
return os.path.join(pathname,self.setname) + u".state"
# end
def savestate(self):
# emit(u"CardStates.savestate {0} states".format(len(self.cardstates)))
emit(u"CardStates.savestate %s states" % (len(self.cardstates)))
f = open(self.filename(),'w')
for cs in self.cardstates :
cs.save(f)
# end
f.close()
# end
def loadstate(self):
"""
Returns a code indicating the result. It can happen that the
user will update the cards file. In such a case the states file
will have to be updated to match.
"""
t = time.time()
f = open(self.filename(), 'r')
cr = 0 # count read
cu = 0 # count used
lc = self.cards.count()
# Initialize array of cardstates to empty .
for i in range(lc):
self.cardstates.append(None)
for s in f:
cr += 1 # count how many we read so that we can tell if
# there were duplicates
cs = CardState(0, 0)
cs.loadfromstr(s)
if cs.card < lc :
# Note that we do not just append because we want to ensure
# that later duplicates override the earlier ones
if self.cardstates[cs.card] == None :
cu += 1
# end
# overwrite even if was not null.
self.cardstates[cs.card] = cs
else:
# do nothing, discard state for non-existent card
pass
# end
# end
if s == None:
break
f.close # want to open it for writing again.
# emit(u"CardStates load: {0} states in {1} seconds".format(cr, time.time()-t))
# emit(u" : {0} state used".format(cu))
emit(u"CardStates load: %s states in %s seconds" % (cr, time.time()-t))
emit(u" : %s state used" % (cu))
if cu < lc :
# some cards do not have a state. This happens when the user
# overwrites the cards file with a new longer (more lines)
# file.
return lsTooFewStates
elif cr != cu :
# some cards had duplicate state records this is not a bug, it
# happens because when we write a new state record we do just
# that instead of rewriting the whole state file. When we start
# the program we remove the duplicates and rewrite the file.
return lsLoadedWithDuplicates
else:
return lsLoaded
# end
# end
def cardstate(self, card):
return self.cardstates[card]
# end
def savecardstate(self, card):
f = open(self.filename(), "a")
# cs:CardState = cardstates[card]
self.cardstate(card).save(f)
f.close()
# end
def promote(self, card):
cs = self.cardstates[card]
cs.promote()
self.savecardstate(card)
# end
def demote(self, card):
cs = self.cardstates[card]
cs.demote()
self.savecardstate(card)
# end
def initstate(self):
# not found, first time
for i in range(self.cards.count()):
cs = CardState(i, 1)
self.cardstates.append(cs)
# end
self.savestate()
# end
def qfixupstates(self):
""" Attempt to add states for cards added to the cards file
and remove states that are no longer needed. At this stage
the cardstates and cards list are both ordered by card number
so all we have to do is look for nulls in the cardstates list.
"""
emit(u"CardStates.qfixupstates")
for i in range(len(self.cardstates)):
cs = self.cardstates[i]
if cs == None :
# no state for this card so add one in deck 1.
self.cardstates[i] = CardState(i, 1)
# end
# end
# end
def __init__(self, setname):
self.setname = setname
self.cardstates = []
self.cards = Cards(setname)
if os.path.exists(self.filename()) :
r = self.loadstate()
if r == lsTooFewStates :
self.qfixupstates()
self.savestate()
elif r == lsTooManyStates :
self.qfixupstates()
self.savestate()
elif r == lsZeroLength :
self.initstate()
self.savestate()
elif r == lsLoadedWithDuplicates :
# Save the state to remove duplicates
self.savestate()
pass
elif r == lsLoaded :
# success, nothing to do
pass
else:
emit(u"Unxpected result from loadstates: %s" % (r))
# end
else:
self.initstate()
# end
# end
def getnext(self, currentcard):
now = time.time()
c = self.count()
cc = currentcard
while cc+1 < c:
cc += 1
e = self.cardstate(cc).expires
if e <= now :
return cc
return -1
# end# end
# States
ShowingFront = 0
ShowingBack = 1class Flash_Set: # setname
# cardstates # :CardStates
# currentcard
# currentdeck
# Load from disk if possible.
def __init__(self, name):
self.setname = name
self.cardstates = CardStates(name)
self.currentcard = -1
self.currentdeck = 1
self.state = 0
# A hack to let me overcome the fact that the cursor in a text
# object is moved by the navigation keys
self.timer = e32.Ao_timer()
def getnext(self):
c = self.cardstates.getnext(self.currentcard)
if c != -1 :
return c
# end
# Ran off the end so check from beginning again in case any have been demoted.
emit(u"Studied all cards due today, checking for demoted cards.")
self.currentcard = -1
return self.cardstates.getnext(self.currentcard)
# end
def promote(self):
self.cardstates.promote(self.currentcard)
# end
def demote(self):
self.cardstates.demote(self.currentcard)
# end def showfront(self):
"""Show the front of the current card.
"""
self.currentcard = self.getnext()
if self.currentcard == -1 :
return CmdAllDone
self.current = self.cardstates.card(self.currentcard)
# emit(u"{0} {1} {2}".format(self.currentdeck, self.currentcard, c.front))
emit(u"%s %s %s" % (self.currentdeck, self.currentcard, self.current.front))
self.state = ShowingFront
'''
Return true if all shown or quit.
'''
def shownext(self):
self.showfront()
# wait for user to click a key, don't care what unless it is quit.
k = getcmd()
if k == CmdQuit:
return k # show the back of the card
# print c
emit(self.current.back) # wait for user to respond
k = getcmd()
if k == CmdCorrect:
self.promote()
elif k == CmdWrong:
self.demote()
# end return k # end
def movecursortoend(arg):
"""Move the cursor to the end of the text because it is distracting.
"""
if runningOnMobile:
text.set_pos(text.len())
def handleup(self):
# Simple hack to move the cursor to the end out of the text
# after the underlying up arrow event has been handled by the
# text control because I find it distracting that the up key
# moves the cursor to the middle of the line above the end. A
# ten milli-second delay is enough on the N73.
self.timer.after(0.01, self.movecursortoend)
if self.state == ShowingBack:
self.promote()
return self.showfront()
else:
emit(u"%s" % self.current.back)
self.state = ShowingBack
def handledown(self):
if self.state == ShowingBack:
self.demote()
return self.showfront()
else:
emit(u"%s" % self.current.back)
self.state = ShowingBack
def showall(self):
self.showfront()
while True:
k = getcmd()
if k == CmdWrong:
k = self.handledown()
elif k == CmdCorrect:
k = self.handleup() if (k in [CmdQuit, CmdAllDone]):
break
if k == CmdAllDone:
emit(u"Studied all cards + nothing left to don today.")
else:
emit(u"User quitting") # end# end
#Define the exit function
def quit():
app_lock.signal()
# define functions to show notifications
def up():
f.handleup()
def down():
f.handledown()
def initMobile(): global app_lock
app_lock = e32.Ao_lock() appuifw.app.exit_key_handler = quit
# Create an instance of Text and set it as the application's body
global text
text = appuifw.Text()
appuifw.app.body = text
def runMobile(): text.add(u"Flashcards for Symbian\n")
# Bind keys
text.bind(key_codes.EKeyUpArrow, up)
text.bind(key_codes.EKeyDownArrow, down)
# show the first card
f.showfront() # Wait for the user to request the exit
app_lock.wait()# main#ui.keys(ui.strokes) # return keystrokes
pathname = os.path.dirname(sys.argv[0])
pathname = os.path.abspath(pathname)
# print pathnameif runningOnMobile:
# Do this before loading anything because the load functions emit
# logging information.
import appuifw, e32, key_codes
initMobile()f = Flash_Set("flashcards")
if runningOnMobile:
runMobile()
else:
f.showall()
Saturday, 28 August 2010
Sustainable Energy - without the hot air
I wanted to read David McKay's book on my mobile but there doesn't seem to be a reader for ePub format files for the Nokia N73.
So Free Software to the rescue in the form of Calibre by Kovid Goyal <http://calibre-ebook.com/>. I'm using Ubuntu so all I had to do was start Synaptic and install Calibre from there. It's not quite the latest version but it seems to work. If you aren't using a distro with Calibre in the repository or if that sentence makes no sense to you (using Windows or Mac?) or if you simply want the latest version download it from the Calibre web site.
The web page for the book is http://www.withouthotair.com/, the ePub version is at http://www.ivor.org/withouthotair/ and the version converted from ePub to Mobi by Calibre is attached to this blog entry
Monday, 23 August 2010
In the Beginning was the Command Line by Neal Stephenson, excerpt.
I hope Neal Stephenson doesn't mind me posting this excerpt from "In the Beginning was the Command Line".
There was a competing bicycle dealership next door (Apple) that one day began selling motorized vehicles--expensive but attractively styled cars with their innards hermetically sealed, so that how they worked was something of a mystery.The big dealership responded by rushing a moped upgrade kit (the original Windows) onto the market. This was a Rube Goldberg contraption that, when bolted onto a three-speed bicycle, enabled it to keep up, just barely, with Apple-cars. The users had to wear goggles and were always picking bugs out of their teeth while Apple owners sped along in hermetically sealed comfort, sneering out the windows. But the Micro-mopeds were cheap, and easy to fix compared with the Apple-cars, and their market share waxed.Eventually the big dealership came out with a full-fledged car: a colossal station wagon (Windows 95). It had all the aesthetic appeal of a Soviet worker housing block, it leaked oil and blew gaskets, and it was an enormous success. A little later, they also came out with a hulking off-road vehicle intended for industrial users (Windows NT) which was no more beautiful than the station wagon, and only a little more reliable.Since then there has been a lot of noise and shouting, but little has changed. The smaller dealership continues to sell sleek Euro-styled sedans and to spend a lot of money on advertising campaigns. They have had GOING OUT OF BUSINESS! signs taped up in their windows for so long that they have gotten all yellow and curly. The big one keeps making bigger and bigger station wagons and ORVs.On the other side of the road are two competitors that have come along more recently.One of them (Be, Inc.) is selling fully operational Batmobiles (the BeOS). They are more beautiful and stylish even than the Euro-sedans, better designed, more technologically advanced, and at least as reliable as anything else on the market--and yet cheaper than the others.With one exception, that is: Linux, which is right next door, and which is not a business at all. It's a bunch of RVs, yurts, tepees, and geodesic domes set up in a field and organized by consensus. The people who live there are making tanks. These are not old-fashioned, cast-iron Soviet tanks; these are more like the M1 tanks of the U.S. Army, made of space-age materials and jammed with sophisticated technology from one end to the other. But they are better than Army tanks. They've been modified in such a way that they never, ever break down, are light and maneuverable enough to use on ordinary streets, and use no more fuel than a subcompact car. These tanks are being cranked out, on the spot, at a terrific pace, and a vast number of them are lined up along the edge of the road with keys in the ignition. Anyone who wants can simply climb into one and drive it away for free.Customers come to this crossroads in throngs, day and night. Ninety percent of them go straight to the biggest dealership and buy station wagons or off-road vehicles. They do not even look at the other dealerships.Of the remaining ten percent, most go and buy a sleek Euro-sedan, pausing only to turn up their noses at the philistines going to buy the station wagons and ORVs. If they even notice the people on the opposite side of the road, selling the cheaper, technically superior vehicles, these customers deride them cranks and half-wits.The Batmobile outlet sells a few vehicles to the occasional car nut who wants a second vehicle to go with his station wagon, but seems to accept, at least for now, that it's a fringe player.The group giving away the free tanks only stays alive because it is staffed by volunteers, who are lined up at the edge of the street with bullhorns, trying to draw customers' attention to this incredible situation. A typical conversation goes something like this:Hacker with bullhorn: "Save your money! Accept one of our free tanks! It is invulnerable, and can drive across rocks and swamps at ninety miles an hour while getting a hundred miles to the gallon!"Prospective station wagon buyer: "I know what you say is true...but...er...I don't know how to maintain a tank!"Bullhorn: "You don't know how to maintain a station wagon either!"Buyer: "But this dealership has mechanics on staff. If something goes wrong with my station wagon, I can take a day off work, bring it here, and pay them to work on it while I sit in the waiting room for hours, listening to elevator music."Bullhorn: "But if you accept one of our free tanks we will send volunteers to your house to fix it for free while you sleep!"Buyer: "Stay away from my house, you freak!"Bullhorn: "But..."Buyer: "Can't you see that everyone is buying station wagons?"
Imagine a crossroads where four competing auto dealerships are situated. One of them (Microsoft) is much, much bigger than the others. It started out years ago selling three-speed bicycles (MS-DOS); these were not perfect, but they worked, and when they broke you could easily fix them.
Blog Archive
-
▼
2010
(286)
-
►
October
(9)
- xkcd is hopelessly romantic
- The enemy of your enemy isn't your friend: He's ju...
- The enemy of your enemy isn't your friend: He's ju...
- ... on Twitpic
- TEACHINGS OF DIOGENES
- Ilya Martynov's blog: Erlang debugging tips
- Erlang Community - How to use ei to marshal binary...
- Parallel port output in Linux with Python
- Wayback: A User-level Versioning File System for L...
-
►
September
(13)
- Fetch email from gmail by command
- Send email from the command line to gmail
- Buffered csp oscilloscope
- CSP Oscilloscope
- Electric.py
- Python GUI
- Emacs
- Synergy multi-screen
- mental_floss Blog » Alarming Situations
- Audio recording, Linux, Python
- -inurl:(htm|html|php) intitle:"index of" "last mo...
- -inurl:(htm|html|php) intitle:"index of" "last mo...
- IP Catcher - Link Record Log
-
►
October
(9)
I think I'll have to start archiving these comments myself. Ostmark's has been deleted and so has the reply but worse the fact of the reply has disappeared as well.