Skip to content

Commit

Permalink
Merge branch 'release/1.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
glennmatthews committed Aug 5, 2016
2 parents c2ef076 + 91783a8 commit a11b272
Show file tree
Hide file tree
Showing 53 changed files with 1,628 additions and 877 deletions.
1 change: 1 addition & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# .coveragerc to control coverage.py
[run]
branch = True
omit =
COT/tests/*
COT/helpers/tests/*
Expand Down
4 changes: 2 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,15 @@ disable=bad-continuation,
max-args=10
# default: max-attributes=7
# current worst offender: OVF
max-attributes=98
max-attributes=29
# default: max-bool-expr=5
# default: max-branches=12
# default: max-locals=15
# current worst offender: OVF.profile_info_list
max-locals=29
# default: max-public-methods=20
# current worst offender: OVF
max-public-methods=76
max-public-methods=74
# default: max-returns=6
# default: max-statements=50

Expand Down
12 changes: 8 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ sudo: false

language: python
python:
- "2.7"
- 2.6
- 2.7
- 3.3
- 3.4
- 3.5

addons:
apt:
Expand All @@ -18,8 +22,8 @@ before_script:
- export PREFIX=$PWD

install:
- pip install tox
- pip install coveralls
- pip install tox-travis
- pip install codecov

cache:
apt: true
Expand All @@ -29,4 +33,4 @@ cache:
script: tox

after_success:
- coveralls
- codecov
35 changes: 35 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,38 @@ Change Log
All notable changes to the COT project will be documented in this file.
This project adheres to `Semantic Versioning`_.

`1.7.0`_ - 2016-08-05
---------------------

**Added**

- Support for Python 3.5
- Enhancements to ``cot edit-properties`` (`#50`_):

- Added ``--user-configurable`` option to set whether created/updated
properties are marked as user-configurable in the OVF.
- Added ``--labels`` and ``--descriptions`` options to set/update the
labels and descriptions associated with properties.
- It's now valid to set no default value for a property by
omitting the ``=value``, as in ``-p property-with-no-value``, as well as
the existing ``-p property-with-empty-value=`` syntax to set
an empty string as the value.
- Users can now optionally specify the property type to enforce for each
property by using the delimiter ``+type``, as in ``-p key=1+boolean``.

**Changed**

- Switched from statement coverage to branch coverage for better test analysis.
- Moved from `Coveralls`_ to `Codecov`_ for test coverage tracking, since
Coveralls does not support branch coverage reporting.

**Fixed**

- When ``cot edit-hardware`` is used to create new NICs in an OVF that
previously had none, and the user does not specify any corresponding Network
entries, automatically create a 'VM Network' entry, because all NICs must
be mapped to Networks for a valid OVF descriptor.

`1.6.1`_ - 2016-07-07
---------------------

Expand Down Expand Up @@ -448,6 +480,7 @@ Initial public release.
.. _#47: https://github.com/glennmatthews/cot/issues/47
.. _#48: https://github.com/glennmatthews/cot/issues/48
.. _#49: https://github.com/glennmatthews/cot/issues/49
.. _#50: https://github.com/glennmatthews/cot/issues/50

.. _Semantic Versioning: http://semver.org/
.. _`PEP 8`: https://www.python.org/dev/peps/pep-0008/
Expand All @@ -473,8 +506,10 @@ Initial public release.
.. _Pylint: https://www.pylint.org/
.. _`pep8-naming`: https://pypi.python.org/pypi/pep8-naming
.. _mccabe: https://pypi.python.org/pypi/mccabe
.. _Codecov: https://codecov.io

.. _Unreleased: https://github.com/glennmatthews/cot/compare/master...develop
.. _1.7.0: https://github.com/glennmatthews/cot/compare/v1.6.1...v1.7.0
.. _1.6.1: https://github.com/glennmatthews/cot/compare/v1.6.0...v1.6.1
.. _1.6.0: https://github.com/glennmatthews/cot/compare/v1.5.2...v1.6.0
.. _1.5.2: https://github.com/glennmatthews/cot/compare/v1.5.1...v1.5.2
Expand Down
34 changes: 21 additions & 13 deletions COT/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,12 @@ def fill_usage(self, subcommand, usage_list):
::
>>> fill_usage('add-file', ["FILE PACKAGE [-o OUTPUT] [-f FILE_ID]"])
>>> print(CLI(50).fill_usage('add-file',
... ["FILE PACKAGE [-o OUTPUT] [-f FILE_ID]"]))
<BLANKLINE>
cot add-file --help
cot add-file FILE PACKAGE [-o OUTPUT]
[-f FILE_ID]
cot <opts> add-file FILE PACKAGE [-o OUTPUT]
[-f FILE_ID]
:param str subcommand: Subcommand name/keyword
:param list usage_list: List of usage strings for this subcommand.
Expand Down Expand Up @@ -230,7 +232,7 @@ def fill_examples(self, example_list):
::
>>> fill_examples([
>>> print(CLI(70).fill_examples([
... ("Deploy to vSphere/ESXi server 192.0.2.100 with credentials"
... " admin/admin, creating a VM named 'test_vm' from foo.ova.",
... 'cot deploy foo.ova esxi 192.0.2.100 -u admin -p admin'
Expand All @@ -239,18 +241,18 @@ def fill_examples(self, example_list):
... " admin (prompting the user to input a password at runtime),"
... " creating a VM based on profile '1CPU-2.5GB' in foo.ova.",
... 'cot deploy foo.ova esxi 192.0.2.100 -u admin -c 1CPU-2.5GB')
... ])
... ]))
Examples:
Deploy to vSphere/ESXi server 192.0.2.100 with credentials
admin/admin, creating a VM named 'test_vm' from foo.ova.
<BLANKLINE>
cot deploy foo.ova esxi 192.0.2.100 -u admin -p admin \
-n test_vm
<BLANKLINE>
Deploy to vSphere/ESXi server 192.0.2.100, with username admin
(prompting the user to input a password at runtime), creating a VM
based on profile '1CPU-2.5GB' in foo.ova.
<BLANKLINE>
cot deploy foo.ova esxi 192.0.2.100 -u admin -c 1CPU-2.5GB
:param list example_list: List of (description, CLI example)
Expand Down Expand Up @@ -531,7 +533,8 @@ def parse_args(self, argv):

return args

def args_to_dict(self, args): # pylint: disable=no-self-use
@staticmethod
def args_to_dict(args):
"""Convert args to a dict and perform any needed cleanup."""
arg_dict = vars(args)
del arg_dict["_verbosity"]
Expand All @@ -548,7 +551,8 @@ def args_to_dict(self, args): # pylint: disable=no-self-use
arg_dict[arg] = [v for l in value for v in l]
return arg_dict

def set_instance_attributes(self, arg_dict): # pylint: disable=no-self-use
@staticmethod
def set_instance_attributes(arg_dict):
"""Pass the CLI argument dictionary to the instance attributes TODO.
:raise InvalidInputError: if attributes are not validly set.
Expand Down Expand Up @@ -609,14 +613,18 @@ def main(self, args):
"Please contact the COT development team."
.format(e.args[0]))
except EnvironmentError as e:
# EnvironmentError may have both or neither of (errno, strerror).
# EnvironmentError may have some of (errno, strerror, filename).
if e.errno is not None:
print(e.strerror)
if e.filename is not None:
# implicitly we also have e.strerror
print("{0}: {1}".format(e.filename, e.strerror))
else:
print(e)
sys.exit(e.errno)
else:
print(e.args[0])
sys.exit(1)
except KeyboardInterrupt:
except (KeyboardInterrupt, EOFError):
sys.exit("\nAborted by user.")
finally:
if self.master_logger:
Expand Down
43 changes: 30 additions & 13 deletions COT/data_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
positive_int
to_string
validate_int
truth_value
**Constants**
Expand All @@ -55,6 +56,7 @@

import xml.etree.ElementTree as ET
import re
from distutils.util import strtobool


def to_string(obj):
Expand Down Expand Up @@ -271,44 +273,59 @@ def no_whitespace(string):


def validate_int(string,
min=None, max=None, # pylint: disable=redefined-builtin
minimum=None, maximum=None,
label="input"):
"""Parser helper function for validating integer arguments in a range.
:param str string: String to convert to an integer and validate
:param int min: Minimum valid value (optional)
:param int max: Maximum valid value (optional)
:param int minimum: Minimum valid value (optional)
:param int maximum: Maximum valid value (optional)
:param str label: Label to include in any errors raised
:return: Validated integer value
:raise ValueUnsupportedError: if :attr:`string` can't be converted to int
:raise ValueTooLowError: if value is less than :attr:`min`
:raise ValueTooHighError: if value is more than :attr:`max`
:raise ValueTooLowError: if value is less than :attr:`minimum`
:raise ValueTooHighError: if value is more than :attr:`maximum`
"""
try:
i = int(string)
except ValueError:
raise ValueUnsupportedError(label, string, "integer")
if min is not None and i < min:
raise ValueTooLowError(label, i, min)
if max is not None and i > max:
raise ValueTooHighError(label, i, max)
if minimum is not None and i < minimum:
raise ValueTooLowError(label, i, minimum)
if maximum is not None and i > maximum:
raise ValueTooHighError(label, i, maximum)
return i


def non_negative_int(string):
"""Parser helper function for integer arguments that must be 0 or more.
Alias for :func:`validate_int` setting :attr:`min` to 0.
Alias for :func:`validate_int` setting :attr:`minimum` to 0.
"""
return validate_int(string, min=0)
return validate_int(string, minimum=0)


def positive_int(string):
"""Parser helper function for integer arguments that must be 1 or more.
Alias for :func:`validate_int` setting :attr:`min` to 1.
Alias for :func:`validate_int` setting :attr:`minimum` to 1.
"""
return validate_int(string, min=1)
return validate_int(string, minimum=1)


def truth_value(value):
"""Parser helper function for truth values like '0', 'y', or 'false'."""
if isinstance(value, bool):
return value
try:
return strtobool(value)
except ValueError:
raise ValueUnsupportedError(
"truth value",
value,
['y', 'yes', 't', 'true', 'on', 1,
'n', 'no', 'f', 'false', 'off', 0]
)


# Some handy exception and error types we can throw
Expand Down
2 changes: 1 addition & 1 deletion COT/deploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import logging
import re

from .submodule import COTReadOnlySubmodule
from COT.submodule import COTReadOnlySubmodule
from COT.data_validation import InvalidInputError, ValueUnsupportedError

logger = logging.getLogger(__name__)
Expand Down
6 changes: 4 additions & 2 deletions COT/deploy_esxi.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ def __enter__(self):
"otherwise not recognized as valid. "
"Accept certificate anyway?"
.format(self.server))
# pylint: disable=protected-access
# pylint: disable=protected-access, no-member
# ssl._create_unverified_context doesn't exist in Python 3.3.
_create_unverified_context = ssl._create_unverified_context
ssl._create_default_https_context = _create_unverified_context
return super(SmarterConnection, self).__enter__()
Expand All @@ -105,7 +106,8 @@ def __exit__(self, # pylint: disable=arguments-differ
logger.error("Session failed - %s", exc_value)
# TODO - re-enable SSL certificate validation?

def unwrap_connection_error(self, outer_e): # pylint: disable=no-self-use
@staticmethod
def unwrap_connection_error(outer_e):
"""Extract inner attributes from a ConnectionError.
ConnectionError often wraps another exception with more context;
Expand Down
Loading

0 comments on commit a11b272

Please sign in to comment.