PKG_INFO_BASENAME='pkg-info.rst' PKG_INFO_FN=None PKG_INFO=None """python setup.py / python .egg distribution boiler plate utilities For reasons that should be obvious this can not be in its own package. Some exmples of use, assuming you place a copy of this file allong side your setup.py and use pkg-info.rst for your build meta information. A setup.py that gets its release meta data from a .rst format plain text file. execfile('pkg_info.py', globals()) setup( name=PKG_INFO['Name'][0], version=PKG_INFO['Version'][0], provides=PKG_INFO.get('Provides',PKG_INFO['Name'])[0], install_requires=PKG_INFO.get('Requires',[]), description=PKG_INFO['Summary'][0], license=PKG_INFO['License'][0], author=PKG_INFO['Author'][0], author_email=PKG_INFO['Author-email'][0], package_dir = {'':'lib'}, packages = find_packages('lib', exclude=( 'ez_setup','develop', '*.tests','*.tests.*','tests.*', 'tests')) ) Activation of a distribution in a particular source tree in preference to an existing install (or python setup.py develop install) with the same name and "better" version:: pkg_info_py_fn = join( dirname(dirname(abspath(normpath(expanduser(__file__))))), 'pkg_info.py' ) if isfile(pkg_info_py_fn): ns = globals().copy() ns.update(dict( __file__=pkg_info_py_fn, __use_this_source_version__=True) ) execfile(pkg_info_py_fn, ns) # go ahead with normal application & dependent imports """ def get_info(data=None, fn=None, fileobj=None): import re info={} data = data or fn and file(fn).read() or fileobj and fileobj.read() for k,v,_ in re.findall( r'(?ims)^:?(?P[a-z][\w\-_ ]*):\s*' '(?P.*?' '(?=(\Z|\n^:?[a-z][\w\-_ ]*:)))', data): info.setdefault(k,[]).append(v) return info def read_info(relativeto=__file__, fn=PKG_INFO_BASENAME): from os.path import expanduser, join, abspath, normpath, dirname from os.path import isfile, isdir relativeto=abspath(normpath(expanduser(relativeto))) if isfile(relativeto): relativeto=dirname(relativeto) assert isdir(relativeto) pkg_info_fn=join(relativeto, fn) pkg_info=get_info(fn=pkg_info_fn) return pkg_info_fn, pkg_info try: PKG_INFO_FN, PKG_INFO = read_info() except (IOError, OSError): from traceback import print_exc print_exc() def use_source_dist(project_name, distdir, ws=None, search_path=None): from os.path import isdir from operator import itemgetter assert isdir(distdir), '"%s" is not a directory' % distdir import pkg_resources if ws is None: ws = pkg_resources.working_set if search_path is None: search_path = sys.path pruned = remove_projects(ws, search_path, pkg_resources.safe_name(project_name) ) if pruned: print 'Pruned: %s' % ', '.join(map(itemgetter(0), pruned)) else: print 'No potentialy conflicting versions exist for "%s"' % project_name ws.add_entry(distdir) dist = pkg_resources.get_distribution(project_name) assert dist print 'added:', dist.project_name, dist.location def yield_dist_entries(ws): seen = {} for item in ws.entries: for key in ws.entry_keys[item]: if key not in seen: seen[key]=1 yield item, key, ws.by_key[key] def remove_projects(ws=None, search_path=None, *project_names): """Explicitly remove all named projects from the working set. With a normal setuptools environment it is dificult to have *both* a python setup.py develop/install of a project and an arbitrary non installed development source tree side by side. In the development source tree, to force use of the python modules in that tree, first call this function to remove all 'normal' installs from both sys.path and pkg_resources.working_set """ import pkg_resources if ws is None: ws = pkg_resources.working_set if search_path is None: search_path = sys.path project_names = set(map(pkg_resources.safe_name, project_names)) seen=set([]) entry_prune = [] pth_prune = set([]) pruned = [] for e, k, d in list(yield_dist_entries(ws)): if e in seen: continue seen.add(e) if d.project_name not in project_names: continue if e in ws.entry_keys: ws.entry_keys[e][:] = [ kk for kk in ws.entry_keys[e] if k != kk ] if not ws.entry_keys[e]: del ws.entry_keys[e] if k in ws.by_key: del ws.by_key[k] pruned.append((e, k, d)) pth_prune.add(e) #pth_prune.add(d.location) search_path[:] = [pth for pth in sys.path if pth not in pth_prune] ws.entries[:] = [ent for ent in ws.entries if ent not in pth_prune] return pruned try: if __use_this_source_version__: from os.path import dirname # Assumes __file__ is set appropriately; which causes the # automatic call of read_info (above) to do the "right thing" use_source_dist(PKG_INFO['Name'][0], dirname(__file__)) except NameError: pass #