From 5946a25c9107e08d0f4d72eb525d0f774262c4bb Mon Sep 17 00:00:00 2001 From: Yeukhon Wong Date: Thu, 9 May 2013 04:59:42 -0400 Subject: [PATCH 1/2] Pip's name key can now accept remote package address. Summary: Pip module would abort when name is a remote package address because the module was expecting a version if ``=`` is part of the name value. Furthermore, the pip module would require either name or requirement to be a key, although the documentation table said neither was required. The fact that one of them must be present is not documented in the documentation leads to confusion. This commit added this fact as part of description. In this commit, we resolve the confusion by stating either ``name`` or ``requirement`` is needed. Next, if the user puts remote address as the value of the ``name`` key, we will not use mirror. Lastly, if the user uses the remote serivice address as the name of the package and the user does not supply -e option in extra_vars (which is the whole point of this commit), we will add -e to extra_vars so pip command can run with -e option. --- library/packaging/pip | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/library/packaging/pip b/library/packaging/pip index 06314c6ec3..1dcaf6331d 100644 --- a/library/packaging/pip +++ b/library/packaging/pip @@ -26,12 +26,13 @@ DOCUMENTATION = ''' module: pip short_description: Manages Python library dependencies. description: - - Manage Python library dependencies. + - Manage Python library dependencies. To use this module, one of the following keys is required: C(name) + or C(requirements). version_added: "0.7" options: name: description: - - The name of a Python library to install + - The name of a Python library to install or the url of the remote package. required: false default: null version: @@ -93,6 +94,8 @@ examples: description: Install I(flask) python package. - code: "pip: name=flask version=0.8" description: Install I(flask) python package on version 0.8. + - code: "pip: name='svn+http://myrepo/svn/MyApp#egg=MyApp'" + description: Install I(MyApp) using one of the remote protocols (bzr,hg,git,svn) C(pip) supports. You do not have to supply '-e' option in extra_args. - code: "pip: name=flask virtualenv=/my_app/venv" description: "Install I(Flask) (U(http://flask.pocoo.org/)) into the specified I(virtualenv), inheriting none of the globally installed modules" - code: "pip: name=flask virtualenv=/my_app/venv virtualenv_site_packages=yes" @@ -180,9 +183,18 @@ def main(): if state == 'latest' and version is not None: module.fail_json(msg='version is incompatible with state=latest') - if name and '=' in name: - module.fail_json(msg='version must be specified in the version parameter') + # before we move on, check if name is #egg (remote repository/package) + # if it is, mark it as package so we can skip --use-mirrors and skip + # version arg checks + is_package = False + if '#egg=' in name: + is_package = True + else: + # we have to handle the case when version is required for non-remote package + if name and '=' in name: + module.fail_json(msg='version must be specified in the version parameter') + err = '' out = '' @@ -208,7 +220,19 @@ def main(): pip = _get_pip(module, env) cmd = '%s %s' % (pip, state_map[state]) - if state != 'absent' and use_mirrors: + + # If is_package is True, we must not add --use-mirrors option. + # Also, if -e option is not added by the user via extra_args, + # we must add -e ourselves. + if is_package: + args_list = [] # used if extra_args is not used at all + if extra_args: + args_list = extra_args.split(' ') + if '-e' not in args_list: + args_list.append('-e') + # Ok, we will reconstruct the option string + extra_args = ' '.join(args_list) + if not is_package or state != 'absent' and use_mirrors: cmd += ' --use-mirrors' if extra_args: cmd += ' %s' % extra_args @@ -216,7 +240,7 @@ def main(): cmd += ' %s' % _get_full_name(name, version) elif requirements: cmd += ' -r %s' % requirements - + if module.check_mode: module.exit_json(changed=True) os.chdir(tempfile.gettempdir()) From 08a486fe3123464a2d21a44bba7d3f37961fe224 Mon Sep 17 00:00:00 2001 From: Yeukhon Wong Date: Sat, 18 May 2013 05:26:45 +0000 Subject: [PATCH 2/2] Pip can now accept vcs or tarball as name. Prevented adding mirrors when name is vcs. **Summary**: There was a bug in the previous commit; pip module would add --use-mirrors options to a source package when state is absent. The bug is resolved in this commit by checking ``not is_package`` in the if branch. Furthermore, in order to support non-vcs source name like tarballs, we must not add -e option to the arg list. Given this circumstance, this commit have is_tar and is_vcs and the latter is checked to add -e option. Since mirrors do not make sense with vcs or tarball source, this commit will not add --use-mirrors (default to True) as always. --- library/packaging/pip | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/library/packaging/pip b/library/packaging/pip index 1dcaf6331d..d4311c6f36 100644 --- a/library/packaging/pip +++ b/library/packaging/pip @@ -95,7 +95,7 @@ examples: - code: "pip: name=flask version=0.8" description: Install I(flask) python package on version 0.8. - code: "pip: name='svn+http://myrepo/svn/MyApp#egg=MyApp'" - description: Install I(MyApp) using one of the remote protocols (bzr,hg,git,svn) C(pip) supports. You do not have to supply '-e' option in extra_args. + description: Install I(MyApp) using one of the remote protocols (bzr+,hg+,git+,svn+) or tarballs (zip, gz, bz2) C(pip) supports. You do not have to supply '-e' option in extra_args. For these source names, C(use_mirrors) is ignored and not applicable. - code: "pip: name=flask virtualenv=/my_app/venv" description: "Install I(Flask) (U(http://flask.pocoo.org/)) into the specified I(virtualenv), inheriting none of the globally installed modules" - code: "pip: name=flask virtualenv=/my_app/venv virtualenv_site_packages=yes" @@ -184,17 +184,22 @@ def main(): if state == 'latest' and version is not None: module.fail_json(msg='version is incompatible with state=latest') - # before we move on, check if name is #egg (remote repository/package) - # if it is, mark it as package so we can skip --use-mirrors and skip - # version arg checks - is_package = False - if '#egg=' in name: - is_package = True - else: - # we have to handle the case when version is required for non-remote package - if name and '=' in name: - module.fail_json(msg='version must be specified in the version parameter') - + # pip can accept a path to a local project or a VCS url beginning + # with svn+, git+, hg+, or bz+ and these sources usually do not qualify + # --use-mirrors. Furthermore, the -e option is applied only when + # source is a VCS url. Therefore, we will have branch cases for each + # type of sources. + # + # is_vcs includes those begin with svn+, git+, hg+ or bzr+ + # is_tar ends with .zip, .tar.gz, or .tar.bz2 + is_vcs = False + is_tar = False + if name.endswith('.tar.gz') or name.endswith('.tar.bz2') or name.endswith('.zip'): + is_tar = True + elif name.startswith('svn+') or name.startswith('git+') or \ + name.startswith('hg+') or name.startswith('bzr+'): + is_vcs = True + err = '' out = '' @@ -221,10 +226,9 @@ def main(): cmd = '%s %s' % (pip, state_map[state]) - # If is_package is True, we must not add --use-mirrors option. - # Also, if -e option is not added by the user via extra_args, - # we must add -e ourselves. - if is_package: + + # If is_vcs=True, we must add -e option (we assume users won't add that to extra_args). + if is_vcs: args_list = [] # used if extra_args is not used at all if extra_args: args_list = extra_args.split(' ') @@ -232,7 +236,9 @@ def main(): args_list.append('-e') # Ok, we will reconstruct the option string extra_args = ' '.join(args_list) - if not is_package or state != 'absent' and use_mirrors: + # for tarball or vcs source, applying --use-mirrors doesn't really make sense + is_package = is_vcs or is_tar # just a shortcut for bool + if not is_package and state != 'absent' and use_mirrors: cmd += ' --use-mirrors' if extra_args: cmd += ' %s' % extra_args