Hello,
I had this patch sitting around for some time but didn't get around to polishing and submitting it lately. The ticket was now claimed by "rga" (I assume that's the person who goes by Darth Vader here?). I'm sharing the work hoping that it doesn't get done twice.

https://fedorahosted.org/freeipa/ticket/3460


BTW, this is the first small step in my framework refactoring master plan (http://www.freeipa.org/page/V3/Refactorings#Mutable_Command_objects).

--
PetrĀ³
From 5f19318c3a92a71555282ae6417a5c77c581b269 Mon Sep 17 00:00:00 2001
From: Petr Viktorin <pvikt...@redhat.com>
Date: Wed, 16 Jan 2013 10:26:37 -0500
Subject: [PATCH] Remove the unused ipalib.frontend.Property class

This class was built into the framework from its early days but it's
not used anywhere.
Remove it along with its tests

https://fedorahosted.org/freeipa/ticket/3460
---
 doc/guide/guide.org                   |  2 +-
 ipalib/__init__.py                    |  7 +--
 ipalib/frontend.py                    | 57 ++-----------------------
 ipatests/test_ipalib/test_frontend.py | 80 +++++++----------------------------
 make-lint                             |  4 +-
 5 files changed, 23 insertions(+), 127 deletions(-)

diff --git a/doc/guide/guide.org b/doc/guide/guide.org
index bca7b34fabfbab02e68a62382a59cdef54a098d3..ad0c5953a9682a63d922e69264a6385751cd6bef 100644
--- a/doc/guide/guide.org
+++ b/doc/guide/guide.org
@@ -91,7 +91,7 @@ directly associated objects and may perform actions over few of those. Objects a
 using data store represented by a back end, and one of most useful back ends is LDAP store
 back end.
 
-Altogether, set of =Object=, =Property=, =Method=, =Command=, and =Backend= instances
+Altogether, set of =Object=, =Method=, =Command=, and =Backend= instances
 represent application programming interface, API, of FreeIPA core framework.
 
 In Python programming language object oriented support is implemented using a fairly
diff --git a/ipalib/__init__.py b/ipalib/__init__.py
index ab89ab77ec94603d242e56436021c9b6ed8663cb..553c07197ddc95025da9df9e6c1fcddadadff4d8 100644
--- a/ipalib/__init__.py
+++ b/ipalib/__init__.py
@@ -883,7 +883,7 @@ class my_command(Command):
 import plugable
 from backend import Backend
 from frontend import Command, LocalOrRemote, Updater, Advice
-from frontend import Object, Method, Property
+from frontend import Object, Method
 from crud import Create, Retrieve, Update, Delete, Search
 from parameters import DefaultFrom, Bool, Flag, Int, Decimal, Bytes, Str, IA5Str, Password, DNParam, DeprecatedParam
 from parameters import BytesEnum, StrEnum, IntEnum, AccessTime, File
@@ -910,14 +910,11 @@ def create_api(mode='dummy'):
 
         - `frontend.Method`
 
-        - `frontend.Property`
-
         - `frontend.Advice`
 
         - `backend.Backend`
     """
-    api = plugable.API(Command, Object, Method, Property, Backend, Updater,
-                       Advice)
+    api = plugable.API(Command, Object, Method, Backend, Updater, Advice)
     if mode is not None:
         api.env.mode = mode
     assert mode != 'production'
diff --git a/ipalib/frontend.py b/ipalib/frontend.py
index 4d0333e0d61cf1efef0673ef2c2928ac5fff5679..76c53eba5de8896a79f7eae90a3e51700849ed9d 100644
--- a/ipalib/frontend.py
+++ b/ipalib/frontend.py
@@ -1126,7 +1126,6 @@ class Object(HasParam):
     # Create stubs for attributes that are set in _on_finalize()
     backend = Plugin.finalize_attr('backend')
     methods = Plugin.finalize_attr('methods')
-    properties = Plugin.finalize_attr('properties')
     params = Plugin.finalize_attr('params')
     primary_key = Plugin.finalize_attr('primary_key')
     params_minus_pk = Plugin.finalize_attr('params_minus_pk')
@@ -1139,9 +1138,6 @@ def _on_finalize(self):
         self.methods = NameSpace(
             self.__get_attrs('Method'), sort=False, name_attr='attr_name'
         )
-        self.properties = NameSpace(
-            self.__get_attrs('Property'), sort=False, name_attr='attr_name'
-        )
         self._create_param_namespace('params')
         pkeys = filter(lambda p: p.primary_key, self.params())
         if len(pkeys) > 1:
@@ -1196,25 +1192,19 @@ def get_params(self):
         """
         This method gets called by `HasParam._create_param_namespace()`.
         """
-        props = self.properties.__todict__()
         for spec in self._get_param_iterable('params'):
             if type(spec) is str:
                 key = spec.rstrip('?*+')
             else:
                 assert isinstance(spec, Param)
                 key = spec.name
-            if key in props:
-                yield props.pop(key).param
-            else:
-                yield create_param(spec)
+            yield create_param(spec)
         def get_key(p):
             if p.param.required:
                 if p.param.default_from is None:
                     return 0
                 return 1
             return 2
-        for prop in sorted(props.itervalues(), key=get_key):
-            yield prop.param
 
 
 class Attribute(Plugin):
@@ -1249,8 +1239,7 @@ class Attribute(Plugin):
     'add'
 
     In practice the `Attribute` class is not used directly, but rather is
-    only the base class for the `Method` and `Property` classes.  Also see
-    the `Object` class.
+    only the base class for the `Method` class.  Also see the `Object` class.
     """
     finalize_early = False
 
@@ -1350,8 +1339,7 @@ class Method(Attribute, Command):
     {'result': 'Added the user!'}
 
     The `Attribute` base class implements the naming convention for the
-    attribute-to-object association.  Also see the `Object` and the
-    `Property` classes.
+    attribute-to-object association.  Also see the `Object` class.
     """
     extra_options_first = False
     extra_args_first = False
@@ -1373,45 +1361,6 @@ def get_output_params(self):
             yield param
 
 
-class Property(Attribute):
-    klass = Str
-    default = None
-    default_from = None
-    normalizer = None
-
-    def __init__(self):
-        super(Property, self).__init__()
-        # FIXME: This is a hack till Param.label is updated to require a
-        # LazyText instance:
-        self.label = None
-        self.rules = tuple(
-            sorted(self.__rules_iter(), key=lambda f: getattr(f, '__name__'))
-        )
-        self.kwargs = tuple(
-            sorted(self.__kw_iter(), key=lambda keyvalue: keyvalue[0])
-        )
-        kw = dict(self.kwargs)
-        self.param = self.klass(self.attr_name, *self.rules, **kw)
-
-    def __kw_iter(self):
-        for (key, kind, default) in self.klass.kwargs:
-            if getattr(self, key, None) is not None:
-                yield (key, getattr(self, key))
-
-    def __rules_iter(self):
-        """
-        Iterates through the attributes in this instance to retrieve the
-        methods implementing validation rules.
-        """
-        for name in dir(self.__class__):
-            if name.startswith('_'):
-                continue
-            base_attr = getattr(self.__class__, name)
-            if is_rule(base_attr):
-                attr = getattr(self, name)
-                if is_rule(attr):
-                    yield attr
-
 class Updater(Method):
     """
     An LDAP update with an associated object (always update).
diff --git a/ipatests/test_ipalib/test_frontend.py b/ipatests/test_ipalib/test_frontend.py
index ce943a7e97287e98923c6ada240b5ca65ff77e95..c77783655efcb1fb92f306527ab06bec6f89ac6f 100644
--- a/ipatests/test_ipalib/test_frontend.py
+++ b/ipatests/test_ipalib/test_frontend.py
@@ -861,7 +861,6 @@ def test_class(self):
         """
         assert self.cls.backend is None
         assert self.cls.methods is None
-        assert self.cls.properties is None
         assert self.cls.params is None
         assert self.cls.params_minus_pk is None
         assert self.cls.takes_params == tuple()
@@ -873,10 +872,8 @@ def test_init(self):
         o = self.cls()
         assert o.backend is None
         assert o.methods is None
-        assert o.properties is None
         assert o.params is None
         assert o.params_minus_pk is None
-        assert o.properties is None
 
     def test_set_api(self):
         """
@@ -906,23 +903,15 @@ def get_attributes(cnt, format):
                     yield DummyAttribute(name, format % i)
 
         cnt = 10
-        formats = dict(
-            methods='method_%d',
-            properties='property_%d',
-        )
-
+        methods_format = 'method_%d'
 
         _d = dict(
             Method=plugable.NameSpace(
-                get_attributes(cnt, formats['methods'])
-            ),
-            Property=plugable.NameSpace(
-                get_attributes(cnt, formats['properties'])
+                get_attributes(cnt, methods_format)
             ),
         )
         api = plugable.MagicDict(_d)
         assert len(api.Method) == cnt * 3
-        assert len(api.Property) == cnt * 3
 
         class user(self.cls):
             pass
@@ -931,19 +920,19 @@ class user(self.cls):
         o = user()
         o.set_api(api)
         assert read_only(o, 'api') is api
-        for name in ['methods', 'properties']:
-            namespace = getattr(o, name)
-            assert isinstance(namespace, plugable.NameSpace)
-            assert len(namespace) == cnt
-            f = formats[name]
-            for i in xrange(cnt):
-                attr_name = f % i
-                attr = namespace[attr_name]
-                assert isinstance(attr, DummyAttribute)
-                assert attr is getattr(namespace, attr_name)
-                assert attr.obj_name == 'user'
-                assert attr.attr_name == attr_name
-                assert attr.name == '%s_%s' % ('user', attr_name)
+
+        namespace = o.methods
+        assert isinstance(namespace, plugable.NameSpace)
+        assert len(namespace) == cnt
+        f = methods_format
+        for i in xrange(cnt):
+            attr_name = f % i
+            attr = namespace[attr_name]
+            assert isinstance(attr, DummyAttribute)
+            assert attr is getattr(namespace, attr_name)
+            assert attr.obj_name == 'user'
+            assert attr.attr_name == attr_name
+            assert attr.name == '%s_%s' % ('user', attr_name)
 
         # Test params instance attribute
         o = self.cls()
@@ -1147,42 +1136,3 @@ class user_add(self.cls):
         assert o.name == 'user_add'
         assert o.obj_name == 'user'
         assert o.attr_name == 'add'
-
-
-class test_Property(ClassChecker):
-    """
-    Test the `ipalib.frontend.Property` class.
-    """
-    _cls = frontend.Property
-
-    def get_subcls(self):
-        """
-        Return a standard subclass of `ipalib.frontend.Property`.
-        """
-        class user_givenname(self.cls):
-            'User first name'
-
-            @frontend.rule
-            def rule0_lowercase(self, value):
-                if not value.islower():
-                    return 'Must be lowercase'
-        return user_givenname
-
-    def test_class(self):
-        """
-        Test the `ipalib.frontend.Property` class.
-        """
-        assert self.cls.__bases__ == (frontend.Attribute,)
-        assert self.cls.klass is parameters.Str
-
-    def test_init(self):
-        """
-        Test the `ipalib.frontend.Property.__init__` method.
-        """
-        o = self.subcls()
-        assert len(o.rules) == 1
-        assert o.rules[0].__name__ == 'rule0_lowercase'
-        param = o.param
-        assert isinstance(param, parameters.Str)
-        assert param.name == 'givenname'
-        assert unicode(param.doc) == u'User first name'
diff --git a/make-lint b/make-lint
index bbe3f32e45705d5051246d5008e98dfd9326c47a..40483a64baa0f2d41563ca57ce12af4b4de200b0 100755
--- a/make-lint
+++ b/make-lint
@@ -49,8 +49,8 @@ IGNORE_PATHS = ('build', 'rpmbuild', 'dist', 'install/po/test_i18n.py',
     'lite-server.py', 'make-lint', 'make-test', 'ipatests')
 
 class IPATypeChecker(TypeChecker):
-    NAMESPACE_ATTRS = ['Command', 'Object', 'Method', 'Property', 'Backend',
-        'Updater', 'Advice']
+    NAMESPACE_ATTRS = ['Command', 'Object', 'Method', 'Backend', 'Updater',
+        'Advice']
     LOGGING_ATTRS = ['log', 'debug', 'info', 'warning', 'error', 'exception',
         'critical']
 
-- 
1.8.5.3

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to