dave
dave

Reputation: 905

pip not finding setup file

I am getting an error when trying to install a python package with pip.

It is looking in a certain directory for "setup.py" after untaring the package and it can't find it there. The setup.py file is actually one directory down.

It's looking in:

 'virtualenvs/pyling/build/nltk/setup.py'

but it's actually in:

virtualenvs/pyling $ ls build/nltk/nltk-2.0b9/
INSTALL.txt  javasrc  LICENSE.txt  nltk  PKG-INFO  README.txt  setup.py

Is there a way to make pip aware of this nested folder structure in the package?

Thanks

Upvotes: 4

Views: 5812

Answers (5)

quanalyst
quanalyst

Reputation: 23

I had similar problem and gave up on using the default URL for pip. However, if you just want to install nltk, this works for me:

pip install -E <virtualenv-dir> PyYAML #if you have not done so
pip install -E <virtualenv-dir> --no-index --find-links=http://nltk.googlecode.com/ nltk 

Upvotes: 0

Damion K. Wilson
Damion K. Wilson

Reputation: 79

What I found was that pip runs a python command line script that looks like this:

__file__ = '<path to package>/setup.py'

from setuptools.command import egg_info

def replacement_run(self):
    self.mkpath(self.egg_info)

    installer = self.distribution.fetch_build_egg

    for ep in egg_info.iter_entry_points('egg_info.writers'):
        # require=False is the change we're making:

        writer = ep.load(require=False)

        if writer:
            writer(self, ep.name, egg_info.os.path.join(self.egg_info,ep.name))

    self.find_sources()

egg_info.egg_info.run = replacement_run

execfile(__file__)

In the package's top level directory, where there was no setup.py, I placed a setup.py that reproduced this behaviour, but chdir'd to the directory that contained the "real" setup.py and executed that at the end instead.

The only other issue was that pip creates a directory "pip-egg-info" which it expects to be populated, requiring a symbolic link to be created to it in the directory with the "real" setup.py.

The new, top level setup.py looks like this:

#! /usr/bin/env python

from os import chdir, symlink, getcwd
from os.path import join, basename, exists

filename = basename(__file__)

chdir("python")

setupdir = getcwd()

egginfo = "pip-egg-info"

if not exists(egginfo) and exists(join("..", egginfo)):
    symlink(join("..", egginfo), egginfo)

__file__ = join(setupdir, filename)

from setuptools.command import egg_info

def replacement_run(self):
    self.mkpath(self.egg_info)

    installer = self.distribution.fetch_build_egg

    for ep in egg_info.iter_entry_points('egg_info.writers'):
        # require=False is the change we're making:

        writer = ep.load(require=False)

        if writer:
            writer(self, ep.name, egg_info.os.path.join(self.egg_info,ep.name))

    self.find_sources()

egg_info.egg_info.run = replacement_run

execfile(__file__)

It's probably brittle, but should continue to work until pip changes the command line python code that it's generating

Upvotes: 1

Sebastian Blask
Sebastian Blask

Reputation: 2938

I already had this problem when calling pip from a directory different from the one the setup.py is in. The solution was adding the following to setup.py:

import os os.chdir(os.path.dirname(os.path.abspath(__file__)))

Maybe you call pip from virtualenvs/pyling/build/nltk/ where it should be virtualenvs/pyling/build/nltk/nltk-2.0b9/ ? Then just add what I did.

Upvotes: 0

jfs
jfs

Reputation: 414745

  • fix the package to follow a standard package layout i.e., setup.py should be in a top directory.

or

  • untar the archive and point pip to a directory with the setup.py file.

Upvotes: 0

dave
dave

Reputation: 905

i added a little function and call it in the property definition for setup_py in the pip/req.py file.

this seems to make it work the way i expect, that is if the setup.py file is only one layer deeper. hopefully nothing gets busted when bundling and freezing...

import os

def get_setup_path(in_path):
    print "starting path is %s"%in_path
    fileList=os.listdir(in_path)
    if fileList.__contains__("setup.py"):
        print "setup.py is indeed there"
        return in_path
    for f in fileList:
        f=os.path.join(in_path,f)
        if os.path.isdir(f):
            contents=os.listdir(f)
            if contents.__contains__("setup.py"):
                out_path=os.path.join(in_path,f)
                return out_path
    print "could not find setup.py by looking one level deeper"
    return in_path

and then call it here in req.py

(around line 195 in req.py)
@property   
def setup_py(self):
     self.source_dir= get_setup_path(self.source_dir)
     return os.path.join(self.source_dir, 'setup.py')

Upvotes: 0

Related Questions