Limit class names to not contain spaces
Signed-off-by: martin f. krafft <madduck@madduck.net>
diff --git a/doc/source/changelog.rst b/doc/source/changelog.rst
index 96514ad..4604c6a 100644
--- a/doc/source/changelog.rst
+++ b/doc/source/changelog.rst
@@ -5,6 +5,7 @@
========= ========== ========================================================
Version Date Changes
========= ========== ========================================================
+ * Class names must not contain spaces
1.1 2013-08-28 Salt adapter: fix interface to include minion_id, filter
output accordingly; fixes master_tops
1.0.2 2013-08-27 Fix incorrect versioning in setuptools
diff --git a/doc/source/concepts.rst b/doc/source/concepts.rst
index 67816d8..76b5818 100644
--- a/doc/source/concepts.rst
+++ b/doc/source/concepts.rst
@@ -25,6 +25,8 @@
A class consists of zero or more parent classes, zero or more applications,
and any number of parameters.
+A class name must not contain spaces.
+
A node is almost equivalent to a class, except that it usually does not (but
can) specify applications.
diff --git a/reclass/datatypes/classes.py b/reclass/datatypes/classes.py
index dcb6852..132db31 100644
--- a/reclass/datatypes/classes.py
+++ b/reclass/datatypes/classes.py
@@ -8,6 +8,9 @@
#
import types
+from reclass.errors import InvalidClassnameError
+
+INVALID_CHARACTERS_FOR_CLASSNAMES = ' '
class Classes(object):
'''
@@ -51,12 +54,19 @@
raise TypeError('%s instances can only contain strings, '\
'not %s' % (self.__class__.__name__, type(item)))
+ def _assert_valid_characters(self, item):
+ for c in INVALID_CHARACTERS_FOR_CLASSNAMES:
+ if c in item:
+ raise InvalidClassnameError("Invalid character '{0}' "
+ "in class name '{1}'.".format(c, item))
+
def _append_if_new(self, item):
if item not in self._items:
self._items.append(item)
def append_if_new(self, item):
self._assert_is_string(item)
+ self._assert_valid_characters(item)
self._append_if_new(item)
def __repr__(self):
diff --git a/reclass/datatypes/tests/test_classes.py b/reclass/datatypes/tests/test_classes.py
index 7f55185..c15a6d1 100644
--- a/reclass/datatypes/tests/test_classes.py
+++ b/reclass/datatypes/tests/test_classes.py
@@ -7,11 +7,13 @@
# Released under the terms of the Artistic Licence 2.0
#
from reclass.datatypes import Classes
+from reclass.datatypes.classes import INVALID_CHARACTERS_FOR_CLASSNAMES
import unittest
try:
import unittest.mock as mock
except ImportError:
import mock
+from reclass.errors import InvalidClassnameError
TESTLIST1 = ['one', 'two', 'three']
TESTLIST2 = ['red', 'green', 'blue']
@@ -67,6 +69,12 @@
with self.assertRaises(TypeError):
c.append_if_new(0)
+ def test_append_invalid_characters(self):
+ c = Classes()
+ invalid_name = ' '.join(('foo', 'bar'))
+ with self.assertRaises(InvalidClassnameError):
+ c.append_if_new(invalid_name)
+
def test_merge_unique(self):
c = Classes(TESTLIST1)
c.merge_unique(TESTLIST2)
diff --git a/reclass/errors.py b/reclass/errors.py
index 5bec2c1..b7940d6 100644
--- a/reclass/errors.py
+++ b/reclass/errors.py
@@ -101,3 +101,15 @@
msg = "Infinite recursion while resolving %s at %s" \
% (ref.join(PARAMETER_INTERPOLATION_SENTINELS), path)
super(InfiniteRecursionError, self).__init__(msg)
+
+
+class NameError(ReclassException):
+
+ def __init__(self, msg, rc=posix.EX_DATAERR):
+ super(NameError, self).__init__(msg, rc)
+
+
+class InvalidClassnameError(NameError):
+
+ def __init__(self, msg):
+ super(InvalidClassnameError, self).__init__(msg)