All My Brain Where stuff from my brain lands

November 17, 2009

Dual Master Git Repositories

Filed under: Programming — Tags: , , — Dennis @ 10:23 am

One of the nice things about git, is the ability to work in a distributed manor. Instead of having to have a central repository for your source code, you can create a copy of your repository and do work, while sharing the changes, on any number of machines. Often, when a few developers share code, they still use git with a central repository. There isn’t anything wrong with this, but sometimes, I find myself wanting to set something like this when I only want to share code between a couple computers where I am the only developer. In this case, I don’t need 3 copies of the code. I want to be able to push or pull changes between each of the machines without having to push to a 3rd repository.

So, you might try the following steps:

# on the 1st machine
> git init .
> # make some code changes
> git add ...
> git commit
# 2nd machine
> git clone <1st machine ref>
> # make some changes
> git commit
> git push # here is the problem

When you push from the 2nd machine to the 1st, the HEAD on the 1st machine is updated. The problem is that your working copy is NOT updated. To fix this, there are two solutions.

Mediocre, recover from doing the push solution:

# warning, the following will destroy any local changes you had made.
> git reset --hard HEAD

If you had made changes on the 1st machine and forgot to commit them, you’d need to stash them, check out to a branch, or whatever.

Better way, avoid the reset all together

# on the 2nd machine
> git push origin master:refs/heads/tmp_branch_name
# on the 1st machine
> git merge tmp_branch_name
> git branch -d tmp_branch_name

Another solution would be to add a remote on the 1st machine that points to the 2nd machine. Then each machine can just pull from the other rather than doing any pushes at all.
Have fun.

October 21, 2009

The Python install system needs an overhaul

Filed under: Programming — Tags: , , , — Dennis @ 10:58 am

Perhaps this is more of a rant than a useful blog post. I do plan on posting something useful though, so bear with me. First, a little background.

I’ve been working on installing a website based on Django for the last while. As part of the process, I wanted to bring in all the dependencies of my project with a setup.py file so I can easily move the site around to different development machines or server environments as needed. I wanted to make sure I didn’t install different versions on a different machine, so I’ve provided a packages directory and install the file with the dependencies locked at specific versions and the packages directory noted. Easy install then just uses the package I place in the packages directory and every place I install this website, I get the same setup.

My setup.py snippets

setup (
 # ...
 install_requires=[
  'Django=1.1',
  'MySQL-Python==1.2.3c1',
  # etc 
 ],
 dependency_links = [ 'packages' ],
 # ...
)

So far so good. I should point out that some have suggested pip as a replacement to easy_install. For my rant portion of this post, both pip and easy_install don’t offer any help. If I’m wrong about pip, somebody please point out the proper way to do this..

My problem begins when I find a package with no setup.py file. The package I’m attempting to use is the forum module from Sphene Community Tools. As I download and go through their documentation, I find that they pretty much expect you to just add the sphene package to your python path. That doesn’t fit with my installable website model though so I want to add a simple setup.py file and install it with the rest of my packages.

Issues:

  1. Package Data

    Turbogears contributers worked on a find_package_data function that can recursively add your package data. The fact that this isn’t included yet in the distutils api is quite annoying. I copied the file from another project [1]. I also added ‘.svn’ to the ignore directory list since I was building from the svn view.

  2. Extra Data

    Just as annoying as the package data problem is the static data. I originally thought I could just include the static directory in data files like this:

     data_files=[ ('static', findall('static') ]
    

    That just puts every file recursively found in the static directory all in one static directory for the install. Instead, I modified the result returned by the find_package_data function to use the data_files format. Here is my completed setup.py file:

    import os
    from setuptools import setup, find_packages
    from finddata import find_package_data
    
    packages=find_packages('sphenecoll')
    package_data=find_package_data('sphenecoll')
    static = find_package_data('static','sphene') 
    # not in correct format
    static_dict={} # dir -> files
    for path in static['sphene']:
       dir, file = os.path.split(path)
       dir = os.path.join('static', dir )
       files = static_dict.setdefault( dir, [] )
       files.append(os.path.join('static',path))
    
    setup(
     name='sphene',
     version='0.6dev',
     packages=packages,
     package_data=package_data,
     package_dir={'sphene':'sphenecoll/sphene'},
     scripts=['dist/scripts/make-messages.py', 'dist/scripts/compile-all-sph-messages.py' ],
     data_files=static_dict.items()
    )
    

    If someone else is interested, you can put finddata.py and this setup.py in the sphene/communitytools directory and build your own egg. Not really the point of this post, but perhaps someone will find it useful. Actually, the Sphene tools should be installable I think. The expectation to just put the directory in your PYTHONPATH isn’t very flexible.

  3. Install from source

    Both easy_install and pip didn’t actually copy any of the package data or data files into the installed site-packages. I had to use setuptools bdist_egg and then installing the egg caused the files to be copied correctly.

  4. No uninstall

    This one isn’t really an issue with this install in particular, but it is always annoying.

Maybe one of these days some Python developer will come up with a good solution to the install mess. I’m too busy working on the projects I’ve got to get done aside form the occasional sidetrack that installing Python modules causes.

1: I copied paste.util.finddata http://trac.pythonpaste.org/pythonpaste/browser/Paste/trunk/paste/util/finddata.py

September 21, 2009

How to remove or edit a commit in your git repository

Filed under: Programming — Tags: , , — Dennis @ 12:37 pm

So you just committed 15 things to your git repository and now you want to push your changes. Oops, commit #2 added your password file. Or perhaps you misspelled words in the commit message. Now, being a git expert, you think to yourself, I’ll just create a temporary branch, cherry-pick the commits that are correct, re-commit correctly the incorrect commit, and then merge/push my temporary branch instead of this flawed branch I have. That all works fine, but luckily there is a much easier way to do it.

> git rebase -i 

When you use ‘-i’ with rebase, you get an interactive edit screen that gives you an option for each commit _after_ the sha1 you enter. For each commit you can either delete the entry entirely or replace the word “pick” with “edit”. Deleting an entry causes that commit to lost. Editing a commit gives you the option to unstage some of the files, edit the commit message, or really, to do whatever you want to change it how you intended. If you edit, or the rebase has a conflict, after setting things how you like, just use rebase –continue to go on your way.

July 1, 2009

Example Image Upload with YUI Rich Text Editor 2.7.0

Filed under: Programming — Tags: , , , , , — Dennis @ 7:20 am

It’s somewhat slow coming, but I’ve checked compatibility with the image uploader and YUI version 2.7.0. If you haven’t read the original YUI Image Uploader page, start there. After that, you can use this page for an example getting the script to work with the latest YUI.

(more…)

June 27, 2009

Launching wxPython apps with an iPython shell

Filed under: Programming — Tags: , , , , — Dennis @ 12:52 pm

Suppose you want to run your fancy wxPython application but have a shell in the background to peek and poke at certains settings, help debug, and possibly even use an API that your program provides to automate tasks. iPython has built in wx support (as well as support for other GUIs and frontends). So anyway, I’ve been playing around with this lately and have noticed an inconsistency that needs addressed.

Launching other GUIs with iPython does not block. You instantly get a shell and your application loads. The “-wthread” option for wx applications executes any passed in script before dropping to the shell though.

Problem:

> ipython -wthread myapp.py
> # application runs here
> # no shell yet
> # you exit the application
"Welcome to iPython"
>>> 

If you happened to do things like this, you’d get the expected response:

> ipython -wthread
"Welcome to iPython"
>>> import myapp
# application loads
# you instantly have a prompt
>>>

Solution:

Tell iPython to launch your app after it starts:

> ipython -wthread -c "import myapp" -i
# app loads
"Welcome to iPython"
# you've got a shell
>>>

Anyway, for other threading backends in iPython, the shell doesn’t block while the application loads. Perhaps there is a way to get the wx backend to behave the same. In the mean time, I’m using this workaround without any serious issue. Perhaps I’ll find a better solution or submit a patch to iPython one of these days.

May 12, 2009

Extending std::exception

Filed under: Programming — Tags: , , , — Dennis @ 4:06 pm

So you’re writing some C++ code, feeling all object oriented and all, and you decide you’d like an application specific exception whenever one of your methods has an issue. You’d like to have error messages that the exception can print up if thrown and you think to yourself, “hey, I’ll just extend std::exception, add the error string, and be on my way.”

Problem: So here is the puzzle. What is wrong with this code:

#include 
#include 
using namespace std;
class my_error : public exception {
  private:
   string m_err;
  public:
    my_error ( const string &err) : m_err(err) {}
    const char* what() { return m_err.c_str(); }
};

Think about it for a bit before scrolling down more. Take a look at the header definition for exception.

Ok, ready to move on? Did you find the problem?

Answer:

The standard exception does not declare it’s copy constructor virtual.

 exception& operator= (const exception&) throw();

This is in part because in order to provide exception safe c++, the exception class can’t throw exceptions itself. This is the same reason using strings member variables is discouraged for exceptions. Their constructors can also throw exceptions. Anyway, the result is that if client code catches std::exception, copies the exception, and prints it, m_str hasn’t been copied and you get garbage or errors. Not what was expected was it.

Solution

This whole problem was loaded just slightly. There is already a standard exception that can take a string message as an argument.

#include 
class my_exc : public runtime_error {
 public:
  my_exc ( const string &err ) : runtime_error (err ) {}
  // there, you can add more methods here.
  // remember, you can't add data members any more here
  // than you can add them to exception derived classes though.
};

Get it? Got it? Good.

« Newer PostsOlder Posts »

Powered by WordPress

css.php
%d bloggers like this: