PKUYPHQ-9r"virtualenvutils/virtualenvutils.py# coding: utf-8 from __future__ import print_function from __future__ import absolute_import import sys from ruamel.std.pathlib import Path from ruamel.yaml.compat import ordereddict class VirtualEnvUtils(object): def __init__(self, args, config): self._args = args self._config = config self._venv_dirs = None def alias(self): aliases = ordereddict() venv_dirs = self.venv_dirs[:] for d in venv_dirs[:]: # check for configuration file conf = d / 'virtualenvutils.conf' if not conf.exists(): continue venv_dirs.remove(d) # print('conf file', d, file=sys.stderr) for line in conf.read_text().splitlines(): # print('line', line, file=sys.stderr) if u':' in line: util, full = line.strip().split(u":", 1) full = d / 'bin' / full else: util = line.strip() full = d / 'bin' / util if not full.exists(): print('cannot find {}\n from line {}\ in {}'.format( full, line, conf), file=sys.stderr) if util in aliases: print('virtualenvutils name clashes {}\n {}\n {}'.format( util, util, aliases[util], ), file=sys.stderr) else: aliases[util] = full for d in venv_dirs[:]: util = d / 'bin' / (d.stem) if not util.exists(): continue venv_dirs.remove(d) # print('matching virtualenv name', d, file=sys.stderr) if util.name in aliases: print('virtualenvutils name clashes {}\n {}\n {}'.format( util.name, util, aliases[util.name], ), file=sys.stderr) else: aliases[util.stem] = util for d in venv_dirs[:]: for util in (d / 'bin').glob('*'): if not util.is_file(): continue for skip in ['activate', 'easy_install', 'python', 'pip', 'wheel']: if util.stem.startswith(skip): break else: if d in venv_dirs: # only first time venv_dirs.remove(d) if util.name.endswith('.so'): continue if util.name.endswith('.pyc'): continue if util.name.endswith('.py'): # can make xyz.py into util xyz, or skip. Yeah, skip continue if util.name in aliases: if self._args.verbose > 0: print('skipping name clashes {}\n {}\nin favor of\n {}'.format( util.name, util, aliases[util.name], ), file=sys.stderr) else: aliases[util.name] = util assert not venv_dirs for k in aliases: print("alias {}='{}'".format(k, aliases[k])) @property def venv_dirs(self): def test_a_dir(sub_dir): if not sub_dir.is_dir(): return False for x in ('bin', 'lib', 'include'): sub_sub_dir = sub_dir / x if not sub_sub_dir.exists(): break if not sub_sub_dir.is_dir(): break else: activate = sub_dir / 'bin' / 'activate' if activate.exists() and activate.is_file(): self._venv_dirs.append(sub_dir) return True return False if self._venv_dirs is not None: return self._venv_dirs self._venv_dirs = [] for d in self._args.dir: d = Path(d).expanduser() if test_a_dir(d): continue for sub_dir in d.glob('*'): test_a_dir(sub_dir) return self._venv_dirs def update(self): import pkgutil # NOQA import pkg_resources # NOQA # pkg_resources.working_set is what pip relies upon, that is bound to the # pip/python that is running # print('x', [x for x in pkg_resources.working_set]) # print('pip', pip.__file__) pip_args = ['list', '--outdated'] pre = ['--pre'] if self._args.pre else [] for d in self.venv_dirs: pip_cmd = [str(d / 'bin' / 'pip')] res = [x.split(None, 1)[0] for x in check_output( pip_cmd + pip_args + pre).splitlines()] print('update', d, res) # NOT WORKING: this gives you the packages from the calling environment # for package in pip.get_installed_distributions(): # print('package', package) # # for p in (d / 'lib').glob('python*'): # if p: # break # else: # continue # no lib/python* found # pth = [str(p / 'site-packages')] # NOT WORKING: does give you only toplevel names and not in original dotted # package form # for pkg in pkgutil.iter_modules(path=pth): # continue # if pkg[2]: # print('pkg', pkg[1]) # # NOT WORKING: only gives non-namespace packages # for pkg in pkgutil.walk_packages(path=pth): # continue # if pkg[2]: # print('pkg', pkg[1]) # if res: print(check_output(pip_cmd + ['install', '-U'] + pre + res)) def install(self): for d in self._args.dir: p = Path(d) if self._args.pkg: assert len(self._venv.dirs) == 1 pkg = self._args.pkg else: pkg = Path(d).name print('pkg', pkg) cmd = ['virtualenv'] if self._args.python: cmd.extend(['--python', self._args.python]) check_output(cmd + [str(p)], verbose=2) check_output([str(p / 'bin' / 'pip'), 'install', pkg], verbose=2) def check_output(*args, **kw): import subprocess verbose = kw.pop('verbose', 0) if verbose > 1: print('cmd', args[0]) res = subprocess.check_output(*args, **kw).decode('utf-8') if verbose > 0: print(res) return res PKi[PHTvirtualenvutils/__init__.py# coding: utf-8 from __future__ import print_function from __future__ import absolute_import _package_data = dict( full_package_name="virtualenvutils", version_info=(0, 2, 1), author="Anthon van der Neut", author_email="a.van.der.neut@ruamel.eu", description="manage virtualenv based utilities", keywords="virtualenv utilities", entry_points='virtualenvutils=virtualenvutils.__main__:main', # entry_points=None, license="MIT License", since=2016, # status: "α|β|stable", # the package status on PyPI # data_files="", universal=True, install_requires=dict( any=["ruamel.appconfig", "ruamel.std.argparse", "ruamel.std.pathlib"], # py27=["ruamel.ordereddict"], ), ) def _convert_version(tup): """Create a PEP 386 pseudo-format conformant string from tuple tup.""" ret_val = str(tup[0]) # first is always digit next_sep = "." # separator for next extension, can be "" or "." for x in tup[1:]: if isinstance(x, int): ret_val += next_sep + str(x) next_sep = '.' continue first_letter = x[0].lower() next_sep = '' if first_letter in 'abcr': ret_val += 'rc' if first_letter == 'r' else first_letter elif first_letter in 'pd': ret_val += '.post' if first_letter == 'p' else '.dev' return ret_val version_info = _package_data['version_info'] __version__ = _convert_version(version_info) del _convert_version PKFMH,h virtualenvutils/__main__.py# coding: utf-8 from __future__ import print_function from __future__ import absolute_import import sys import os # NOQA from ruamel.std.argparse import ProgramBase, option, CountAction, \ SmartFormatter, sub_parser, version from ruamel.appconfig import AppConfig from . import __version__ from .virtualenvutils import VirtualEnvUtils def to_stderr(*args): sys.stderr.write(' '.join(args)) class VirtualEnvUtilsCmd(ProgramBase): def __init__(self): super(VirtualEnvUtilsCmd, self).__init__( formatter_class=SmartFormatter, # aliases=True, # usage="""""", ) # you can put these on __init__, but subclassing VirtualEnvUtilsCmd # will cause that to break @option('--verbose', '-v', help='increase verbosity level', action=CountAction, const=1, nargs=0, default=0, global_option=True) @version('version: ' + __version__) def _pb_init(self): # special name for which attribs are included in help pass def run(self): self.virtualenvutils = VirtualEnvUtils(self._args, self._config) if hasattr(self._args, 'func'): # not there if subparser selected return self._args.func() self._parse_args(['--help']) # replace if you use not subparsers def parse_args(self): self._config = AppConfig( 'virtualenvutils', filename=AppConfig.check, parser=self._parser, # sets --config option warning=to_stderr, add_save=False, # add a --save-defaults (to config) option ) # self._config._file_name can be handed to objects that need # to get other info>mation from the configuration directory self._config.set_defaults() self._parse_args( # default_sub_parser="", ) @sub_parser(help='generate aliases from virtualenv utility installations') # @option('--session-name', default='abc') @option('dir', nargs='+') def alias(self): self.virtualenvutils.alias() @sub_parser(help='update packages in virtualenvs') @option('--pre', action='store_true', help="""pass on --pre to update""") @option('dir', nargs='+') def update(self): self.virtualenvutils.update() @sub_parser(help='install package(s) in virtualenvs') @option('--python', '-p', help='path to python binary to be used for virtualenv') @option('--pkg', help='name of the package to be installed (default: taken from' 'last part of dir)') @option('dir', nargs='+') def install(self): self.virtualenvutils.install() def main(): n = VirtualEnvUtilsCmd() n.parse_args() sys.exit(n.run()) if __name__ == '__main__': main() PKw[PHx></virtualenvutils-0.2.1.dist-info/DESCRIPTION.rst=================== ``virtualenvutils`` =================== You can manage virtualenv based utilities with this utility. Its primary (and initial) use is to generate Bash `alias`es for utilities that are installed in separate virtualenvs. In such a setup, you don't want to extend your path with the ``bin`` directory of each of the virtualenvs, as that gives you: - a long PATH - multiple python executables in your PATH - all utilties that are a result of installing some Python package dependency and for which you might want to use a different version (or not all). ``virtualenvutils alias dir1 dir2`` scans directories, non-recursive, under ``dir1`, ``dir2`` for virtualenvs. Any directory containing ``bin``, ``lib``, ``include`` subdirectories as well as a file ``bin/activate`` is considered a virtualenv. For any of those virtualenvs it does one of following (checked in this order): - if there is a virtualenvutils.conf file it is loaded to determine the utilties and possibly their mapping. - if the name of the directory under ``dir1``, etc., is e.g. ``do_xyx``, and ``dir1/do_xyz/bin/do_xyz`` exists and is executable then this is the utility - if there is no matching name, then all of the executable files under ``bin`` except those matching ``activate*``, ``easy_install*``, ``pip*``, ``python*``, ``wheel*`` are considered utilities, unless they have extensions matching ".so", ".py", or ".pyc". the utility then generates aliases for all utilities found this way, making sure they are unique if added by the last method, and writes those alias definitions to stdout. Any error go to stderr. Other functionalities include: - updating all packages for all virtualenvs see ``virtualenvutils --help`` for the full list of subcommands ``virtualenvutils.conf`` ------------------------ The ``virtualenvutils.conf`` file, if provided, has to be in the toplevel directory of the virtualenv (i.e. next to ``bin``, ``include`` and ``lib`` and consist of single line with or without a colon (:). If there is no colon, then the line is considered to be the name of an executable file under that virtualenvs ``bin``. If there is a colon, the part before the colon is considered the name for executable under ``bin``, for which the executable name is the part behind the colon. Example ------- You want to install docker-compose in a virtualenv. If you do:: mkvirtualenv -p /opt/python3/bin/python /opt/util/docker-compose source !$/bin/activate pip install docker-compose deactivate virtualenvutils alias /opt/util you will get:: alias docker-compose='/opt/util/docker-compose/bin/docker-compose' If you would have specified a different final directory:: mkvirtualenv -p /opt/python3/bin/python /opt/util/compose source !$/bin/activate pip install docker-compose deactivate virtualenvutils alias /opt/util you will get:: alias docker-compose='/opt/util/compose/bin/docker-compose' alias jsonschema='/opt/util/compose/bin/jsonschema' In either of these two examples you can force the way the aliases are generated (the example is based on the first):: echo 'dc:docker-compose' > /opt/util/docker-compose/virtualenvutils.conf virtualenvutils alias /opt/util you will get:: alias dc='/opt/util/docker-compose/bin/docker-compose' and if you then append:: echo 'docker-compose' >> /opt/util/docker-compose/virtualenvutils.conf will get you:: alias dc='/opt/util/docker-compose/bin/docker-compose' alias docker-compose='/opt/util/docker-compose/bin/docker-compose' Usage ``.bashrc`` ----------------- You would normally put something like:: /opt/util/virtualenvutils/bin/virtualenvutils alias /opt/util/ > /tmp/$$.alias source /tmp/$$.alias rm -f /tmp/$$.alias in your ``~/.bashrc`` to get the appropriate aliases loaded (of course assuming that you installed ``virtualenvutils`` in a virtualenv ``/opt/util/virtualenvutils``, which is not necessary, as long as ``bash`` can find the utility). Updating existing virtualenvs ============================= You can update all packages for all virtualenv utilities (under `/opt/util`) by using: virtualenvutils update /opt/util The arguments to `update` are checked to see if they are virtualenvs. If they are they get update on an individual basis. If they are not (as in the above example) each of their subdirs are checked to be virtualenvs (non-recursive). Installing a new util ===================== You can install one or more new virtualenv based utilities using something like: virtualenvutils install /opt/util/{docker-compose,ruamel.yaml.cmd} ``virtualenv`` has to be in your path for this, you can use ``--pkg`` to give a package name that differs from the final part of the path (in which case you can of course only specify one path), and with ``--python /opt/python/3/bin/python`` you can explicitly specify the python version to use. Don't forget that you probably have to logout and login for if you set your aliases through as scan initiated in ``.bashrc``, before you can use the commands. PKw[PHA\\+virtualenvutils-0.2.1.dist-info/LICENSE.txt The MIT License (MIT) Copyright (c) 2016 Anthon van der Neut, Ruamel bvba Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. PKv[PHNHCC0virtualenvutils-0.2.1.dist-info/entry_points.txt[console_scripts] virtualenvutils = virtualenvutils.__main__:main PKw[PH~-virtualenvutils-0.2.1.dist-info/metadata.json{"classifiers": ["Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python"], "extensions": {"python.commands": {"wrap_console": {"virtualenvutils": "virtualenvutils.__main__:main"}}, "python.details": {"contacts": [{"email": "a.van.der.neut@ruamel.eu", "name": "Anthon van der Neut", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst", "license": "LICENSE.txt"}, "project_urls": {"Home": "https://bitbucket.org/ruamel/virtualenvutils"}}, "python.exports": {"console_scripts": {"virtualenvutils": "virtualenvutils.__main__:main"}}}, "extras": [], "generator": "bdist_wheel (0.28.0)", "keywords": ["virtualenv", "utilities"], "license": "MIT License", "metadata_version": "2.0", "name": "virtualenvutils", "run_requires": [{"requires": ["ruamel.appconfig", "ruamel.std.argparse", "ruamel.std.pathlib"]}], "summary": "manage virtualenv based utilities", "version": "0.2.1"}PKv[PH26virtualenvutils-0.2.1.dist-info/namespace_packages.txt PKv[PH+-virtualenvutils-0.2.1.dist-info/top_level.txtvirtualenvutils PKw[PH>nn%virtualenvutils-0.2.1.dist-info/WHEELWheel-Version: 1.0 Generator: bdist_wheel (0.28.0) Root-Is-Purelib: true Tag: py2-none-any Tag: py3-none-any PKw[PHkJJ(virtualenvutils-0.2.1.dist-info/METADATAMetadata-Version: 2.0 Name: virtualenvutils Version: 0.2.1 Summary: manage virtualenv based utilities Home-page: https://bitbucket.org/ruamel/virtualenvutils Author: Anthon van der Neut Author-email: a.van.der.neut@ruamel.eu License: MIT License Keywords: virtualenv utilities Platform: UNKNOWN Classifier: Development Status :: 4 - Beta Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: MIT License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Requires-Dist: ruamel.appconfig Requires-Dist: ruamel.std.argparse Requires-Dist: ruamel.std.pathlib =================== ``virtualenvutils`` =================== You can manage virtualenv based utilities with this utility. Its primary (and initial) use is to generate Bash `alias`es for utilities that are installed in separate virtualenvs. In such a setup, you don't want to extend your path with the ``bin`` directory of each of the virtualenvs, as that gives you: - a long PATH - multiple python executables in your PATH - all utilties that are a result of installing some Python package dependency and for which you might want to use a different version (or not all). ``virtualenvutils alias dir1 dir2`` scans directories, non-recursive, under ``dir1`, ``dir2`` for virtualenvs. Any directory containing ``bin``, ``lib``, ``include`` subdirectories as well as a file ``bin/activate`` is considered a virtualenv. For any of those virtualenvs it does one of following (checked in this order): - if there is a virtualenvutils.conf file it is loaded to determine the utilties and possibly their mapping. - if the name of the directory under ``dir1``, etc., is e.g. ``do_xyx``, and ``dir1/do_xyz/bin/do_xyz`` exists and is executable then this is the utility - if there is no matching name, then all of the executable files under ``bin`` except those matching ``activate*``, ``easy_install*``, ``pip*``, ``python*``, ``wheel*`` are considered utilities, unless they have extensions matching ".so", ".py", or ".pyc". the utility then generates aliases for all utilities found this way, making sure they are unique if added by the last method, and writes those alias definitions to stdout. Any error go to stderr. Other functionalities include: - updating all packages for all virtualenvs see ``virtualenvutils --help`` for the full list of subcommands ``virtualenvutils.conf`` ------------------------ The ``virtualenvutils.conf`` file, if provided, has to be in the toplevel directory of the virtualenv (i.e. next to ``bin``, ``include`` and ``lib`` and consist of single line with or without a colon (:). If there is no colon, then the line is considered to be the name of an executable file under that virtualenvs ``bin``. If there is a colon, the part before the colon is considered the name for executable under ``bin``, for which the executable name is the part behind the colon. Example ------- You want to install docker-compose in a virtualenv. If you do:: mkvirtualenv -p /opt/python3/bin/python /opt/util/docker-compose source !$/bin/activate pip install docker-compose deactivate virtualenvutils alias /opt/util you will get:: alias docker-compose='/opt/util/docker-compose/bin/docker-compose' If you would have specified a different final directory:: mkvirtualenv -p /opt/python3/bin/python /opt/util/compose source !$/bin/activate pip install docker-compose deactivate virtualenvutils alias /opt/util you will get:: alias docker-compose='/opt/util/compose/bin/docker-compose' alias jsonschema='/opt/util/compose/bin/jsonschema' In either of these two examples you can force the way the aliases are generated (the example is based on the first):: echo 'dc:docker-compose' > /opt/util/docker-compose/virtualenvutils.conf virtualenvutils alias /opt/util you will get:: alias dc='/opt/util/docker-compose/bin/docker-compose' and if you then append:: echo 'docker-compose' >> /opt/util/docker-compose/virtualenvutils.conf will get you:: alias dc='/opt/util/docker-compose/bin/docker-compose' alias docker-compose='/opt/util/docker-compose/bin/docker-compose' Usage ``.bashrc`` ----------------- You would normally put something like:: /opt/util/virtualenvutils/bin/virtualenvutils alias /opt/util/ > /tmp/$$.alias source /tmp/$$.alias rm -f /tmp/$$.alias in your ``~/.bashrc`` to get the appropriate aliases loaded (of course assuming that you installed ``virtualenvutils`` in a virtualenv ``/opt/util/virtualenvutils``, which is not necessary, as long as ``bash`` can find the utility). Updating existing virtualenvs ============================= You can update all packages for all virtualenv utilities (under `/opt/util`) by using: virtualenvutils update /opt/util The arguments to `update` are checked to see if they are virtualenvs. If they are they get update on an individual basis. If they are not (as in the above example) each of their subdirs are checked to be virtualenvs (non-recursive). Installing a new util ===================== You can install one or more new virtualenv based utilities using something like: virtualenvutils install /opt/util/{docker-compose,ruamel.yaml.cmd} ``virtualenv`` has to be in your path for this, you can use ``--pkg`` to give a package name that differs from the final part of the path (in which case you can of course only specify one path), and with ``--python /opt/python/3/bin/python`` you can explicitly specify the python version to use. Don't forget that you probably have to logout and login for if you set your aliases through as scan initiated in ``.bashrc``, before you can use the commands. PKw[PHe+__&virtualenvutils-0.2.1.dist-info/RECORDvirtualenvutils/__init__.py,sha256=Q0BDQaJyyntb7QtlMF7ccEIkrYd0My-_FIu1HA_OfLU,1505 virtualenvutils/__main__.py,sha256=E8in115wXoDjQeMfjpiRic9aBuhwlvh4FTMXhVvCF58,2789 virtualenvutils/virtualenvutils.py,sha256=POvVKRRxWUseCE4U0lCIFV8FUMNHV_tR5g44_2-DfH8,6851 virtualenvutils-0.2.1.dist-info/DESCRIPTION.rst,sha256=lwbvoE2sNBz7gTcdPKeBK74C67Twa158GEeIb9iywNw,5081 virtualenvutils-0.2.1.dist-info/LICENSE.txt,sha256=Smw718mzZPOThnJhronI9rcmCOW88mXaXetmGxzNCbw,1116 virtualenvutils-0.2.1.dist-info/METADATA,sha256=wpaRFLNs7OznDpSUes60GhpQEeGpDUUpze_Um2XAQDA,5706 virtualenvutils-0.2.1.dist-info/RECORD,, virtualenvutils-0.2.1.dist-info/WHEEL,sha256=c5du820PMLPXFYzXDp0SSjIjJ-7MmVRpJa1kKfTaqlc,110 virtualenvutils-0.2.1.dist-info/entry_points.txt,sha256=fFMMmj9MY-_-vJzs40rXoDR-omi1i3JTz70hpy9IEKc,67 virtualenvutils-0.2.1.dist-info/metadata.json,sha256=yhUcX2M-FnoMgGMC8s5YphgA0DBcT_eTfS3rhtAmWbk,1015 virtualenvutils-0.2.1.dist-info/namespace_packages.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1 virtualenvutils-0.2.1.dist-info/top_level.txt,sha256=yJPLxeBVRZjO-Hnk6d50e9Ewl4mDwKTpW_sDn93c3us,16 PKUYPHQ-9r"virtualenvutils/virtualenvutils.pyPKi[PHTvirtualenvutils/__init__.pyPKFMH,h !virtualenvutils/__main__.pyPKw[PHx></;,virtualenvutils-0.2.1.dist-info/DESCRIPTION.rstPKw[PHA\\+a@virtualenvutils-0.2.1.dist-info/LICENSE.txtPKv[PHNHCC0Evirtualenvutils-0.2.1.dist-info/entry_points.txtPKw[PH~-Evirtualenvutils-0.2.1.dist-info/metadata.jsonPKv[PH26Ivirtualenvutils-0.2.1.dist-info/namespace_packages.txtPKv[PH+-.Jvirtualenvutils-0.2.1.dist-info/top_level.txtPKw[PH>nn%Jvirtualenvutils-0.2.1.dist-info/WHEELPKw[PHkJJ(:Kvirtualenvutils-0.2.1.dist-info/METADATAPKw[PHe+__&avirtualenvutils-0.2.1.dist-info/RECORDPK mf