Как правильно получить каталог console_scripts install_scripts? - PullRequest
0 голосов
/ 21 января 2019

Люди,

Я разбил сложный скрипт на Python на пакет для облегчения обслуживания и распространения. Я создал новый setup.py (используя setupmeta) с точкой входа console_scripts и структурой пакета. Пока все хорошо.

У меня были некоторые необычные требования:

  • пакет всегда должен быть установлен в virtualenvwrapper проекте,
  • поэтому скрипт установлен в каталоге ${VIRTUAL_ENV}/bin ...
  • ... и я должен создать символическую ссылку для сценария в каталоге ${VIRTUALENVWRAPPER_PROJECT_PATH}/bin. (не спрашивай ...: -)

Для этой цели:

  1. Я добавил locate_project_path() функцию в сценарий setup.py,
  2. добавил следующий install_and_symlink_script подкласс к setuptools.command.install.install:

    class install_and_symlink_script(install):                           
        """Do normal install, but symlink script to project directory""" 
    
        def run(self):                                                   
            install.run(self)                                            
    
            script_path = os.path.join(self.install_scripts, SCRIPT_NAME)
            project_path = locate_project_path()                         
            symlink_path = os.path.join(project_path, "bin", SCRIPT_NAME)
    
            print("creating %s script symlink" % SCRIPT_NAME)            
    
            if os.path.exists(symlink_path):                             
                print("removing existing symlink %s" % symlink_path)     
                os.unlink(symlink_path)                                  
    
            print("creating symlink from %s to %s" % (                   
                symlink_path, script_path))                              
            os.symlink(script_path, symlink_path)                        
    
  3. и настроен setup() таким образом:

    setup(
        ...
        entry_points={
            "console_scripts": ["%s=myscriptpackage.cli:main" % SCRIPT_NAME],
        },
        cmdclass={
            "install": install_and_symlink_script,
        },
        ...
    )
    

При выполнении локального python ./setup.py install установка пакета и создание символической ссылки работают отлично.

Но при выполнении pip install git+ssh://.../myscriptpackage.git происходит сбой:

...
running install_egg_info
Copying src/myscriptpackage.egg-info to build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0-py2.7.egg-info
running install_scripts
creating my-script script symlink
creating symlink from /path/to/virtualenvwrapper/project/bin/my-script to build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0.data/scripts/my-script
error: [Errno 17] File exists
error
Failed building wheel for myscriptpackage
...

Значение при установке через pip вместо python ./setup.py install:

  1. он не может обнаружить существующую символическую ссылку и удалить ее.
  2. переменная install_and_symlink_script.install_scripts указывает на скрипт внутри каталога сборки вместо каталога окончательной установки скриптов ...: - |

Итак ... знаете ли вы способ получить правильный каталог установки скриптов, совместимый как с pip install, так и с python ./setup.py install?

(Кстати, я использую python 2.7.13, setuptools 39.1.0, virtualenvwrapper 4.8.2 под Debian 9)

ОБНОВЛЕНИЕ 1

Я знал, что проблема error: [Errno 17] File exists исходила от os.path.exists(symlink_path) звонка.

Я просто понял, почему: если символическая ссылка была создана из предыдущей установки, эта символическая ссылка не работает во время новой установки. os.path.exists возвращает False для прерванной символической ссылки. OTOH, os.path.lexists возвращает True, если символическая ссылка существует, повреждена или нет ...

Ответы [ 2 ]

0 голосов
/ 21 января 2019

Я нашел способ последовательно получать каталог установки сценариев при установке через python ./setup.py install или через pip install, используя функцию wheel.paths.get_install_paths().

Моя пользовательская команда установки setuptools теперь:

...
from wheel.paths import get_install_paths

__title__ = "myscriptpackage"
...

class install_and_symlink_script(install):                            
    """Do normal install, but symlink script to project directory"""  

    def run(self):                                                    
        install.run(self)                                             

        wheel_install_paths = get_install_paths(__title__)            
        script_path = os.path.join(wheel_install_paths['scripts'], SCRIPT_NAME)                  
        # instead of: script_path = os.path.join(self.install_scripts, SCRIPT_NAME)

        project_path = locate_project_path()                          
        symlink_path = os.path.join(project_path, "bin", SCRIPT_NAME) 

        print("creating %s script symlink" % SCRIPT_NAME)             

        if os.path.lexists(symlink_path):                             
            print("removing existing symlink %s" % symlink_path)      
            os.unlink(symlink_path)                                   

        print("creating symlink from %s to %s" % (                    
            symlink_path, script_path))                               
        os.symlink(script_path, symlink_path)                         
0 голосов
/ 21 января 2019

Я подозреваю, что права администратора на вашей машине могут быть проблемой.не могли бы вы попробовать запустить cmd в режиме администратора, а затем, перейдя по пути, где лежит setup.py, можете просто запустить:

 python setup.py 

Затем он пытается создать символическую ссылку в папке

build/bdist.linux-x86_64/wheel/myscriptpackage-0.4.0.data/scripts/my-script

I request you to try making symlink on your own in this folder.

Если это не решение, значит, имеется какое-то несоответствие версии.Просто дайте мне знать, если это поможет

...