...
 
Commits (4)
...@@ -2,6 +2,16 @@ ...@@ -2,6 +2,16 @@
History History
======= =======
0.1.4 (2019-12-12)
------------------
* Includes examples directory and a test ``scope_config.yaml``
* Fixes a small logging error in the command line interface
* Updates documentation of main module
* Adds pre and post hooks functionality
* Changes maximum line length in flake8 to 160 characters, black code style for
120 characters.
0.1.3 (2019-12-4) 0.1.3 (2019-12-4)
----------------- -----------------
......
...@@ -53,6 +53,9 @@ clean-test: ## remove test and coverage artifacts ...@@ -53,6 +53,9 @@ clean-test: ## remove test and coverage artifacts
lint: ## check style with flake8 lint: ## check style with flake8
flake8 scope tests flake8 scope tests
style: ## run black on scope
black -l 120 scope
test: ## run tests quickly with the default Python test: ## run tests quickly with the default Python
python setup.py test python setup.py test
......
...@@ -4,6 +4,6 @@ ...@@ -4,6 +4,6 @@
__author__ = """Paul Gierz""" __author__ = """Paul Gierz"""
__email__ = "pgierz@awi.de" __email__ = "pgierz@awi.de"
__version__ = "__version__ = '0.1.3'" __version__ = "__version__ = '0.1.4'"
from .scope import * from .scope import *
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"""Console script for scope.""" """Console script for scope."""
import logging
import sys import sys
import click import click
import yaml import yaml
import jinja2 import jinja2
from scope import Regrid, Preprocess from scope import Regrid, Preprocess
...@@ -43,12 +45,12 @@ def yaml_file_to_dict(filepath): ...@@ -43,12 +45,12 @@ def yaml_file_to_dict(filepath):
del parsed_dict["template_replacements"] del parsed_dict["template_replacements"]
return parsed_dict return parsed_dict
except IOError as error: except IOError as error:
logger.debug( logging.debug(
"IOError (%s) File not found with %s, trying another extension pattern.", "IOError (%s) File not found with %s, trying another extension pattern.",
error.errno, error.errno,
filepath + extension, filepath + extension,
) )
raise FileNotFoundError("All file extensions tried and none worked for %s" % filepath) raise OSError("All file extensions tried and none worked for %s" % filepath)
@click.group() @click.group()
......
...@@ -167,6 +167,25 @@ class Scope(object): ...@@ -167,6 +167,25 @@ class Scope(object):
class ScopeDecorators(object): class ScopeDecorators(object):
"""Contains decorators you can use on class methods""" """Contains decorators you can use on class methods"""
# FIXME: I don't really like that this is exactly the same above with
# only a positional change. Probably it can abstracted away...
@staticmethod
def _wrap_hook(self, meth):
program_to_call = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("program")
flags_for_program = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("flags_for_program")
arguments_for_program = (
self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("arguments_for_program")
)
full_process = program_to_call
if flags_for_program:
full_process += flags_for_program
if arguments_for_program:
full_process += arguments_for_program
subprocess.run(full_process, shell=True, check=True)
# PG: Why is it a classmethod? I don't understand this yet... # PG: Why is it a classmethod? I don't understand this yet...
@classmethod @classmethod
def pre_hook(cls, meth): def pre_hook(cls, meth):
...@@ -179,45 +198,17 @@ class Scope(object): ...@@ -179,45 +198,17 @@ class Scope(object):
# https://www.thecodeship.com/patterns/guide-to-python-function-decorators/ # https://www.thecodeship.com/patterns/guide-to-python-function-decorators/
@wraps(meth) @wraps(meth)
def wrapped_meth(self, *args): def wrapped_meth(self, *args):
program_to_call = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("program") self._wrap_hook(self, meth)
flags_for_program = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("flags_for_program")
arguments_for_program = (
self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("arguments_for_program")
)
full_process = program_to_call
if flags_for_program:
full_process += flags_for_program
if arguments_for_program:
full_process += arguments_for_program
subprocess.run(full_process, shell=True, check=True)
meth(self, *args) meth(self, *args)
return wrapped_meth return wrapped_meth
# FIXME: I don't really like that this is exactly the same above with
# only a positional change. Probably it can abstracted away...
@classmethod @classmethod
def post_hook(cls, meth): def post_hook(cls, meth):
@wraps(meth) @wraps(meth)
def wrapped_meth(*args): def wrapped_meth(self, *args):
meth(*args) meth(*args)
program_to_call = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("program") self._wrap_hook(self, meth)
flags_for_program = self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("flags_for_program")
arguments_for_program = (
self.config[self.whos_turn].get("pre_" + meth.__name__, {}).get("arguments_for_program")
)
full_process = program_to_call
if flags_for_program:
full_process += flags_for_program
if arguments_for_program:
full_process += arguments_for_program
subprocess.run(full_process, shell=True, check=True)
return wrapped_meth return wrapped_meth
......
[bumpversion] [bumpversion]
current_version = 0.1.3 current_version = 0.1.4
commit = True commit = True
tag = True tag = True
...@@ -16,6 +16,7 @@ universal = 1 ...@@ -16,6 +16,7 @@ universal = 1
[flake8] [flake8]
exclude = docs exclude = docs
max-line-length = 160
[aliases] [aliases]
...@@ -48,6 +48,6 @@ setup( ...@@ -48,6 +48,6 @@ setup(
test_suite='tests', test_suite='tests',
tests_require=test_requirements, tests_require=test_requirements,
url='https://gitlab.awi.de/pgierz/scope', url='https://gitlab.awi.de/pgierz/scope',
version='0.1.3', version='0.1.4',
zip_safe=False, zip_safe=False,
) )