saffsd
saffsd

Reputation: 24322

How do I work with multiple git branches of a python module?

I want to use git to allow me to work on several features in a module I'm writing concurrently. I'm currently using SVN, with only one workspace, so I just have the workspace on my PYTHONPATH. I'm realizing this is less than ideal, so I was wondering if anyone could suggest a more 'proper' way of doing this.

Let me elaborate with a hypothetical situation: I say I have a module 'eggs', with sub-modules 'foo' and 'bar'. Components in 'bar' use code in foo, so eggs/bar/a.py may 'import eggs.foo'.

Say that 'eggs' is in a git repository. I want to try out some changes to 'foo', so I copy it. The problem is that 'import eggs.foo' in eggs/bar finds the original repository in the PYTHONPATH, so it ends up using the old 'foo' instead of my modified one.

How do I set myself up such that each copy of the module uses its own associated 'foo'? Thanks.

edit- Thanks for the pointer to relative imports. I've read up on it and I can see how to apply it. One problem I'd have with using it is that I've built up a fairly large codebase, and I haven't been too neat about it so most modules have a quick 'self-test' under if __name__ == '__main__':, which from what I've read does not play with relative imports:

The other solution I've been able to google up is to deliberately manipulate sys.path, which seems like an even worse hack. Are there any other possibilities?

edit - Thanks for the suggestions. I'd originally misunderstood git branches, so as pointed out branches are exactly what I want. Nonetheless, I hadn't heard of relative imports before so thanks for that as well. I've learnt something new and may incorporate its use.

Upvotes: 2

Views: 2788

Answers (3)

jfs
jfs

Reputation: 414685

Relative imports (PEP 328) might help:

eggs/
  __init__.py
  foo.py
  bar.py

# foo.py
from __future__ import absolute_import
from . import bar

See How do you organize Python modules? for other options.

EDIT:

Yet another option is to use S.Lott's and Jim's suggestions i.e, restructure your package to factor out a eggs.foo part used by eggs.bar.a and use git to work on experimental branches (see Git Community Book).

Here's an example:

$ git status
# On branch master
nothing to commit (working directory clean)

[just to make sure that all is good]

$ git checkout -b experimental
Switched to a new branch "experimental"

[work on experimental stuff]

$ git commit -a

[commit to experimental branch]

$ git checkout master
Switched to branch "master"

[work on master branch]

$ git commit -a

To merge changes into master branch:

$ git merge experimental

See chapter Basic Branching and Merging from the above book.

Upvotes: 3

Mr_Pink
Mr_Pink

Reputation: 109416

Maybe I'm not understanding correctly, but it seems that git would be the solution here, since git's branches don't need separate paths.

Create a branch for each working version of your eggs module. Then when you checkout that branch, the entire module is changed to a state matching the version of your sub-module. You could then merge what you need back and forth between the branches.

And as S.Lott pointed out, may a little refactoring couldn't hurt either ;)

Upvotes: 1

S.Lott
S.Lott

Reputation: 391962

"say I have a module 'eggs', with sub-modules 'foo' and 'bar'. Components in 'bar' use code in foo, so eggs/bar/a.py may 'import eggs.foo'."

This may not be the best structure. I suggest you have some other modules struggling to get out.

You have eggs.bar.a depending on eggs.foo. I'm guessing other stuff on eggs depends on eggs.foo. Further, I suspect that eggs.foo could be partitioned into eggs.foo and eggs.quux and things might be simpler.

I'd recommend refactoring this to get a better structure. The PYTHONPATH issues are symptomatic of too many things in the wrong places in the module tree.

Upvotes: 1

Related Questions