summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Pokorný <jpokorny@redhat.com>2014-09-03 19:21:16 +0200
committerJan Pokorný <jpokorny@redhat.com>2014-09-03 19:23:01 +0200
commit2320b49d30011b44a791a341048f2afeab36705b (patch)
treeb4e0d667da664ba878fda5c8d4decd2da97f8a44
parent20be3b7463ada2d79d337c656c4f8c101504851a (diff)
downloadclufter-2320b49d30011b44a791a341048f2afeab36705b.tar.gz
clufter-2320b49d30011b44a791a341048f2afeab36705b.tar.xz
clufter-2320b49d30011b44a791a341048f2afeab36705b.zip
format: fix multiple class-level __init__ per one __new__ result
+ modify tests/run_cmd to trigger such a case Reported-by: Tomáš Jelínek" <tojelinek@redhat.com> Signed-off-by: Jan Pokorný <jpokorny@redhat.com>
-rw-r--r--format.py8
-rw-r--r--plugin_registry.py3
-rw-r--r--tests/run_cmd.py26
3 files changed, 25 insertions, 12 deletions
diff --git a/format.py b/format.py
index c4bc08e..3b9851f 100644
--- a/format.py
+++ b/format.py
@@ -42,8 +42,12 @@ class FormatError(ClufterError):
class formats(PluginRegistry):
"""Format registry (to be used as a metaclass for formats)"""
def __init__(cls, name, bases, attrs):
- # NOTE could be called multiple times, with popattr-destroyed
- # form (attrs missing), so defer to attrs then
+ # could be called multiple times but only once per respective
+ # __new__ (in plugin_registry) is required, rest would be waste
+ # of resources if not harmful due to non-idempotent modifications
+ if cls._probes > 1:
+ return
+
cls._protocols, cls._validators, cls._protocol_attrs = {}, {}, set()
cls._context = set(popattr(cls, 'context_specs',
attrs.pop('context_specs', ())))
diff --git a/plugin_registry.py b/plugin_registry.py
index 217c1bf..2862b36 100644
--- a/plugin_registry.py
+++ b/plugin_registry.py
@@ -47,6 +47,8 @@ class PluginRegistry(type):
# non-API
def __new__(registry, name, bases, attrs):
+ assert '_probes' not in attrs, "sabotage of the meta level detected"
+ attrs['_probes'] = 0
if '__metaclass__' not in attrs and MetaPlugin not in bases:
# alleged end-use plugin
ret = registry.probe(name, bases, attrs)
@@ -67,6 +69,7 @@ class PluginRegistry(type):
ret = super(PluginRegistry, registry).__new__(registry, name,
bases, attrs)
+ ret._probes += 1
return ret
#
diff --git a/tests/run_cmd.py b/tests/run_cmd.py
index f6ab60b..5a498a6 100644
--- a/tests/run_cmd.py
+++ b/tests/run_cmd.py
@@ -7,7 +7,7 @@ __author__ = "Jan Pokorný <jpokorny @at@ Red Hat .dot. com>"
import unittest
from os.path import dirname, exists, join
-from os import unlink
+#from os import unlink
import _bootstrap
@@ -20,7 +20,7 @@ class Main(unittest.TestCase):
# testcib = join(dirname(__file__), '.testcib.xml')
# testcoro = join(dirname(__file__), '.testcorosync.conf')
- # files = dict(
+ # outputs = dict(
# cib=testcib,
# coro=testcoro,
# )
@@ -28,9 +28,9 @@ class Main(unittest.TestCase):
# input=testfile,
# nocheck=True,
# batch=True,
- # **files)
+ # **outputs)
# )
- # for f in files.itervalues():
+ # for f in outputs.itervalues():
# try:
# unlink(f)
# except OSError:
@@ -38,25 +38,31 @@ class Main(unittest.TestCase):
# cmd_manager = CommandManager.implicit()
# self.assertFalse(cmd_manager.commands["ccs2pcs-needle"](clufter_args))
# # just the existence of the files is enough for now...
- # map(lambda f: self.assertTrue(exists(f)), files.itervalues())
+ # map(lambda f: self.assertTrue(exists(f)), outputs.itervalues())
def testCcs2PcsNeedleBetter(self):
testfile = join(dirname(__file__), 'filled.conf')
+ from clufter.formats.simpleconfig import simpleconfig
+ #from clufter.protocol import protocols
+ #protocols = protocols.plugins
- files = {
- "cib": {'passin': 'bytestring', },
- "coro": {'passin': 'bytestring', },
+ outputs = {
+ # alternatives for posterity:
+ #"cib" : {'passin': protocols['bytestring']},
+ #"cib" : {'passin': 'bytestring'},
+ "cib" : {'passin': simpleconfig.BYTESTRING},
+ "coro": {'passin': simpleconfig.STRUCT},
}
clufter_args = type("cluster_args", (object, ), dict(
input=testfile,
nocheck=True,
batch=True,
- **files)
+ **outputs)
)
cmd_manager = CommandManager.implicit()
self.assertFalse(cmd_manager.commands["ccs2pcs-needle"](clufter_args))
# just the existence of non-null strings is enough for now...
- map(lambda fspec: self.assertTrue(fspec['passout']), files.values())
+ map(lambda fspec: self.assertTrue(fspec['passout']), outputs.values())
if __name__ == '__main__':