Migrating to XFCE

The following was from a Google+ post that I figured I would share here as well.

Well I think I’m finally switching my main desktop from KDE to XFCE. Too much flash and pizazz and having to turn off behaviors and mannerisms for my liking. I guess I’m just getting too old for these young peoples’ desktops.

It was a decent 9+ years, KDE. Sorry you had to turn into GNOME.

A later follow-up comment:

[warning: non-proofread, off-the-cuff rant ahead]

Made the switch last night. Very refreshing!

Not sure if others get the same feeling, but I believe desktops have a measurable weight in terms of interaction and feel. As of late (read KDE 4.*), KDE has lost weight and felt ungrounded. Delayed click responses, bouncing icons, crashing UI effects, windows partially disappearing, and the ‘improved’ graphics all tend to lend way to a flighty feel and experience. But not in a good way, but rather a lack of solidity that I want from a desktop. I want a concrete user experience that shows of it’s strength in the back-end by portraying a solid and consistently reliable front-end. I’ll trade ‘sleek’, ‘cutting-edge’, and ‘feature overflowing’ for solidity and reliability any day. When productivity calls what really matters?

Is it just me feeling the departure of usability? I am one who spends 75% of my computing time tied to a terminal emulator. Maybe I am simply disconnected from what is truly meant to be the modern desktop experience. I look to OS X and Windows Vista/7 for comparison and see similar qualities to KDE 4 and GNOME 3. It’s quite possible that these are the ways of today and are in response to what the majority of users demand from their desktops.

One of the major selling points for Linux is obviously the stability and reliability of the kernel. Therefore, I would expect that the layering OS and desktop should reflect such qualities and do nothing but to bring out the best possible performance and usability of the Linux kernel. KDE4 and GNOME3 seem to have diverged greatly from these ideas. Is it time for distributions to begin defaulting their OSes to a more reasonable (see qualities above for a definition of reasonable) desktop? Maybe Xubuntu should really become Ubuntu, leaving Kubuntu and Gubuntu (?) as unique, non-default variations.


 

Posted in Linux, Rants | Tagged , , , , | Comments Off

Google+ vs Facebook

I received a pretty early invite to Google+ a while back and I’ve been really buying into the revolutionary(?) social networking service wholeheartedly. I would be inclined to suggest dropping the term social here as I feel it is a mature platform more apt for productivity; not to sound pretentious, but the grown-ups’ Facebook. There is an overload of commentary on Google+ and how it compares to Facebook so I won’t really try to jump into the fray here. However, I did have a few thoughts tonight while playing around on both sites and will simply throw out a quick list of some things that came to mind.

Here is the link to the Google+ post.

Or here is the post content:

Google+ vs Facebook

Things I really like about Google+ over Facebook (in no particular order and not fully inclusive – more of an off the cuff list):

- MUCH easier to find people
– Circles are how it should always be with social networks/applications
– Cleaner and faster interface
– No zombie pirate mining farms
– Productivity and efficiency in mind
– Huddles and hangouts are really well done so far
– Keyboard shortcuts such as bold and italicized
– No spamming overlords (yet?)
– Real names (although I don’t agree with the harsh lockouts I guess)
– Google product integration is pretty slick
– The mobile app is light years beyond the facebook app (at least on ios)
And last but not least, the open source community is present and accounted for!

- Oh and apparently on Facebook this has to be a note since it’s longer than 400 (or so) characters… come on…. I can rant away on Google+

We’ll have to see how things pan out as more people adopt Google+ and development rolls along. At this point, I will admit that I was an early advocate and fan. After some solid use of all the features and side-by-side comparison of day to day posting and usage, I remain and advocate and fan.

See you on Google+! [me]

Posted in Rants, Reviews, thingsilikethatifoundonline | Tagged , , | Comments Off

Python – Dynamically Printing to Single Line of Stdout

It’s that time again; code snippet time. This is a short and sweet bit of a code that has some really practical and powerful implications.

When handling large amounts of data processing, it’s often desirable to keep the user informed of where things are in terms of progress. However, filling up the scrollback buffer with thousands of “Completed processing [item X]” or “X % completed” is not always desirable. So, how do we handle verbosity without filling scrollback?

Here, we will print data using stdout but we will continually use the same line of the terminal. It’s extremely simple; before each data print, we will move the cursor back to the beginning of the current line, cut out the entire line of text, and then print our current bit of data.

*Note: This is using ANSI escape sequences and therefore will work on any VT100 type terminal.

 

The code:

import sys

class Printer():
	"""
	Print things to stdout on one line dynamically
	"""

	def __init__(self,data):

		sys.stdout.write("\r\x1b[K"+data.__str__())
		sys.stdout.flush()

 

To output data we might do something like:

totalFiles = len(fileList)
currentFileNum = 1.0

for f in fileList:
	ProcessFile(f)
	currentPercent = currentFileNum/totalFiles*100
	output = "%f of %d completed." % (currentPercent,totalFiles)
	Printer(output)
	currentFileNum += 1

 

And here is an example of what our output would look like in a practical scenario.

Processing some data

Progressing along with dynamic status updates

Simple. You can test it out using an 'for x in range(1,100)' sort of statement as well. Now we can keep a persistent display of data processing or program progress without slamming the scrollback buffer of the user's terminal.

Posted in Hacks, Linux, Programming, Python | Tagged , , , , , , , | Comments Off

Installing Google Chrome in Slackware 13 (13.37)

Trying to install Google-Chrome via RPM (with rpm2tgz) will give you an error with libnss3. Don’t fret, there is already a way to build Google-Chrome without much effort. Below is a quick way using the mirror from Penn State (carroll), but if you have your install media, you can find the same files there in /extra.

Go to: ftp://carroll.cac.psu.edu/pub/linux/distributions/slackware/slackware-13.37/extra/google-chrome/

The README file is pretty self explanatory, but essentially you want to do the following:

  1. Become rootSetup a build directory (mkdir chrome && cd chrome)
  2. Wget these files: [ ftp://carroll.cac.psu.edu/pub/linux/distributions/slackware/slackware-13.37/extra/google-chrome/google-chrome.SlackBuild ] [ ftp://carroll.cac.psu.edu/pub/linux/distributions/slackware/slackware-13.37/extra/google-chrome/google-chrome-pam-solibs-1.1.3-i486-1.txz ] [ ftp://carroll.cac.psu.edu/pub/linux/distributions/slackware/slackware-13.37/extra/google-chrome/ORBit2-2.14.19-i486-1.txz ] [ ftp://carroll.cac.psu.edu/pub/linux/distributions/slackware/slackware-13.37/extra/google-chrome/GConf-2.32.1-i486-1.txz ]
  3. Change execution bit on slackbuild file and run it (chmod +x google-chrome.SlackBuild && ./google-chrome.SlackBuild)
  4. Go to tmp and install the file (cd /tmp && upgradepkg –install-new google-chrome.txz)
  5. Go back and install the other files (cd /root/chrome/ && upgradepkg –install-new *.txz)

Now you should have a fully functional google-chrome install.

Posted in Hacks, Linux | Tagged , , , , , , | Comments Off

Stumpy Updated – v1.4.3

The Mutaku URL shortener, Stumpy, has now been updated to version 1.4.3.

You can find out more about Stumpy by clicking the first link in this post to read the initial write up on Mutaku, or you can go to the project page on Github.

Stumpy main page

This release includes a few small bug fixes as well as incorporating a new feature that, for logged in users, shows all of their submitted URLS at the bottom of the main page. Previously, this was only viewable by going through the admin interface. If you are not logged in, you will see the traditional view with the 5 most recent and 5 most visited URLs.

You get get the newest release at the Github page here: v1.4.3

Posted in Mutaku, Programming, Python | Tagged , , , , , , | Comments Off

Better Trackpad Functionality with CR-48 in Ubuntu

There is a great post on patching up synaptics based on what is found in opensuse here.

Takes all of 5 minutes and after patching and building the packages, a quick install, and then logging out and back in, you can now use a more functional cr-48 trackpad with your dev-mode ubuntu install.

Confirmed working in 11.04.

Posted in CR-48, Hacks, Linux | Tagged , , , , , | Comments Off

Uploading Images to imgur with Python

That time again. Code snippet time.

UPDATE: See the bottom of the post for the most up-to-date version of the code.

Another brief one. We are going to start working on a class to upload images to imgur.com. There are many ways we can go about doing this, but to start things off, we’ll use the simplest way which is to use the public/anonymous API. This means that anyone can view our images and that we do not need to worry about authentication just yet.

We will use pycurl for the url handling and parameter passing and to decipher our results we will utilize the XML minidom.

Let’s jump right in and see the code. You will need an API key, available here, that you will need to substitute for the key parameter string “YOUR_API_KEY_HERE”.

class UploadImage():
	"""
	Upload images to imgur
	"""

	# Not very verbose at the moment in terms of errors - will build on that later
	def __init__(self,image,upload_method="anon"):
		import pycurl
		from xml.dom import minidom
		import cStringIO

		# setup some initial items we will need
		self.c = pycurl.Curl()
		self.response = cStringIO.StringIO()
		self.minidom = minidom
		self.image = image
		self.imageURL = ""
		self.error = ""

		# provide some various methods for uploading
		# by default - at least for now in testing - we will use anonymous upload method
		if upload_method == "anon":
			self.anon_upload()
		# later or on-demand we can switch to oauth based uploads
		elif upload_method == "oauth":
			self.auth_upload()

	# anonymous upload method
	def anon_upload(self):
		"Upload anonymously to imgur"

		# setup the basic parameters
		params = [
				("key", "YOUR_API_KEY_HERE"),
				("image", (self.c.FORM_FILE, self.image))
			]

		# setup the url and pipe in our key and image
		self.c.setopt(self.c.URL, "http://api.imgur.com/2/upload.xml")
		self.c.setopt(self.c.HTTPPOST, params)

		# we want to capture the output so lets set the write output to go to our cStringIO so we can parse it
		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		# run it
		self.c.perform()
		self.c.close()

		try:
			# parse the XML return string and get the URL of our image
			xml = self.minidom.parseString(self.response.getvalue())
			self.imageURL = xml.getElementsByTagName("original")[0].firstChild.data

		except:
			self.error = "Problem uploading anonymously."

		return self.imageURL,self.error

	# oauth-based upload method
	def oauth_upload(self):
		"Upload using oauth to imgur"

		### Not coded yet but we will use python-oauth2
		pass

To use our uploader, all we have to do is something like the following:

In [1]: from handlers import UploadImage as U

In [2]: a = U('roosevelt.jpg')

In [3]: a.imageURL
Out[3]: u'http://i.imgur.com/cUWzn.jpg'

In [4]: a.error
Out[4]: ''

As you can surmise, we could simply check that there was no error and then utilize the returned URL of our newly uploaded image. Pretty simple stuff and very handy for some quick public/disposable image uploads.

Next time, we will expand our uploader to include an oAuth method that we can utilize for private uploads. Additionally, we will explore our XML returns a little deeper for methods to delete our files or grab some basic view statistics.

Updated code: Here, we are using things in the context of Django, hence the settings call for pulling in the API key and so forth.

class UploadImage():
	"""
	Upload images to imgur
	  returns either .error or .imageURL

	TO DO:

	POSSIBLE TO DO:
		- add stats and image info functions
		- allow for full JSON responses instead of having to manually parse XML

	"""

	# Not very verbose at the moment in terms of errors - will build on that later
	def __init__(self,image="",dhash="",delete=False):

		# setup some initial items and placeholders we will need
		self.c = pycurl.Curl()
		self.response = cStringIO.StringIO()
		self.minidom = minidom
		self.image = image
		self.dhash = dhash.__str__()
		self.delete = delete
		self.message = ""
		self.imageURL = {}
		self.error = []

		if self.dhash and self.delete:
			# if we have a hash and a delete trigger, lets try to wipe the image
			self.wipe()

		else:
			# fire away an upload - we will return an imageURL dictionary with attributes or an error
			self.upload()

	def upload(self):
		"Upload anonymously to imgur"

		# setup the basic parameters
		params = [
				("key", settings.imgur["anon_key"]),
				("image", (self.c.FORM_FILE, self.image))
			]

		# setup the url and pipe in our key and image
		self.c.setopt(self.c.URL, "http://api.imgur.com/2/upload.xml")
		self.c.setopt(self.c.HTTPPOST, params)

		# we want to capture the output so lets set the write output to go to our cStringIO so we can parse it
		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		try:
			# run it
			self.c.perform()
			self.c.close()

		except:
			self.error.append("Problem uploading image.")

		if not self.error:
			# parse the xml
			self.parseXML()

		return self.message,self.imageURL,self.error

	def wipe(self):
		"Wipe an anonymouse image from imgur"

		deleteURL = "http://api.imgur.com/2/delete/%s" % self.dhash

		self.c.setopt(self.c.URL, deleteURL)

		self.c.setopt(self.c.WRITEFUNCTION, self.response.write)

		try:
			self.c.perform()
			self.c.close()

		except:
			self.error.append("Problem deleting image.")

		if not self.error:
			self.parseXML(delete=True)

	def parseXML(self,delete=False):
		"Parse the XML ouput from IMGUR and write to the imageURL dictionary"

		try:
			# parse the XML string into the dom
			xml = self.minidom.parseString(self.response.getvalue())

			if delete:
				self.message = xml.getElementsByTagName("message")[0].firstChild.data

			else:
				# grab out some helpful/interesting data and setup in the imageURL dictionary
				self.imageURL['url'] = xml.getElementsByTagName("original")[0].firstChild.data
				self.imageURL['hash'] = xml.getElementsByTagName("hash")[0].firstChild.data
				self.imageURL['deletehash'] = xml.getElementsByTagName("deletehash")[0].firstChild.data
				self.imageURL['smallthumb'] = xml.getElementsByTagName("small_square")[0].firstChild.data
				self.imageURL['bigthumb'] = xml.getElementsByTagName("large_thumbnail")[0].firstChild.data

		except:
			self.error.append("Problem parsing XML output.")
Posted in Hacks, Programming, Python | Tagged , , , , , , | Comments Off

Epic Space vs. Earth Chess Battle

In case you were not aware, there is an ongoing chess battle between astronauts aboard the International Space Station and earthbound individuals. Greg Chamitoff and Greg H. Johnson are battling against moves voted upon by earthlings following the tournament online.

Chess - SPACE VS. EARTH 2011

You can follow the match or jump in on the action at the following sites:

http://twitter.com/Astro_Taz

http://facebook.com/ISS

http://www.facebook.com/EarthVsSpaceChess2011

http://www.uschess.org/content/blogcategory/301/629

Posted in thingsilikethatifoundonline | Tagged , , , , , | Comments Off

Python Cookies

Code snippet time again.

Today, let’s look at a few simple classes to handle cookies. We will create functionality to deal with some user tracking cookies so please note that these are NOT being used for security or authentication purposes. We only wish to provide a simple and quick way to allow for synchronous tracking across any browser for a user. An example of usage would be to allow users to obtain a new cookie or duplicate one given a user-associated hash to enable linking of browsers across various machines, say, for url submission tagging in a URL shortener.

We will create three classes; get the token from the established cookie to tag the user, create a cookie based on a random hash if one is not present, or use an existing token to create a duplicate cookie for another browser. The code should be fairly self explanatory and will use hashlib for the hashing and simplecookie for the cookie management.

#!/usr/bin/env python

class CreateCookie():
	"Generate a Cookie using given name"
	def __init__(self,NAME,HASH=""):
		from Cookie import SimpleCookie
		self.C = SimpleCookie()
		self.NAME = NAME
		self.HASH = HASH
		self.makeCookie()
	def makeHash(self):
		import hashlib,random
		self.R = str(random.random())
		self.H = hashlib
		self.FULLTOKEN = self.H.sha256(self.R).hexdigest()
		self.TOKEN = self.FULLTOKEN[:10]
		return self.TOKEN
	def makeCookie(self):
		if self.HASH:
			self.C[self.NAME] = self.HASH
		else:
			self.C[self.NAME] = self.makeHash()
		print self.C

class GetCookie():
	"Retrieve cookie value or generate one if can't find it by given name"
	def __init__(self,NAME):
		from Cookie import SimpleCookie
		import os
		self.NAME = NAME
		if "HTTP_COOKIE" not in os.environ.keys():
			CreateCookie(self.NAME)
		else:
			self.E = os.environ["HTTP_COOKIE"]
			self.C = SimpleCookie(self.E)
			self.getToken()
	def getToken(self):
		try:
			self.TOKEN = self.C[self.NAME].value
			return self.TOKEN
		except:
			print "Can't find Cookie. Generating one."
			CreateCookie(self.NAME)

class CopyCookie():
	"Make a duplicate cookie from existing hash to tack in another browser"
	def __init__(self,NAME,HASH):
		self.HASH = HASH
		self.NAME = NAME
		if not self.HASH.isalnum() or len(self.HASH)>10:
			print "Improper hash."
		else:
			CreateCookie(self.NAME,self.HASH)

Please remember, this is not an attempt to create a secure cookie or one that would, or should, be used for any sort of trusted authentication. This is simply an untrusted cookie tracker and is more of a proof-of-concept that shows simple cookie functionality. From this basic assignment and retrieval, you can start to build a cookie system. Just be sure to read up on security implications and remember to add validation checks. For something production critical, it would be better to pull in established authentication modules from projects like Django or Webpy.

As always, you can check out various code and associated projects under the programming category or visit the Mutaku Github page.

Posted in Hacks, Programming, Python | Tagged , , , , , | Comments Off

Stumpy v1.4.1 – Critical bug fix

Stumpy has been updated to version 1.4.1 to fix a critical bug that was in all previous versions [Thanks, Erik!]. There was an issue with case-sensitivity in short url lookups that is now all patched up.

For general information on the newer v1.4+ Stumpy, see post here.

Get the newest, fixed version here.

Posted in Programming, Python, Server/Webserver | Tagged , , , , , , , | Comments Off