Showing posts with label python. Show all posts
Showing posts with label python. Show all posts

Saturday, July 30, 2011

Auto incrementing version numbers in Xcode

Over the last month or so i've had to kick out a lot of betas for a project. Seeing as i use the fantastic Test Flight. I have to change the version number before i upload each build otherwise Test Flight will overwrite an existing build which is the last thing that we want.

I don't think anyone actually enjoys editing a plists, whether its in Xcode plist editor or the down and dirty XML. So has a result it was the perfect opportunity to get familiar with xcode's build process, and how to tie external scripts into it.

I use 3 segment version numbers (1.1.1), where the first digit is the major version, second digit is the minor version, and the 3rd digit is the build. For the benefit of the team, i wanted to have the latest commit hash in the build number so that people could quickly reference it and know whats going on.

With some direction from this post by Duane Sibilly i was able to hack together the below.

Friday, May 08, 2009

It's over!

Quick post to mention that i've finished my degree! more importantly i that i can get back to doing what i love, writing code (and playing FM).

Heres some extremely basic python for transforming a simple list of CRLF separated values into a sql statement.



def main():
fh = open('list.txt')

sql = open('sqlDump.txt','w')

i = 0
for line in fh:
statement = "INSERT INTO table (name) VALUES ('%s');\r" % line.rstrip()

sql.write( statement )

fh.close()
sql.close()

if __name__ == '__main__':
main()


Nothing special.

Off to china on sunday!!
再见

Wednesday, July 23, 2008

OSS: Python webpage link checker

Another piece of python to go. Nothing special, but something fairly useful that i've thrown together. 
The following code samples are released under the terms of the GPL 2.0

It's URL link checker, it's not fully recursive (working on it, they don't teach recursive algorithms on my course). But checks all the anchor tags on the given page, returning warnings and the like depending on what it finds.

Usage: To use this just run it like so "python [scriptname]"
It will then ask for the url of the page you wish to check, and then it will print a report, like so.

Python

#Link Checker
#Brazen attempt to write one in 15 minutes
# Jonathan Dalrymple
# July 15,2008
# Start 11:52
# End 12:35

import httplib
import sgmllib
import re

#HTML Parser
class LinkChecker( sgmllib.SGMLParser ):
def __init__(self, verbose = 0):
sgmllib.SGMLParser.__init__( self, verbose )

self.linkList = []
self.inLink = False
self.lastHref = None
self.hostName = None

print 'Parsing file...'

def parse( self, fileStr ):
self.feed( fileStr )
self.close()

def start_a( self, attr ):

#Show user that the parser is working
#print '*'

self.inLink = True

for name, val in attr:
if name == 'href':
self.lastHref = val

def end_a( self):
self.inLink = False

def handle_data(self, str):

if self.inLink:

tmp = self.__parseUrl( self.lastHref )
self.linkList.append( (str,tmp['host'],tmp['path']) )

def __parseUrl( self, str ):
ret = {}

#slice of preceeding http
#if str[0:7] == 'http://':
# str = str[7:len(str)]

# Extract path regex "\w+\.(\w*)\.(\w{2}\.)?(\w{2,3})"
m = re.compile("\w+\.(\w*)\.(\w{2}\.)?(\w{2,3})").match( str )

if m == None:
#print 'Error in handle url, regex failed'

ret['host'] = None
ret['path'] = str
else:
ret['host'] = m.string[0:m.end()]

if m.end() <>
ret['path'] = str[ m.end(): len(str) ]
else:
ret['path'] = None

return ret
#Check link
def __checkLink( self, displayName, host = None, path = '/' ):
if host == None:
host = self.hostName

#slice path and determine if it is a full url
reqObj = httplib.HTTPConnection( host, 80 )

#print '---Requesting %s' % url+path
reqObj.request('get', path )

response = reqObj.getresponse()

if response.status == 200:
retVal = "SUCCESS |%s returned %d" % (displayName, response.status )
elif response.status == 404:
retVal = "FAILURE |%s returned %d, (%s)" % (displayName, response.status, path )
else:
retVal = "WARNING |%s returned %d, (%s)" % (displayName, response.status, path )

return retVal
def testUrlParser( self, list ):
for u in list:
print '--' + str(self.__parseUrl( u ))
def runReport( self, urlStr ):
urlDict = self.__parseUrl( urlStr )

if urlDict != None:
self.hostName = urlDict['host']
req = httplib.HTTPConnection(urlDict['host'], 80)

req.request('get',urlDict['path'])
response = req.getresponse()

if response.status == 200:

htmlStr = response.read()

self.parse( htmlStr )

print "%d links found" % len( self.linkList )

for v in self.linkList:
#print v
print self.__checkLink( v[0], v[1], v[2] )
else:
print "Download Request for %s failed: %d" % ( response.reason, response.status)


def main():

#urlStr = "http://www.google.co.uk/search?hl=en&q=bar&btnG=Google+Search&meta="
urlStr = raw_input('Url you wish to check:')
if urlStr != None:
bar = LinkChecker()
#foo = ('www.google.com','http://www.google.com','http://docs.python.org/lib/lib.html','docs.python.org/test')
#bar.testUrlParser( foo )
bar.runReport( urlStr )

if __name__ == '__main__':
main()


Quote of the Day
I now finally understand why those guys buy £100,000  cars, only to sit in traffic. It's because they remember the days of running for the train, only to find that it's standing room only and their new best friend is a significantly taller gentleman's (or lady!!) armpit and or sweaty back.

Realizations, Andorra here i come

Saturday, June 21, 2008

Facebook Chat

This started as a long post, but as i am learning actions speak louder than words

Sunday, May 18, 2008

Snake in the torrents ...

I decided to branch out last week and use python seriously for the first time.

Turns out it is as good as all the praise it gets. This conversion was round about the same time i switched to Transmission for my torrenting needs as the jre + azuerus don't do my memory usage any real favours. The main thing that i love about azuerus was the fact that i could have it subscribe to a rss feed and download "linux iso's" automatically. Coupled with the fact that everyones favourite release group, EZTV provides there releases in the RSS form, it was perfect. However the plugin stopped working correctly about a month ago and i've been forced to actually operate my torrent client, gasp!

Anyways, while having a shower (Yes, i come up with concepts in the shower), i thought maybe i can replicate that functionality using python! Transmission has a feature that makes it scan a folder for torrents, so in theory i would simply need to do the following ...
  • Read a list of files/shows
  • extract the respective links from a rss/xml feed
  • calculate which ones are the most recent
  • download the torrent files
Below is the entire script. It stores all torrent information in sqlite database, meaning that you can extend anyway you want. The script is released under GPL 2.0. I haven't done any real testing, but it works fine with the following conditions
  • Python 2.5.1
  • OS X 10.5
  • Atom RSS source feed (Mininova)
My plan to schedule it as a cron job and sit back and watch.

Python



#Channel 0.1
# Jonathan Dalrymple
# May 17th, 2008

from xml.etree import ElementTree as ET
import os
import shutil
import sqlite3
import urllib

currentDirectory = os.path.dirname( os.path.abspath( __file__ ))

#Create SQL
dbConn = sqlite3.connect( os.path.join( currentDirectory,"torrentsDB") )

#Create the new table
sql = "DROP TABLE IF EXISTS torrents"

dbConn.execute( sql )

sql = """
CREATE TABLE IF NOT EXISTS torrents (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT,
date TEXT,
url TEXT
)
"""

dbConn.execute( sql )
dbConn.commit()

#Get XML file
response = urllib.urlretrieve( "http://www.mininova.org/rss.xml?user=eztv" )

shutil.copyfile(response[0], os.path.join( currentDirectory,"rssSource.xml") )

xmlFile = os.path.join( currentDirectory, "rssSource.xml" )

try:

tree = ET.parse( xmlFile )

selection = tree.getiterator('item')

i = 0
#For each item tag
for element in selection:
#Get the request elements from the selection

title = element.findtext('title')
date = element.findtext('pubDate')
enclosure = element.find('enclosure').attrib['url']

sql = "INSERT INTO torrents (title, date, url ) VALUES ( '%s','%s','%s')" % (title, date, enclosure)

dbConn.execute( sql )

i += 1

#Commit records
dbConn.commit()

print '%d Torrents have been processed and added to the database' % (i)

except Exception, inst:
print 'Parse Error: %s' % (inst)

#Read the config file for the shows
configFile = file("shows.txt")
shows = configFile.readlines()

#Get the url for the show
print "The following torrents where found ..."

for show in shows:

dataSet = dbConn.cursor()

dataSet.execute( "SELECT title, url FROM torrents WHERE title LIKE '%" + show.rstrip() +"%' ORDER BY id DESC LIMIT 1" )

row = dataSet.fetchone()

#Test to ensure that a record exists
if type(row) == type(tuple()):
try:
print row[0]

#download the torrent file
response = urllib.urlretrieve( row[1] )

newFilename = os.path.join (currentDirectory, show + ".torrent")
#Move from the temp folder
shutil.copyfile( response[0], newFilename )

except Exception, inst:
print 'Download Error: %s' % (inst)

print 'Complete'


Lastly to create the config file, just open your favourite text editor and list your tv shows, delimited using return, mine looks like this

Lost
Battlestar Galactica
House
Cops
American Dad

It's not case sensitive, so don't panic.