Skip to content

Commit

Permalink
updates #12
Browse files Browse the repository at this point in the history
  • Loading branch information
Adam Kaufman committed Mar 2, 2015
1 parent 88bb7b6 commit 8daa7e2
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 121 deletions.
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ a python virtual environment in a known location.

|Travis Status| |Coveralls Status|

**Master on Windows**
**Master on Windows**

|Appveyor Status|

Expand Down Expand Up @@ -57,15 +57,15 @@ virtualenv creation.
Usage
-----

``fencepy -c``: Create a new virtual environment
``fencepy create``: Create a new virtual environment

``. `fencepy -a```: Activate the virtual environment in a bash-like shell
``. `fencepy activate```: Activate the virtual environment in a bash-like shell

``source (fencepy -a)``: Activate the virtual environment in fish shell
``source (fencepy activate)``: Activate the virtual environment in fish shell

``. $(fencepy -a)``: Activate the virtual environment in windows powershell
``. $(fencepy activate)``: Activate the virtual environment in windows powershell

``fencepy -e``: Remove the virtual environment
``fencepy erase``: Remove the virtual environment

Additional notes
----------------
Expand Down
139 changes: 57 additions & 82 deletions fencepy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Main CLI logic
"""

import argparse
import docopt
import os
import shutil
import sys
Expand All @@ -19,144 +19,119 @@
from logging.handlers import RotatingFileHandler
import logging as l

DOCOPT = """
fencepy -- Standardized fencing off of python virtual environments on a per-project basis
Usage:
fencepy create [options]
fencepy activate [options]
fencepy erase [options]
Options:
-h --help Show this screen
-v --verbose Print/log more verbose output
-q --quiet Silence all console output
-s --silent Silence ALL output, including log output (except "activate")
-C FILE --config-file=FILE Config file to use [default: ~/.fencepy/fencepy.conf]
-P LIST --plugins=LIST Comma-separated list of plugins to apply (only "create")
Path Overrides:
-d DIR --dir=DIR Link the fenced environment to DIR instead of the CWD
-D DIR --virtualenv-dir=DIR Use DIR as the root directory for the virtual environment
-F DIR --fencepy-root=DIR Use DIR as the root of the fencepy tree [default: ~/.fencepy]
-G --no-git Don't treat the working directory as a git repository
"""


def _get_args():
"""Do all parsing and processing for command-line arguments"""

parser = argparse.ArgumentParser(prog='fencepy',
usage='%(prog)s -a|-c|-e [options]',
add_help=False)

# action arguments
actions = parser.add_argument_group('actions')
actions.add_argument('-a', '--activate', action='store_true',
help='Print the path to the activate script in the fenced environment -- this is the default behavior')
actions.add_argument('-c', '--create', action='store_true',
help='Create the fenced environment')
actions.add_argument('-e', '--erase', action='store_true',
help='Erase the fenced environment')

# source and destination arguments
paths = parser.add_argument_group('path overrides')
paths.add_argument('-p', '--plain', action='store_true',
help="Don't treat the working directory as a git repository")
paths.add_argument('-d', '--dir',
help='Use DIR as the root path for the fenced environment instead of the CWD')
paths.add_argument('-D', '--virtualenv-dir', metavar='DIR',
help='Use DIR as the root directory for the virtualenv instead of the default')
paths.add_argument('-F', '--fencepy-root', metavar='DIR',
help='Use DIR as the root directory for all fencepy ops instead of the default')

# miscellaneous functionality
misc = parser.add_argument_group('miscellaneous')
misc.add_argument('-P', '--plugins', default='', dest='pluginstr',
help='Comma-separated list of plugins to apply, override any settings in config file')
misc.add_argument('-C', '--config-file',
help='Config file to use instead of ~/.fencepy/fencepy.conf')
misc.add_argument('-v', '--verbose', '--debug', action='store_true',
help='Print debug logging')
misc.add_argument('-q', '--quiet', action='store_true',
help='Silence all console output')
misc.add_argument('-s', '--silent', action='store_true',
help='Silence ALL output, including log output')
misc.add_argument("-h", "--help", action="help",
help="Show this help message and exit")

args = vars(parser.parse_args())
args = docopt.docopt(DOCOPT)

# set up the root directory
if not args['fencepy_root']:
args['fencepy_root'] = os.path.join(os.path.expanduser('~'), '.fencepy')
if not os.path.exists(args['fencepy_root']):
os.mkdir(args['fencepy_root'])
args['--fencepy-root'] = os.path.expanduser(args['--fencepy-root'])
if not os.path.exists(args['--fencepy-root']):
os.mkdir(args['--fencepy-root'])

# set up logging
if not args['silent']:
if not args['--silent']:
f = l.Formatter('%(asctime)s [%(levelname)s] %(module)s: %(message)s')
h = RotatingFileHandler(os.path.join(args['fencepy_root'], 'fencepy.log'))
h = RotatingFileHandler(os.path.join(args['--fencepy-root'], 'fencepy.log'))
h.setFormatter(f)
l.getLogger('').addHandler(h)
if not (args['silent'] or args['quiet']):
if not (args['--silent'] or args['--quiet']):
f = l.Formatter('[%(levelname)s] %(message)s')
h = l.StreamHandler()
h.setFormatter(f)
l.getLogger('').addHandler(h)

if args['verbose']:
if args['--verbose']:
l.getLogger('').setLevel(l.DEBUG)
l.getLogger('sh').setLevel(l.INFO)
else:
l.getLogger('').setLevel(l.INFO)
l.getLogger('sh').setLevel(l.ERROR)

# we need to do some work to get the root directory we care about here
if not args['dir']:
args['dir'] = os.getcwd()
if not args['plain']:
if not args['--dir']:
args['--dir'] = os.getcwd()
if not args['--no-git']:
try:
output = getoutputoserror('git rev-parse --show-toplevel')
args['dir'] = output.strip()
args['--dir'] = output.strip()
except OSError as e:
l.debug("tried to handle {0} as a git repository but it isn't one".format(args['dir']))
l.debug("tried to handle {0} as a git repository but it isn't one".format(args['--dir']))

# reset the virtualenv root, if necessary
if not args['virtualenv_dir']:
venv_root = os.path.join(args['fencepy_root'], 'virtualenvs')
if not args['--virtualenv-dir']:
venv_root = os.path.join(args['--fencepy-root'], 'virtualenvs')

# if we're one directory below the root, this logic needs to work differently
parent = os.path.dirname(args['dir'])
parent = os.path.dirname(args['--dir'])
if parent in ('/', os.path.splitdrive(parent)[0]):
args['virtualenv_dir'] = os.path.join(venv_root, os.path.basename(args['dir']))
args['--virtualenv-dir'] = os.path.join(venv_root, os.path.basename(args['--dir']))

else:
# need the realpath here because in some circumstances windows paths get passed
# with a '/' and others see it coming in as a '\'
tokens = os.path.dirname(os.path.realpath(args['dir'])).split(os.path.sep)
tokens = os.path.dirname(os.path.realpath(args['--dir'])).split(os.path.sep)
tokens.reverse()
if tokens[-1] == '':
tokens = tokens[:-1]
prjpart = '.'.join([os.path.basename(args['dir']), '.'.join([d[0] for d in tokens])])
args['virtualenv_dir'] = os.path.join(venv_root, '-'.join((prjpart, pyversionstr())))

# set the mode properly
modecount = [args['activate'], args['create'], args['erase']].count(True)
if modecount > 1:
raise RuntimeError('please specify only one of -a, -c, -e')
elif modecount == 0:
args['activate'] = True
prjpart = '.'.join([os.path.basename(args['--dir']), '.'.join([d[0] for d in tokens])])
args['--virtualenv-dir'] = os.path.join(venv_root, '-'.join((prjpart, pyversionstr())))

# only populate the parser if there's a valid file
config = SafeConfigParser()
readconf = True
if args['config_file']:
if not os.path.exists(args['config_file']):
raise IOError('specified config file {0} does not exist'.format(args['config_file']))
else:
args['config_file'] = os.path.join(args['fencepy_root'], 'fencepy.conf')
if not os.path.exists(args['config_file']):
if args['--config-file'] == '~/.fencepy/fencepy.conf':
args['--config-file'] = os.path.join(args['--fencepy-root'], 'fencepy.conf')
if not os.path.exists(args['--config-file']):
readconf = False
elif not os.path.exists(args['--config-file']):
raise IOError('specified config file {0} does not exist'.format(args['--config-file']))
if readconf:
config.read(args['config_file'])
config.read(args['--config-file'])

# plugins -- all false means all true
if args['pluginstr']:
args['plugins'] = dict((key, key in args['pluginstr'].split(',')) for key in plugins.PLUGINS)
if args['--plugins']:
args['plugins'] = dict((key, key in args['--plugins'].split(',')) for key in plugins.PLUGINS)
else:
args['plugins'] = dict((key, True) for key in plugins.PLUGINS)
if config.has_section('plugins'):
for key, value in config.items('plugins'):
print(key, value)
if key not in plugins.PLUGINS:
raise KeyError('invalid configuration: {0} is not a valid plugin'.format(key))
args['plugins'][key] = str2bool(value)

return args


def _activate(args):
"""Print out the path to the appropriate activate script"""

# break out the virtual environment directory for convenience
vdir = args['virtualenv_dir']
vdir = args['--virtualenv-dir']

# make sure the directory exists
if not os.path.exists(vdir):
Expand Down Expand Up @@ -192,8 +167,8 @@ def _create(args):
"""Create a virtualenv for the current project"""

# break out various args for convenience
vdir = args['virtualenv_dir']
pdir = args['dir'] # p for project
vdir = args['--virtualenv-dir']
pdir = args['--dir'] # p for project

# make sure the directory doesn't already exist
if os.path.exists(vdir):
Expand Down Expand Up @@ -232,7 +207,7 @@ def _erase(args):
"""Remove the virtualenv associated with this project"""

# break out various args for convenience
vdir = args['virtualenv_dir']
vdir = args['--virtualenv-dir']

# make sure the directory exists
if not os.path.exists(vdir):
Expand Down
12 changes: 6 additions & 6 deletions fencepy/plugins.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def install_requirements(args):
"""Install requirements out of requirements.txt, if it exists"""

# break out various args for convenience
vdir = args['virtualenv_dir']
pdir = args['dir']
vdir = args['--virtualenv-dir']
pdir = args['--dir']

# install requirements, if they exist
rtxt = os.path.join(pdir, 'requirements.txt')
Expand All @@ -44,8 +44,8 @@ def install_sublime(args):
"""Set up sublime linter to use environment"""

# break out various args for convenience
vdir = args['virtualenv_dir']
pdir = args['dir']
vdir = args['--virtualenv-dir']
pdir = args['--dir']

# set up the sublime linter, if appropriate
scfg = None
Expand All @@ -72,8 +72,8 @@ def install_sublime(args):
def install_ps1(args):
"""Change the PS1 environment name in activate scripts"""

ps1str = '-'.join((os.path.basename(args['dir']), pyversionstr()))
vdir = args['virtualenv_dir']
ps1str = '-'.join((os.path.basename(args['--dir']), pyversionstr()))
vdir = args['--virtualenv-dir']

system = platform.system()
if system == 'Linux':
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@
'fencepy-%s.%s=fencepy:fence' % sys.version_info[:2]]},
test_suite='tests',
install_requires=[
'virtualenv>=1.11',
'psutil>=2.2.1'
'virtualenv>=12.0.7',
'psutil>=2.2.1',
'docopt>=0.6.2'
],
classifiers=[
'Development Status :: 3 - Alpha',
Expand Down
Loading

0 comments on commit 8daa7e2

Please sign in to comment.