The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/pylxd/pull/119

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
The best thing about a good API is that it's guessable, and that the process of extending it has a clear path. The manager methods we provided were nice, but it quickly became clear in #115 that we needed a better/quicker/cleaner way of adding a manager. This simplifies the process greatly.
From 727643767764fd5551fe59960ec6162ce5346c33 Mon Sep 17 00:00:00 2001
From: Paul Hummer <p...@eventuallyanyway.com>
Date: Mon, 30 May 2016 15:14:07 -0600
Subject: [PATCH] Refactor the manager protocol to be a little cleaner

---
 pylxd/client.py    | 95 +++---------------------------------------------------
 pylxd/container.py | 12 ++-----
 pylxd/managers.py  | 45 ++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 100 deletions(-)
 create mode 100644 pylxd/managers.py

diff --git a/pylxd/client.py b/pylxd/client.py
index bd097a2..9b1d115 100644
--- a/pylxd/client.py
+++ b/pylxd/client.py
@@ -11,7 +11,6 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
-import functools
 import os
 
 try:
@@ -22,11 +21,7 @@
 import requests
 import requests_unixsocket
 
-from pylxd import exceptions
-from pylxd.container import Container
-from pylxd.image import Image
-from pylxd.operation import Operation
-from pylxd.profile import Profile
+from pylxd import exceptions, managers
 
 requests_unixsocket.monkeypatch()
 
@@ -114,86 +109,6 @@ class Client(object):
             >>> print api.containers['test'].get().json()
     """
 
-    class Containers(object):
-        """
-        Manager for :class:`~pylxd.container.Container` of a :class:`Client`.
-
-        .. attribute:: all
-
-            Partial of :meth:`Container.all <pylxd.container.Container.all>`,
-            calling it without argument returns the same as calling that method
-            with just the client argument.
-
-        .. attribute:: get
-
-            Partial of of :meth:`Container.get
-            <pylxd.container.Container.get>`.
-
-        .. attribute:: create
-
-            Partial of of :meth:`Container.create
-            <pylxd.container.Container.create>`.
-        """
-        def __init__(self, client):
-            self.get = functools.partial(Container.get, client)
-            self.all = functools.partial(Container.all, client)
-            self.create = functools.partial(Container.create, client)
-
-    class Images(object):
-        """
-        Manager for :py:class:`~pylxd.image.Image` of a :class:`Client`.
-
-        .. attribute:: all
-
-            Partial of :meth:`Image.all <pylxd.image.Image.all>`,
-
-        .. attribute:: get
-
-            Partial of of :meth:`Image.get <pylxd.image.Image.get>`.
-
-        .. attribute:: create
-
-            Partial of of :meth:`Image.create <pylxd.image.Image.create>`.
-        """
-        def __init__(self, client):
-            self.get = functools.partial(Image.get, client)
-            self.all = functools.partial(Image.all, client)
-            self.create = functools.partial(Image.create, client)
-
-    class Operations(object):
-        """
-        Manager for :class:`~pylxd.operation.Operation` of a :class:`Client`.
-
-        .. attribute:: get
-
-            Partial of of :meth:`Operation.get
-            <pylxd.operation.Operation.get>`.
-        """
-        def __init__(self, client):
-            self.get = functools.partial(Operation.get, client)
-
-    class Profiles(object):
-        """
-        Manager for :py:class:`~pylxd.profile.Profile` of a :class:`Client`.
-
-        .. attribute:: all
-
-            Partial of :meth:`Profile.all <pylxd.profile.Profile.all>`,
-
-        .. attribute:: get
-
-            Partial of of :meth:`Profile.get <pylxd.profile.Profile.get>`.
-
-        .. attribute:: create
-
-            Partial of of :meth:`Profile.create
-            <pylxd.profile.Profile.create>`.
-        """
-        def __init__(self, client):
-            self.get = functools.partial(Profile.get, client)
-            self.all = functools.partial(Profile.all, client)
-            self.create = functools.partial(Profile.create, client)
-
     def __init__(self, endpoint=None, version='1.0', cert=None, verify=True):
         if endpoint is not None:
             self.api = _APINode(endpoint, cert=cert, verify=verify)
@@ -219,7 +134,7 @@ def __init__(self, endpoint=None, version='1.0', cert=None, 
verify=True):
                 requests.exceptions.InvalidURL):
             raise exceptions.ClientConnectionFailed()
 
-        self.containers = self.Containers(self)
-        self.images = self.Images(self)
-        self.operations = self.Operations(self)
-        self.profiles = self.Profiles(self)
+        self.containers = managers.ContainerManager(self)
+        self.images = managers.ImageManager(self)
+        self.operations = managers.OperationManager(self)
+        self.profiles = managers.ProfileManager(self)
diff --git a/pylxd/container.py b/pylxd/container.py
index 66a751b..ce9de61 100644
--- a/pylxd/container.py
+++ b/pylxd/container.py
@@ -11,11 +11,9 @@
 #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 #    License for the specific language governing permissions and limitations
 #    under the License.
-import functools
-
 import six
 
-from pylxd import exceptions, mixin
+from pylxd import exceptions, managers, mixin
 from pylxd.deprecation import deprecated
 from pylxd.operation import Operation
 
@@ -33,12 +31,6 @@ class Container(mixin.Waitable, mixin.Marshallable):
     via `Client.containers.create`.
     """
 
-    class Snapshots(object):
-        def __init__(self, client, container):
-            self.get = functools.partial(Snapshot.get, client, container)
-            self.all = functools.partial(Snapshot.all, client, container)
-            self.create = functools.partial(Snapshot.create, client, container)
-
     __slots__ = [
         '_client',
         'architecture', 'config', 'created_at', 'devices', 'ephemeral',
@@ -88,7 +80,7 @@ def __init__(self, **kwargs):
         for key, value in six.iteritems(kwargs):
             setattr(self, key, value)
 
-        self.snapshots = self.Snapshots(self._client, self)
+        self.snapshots = managers.SnapshotManager(self._client, self)
 
     def fetch(self):
         """Reload the container information."""
diff --git a/pylxd/managers.py b/pylxd/managers.py
new file mode 100644
index 0000000..be33b7b
--- /dev/null
+++ b/pylxd/managers.py
@@ -0,0 +1,45 @@
+import functools
+import importlib
+import inspect
+
+
+class BaseManager(object):
+    """A BaseManager class for handling collection operations."""
+
+    @property
+    def manager_for(self):
+        raise AttributeError(
+            "Manager class requires 'manager_for' attribute")
+
+    def __init__(self, *args, **kwargs):
+        manager_for = self.manager_for
+        module = '.'.join(manager_for.split('.')[0:-1])
+        obj = manager_for.split('.')[-1]
+        target_module = importlib.import_module(module)
+        target = getattr(target_module, obj)
+
+        methods = inspect.getmembers(target, predicate=inspect.ismethod)
+        for name, method in methods:
+            func = functools.partial(method, *args, **kwargs)
+            setattr(self, name, func)
+        return super(BaseManager, self).__init__()
+
+
+class ContainerManager(BaseManager):
+    manager_for = 'pylxd.container.Container'
+
+
+class ImageManager(BaseManager):
+    manager_for = 'pylxd.image.Image'
+
+
+class ProfileManager(BaseManager):
+    manager_for = 'pylxd.profile.Profile'
+
+
+class OperationManager(BaseManager):
+    manager_for = 'pylxd.operation.Operation'
+
+
+class SnapshotManager(BaseManager):
+    manager_for = 'pylxd.container.Snapshot'
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to