Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v0.4.1 #45

Merged
merged 10 commits into from
Mar 20, 2020
9 changes: 9 additions & 0 deletions divvy/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from .compute import main
import sys

if __name__ == '__main__':
try:
sys.exit(main())
except KeyboardInterrupt:
print("Program canceled by user!")
sys.exit(1)
2 changes: 1 addition & 1 deletion divvy/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "0.4.0"
__version__ = "0.4.1"
49 changes: 8 additions & 41 deletions divvy/compute.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
from distutils.dir_util import copy_tree

# from attmap import PathExAttMap
from ubiquerg import is_writable
import yacman
from collections import OrderedDict

Expand All @@ -20,13 +21,14 @@
from .utils import parse_config_file, write_submit_script, get_first_env_var
from . import __version__

DEFAULT_CONFIG_FILEPATH = os.path.join(
DEFAULT_CONFIG_FILEPATH = os.path.join(
os.path.dirname(__file__),
"default_config",
"divvy_config.yaml")

_LOGGER = logging.getLogger(__name__)


class ComputingConfiguration(yacman.YacAttMap):
"""
Represents computing configuration objects.
Expand Down Expand Up @@ -65,8 +67,8 @@ def __init__(self, entries=None, filepath=None,
super(ComputingConfiguration, self).__init__(entries, filepath)

if not hasattr(self, "compute_packages"):
raise Exception("Your config file is not in divvy config format (it"
" lacks a compute_packages section)")
raise Exception("Your divvy config file is not in divvy config format (it"
" lacks a compute_packages section): '{}'".format(filepath))
# We require that compute_packages be present, even if empty
self.compute_packages = {}

Expand All @@ -78,7 +80,7 @@ def __init__(self, entries=None, filepath=None,

def write(self, filename=None):
super(ComputingConfiguration, self).write(filename)
filename = filename or getattr(self, FILEPATH_KEY)
filename = filename or getattr(self, yacman.FILEPATH_KEY)
filedir = os.path.dirname(filename)
# For this object, we *also* have to write the template files
for pkg_name, pkg in self.compute_packages.items():
Expand Down Expand Up @@ -313,33 +315,6 @@ def divvy_init(config_path, template_config_path):
_LOGGER.warning("Can't initialize, file exists: {} ".format(config_path))


def _is_writeable(folder, check_exist=False, create=False):
"""
Make sure a folder is writable.

Given a folder, check that it exists and is writable. Errors if requested on
a non-existent folder. Otherwise, make sure the first existing parent folder
is writable such that this folder could be created.

:param str folder: Folder to check for writeability.
:param bool check_exist: Throw an error if it doesn't exist?
:param bool create: Create the folder if it doesn't exist?
"""
folder = folder or "."

if os.path.exists(folder):
return os.access(folder, os.W_OK) and os.access(folder, os.X_OK)
elif create_folder:
os.mkdir(folder)
elif check_exist:
raise OSError("Folder not found: {}".format(folder))
else:
_LOGGER.debug("Folder not found: {}".format(folder))
# The folder didn't exist. Recurse up the folder hierarchy to make sure
# all paths are writable
return _is_writeable(os.path.dirname(folder), strict_exists)


def build_argparser():
"""
Builds argument parser.
Expand All @@ -351,6 +326,7 @@ def build_argparser():
additional_description = "\nhttps://divvy.databio.org"

parser = _VersionInHelpParser(
prog="divvy",
description=banner,
epilog=additional_description)

Expand Down Expand Up @@ -416,11 +392,10 @@ def main():
keys = [str.replace(x, "--", "") for x in remaining_args[::2]]
cli_vars = dict(zip(keys, remaining_args[1::2]))


if args.command == "init":
divcfg = args.config
_LOGGER.debug("Initializing divvy configuration")
_is_writable(os.path.dirname(divcfg), check_exist=False)
is_writable(os.path.dirname(divcfg), check_exist=False)
divvy_init(divcfg, DEFAULT_CONFIG_FILEPATH)
sys.exit(0)

Expand Down Expand Up @@ -449,11 +424,3 @@ def main():
else:
vars_groups = [cli_vars]
dcc.write_script(args.outfile, vars_groups)


if __name__ == '__main__':
try:
sys.exit(main())
except KeyboardInterrupt:
_LOGGER.error("Program canceled by user!")
sys.exit(1)
10 changes: 10 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Changelog

## [0.4.1] -- 2020-03-20
### Fixed
- `NameError` in `divvy init`; [#44](https://github.com/pepkit/divvy/issues/44)

### Added
- possibility to execute library module as a script: `python -m divvy ...`

### Changed
- improved error message when config format is incompatible

## [0.4.0] -- 2019-07-30
### Added
- Default templates for singularity and docker compute packages
Expand Down
1 change: 1 addition & 0 deletions requirements/requirements-all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ yacman>=0.5.0
pandas>=0.20.2
pyyaml>=5.1
logmuse>=0.2.0
ubiquerg>=0.5.0
4 changes: 2 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@
url="https://github.com/pepkit/{}/".format(PACKAGE),
author=u"Nathan Sheffield, Vince Reuter, Michal Stolarczyk",
author_email=u"nathan@code.databio.org, vreuter@virginia.edu, mjs5kd@virginia.edu",
license="BSD2",
license="BSD-2-Clause",
entry_points={
"console_scripts": [
'divvy = divvy.compute:main'
'divvy = divvy.__main__:main'
],
},
package_data={"divvy": [os.path.join("divvy", "*")]},
Expand Down
4 changes: 3 additions & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ def dcc(request):
return divvy.ComputingConfiguration(request.param)



@pytest.fixture
def mock_env_missing(monkeypatch):
[monkeypatch.delenv(env_var, raising=False) for env_var in divvy.const.COMPUTE_SETTINGS_VARNAME]


6 changes: 5 additions & 1 deletion tests/divvy_tests/test_divvy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import pytest
from yacman import YacAttMap, load_yaml
from divvy import DEFAULT_COMPUTE_RESOURCES_NAME
from tests.conftest import DCC_ATTRIBUTES, FILES
from tests.conftest import DCC_ATTRIBUTES, FILES, mock_env_missing


class DefaultDCCTests:
""" Tests the default divvy.ComputingConfiguration object creation"""
Expand All @@ -17,6 +18,9 @@ def test_attrs_produced(self, att, empty_dcc):
""" Test if compute property is produced and is not empty """
empty_dcc[att]

def test_no_env_var(self, mock_env_missing, empty_dcc):
empty_dcc


class DCCTests:
""" Tests the divvy.ComputingConfiguration object creation """
Expand Down