I've moved my code hosting to http://code.google.com/p/openmolar/, switching from bzr to hg.
Why?
https://bugs.launchpad.net/launchpad/+bug/220082
I'm absolutely bloody furious.
However, I feel this move was absolutely necessary.
Launchpad is falling behind other code hosting sites from a my perspective as a coder. Only time will tell if I am right.
p.s. as a dentist.. should i really be using hg?
Random musings on GNU+Linux. open source software, and Python. The main purpose of this blog is to archive (for myself) what I am learning about these wonderful technologies/communities
Wednesday, 15 June 2011
Monday, 13 June 2011
PyQt QSysTrayIcon Example
Following A question in #pyqt on irc.freenode.net, I had a play with QSysTrayIcon."Hugo__" wanted a tray icon in Gnome which showed a different menu for left and right clicking.
Here's one way to achieve such with PyQt4.
Note - I use QtGui.QIcon.fromTheme here.. and do NOT supply a fallback icon.
Hence, the icons will only show on freedesktop standards compliant environments (gnome, KDE etc..)
see
http://standards.freedesktop.org/icon-naming-spec/icon-naming-spec-latest.html for details.
#! /usr/bin/env python
from PyQt4 import QtGui, QtCore
class RightClickMenu(QtGui.QMenu):
def __init__(self, parent=None):
QtGui.QMenu.__init__(self, "Edit", parent)
icon = QtGui.QIcon.fromTheme("edit-cut")
self.addAction(QtGui.QAction(icon, "&Cut", self))
icon = QtGui.QIcon.fromTheme("edit-copy")
self.addAction(QtGui.QAction(icon, "Copy (&X)", self))
icon = QtGui.QIcon.fromTheme("edit-paste")
self.addAction(QtGui.QAction(icon, "&Paste", self))
class LeftClickMenu(QtGui.QMenu):
def __init__(self, parent=None):
QtGui.QMenu.__init__(self, "File", parent)
icon = QtGui.QIcon.fromTheme("document-new")
self.addAction(QtGui.QAction(icon, "&New", self))
icon = QtGui.QIcon.fromTheme("document-open")
self.addAction(QtGui.QAction(icon, "&Open", self))
icon = QtGui.QIcon.fromTheme("document-save")
self.addAction(QtGui.QAction(icon, "&Save", self))
class SystemTrayIcon(QtGui.QSystemTrayIcon):
def __init__(self, parent=None):
QtGui.QSystemTrayIcon.__init__(self, parent)
self.setIcon(QtGui.QIcon.fromTheme("document-save"))
self.right_menu = RightClickMenu()
self.setContextMenu(self.right_menu)
self.left_menu = LeftClickMenu()
self.activated.connect(self.click_trap)
def click_trap(self, value):
if value == self.Trigger: #left click!
self.left_menu.exec_(QtGui.QCursor.pos())
def welcome(self):
self.showMessage("Hello", "I should be aware of both buttons")
def show(self):
QtGui.QSystemTrayIcon.show(self)
QtCore.QTimer.singleShot(100, self.welcome)
if __name__ == "__main__":
app = QtGui.QApplication([])
tray = SystemTrayIcon()
tray.show()
#set the exec loop going
app.exec_()
Making PyQt experimentation easier
Over the past few months, I've encountered the same issue. namely, I want to do *SOMETHING* with the openmolar project be it:
Rather than risk breaking my main codebase however, I believe it always helps to attempt this stuff with a smaller application first I think. So I've written one. It is trivial enough to keep the codebase simple, but complex enough to be realistic.
It raises dialogs, stores data, etc.
I've tried to follow a lot of my coding style choices (which you may hate), but on checking the modules with pylint, most get a 10/10, only decreasing when PyQt4 own naming conventions dictate.
anyways, to cut to the chase.. the code is here is anyone wants a play. This is in the public domain, so do with it as you wish.
download it from my dropbox account http://dl.dropbox.com/u/1989100/example_pyqt_app.tar.bz2
My current focus is writing unittests (something I am ashamed to admit I have never done before), and it is proving VERY interesting.
for example. dialogs are interesting, in that the exec_ function needs to be called to ensure correct code coverage. Calling that during a test run causes a pause in the procedings.. not good.
So what is the best way to call accept() or reject() on such a dialog?
I am experimenting with installEventFilter into QApplication itself, and accepting the dialog when the focus event is encountered seems to be working really well.
- document with sphinx
- write unittests (I know... I should have written them 1st..)
- make a deb or rpm
- make a windows executable
- convert to python 3 with 2to3 etc..
Rather than risk breaking my main codebase however, I believe it always helps to attempt this stuff with a smaller application first I think. So I've written one. It is trivial enough to keep the codebase simple, but complex enough to be realistic.It raises dialogs, stores data, etc.
I've tried to follow a lot of my coding style choices (which you may hate), but on checking the modules with pylint, most get a 10/10, only decreasing when PyQt4 own naming conventions dictate.
anyways, to cut to the chase.. the code is here is anyone wants a play. This is in the public domain, so do with it as you wish.
download it from my dropbox account http://dl.dropbox.com/u/1989100/example_pyqt_app.tar.bz2
My current focus is writing unittests (something I am ashamed to admit I have never done before), and it is proving VERY interesting.
for example. dialogs are interesting, in that the exec_ function needs to be called to ensure correct code coverage. Calling that during a test run causes a pause in the procedings.. not good.
So what is the best way to call accept() or reject() on such a dialog?
I am experimenting with installEventFilter into QApplication itself, and accepting the dialog when the focus event is encountered seems to be working really well.
Tuesday, 7 June 2011
Python Class - Am I a subclass?
Problem...
in #python on freenode, a question was asked about identifying a subclass during the __init__ method.
I came up with this example.
class Example(object):
def __init__(self):
if self.__class__ != Example.mro()[0]:
print "I am an instance of a subclass of Example"
else:
print "I am an instance of Example"
class ExampleDeritive(Example):
''' the most basic of subclasses! '''
pass
>>> Example()
I am an instance of Example
>>> ExampleDeritive()
I am an instance of a subclass of Example
Monday, 23 May 2011
ubuntu-dental doppleganger
my dental life and open source advocacy seldom collide.
however, I'm struck by the likeness between these two women, who are leaders in each field.
This is Marilou-Ciantar, arguably Scotland's most eminent periodontal specialist.
and this is Jane Silber, CEO of canonical (the company behind ubuntu)
uncanny in my opinion.
however, I'm struck by the likeness between these two women, who are leaders in each field.
This is Marilou-Ciantar, arguably Scotland's most eminent periodontal specialist.
and this is Jane Silber, CEO of canonical (the company behind ubuntu)
uncanny in my opinion.
Friday, 8 April 2011
Hiding the MenuBar in a PyQt application.
I've long been a fan of the firefox plugin "tiny menu" where screen real estate is preserved by compressing the application's menubar down into a single menu button.
Here's one way to achieve the same effect in pyqt4.


Here's one way to achieve the same effect in pyqt4.


#! /usr/bin/env python
# -*- coding: utf-8 -*-
'''
A simple application with a shrinkable menu bar.
(similar functionality to firefox4)
At any point either the tiny menu or menubar should be visible.
Therefore if the toolbar is hidden, the menu will re-appear.
to experience this... either
click View>Tiny Menu or hit F11
'''
from PyQt4 import QtGui, QtCore
class DockableMenuBar(QtGui.QMenuBar):
def __init__(self, parent=None):
QtGui.QMenuBar.__init__(self, parent)
self.toggleViewAction = QtGui.QAction(_("Tiny &Menu"), parent)
self.toggleViewAction.setShortcut('f11')
self.toggleViewAction.setCheckable(True)
self.toggleViewAction.triggered.connect(self.toggle_visability)
self.menu_view = QtGui.QMenu(_("&View"), self)
self.menu_view.addAction(self.toggleViewAction)
self.addMenu(self.menu_view)
self._menu_button = None
@property
def menu_button(self):
self._menu_button = QtGui.QToolButton()
self._menu_button.setPopupMode(QtGui.QToolButton.InstantPopup)
self._menu_button.setText(_("Menu"))
self._menu_button.setMenu(self.mini_menu)
self._menu_button.setToolButtonStyle(
QtCore.Qt.ToolButtonFollowStyle)
return self._menu_button
@property
def mini_menu(self):
self._mini_menu = QtGui.QMenu()
for action in self.actions():
self._mini_menu.addAction(action)
return self._mini_menu
def addViewOption(self, action):
'''
add an action to the 'view' category of the toolbar
'''
self.menu_view.addAction(action)
def addMenu(self, *args):
try:
return self.insertMenu(self.actions()[0], *args)
except IndexError:
return QtGui.QMenuBar.addMenu(self, *args)
def addAction(self, *args):
try:
return self.insertAction(self.actions()[0], *args)
except IndexError:
return QtGui.QMenuBar.addAction(self, *args)
def toggle_visability(self, set_visible):
self.setVisible(not set_visible)
if set_visible:
self.emit(QtCore.SIGNAL("mini menu required"), self.menu_button)
else:
self.emit(QtCore.SIGNAL("hide mini menu"))
def setNotVisible(self, menu_bar_visible):
'''
make sure that we don't end up with neither menu visible!
'''
if not menu_bar_visible:
self.setVisible(True)
class DockAwareToolBar(QtGui.QToolBar):
def __init__(self, parent=None):
QtGui.QToolBar.__init__(self, parent)
self.setToolButtonStyle(QtCore.Qt.ToolButtonTextBesideIcon)
self.setObjectName("DockAwareToolbar") #for QSettings
# this should happen by default IMO.
self.toggleViewAction().setText(_("&ToolBar"))
def add_mini_menu(self, menu_button):
self._menu_button = menu_button
if self.actions():
self.insertWidget(self.actions()[0], menu_button)
else:
self.addWidget(menu_button)
self.show()
def clear_mini_menu(self):
self._menu_button.hide()
self._menu_button.setParent(None)
self._menu_button.deleteLater()
self._menu_button = None
class TestMainWindow(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
## initiate instances of our classes
self.toolbar = DockAwareToolBar()
menu_bar = DockableMenuBar(self)
## the menu bar needs this action adding
menu_bar.addViewOption(self.toolbar.toggleViewAction())
## add them to the app
self.addToolBar(QtCore.Qt.TopToolBarArea, self.toolbar)
self.setMenuBar(menu_bar)
## make them aware of one another
self.connect(self.menuBar(), QtCore.SIGNAL("mini menu required"),
self.toolbar.add_mini_menu)
self.connect(self.menuBar(), QtCore.SIGNAL("hide mini menu"),
self.toolbar.clear_mini_menu)
self.toolbar.toggleViewAction().triggered.connect(
self.menuBar().setNotVisible)
## some arbitrary stuff to make the app more realistic
file_action = QtGui.QAction("&File", self)
self.menuBar().addAction(file_action)
line_edit = QtGui.QLineEdit("http://google.com")
self.toolbar.addWidget(line_edit)
go_but = QtGui.QPushButton("Go!")
go_but.setFixedWidth(60)
self.toolbar.addWidget(go_but)
te = QtGui.QTextEdit()
self.setCentralWidget(te)
te.setText(__doc__)
if __name__ == "__main__":
import gettext
gettext.install("")
app = QtGui.QApplication([])
mw = TestMainWindow()
mw.show()
app.exec_()
Thursday, 7 April 2011
Python Class Attributes. A Quiz!
So take a look at this code.
which gives the following output
And here are your questions.
1. Why is the Global statement used on line 11?
2. is there a better way of implementing a unique serial ID for these objects?
3. What would happen if I tried to create an instance with the following call?
5. what is the difference between a "class attribute" or an "instance attribute"?
6. is Person an old or new style class?
7. what would need to change in this code to make it run under python3?
8. what is the __repr__ function for, and what would be the output if it were deleted?
9. what namespace is the __name__ variable found in?
10. why is the trailing underscore used for object_ on the penultimate line of code?
Answers, as always to linc AT thelinuxlink.net, quoting "QUIZ" in the subject field.
#! /usr/bin/env python
'''
A simple class demonstrating attributes
'''
ID_COUNTER = 0
class Person(object):
genus = "homo sapien"
def __init__(self, name, sex="M"):
global ID_COUNTER
assert sex in ("M", "F"), 'INVALID SEX "%s" must be "M" or "F"'% sex
ID_COUNTER += 1
self.id = ID_COUNTER
self.name = name
self._sex = sex
self._profession = None
@property
def sex(self):
return "Male" if self._sex=="M" else "Female"
@property
def profession(self):
if self._profession is None:
return "unknown"
return self._profession
def set_profession(self, profession):
self._profession = profession
def __repr__(self):
return "Person %03d:\n\t%s\n\tGenus\t(%s)\n\t%s\n\t%s"% (
self.id,
self.name,
self.genus,
self.sex,
self.profession)
if __name__ == "__main__":
person1 = Person("Neil")
person1.set_profession("dentist")
person2 = Person("Joan", "F")
person2.genus = "Neanderthal"
person3 = Person("Timrit", "M")
person3.set_profession("refrigeration")
for object_ in (Person.genus, person1, person2, person3):
print object_
print
which gives the following output
homo sapien
Person 001:
Neil
Genus (homo sapien)
Male
dentist
Person 002:
Joan
Genus (Neanderthal)
Female
unknown
Person 003:
Timrit
Genus (homo sapien)
Male
refrigeration
And here are your questions.
1. Why is the Global statement used on line 11?
2. is there a better way of implementing a unique serial ID for these objects?
3. What would happen if I tried to create an instance with the following call?
person4 = Person("ArtV61", "unknown")4. is genus a "class attribute" or an "instance attribute"? 5. what is the difference between a "class attribute" or an "instance attribute"?
6. is Person an old or new style class?
7. what would need to change in this code to make it run under python3?
8. what is the __repr__ function for, and what would be the output if it were deleted?
9. what namespace is the __name__ variable found in?
10. why is the trailing underscore used for object_ on the penultimate line of code?
Answers, as always to linc AT thelinuxlink.net, quoting "QUIZ" in the subject field.
Saturday, 15 January 2011
using pyqt4 to validate XML Schemas
Follow up to the problem solved in the last posting.
lxml worked great, but I don't want to burden folks with yet another 3rd party module.
so I once again looked to pyqt4 for help....
and..
lxml worked great, but I don't want to burden folks with yet another 3rd party module.
so I once again looked to pyqt4 for help....
and..
from PyQt4.QtXmlPatterns import QXmlSchemaValidator, QXmlSchema
#open up the xsd file - and load it into QXMLSchema
f=open("foo.xsd", "r")
xsd = f.read()
f.close()
schema = QXmlSchema()
schema.load(xsd)
#now the xml itself.
f = open("foo.xml", "r")
xml = f.read()
f.close()
validator = QXmlSchemaValidator(schema)
print (validator.validate(xml))
#Returns True :)
validating xml with python
THE XML
I wanted to validate the XML sheets produced by auteurexample XML produced by auteur.
<?xml version="1.0" encoding="UTF-8"?>
<auteur>
<source>
<location>/home/neil/Videos/2010_04_canada/M2U00547.MPG</location>
<timestamp pos="11" />
<clip end="7.5" id="0001" start="1.5" />
<clip end="13.6" id="0002" start="7.5" />
<clip end="1.5" id="0003" start="0.0" />
</source>
<source>
<location>/home/neil/Videos/2010_04_canada/M2U00549.MPG</location>
<timestamp pos="2.678" />
</source>
</auteur>
The Schema
and here's the schema I wrote to check the validity of that data.(saved as foo.xsd)
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:annotation>
<xs:documentation>
The rules in this schema will be used to validate
the content of an auteur project file.
</xs:documentation>
<xs:appinfo source="http://www.auteur-project.org" > </xs:appinfo>
</xs:annotation>
<!--RULES START HERE -->
<!-- ROOT NODE -->
<xs:element name="auteur" >
<xs:complexType>
<xs:sequence>
<!-- SOURCES -->
<xs:element name="source" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<!-- only 1 location allowed per source -->
<xs:element name = "location" type="xs:string" minOccurs="1" maxOccurs="1"/>
<!-- TIMESTAMPS -->
<xs:element name = "timestamp" minOccurs="0" maxOccurs="unbounded" >
<xs:complexType>
<xs:attribute name="pos" type="xs:decimal" use="required" />
</xs:complexType>
</xs:element>
<!-- CLIPS -->
<xs:element name="clip" minOccurs="0" maxOccurs="unbounded" >
<xs:complexType>
<xs:attribute name = "id" type="xs:string" use="required" />
<xs:attribute name = "start" type="xs:decimal" />
<xs:attribute name = "end" type="xs:decimal" />
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
THE PYTHON to put it all together
a short python script to check foo.xml's validity with foo.xsd(note lxml is NOT in python standard lib - a real pity!)
#! /usr/bin/env python
from lxml import etree
try:
doc = etree.parse("foo.xml")
xsd = etree.parse("foo.xsd")
xmlschema = etree.XMLSchema(xsd)
xmlschema.assertValid(doc)
print ("document validates!")
except etree.XMLSyntaxError as e:
print ("PARSING ERROR", e)
except AssertionError as e:
print ("INVALID DOCUMENT", e)
Wednesday, 15 December 2010
QtCore.QDate gotcha for python dictionaries
I came across an odd little issue this morning while creating a data model for a diary I am writing.
In the model, Data is stored in a dictionary, with dates as keys.
For a variety of reasons, my first choice was to use a QDate for the keys, however this produced odd results.
The following example code should demonstrate.
so what is going on? The dictionary DOES have a key of QDate(2011,8,21)... but is unable to find it.
In debugging, I was reminded that python dictionaries hash the key values and it turns out that there is a known bug in QDate.__hash__
this has been fixed in the very latest versions of PyQt4 I believe (including the python3 version)
In the meantime, I am simply adding a step of conversion to python date types for the keys.
In the model, Data is stored in a dictionary, with dates as keys.
For a variety of reasons, my first choice was to use a QDate for the keys, however this produced odd results.
The following example code should demonstrate.
>>> from PyQt4.QtCore import QDate
>>> mydict = {}
>>> for year in range(2009,2013):
... dt = QDate(year,1,1)
... while dt.year() == year:
... mydict[d] = "boo"
... dt = dt.addDays(1)
>>>
>>> mydict.keys()[:3]
3: [PyQt4.QtCore.QDate(2011, 8, 21),
PyQt4.QtCore.QDate(2009, 12, 17),
PyQt4.QtCore.QDate(2009, 7, 15)]
>>>
>>> mydict[QDate(2011,8,21)]
KeyError: PyQt4.QtCore.QDate(2011, 8, 21)
so what is going on? The dictionary DOES have a key of QDate(2011,8,21)... but is unable to find it.
In debugging, I was reminded that python dictionaries hash the key values and it turns out that there is a known bug in QDate.__hash__
>>> d1 = QDate(2009,12,9) >>> d1.__hash__() 4: 48759696 >>> >>> d2 = QDate(2009,12,9) >>> d2.__hash__() 5: 45344152 >>>
this has been fixed in the very latest versions of PyQt4 I believe (including the python3 version)
In the meantime, I am simply adding a step of conversion to python date types for the keys.
>>> d1.toPyDate().__hash__() 6: 5917697570912074722 >>> d2.toPyDate().__hash__() 7: 5917697570912074722 >>>
Thursday, 18 November 2010
a neat(?) postgresql solution using row_number() and self joining
For the scheduling aspect of openmolar, a common task is to find where "freeslots" occur. In the original openmolar, I performed this logic using python code. For openmolar2 the database itself will perform this search.
Here's how.
let's make a trivial diary table
select * from diary;
so the problem is this... how can I query that table to discover my free time on that day?
(there is 90 minutes before lunch)
NOTE - the activities are NOT in order!
the answer (and I found this in the excellent "sql cookbook") involves getting a view of that table in the correct order, and then performing a join on adjacent rows.
so first, get the ordered view.
=> select * from diary order by starttime;
But this doesn't help... because there is no way to definatively refer to the "next" activity, to do this we need to replace ix with a generated rownumber. We will use the row_number() window function of postgres 8.4.
=> select * from (select row_number() over (order by starttime) as rownumber,
starttime, endtime, activity from diary) as ordered_diary;
no we can self join that result set on itself..
(adding columns from the next row to the current row)
=> select * from
(select row_number() over (order by starttime) as row_number, * from diary) as diary1,
(select row_number() over (order by starttime) as row_number, * from diary) as diary2
where diary2.row_number = diary1.row_number+1
or more succinctly...
=> select diary1.activity as first_activity, diary1.endtime as finishes,
diary2.activity as next_activity, diary2.starttime as starts from
(select row_number() over (order by starttime) as row_number, * from diary) as diary1,
(select row_number() over (order by starttime) as row_number, * from diary) as diary2
where diary2.row_number = diary1.row_number+1
so we simply now have to add a check to see if those times differ
so here's the final query!
=> select diary1.endtime as freetime_start, diary2.starttime as freetime_end from
(select row_number() over (order by starttime) as row_number, endtime from diary) as diary1,
(select row_number() over (order by starttime) as row_number, starttime from diary) as diary2
where diary2.row_number = diary1.row_number+1
and diary1.endtime < diary2.starttime
Here's how.
let's make a trivial diary table
create table diary ( ix serial primary key, startTime time, endTime time, activity varchar(80));leading to this table of data.
select * from diary;
| ix | starttime | endtime | activity |
| 1 | 09:00:00 | 09:30:00 | breakfast |
| 2 | 09:30:00 | 10:00:00 | jogging |
| 3 | 13:00:00 | 14:00:00 | lunch |
| 4 | 10:00:00 | 11:30:00 | meeting with joe |
| 5 | 14:00:00 | 18:00:00 | golfing at Royal Dornoch |
so the problem is this... how can I query that table to discover my free time on that day?
(there is 90 minutes before lunch)
NOTE - the activities are NOT in order!
the answer (and I found this in the excellent "sql cookbook") involves getting a view of that table in the correct order, and then performing a join on adjacent rows.
so first, get the ordered view.
=> select * from diary order by starttime;
| ix | starttime | endtime | activity |
| 1 | 09:00:00 | 09:30:00 | breakfast |
| 2 | 09:30:00 | 10:00:00 | jogging |
| 4 | 13:00:00 | 14:00:00 | lunch |
| 3 | 10:00:00 | 11:30:00 | meeting with joe |
| 5 | 14:00:00 | 18:00:00 | golfing at Royal Dornoch |
But this doesn't help... because there is no way to definatively refer to the "next" activity, to do this we need to replace ix with a generated rownumber. We will use the row_number() window function of postgres 8.4.
=> select * from (select row_number() over (order by starttime) as rownumber,
starttime, endtime, activity from diary) as ordered_diary;
| rownumber | starttime | endtime | activity |
| 1 | 09:00:00 | 09:30:00 | breakfast |
| 2 | 09:30:00 | 10:00:00 | jogging |
| 3 | 10:00:00 | 11:30:00 | meeting with joe |
| 4 | 13:00:00 | 14:00:00 | lunch |
| 5 | 14:00:00 | 18:00:00 | golfing at Royal Dornoch |
no we can self join that result set on itself..
(adding columns from the next row to the current row)
=> select * from
(select row_number() over (order by starttime) as row_number, * from diary) as diary1,
(select row_number() over (order by starttime) as row_number, * from diary) as diary2
where diary2.row_number = diary1.row_number+1
| row_number | ix | starttime | endtime | activity | row_number | ix | starttime | endtime | activity |
| 1 | 1 | 09:00:00 | 09:30:00 | breakfast | 2 | 2 | 09:30:00 | 10:00:00 | jogging |
| 2 | 2 | 09:30:00 | 10:00:00 | jogging | 3 | 4 | 10:00:00 | 11:30:00 | meeting with joe |
| 3 | 4 | 10:00:00 | 11:30:00 | meeting with joe | 4 | 3 | 13:00:00 | 14:00:00 | lunch |
| 4 | 3 | 13:00:00 | 14:00:00 | lunch | 5 | 5 | 14:00:00 | 18:00:00 | golfing at Royal Dornoch |
or more succinctly...
=> select diary1.activity as first_activity, diary1.endtime as finishes,
diary2.activity as next_activity, diary2.starttime as starts from
(select row_number() over (order by starttime) as row_number, * from diary) as diary1,
(select row_number() over (order by starttime) as row_number, * from diary) as diary2
where diary2.row_number = diary1.row_number+1
| first_activity | finishes | next_activity | starts |
| breakfast | 09:30:00 | jogging | 09:30:00 |
| jogging | 10:00:00 | meeting with joe | 10:00:00 |
| meeting with joe | 11:30:00 | lunch | 13:00:00 |
| lunch | 14:00:00 | golfing at Royal Dornoch | 14:00:00 |
so we simply now have to add a check to see if those times differ
so here's the final query!
=> select diary1.endtime as freetime_start, diary2.starttime as freetime_end from
(select row_number() over (order by starttime) as row_number, endtime from diary) as diary1,
(select row_number() over (order by starttime) as row_number, starttime from diary) as diary2
where diary2.row_number = diary1.row_number+1
and diary1.endtime < diary2.starttime
| freetime_start | freetime_end |
| 11:30:00 | 13:00:00 |
Friday, 12 November 2010
Firesheep in Action
further to Yesterday's post on installing firesheep on 64-bit ubuntu .... I had a play with the firesheep plugin.
I disabled (temporarily) WPA on my home network, and started monitoring. I was able to hijack both my facebook and twitter sessions.
I disabled (temporarily) WPA on my home network, and started monitoring. I was able to hijack both my facebook and twitter sessions.
Thursday, 11 November 2010
Firesheep.
Firesheep is a plugin for Firefox that is creating a lot of noise in the IT security community. It allows you to hijack sessions of other users on open wifi.
There is a windows/mac version of this plugin, but that is no use to me (and I will point out my intentions are NOT malicious, but to demonstrate to friends/colleagues the dangers of the interwebs).
thanks to information on this page I got it working on my 64-bit ubuntu 10.04(lucid) laptop.
here's what I did to get it working.
regards
Neil.
to install firesheep on lucid
1. get dependencies (your mileage may vary)
2. get the latest firesheep code from github
3. compile the firesheep.xpi "plugin"
4. set up a monitor interface
5. Install the plugin into firefox.
Open Firefox, and from the menu choose "File", then open ~/firesheep/build/firesheep.xpi
restart firefox when asked
6. firesheep needs correct permissions to access your wifi card.
sudo ./firesheep-backend --fix-permissions
note- there WILL be subtle differences in this directory
7. Ready to go!
open firefox and click on
add-ons->firesheep->preferences->interface
then choose mon0 from the drop down list. (see screenshot below)
8. Enable the Firesheep Sidebar.
view->SideBar->firesheep;
(or ctrl-shift-s)
DONE!
There is a windows/mac version of this plugin, but that is no use to me (and I will point out my intentions are NOT malicious, but to demonstrate to friends/colleagues the dangers of the interwebs).
thanks to information on this page I got it working on my 64-bit ubuntu 10.04(lucid) laptop.
here's what I did to get it working.
regards
Neil.
to install firesheep on lucid
1. get dependencies (your mileage may vary)
sudo apt-get install libhal-dev libtool autoconf xulrunner-dev libboost-dev libpcap-dev iw git
2. get the latest firesheep code from github
git clone git://github.com/mickflemm/firesheep.git
3. compile the firesheep.xpi "plugin"
cd firesheep
./autogen.sh
git submodule update --init
make
4. set up a monitor interface
sudo iw wlan0 interface add mon0 type monitor
sudo ifconfig mon0 up
5. Install the plugin into firefox.
Open Firefox, and from the menu choose "File", then open ~/firesheep/build/firesheep.xpi
restart firefox when asked
6. firesheep needs correct permissions to access your wifi card.
cd ~/.mozilla/firefox/7oyiuecg.default/extension/firesheep@codebutler.com/platform/Linux_x86_64-gcc3/
note- there WILL be subtle differences in this directory
7. Ready to go!
open firefox and click on
add-ons->firesheep->preferences->interface
then choose mon0 from the drop down list. (see screenshot below)
8. Enable the Firesheep Sidebar.
view->SideBar->firesheep;
(or ctrl-shift-s)
DONE!
Tuesday, 28 September 2010
Object Orientation Example
I knocked this example up today for a friend on IRC. Thought I would post it here.
#! /usr/bin/env python
################################################################################
## Python Object Orientated example by rowinggolfer ##
## the same object... but extra functionality added in layers ##
## ##
## A noteable "Gotcha" for newbs is the __init__ function. ##
## the base class in this example sets some important attributes in this ##
## function. Therefore classes which inherit from it, but be careful if ##
## re-implementing this function ##
## NOTE - the teenager class does NOT overwrite this function... hence when ##
## a teenager is initiated, python looks up the class hierarchy and executes ##
## the first __init__ method it finds.. in this case the Toddler's __init__ ##
## ##
## ##
## Run this script, and study the output. ##
## ##
## Pay special attention to the attribute "description, and see how it is ##
## altered mid method in the teenage years. ##
## ##
################################################################################
from datetime import date
from base64 import b64decode
class TimritBaby(object):
'''
a baby has a date of birth, a name, and limited functionality
'''
def __init__(self, date_of_birth):
print "TimritBaby initiated"
self.name = 'Scott Murtz'
self.dob = date_of_birth
self.description = "(a baby)"
def poop(self):
print " %s %s can Poop!"% (self.name, self.description)
class TimritToddler(TimritBaby):
'''
a toddler has a new method
'''
def __init__(self, dob):
# call the init method of the base class..
# otherwise the name attribute won't work!!
print "\nTimritToddler initiated"
TimritBaby.__init__(self, dob)
self.description = "(a toddler)"
def walk(self):
print " %s %s can Walk!"% (self.name, self.description)
class TimritTeenager(TimritToddler):
'''
a teenager with a secret habit
'''
def private_time(self):
self.description = "(now a teeneager)"
message = b64decode('aXMgbWFzdHVyYmF0aW5nIGFnYWlu')
print " %s %s %s"% (self.name, self.description, message)
if __name__ == "__main__":
baby = TimritBaby(date(1968,1,1))
baby.poop()
try:
baby.walk()
except AttributeError as e:
print "ERROR - WHOOPS!", e
teenager = TimritTeenager(date(1968,1,1))
teenager.poop()
teenager.walk()
teenager.private_time()
teenager.walk()
Sunday, 12 September 2010
fuzzymatching in postgres on ubuntu
I had a battle getting the soundex function installed into my database on postgres.
but here's how I succeeded.
One - Install the postgres-contrib package
Two - change user to postgres (a database superuser created on install of postgresql
Three - pipe the supplied script into the database (my database is called "openmolar_demo")
Four - test it!
but here's how I succeeded.
One - Install the postgres-contrib package
sudo apt-get install postgresql-contrib
Two - change user to postgres (a database superuser created on install of postgresql
neil@slim-maroon:~$ sudo su - postgres postgres@slim-maroon:~$
Three - pipe the supplied script into the database (my database is called "openmolar_demo")
postgres@slim-maroon:~$ psql -d openmolar_demo -f /usr/share/postgresql/8.4/contrib/fuzzystrmatch.sql SET CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION CREATE FUNCTION postgres@slim-maroon:~$
Four - test it!
openmolar_demo=> SELECT soundex('Neil');
soundex
---------
N400
(1 row)
Subscribe to:
Posts (Atom)


