Tag Archives: programming

Pytaf

My new open source project – PYTAF (Python Test Automation Framework) – is in the process of being announced on Freecode.com. The project can be accessed directly through GitHub. It’s a distillation of the various test harnesses I’ve developed over the past several years, beginning in Java, polished in Ruby, until finally fully formed in Python. This version is actually in Python 3, which I’m not using yet in everyday work. It’s not much different, but developing this project was partly a mechanism for learning about it.

I’m happy to put it out there in the world, as happy as putting out any of my ebooks or earlier open-source projects. If one person finds it useful, that will be ‘abundance’.

announcement also here on opencode

According to opencode’s automated project analyzer:
 Codebase 725 lines
 Effort (est.) 0 person-years
 Estimated Cost $ 7,847

python edition of "the leading cause of problems is solutions"

so i am replacing selenium rc 1 with webdriver (a.l.a. selenium 2) and have found it to both solve old problems and create new ones. yay. i can upload files in every browser. boo, now it can’t find the buttons in javascript frames. does it solve more problems than it creates? unfortunately, it seems to be about even. grrr

Praystation is here (for your Android device)

Many years ago I had the (not terribly original) idea to write a smart-phone app that would simply consist of a green arrow pointing always towards Mecca. I would call it The Sunni Praystation (you get the joke, I’m sure). Well, fast forward to last night, when I realized I needed to learn more Android programming in order to do something for my job, and decided to actually write the darn thing. With much thanks for the Flying Spaghetti Monster as well as various blogs and Android Api documents, I can now present to you, in all its minimal glory, Praystation:

Don’t all applaud at once. Yes, I know, it needs some sprucing up … but next steps also include shoving it onto the Android Market as yet another free app (there are several much nicer looking ones that do the exact same thing, by the way. No patents pending here …)

Easy DIY CouchDB using Ruby

Rather than use somebody’s couch gem, (which may or may not return JSON when you expect it to!), what I’m doing here is rolling my own compact Couch library class in Ruby. The class simply uses net/ssh to make properly formed REST calls to the CouchDB. You also need the ‘json’ gem installed. (Also, I’m using Ruby 1.8.7)

The Couch class needs a host, port and db parameter passed into its initialize method. The db is the name of the db, while the host and port are used by the request method to form the URL.  Most every call to Couch is either a GET or a PUT (there is also a DELETE), so we only need a couple of methods (get, put) to create the right kind of Net::Http object, make the REST call and convert the Http response into JSON.

Here is couch_lib.rb

# begin code

require ‘net/ssh’
require ‘json’

class Couch
  def initialize(host, db, port=5984, options = nil)
    @host = host
    @port = port
    @db = db
    @options = options
  end

def request(req)
    res = Net::HTTP.start(@host, @port) { |http|http.request(req) }
    unless res.kind_of?(Net::HTTPSuccess)
       # if there was some kind of Http error, show it
       puts res
    end
    res
  end

def get(id, parse=true)
    res = request(Net::HTTP::Get.new(“/#{@db}/#{id}”))
    parse or return res.body
    JSON.parse res.body
  end

 def put(id, doc)
    req = Net::HTTP::Put.new(“/#{@db}/#{id}”)
    req["content-type"] = “application/json”
    begin
      req.body = JSON.generate(doc)
      res = request(req)
      $DEBUG and puts “put response: #{res.code} :: #{res.body}”
    rescue
      current = get(id)
      doc["_rev"] = current["_rev"]
      req.body = JSON.generate(doc)
      res = request(req)
    end
    hash = JSON.parse res.body
  end

# here we have a method to create the database
 def create
    req = Net::HTTP::Put.new(“/#{@db}/”)
    req["content-type"] = “application/json”
    res = request(req)
    JSON.parse res.body
  end

 # use clear method to drop and create a db
  def clear
    begin
      request(Net::HTTP::Delete.new(“/#{@db}”))
    rescue
    end
    req = Net::HTTP::Put.new(“/#{@db}/”)
    req["content-type"] = “application/json”
    res = request(req)
    JSON.parse res.body
  end
 

end

# end code

To test the Couch class, I created a new database, put some data into it, created and stored some views, and make queries. The default parameters assume that CouchDB is running on localhost on default port 5984, but those are easily configurable.

# begin code
require ‘rubygems’
require ‘couch_lib’

$DEBUG = true

class CouchTest

  def initialize(p={})
     @params = { “host” => “127.0.0.1″,
                 “port” => “5984″,
                 “db” => “pwp”
                 }.merge! p
     begin
       @db = Couch.new(@params["host"], @params["db"])
     rescue => e
       puts(‘oops. is couchdb running at http://#{@params["host"]}:#{@params["port"]}?’)
       exit(-1)
     end
    
    # make pwp database
    make_pwp_db

    # make pwp-specific view
    make_pwp_views
   
  end

  def make_pwp_db
    puts “delete the existing db and create a new one”
    @db.clear

    unwritten = {“title” => “unwritten rules”,”date” => “2010″,”category” =>”urban fantasy”}
    sidewalk = {“title” => “secret sidewalk”,”date” => “2007″,”category” =>”urban fantasy”}
    renegade = {“title” => “renegade robot”,”date” => “2010″,”category” =>”urban fantasy”}
    zone = {“title” => “time zone”,”date” => “1999″,”category” =>”science fiction”}
    missy = {“title” => “missy tonight”,”date” => “2008″,”category” =>”atheist fiction”}
    @db.put(“unwritten”, unwritten)
    @db.put(“sidewalk”, sidewalk)
    @db.put(“renegade”, renegade)
    @db.put(“zone”, zone)
    @db.put(“missy”, missy)
  end

  def make_pwp_views
    titles_view = { “_id” => “_design/titles “,”language” => “javascript”,
      “views” => {
        “result” => {“map” => “function(doc) { if (doc.title) { emit(doc.title, doc)} }” },
        “all” => {“map” => “function(doc) {  emit(null, doc) }” }      
      }
    }

    dates_view = { “_id” => “_design/dates “,”language” => “javascript”,
      “views” => {
        “result” => {“map” => “function(doc) { if (doc.date) { emit(doc.date, doc)} }” }
      }
    }

   categories_view = { “_id” => “_design/categories “,”language” => “javascript”,
      “views” => {
        “result” => {“map” => “function(doc) { if (doc.category) { emit(doc.category, doc) } }” }
      }
    }

   @db.put “_design/titles”, titles_view
   @db.put “_design/dates”, dates_view
   @db.put “_design/categories”, categories_view
  end

  def delete_doc(doc)
    @db.delete(doc)
  end

  def get_all_items(sorted=false)
   # curl -X GET http://127.0.0.1:5984/pwp/_design/titles/_view/results
   puts “==> get all items”
   dataset = Array.new
   items = @db.get(“_design/titles/_view/all”)["rows"]
   items.each do |row|
      dataset << format_item(row["value"])
    end
    dataset.sort! if sorted
    dataset.each { | s | puts s } if $DEBUG
    return dataset
  end

  def get_all_items_by_date()
   puts “==> get all items by date”
   dataset = Array.new
   items = @db.get(“_design/dates/_view/result”)["rows"]
   items.each do |row|
      dataset << format_item(row["value"])
    end
    dataset.each { | s | puts s } if $DEBUG
    return dataset
  end

  def get_by_date(target=”2010″)
    puts “==> get by date: #{target}”
     dataset = Array.new
     items = @db.get(“_design/dates/_view/result”)["rows"]
     items.each do |row|
      item = row["value"]["date"]
      if item.include?(target)
        $DEBUG and puts JSON.pretty_generate(row)
        dataset << format_item(row["value"])
      end
    end
    dataset.each { | s | puts s } if $DEBUG
    return dataset
  end

 def get_by_title(target=”e”)
    puts “==> get by title: #{target}”
     dataset = Array.new
     items = @db.get(“_design/titles/_view/result”)["rows"]
     items.each do |row|
      item = row["value"]["title"]
      if item.include?(target)
        dataset << format_item(row["value"])
      end
    end
    dataset.each { | s | puts s }
    return dataset
  end

   def get_by_category(target=”e”)
    puts “==> get by category: #{target}”
     dataset = Array.new
     items = @db.get(“_design/categories/_view/result”)["rows"]
     items.each do |row|
      item = row["value"]["category"]
      if item.include?(target)
        dataset << format_item(row["value"])
      end
    end
    dataset.each { | s | puts s } if $DEBUG
    return dataset
  end

  def format_item(item)
    return “title: #{item["title"]}\tdate: #{item["date"]}\tcategory: #{item["category"]}”
  end

  def update_renegade
    puts “==> update renegade, change its category”
    renegade = {“title” => “renegade robot”,”date” => “2010″,”category” =>”science fiction”}
    @db.update “renegade”, renegade
  end

  def delete_renegade
    puts “==> delete renegade”
    r = @db.get(“renegade”)
    @db.delete(r)
  end
 
end

# usage example: ruby couch_test.rb host=localhost port=5984

if $0 == __FILE__
   params = {}
   ARGV.each do|a|
     args = a.split(“=”)
     params[args[0]] = args[1].chomp
   end
   db = CouchTest.new(params)
   db.get_all_items(true)
   db.get_all_items_by_date
   db.get_by_date(“2010″)
   db.get_by_category(“science fiction”)
   db.get_by_title(“secret”)
   db.update_renegade
   db.get_by_category(“science fiction”)
   # db.delete_renegade
   # db.get_by_category(“science fiction”)
end

# end code

gb

messing around with GarageBand this morning I realized that this was the program I really wanted when I started getting into computers back around 1987 (coincidentally, the last time the SF Giants faced the current predicament of being up 3-2 in the NCLS but on the road, eventually to lose both games. please not again!) – computers attracted me for music reasons, which is why i began with an Atari ST (it had built-in MIDI ports) and why I taught myself computer programming. I ended up getting a college degree in music engineering and went to work for a music software company, but the stuff that was available back then could only aspire to GarageBand simplicity and ease of use. There was a lot of great stuff (ProTools, StudioVision, MOTU, etc …) but this application really has what the average user needs.

When (Apple-Centric == Apple-Censored)

Apple’s AppStore banning a novel because it contains the word ‘fuck’? What the fuck? Guess you’ll never be downloading any of my books from an I-Store I-nytime soon :}

(Yes, we’re re-inventing the English language to begin every noun with ‘I’ – if the Rastafarians can do it, why not Apple Computer?)

Censorship is the inevitable result of too-concentrated decision making. Some asshole at the top is bound to determine what passes his or her ‘standards’.

When the asshole at the top is a corporation, the old-fashioned term for that is Fascism. The new-fashioned term for that is “vertical integration” :}

Great Man Theory of Software Development

No matter how much they try to gussy it up or paper it over, or make a cult out of different ‘software development processes’ it still comes down to one or two geniuses acting like dragons, lashing their tails all over the place while the rest of the company hangs on for the ride. You’d damn well better be ‘agile’ if you want to make it through

Googish

So this blog is Pigeon Weather (the name of my production company) and I had recently posted an idea for a story about someone named Fay … Now people googling for Hurricane Fay are hitting that blog spot, and why? Because Google owns Blogger and promotes its blog posts in searches. My WordPress Pigeon Weather site almost never gets any google hits from the same keyword searches.

With Google, the internet is not what it seems to be. ‘Seek and you shall find’ now translates into ‘search and you shall find whatever might possibly generate revenue for Google’. But not only that.

I searched for information on a Microsoft test tool – Google’s top results were all blog posts harshly criticizing that product (it sucks, it’s crap, etc …). When I used a different search engine, I got links to pages of actual relevance (the test tool’s home page, tutorials, sample code, etc …). Google is a rival of Microsoft and has an interest in working against its interests. This is not ‘searching the internet’. This is a new form of censorship.

More and more I’m coming to see that rather than making the internet accessible, and “not doing evil”, in reality Google is filtering the internet, funneling everything in the interests of its profit motive, its bottom line, its shareholders’ pocket books.

I do use Google products extensively (home page, gmail, google docs, blogger) because they are good products. I feel like the people who shop at WalMart because it’s cheap, and then complain about how all the manufacturing jobs have gone overseas, Cause and effect, people.

But, I will be trying to find a better search engine, and hoping for one, an open-source, indifferent, non-profit, liberation search engine. So far it’s not out there as far as I know. Just be aware that when you use Google, you aren’t getting the best results for your search, you’re getting THEIR best results for it.