Monday, May 25, 2009

Python script follow-up

I thought I'd give a little follow-up to the Python script I mentioned in an earlier post.

The script is more or less finished for now, however there are a couple things I'd like to clean up and improve to make it a little more general purpose and easy to maintain. One of the big things that annoys me is the size of the script, right now it weighs in at about 1k lines. Luckily a lot of this is empty lines and heavy comments, however there are some areas I can refactor to improve readability and reduce duplication. Overall though, I'm very happy with how the script turned out. It took me about 6 days to get it thought out, designed and implemented up to this point. While this is longer than I hoped it would take, the results definitely speak for themselves. The person using this script has been extremely happy with it and how much time it saves him when he needs to do a Perforce sync.

One thing I had trouble with was analyzing Perforce actions in order to determine what to perform on the target server. From what I found, there are five file operations you need to be able to support (as of Perforce v2008.2):
  1. Add - Operation executed when a file is added to P4.
  2. Delete - Operation executed when a file is deleted from P4. Also issued when a renaming is done (old file is deleted)
  3. Branch - Operation executed when an existing file is copied to create a new, separate file. Also issued when a renaming is done (new file is branched). In both cases the new file's first operation will be 'branch', not 'add'.
  4. Integrate - Operation executed when an update from another file is integrated into the file in question. This is very similar to an 'edit' operation, however P4 tracks 'integrate' differently because there is now a relationship between the 2 files when an integration is done.
  5. Edit - Operation executed whenever a file is modified and submitted.
I'm sure there is at least one operation I'm forgetting here, however these five were the most common I encountered during my development and testing.

Figuring out Objective-C++

Today I was tinkering with Xcode and Objective-C while trying to think up some ideas for iPhone apps. Eventually, I found myself trying to get some C++ code to compile and execute in the small iPhone test project I had setup and running. Getting this to work actually took me a bit of time to figure out, and looking back I think it's because I had some trouble grasping the conceptual idea of how Objective-C/C++ and vanilla C++ interact.

I started out creating a new C++ class MyTest with a .cpp and .h file. Once that was compiling, I tried hooking the MyTest class into the project's main.m file by include'ing the .h file and calling:

MyTest* test = new MyTest();

Needless to say, the compiler would have none and this made its opinion very clear with several errors. After reading up on Google and toying around, it finally hit me what I'd done wrong. The problem here is 'new' is C++ syntax, and the main.m file is being compiled as an Objective-C file(courtesy of the .m extension), so the compiler didn't understand what was going on. Additionally, my class's header file wasn't being properly read because it contained a C++ class definition, not an Objective-C definition. Once this light went off, I understood why the Objective-C++ (.mm) extension is needed; it allows Objective-C and C++ syntax to co-exist within the same file. To fix this, I hooked the MyTest C++ .h and instantiation into a separate Obj-C class file and changed the extension on said file to .mm. This compiled and ran just as I expected.

Tuesday, May 12, 2009

Stupid brain

I keep meaning to post new stuff on here, however my brain always goes dead as soon as I log onto blogger. What makes things more frustrating is during the day, something usually comes up that would be great to talk about. I'm giving serious thought to carrying a pen and paper wherever I go, that way I can take notes on my day and give my brain a kick-start.

I finally finished the Python script I talked about in an earlier post. It ended up being quite a bit more challenging that I thought, and I know it has a lot of room for improvement. However for the short amount of time I spent on it, I'm quite happy with how it turned out and how well it works. There something magical about taking a task which would normally take a couple hours, and seeing it happen in a few seconds. Cross sync'ing the contents of a project in 2 Perforce servers is probably one of the most horrific and mind numbing tasks I've ever done.

Monday, May 4, 2009

Adventures in Python

A couple days ago at work we realized we'd need a script to automate a process that is incredibly error prone and mind-numbingly boring. Naturally I volunteered for the task, seeing as it would give me a chance to try some new things and challenge myself to think outside the box. To create the script I decided to use Python, partially because I've used it before and wanted to get a refresher, and partially because there is a nice API library available to assist what I'm working on.

The project I'm working on is to automate some Perforce tasks, and thankfully there's an API plugin for Python (aptly named P4Python) to make interacting with a Perforce server a snap. This API has been very nice to work with, it allows me to do server queries for Perforce files and recieve the results as lists or dictionaries. In a previous project I did something very similar, however to get information from Perforce, I had to run a commandline query, direct the results into a file, then parse the file. It was very cumbersome and difficult to develop and debug.

Working with Python has been somewhat of a culture shock. I've spent most of my time working in strongly typed languages, so getting adjusted to Python's dynamic type language system has been weird. I will say, being able to simply create a new variable and not worry about type declaration or memory management is great for quick iteration and turnaround. One thing that keeps biting me though is indentation being used as block delimiters. Apparently my fingers love hitting the delete key without me realizing it, so I often get errors about a certain block of code not being indented correctly.