Repository: googleapis/google-cloud-python

Issue:
Move nested 'storage.acl.ACL.Entity' to module scope
Nested classes don't feel right, here.



Discussion:

Resolving patch:
diff --git a/gcloud/storage/acl.py b/gcloud/storage/acl.py
--- a/gcloud/storage/acl.py
+++ b/gcloud/storage/acl.py
@@ -28,14 +28,14 @@
 And you are able to ``grant`` and ``revoke`` the following roles:
 
 - **Reading**:
-  :func:`ACL.Entity.grant_read` and :func:`ACL.Entity.revoke_read`
+  :func:`_ACLEntity.grant_read` and :func:`_ACLEntity.revoke_read`
 - **Writing**:
-  :func:`ACL.Entity.grant_write` and :func:`ACL.Entity.revoke_write`
+  :func:`_ACLEntity.grant_write` and :func:`_ACLEntity.revoke_write`
 - **Owning**:
-  :func:`ACL.Entity.grant_owner` and :func:`ACL.Entity.revoke_owner`
+  :func:`_ACLEntity.grant_owner` and :func:`_ACLEntity.revoke_owner`
 
 You can use any of these like any other factory method
-(these happen to be :class:`ACL.Entity` factories)::
+(these happen to be :class:`_ACLEntity` factories)::
 
   >>> acl.user('me@example.org').grant_read()
   >>> acl.all_authenticated().grant_write()
@@ -72,110 +72,110 @@
 """
 
 
-class ACL(object):
-    """Container class representing a list of access controls."""
+class _ACLEntity(object):
+    """Class representing a set of roles for an entity.
+
+    This is a helper class that you likely won't ever construct
+    outside of using the factor methods on the :class:`ACL` object.
+    """
 
     READER_ROLE = 'READER'
     WRITER_ROLE = 'WRITER'
     OWNER_ROLE = 'OWNER'
 
-    class Entity(object):
-        """Class representing a set of roles for an entity.
+    def __init__(self, entity_type, identifier=None):
+        """Entity constructor.
 
-        This is a helper class that you likely won't ever construct
-        outside of using the factor methods on the :class:`ACL` object.
-        """
-
-        def __init__(self, entity_type, identifier=None):
-            """Entity constructor.
+        :type entity_type: string
+        :param entity_type: The type of entity (ie, 'group' or 'user').
 
-            :type entity_type: string
-            :param entity_type: The type of entity (ie, 'group' or 'user').
+        :type identifier: string
+        :param identifier: The ID or e-mail of the entity. For the special
+                           entity types (like 'allUsers') this is optional.
+        """
+        self.identifier = identifier
+        self.roles = set([])
+        self.type = entity_type
 
-            :type identifier: string
-            :param identifier: The ID or e-mail of the entity. For the special
-                               entity types (like 'allUsers') this is optional.
-            """
+    def __str__(self):
+        if not self.identifier:
+            return str(self.type)
+        else:
+            return '{self.type}-{self.identifier}'.format(self=self)
 
-            self.identifier = identifier
-            self.roles = set([])
-            self.type = entity_type
+    def __repr__(self):
+        return '<ACL Entity: {self} ({roles})>'.format(
+            self=self, roles=', '.join(self.roles))
 
-        def __str__(self):
-            if not self.identifier:
-                return str(self.type)
-            else:
-                return '{self.type}-{self.identifier}'.format(self=self)
+    def get_roles(self):
+        """Get the list of roles permitted by this entity.
 
-        def __repr__(self):
-            return '<ACL Entity: {self} ({roles})>'.format(
-                self=self, roles=', '.join(self.roles))
+        :rtype: list of strings
+        :returns: The list of roles associated with this entity.
+        """
 
-        def get_roles(self):
-            """Get the list of roles permitted by this entity.
+        return self.roles
 
-            :rtype: list of strings
-            :returns: The list of roles associated with this entity.
-            """
+    def grant(self, role):
+        """Add a role to the entity.
 
-            return self.roles
+        :type role: string
+        :param role: The role to add to the entity.
 
-        def grant(self, role):
-            """Add a role to the entity.
+        :rtype: :class:`_ACLEntity`
+        :returns: The entity class.
+        """
 
-            :type role: string
-            :param role: The role to add to the entity.
+        self.roles.add(role)
+        return self
 
-            :rtype: :class:`ACL.Entity`
-            :returns: The entity class.
-            """
+    def revoke(self, role):
+        """Remove a role from the entity.
 
-            self.roles.add(role)
-            return self
+        :type role: string
+        :param role: The role to remove from the entity.
 
-        def revoke(self, role):
-            """Remove a role from the entity.
+        :rtype: :class:`_ACLEntity`
+        :returns: The entity class.
+        """
 
-            :type role: string
-            :param role: The role to remove from the entity.
+        if role in self.roles:
+            self.roles.remove(role)
+        return self
 
-            :rtype: :class:`ACL.Entity`
-            :returns: The entity class.
-            """
+    def grant_read(self):
+        """Grant read access to the current entity."""
 
-            if role in self.roles:
-                self.roles.remove(role)
-            return self
+        return self.grant(_ACLEntity.READER_ROLE)
 
-        def grant_read(self):
-            """Grant read access to the current entity."""
+    def grant_write(self):
+        """Grant write access to the current entity."""
 
-            return self.grant(ACL.READER_ROLE)
+        return self.grant(_ACLEntity.WRITER_ROLE)
 
-        def grant_write(self):
-            """Grant write access to the current entity."""
+    def grant_owner(self):
+        """Grant owner access to the current entity."""
 
-            return self.grant(ACL.WRITER_ROLE)
+        return self.grant(_ACLEntity.OWNER_ROLE)
 
-        def grant_owner(self):
-            """Grant owner access to the current entity."""
+    def revoke_read(self):
+        """Revoke read access from the current entity."""
 
-            return self.grant(ACL.OWNER_ROLE)
+        return self.revoke(_ACLEntity.READER_ROLE)
 
-        def revoke_read(self):
-            """Revoke read access from the current entity."""
+    def revoke_write(self):
+        """Revoke write access from the current entity."""
 
-            return self.revoke(ACL.READER_ROLE)
+        return self.revoke(_ACLEntity.WRITER_ROLE)
 
-        def revoke_write(self):
-            """Revoke write access from the current entity."""
+    def revoke_owner(self):
+        """Revoke owner access from the current entity."""
 
-            return self.revoke(ACL.WRITER_ROLE)
+        return self.revoke(_ACLEntity.OWNER_ROLE)
 
-        def revoke_owner(self):
-            """Revoke owner access from the current entity."""
 
-            return self.revoke(ACL.OWNER_ROLE)
+class ACL(object):
+    """Container class representing a list of access controls."""
 
     def __init__(self):
         self.entities = {}
@@ -187,7 +187,7 @@ def __iter__(self):
                     yield {'entity': str(entity), 'role': role}
 
     def entity_from_dict(self, entity_dict):
-        """Build an ACL.Entity object from a dictionary of data.
+        """Build an _ACLEntity object from a dictionary of data.
 
         An entity is a mutable object
         that represents a list of roles
@@ -199,7 +199,7 @@ def entity_from_dict(self, entity_dict):
         :type entity_dict: dict
         :param entity_dict: Dictionary full of data from an ACL lookup.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An Entity constructed from the dictionary.
         """
 
@@ -217,7 +217,7 @@ def entity_from_dict(self, entity_dict):
             entity = self.entity(entity_type=entity_type,
                                  identifier=identifier)
 
-        if not isinstance(entity, ACL.Entity):
+        if not isinstance(entity, _ACLEntity):
             raise ValueError('Invalid dictionary: %s' % entity_dict)
 
         return entity.grant(role)
@@ -225,7 +225,7 @@ def entity_from_dict(self, entity_dict):
     def has_entity(self, entity):
         """Returns whether or not this ACL has any entries for an entity.
 
-        :type entity: :class:`ACL.Entity`
+        :type entity: :class:`_ACLEntity`
         :param entity: The entity to check for existence in this ACL.
 
         :rtype: bool
@@ -237,14 +237,14 @@ def has_entity(self, entity):
     def get_entity(self, entity, default=None):
         """Gets an entity object from the ACL.
 
-        :type entity: :class:`ACL.Entity` or string
+        :type entity: :class:`_ACLEntity` or string
         :param entity: The entity to get lookup in the ACL.
 
         :type default: anything
         :param default: This value will be returned if the entity
                         doesn't exist.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: The corresponding entity or the value provided
                   to ``default``.
         """
@@ -254,7 +254,7 @@ def get_entity(self, entity, default=None):
     def add_entity(self, entity):
         """Add an entity to the ACL.
 
-        :type entity: :class:`ACL.Entity`
+        :type entity: :class:`_ACLEntity`
         :param entity: The entity to add to this ACL.
         """
 
@@ -276,11 +276,11 @@ def entity(self, entity_type, identifier=None):
         :param identifier: The ID of the entity (if applicable).
                            This can be either an ID or an e-mail address.
 
-        :rtype: :class:`ACL.Entity`
-        :returns: A new Entity or a refernece to an existing identical entity.
+        :rtype: :class:`_ACLEntity`
+        :returns: A new Entity or a reference to an existing identical entity.
         """
 
-        entity = ACL.Entity(entity_type=entity_type, identifier=identifier)
+        entity = _ACLEntity(entity_type=entity_type, identifier=identifier)
         if self.has_entity(entity):
             entity = self.get_entity(entity)
         else:
@@ -293,7 +293,7 @@ def user(self, identifier):
         :type identifier: string
         :param identifier: An id or e-mail for this particular user.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An Entity corresponding to this user.
         """
 
@@ -305,7 +305,7 @@ def group(self, identifier):
         :type identifier: string
         :param identifier: An id or e-mail for this particular group.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An Entity corresponding to this group.
         """
 
@@ -317,7 +317,7 @@ def domain(self, domain):
         :type domain: string
         :param domain: The domain for this entity.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An entity corresponding to this domain.
         """
 
@@ -326,7 +326,7 @@ def domain(self, domain):
     def all(self):
         """Factory method for an Entity representing all users.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An entity representing all users.
         """
 
@@ -335,7 +335,7 @@ def all(self):
     def all_authenticated(self):
         """Factory method for an Entity representing all authenticated users.
 
-        :rtype: :class:`ACL.Entity`
+        :rtype: :class:`_ACLEntity`
         :returns: An entity representing all authenticated users.
         """
 
@@ -344,7 +344,7 @@ def all_authenticated(self):
     def get_entities(self):
         """Get a list of all Entity objects.
 
-        :rtype: list of :class:`ACL.Entity` objects
+        :rtype: list of :class:`_ACLEntity` objects
         :returns: A list of all Entity objects.
         """
 


Test patch:
diff --git a/gcloud/storage/test_acl.py b/gcloud/storage/test_acl.py
--- a/gcloud/storage/test_acl.py
+++ b/gcloud/storage/test_acl.py
@@ -1,11 +1,11 @@
 import unittest2
 
 
-class Test_ACL_Entity(unittest2.TestCase):
+class Test_ACLEntity(unittest2.TestCase):
 
     def _getTargetClass(self):
-        from gcloud.storage.acl import ACL
-        return ACL.Entity
+        from gcloud.storage.acl import _ACLEntity
+        return _ACLEntity
 
     def _makeOne(self, *args, **kw):
         return self._getTargetClass()(*args, **kw)
@@ -73,47 +73,41 @@ def test_revoke_hit(self):
         self.assertEqual(entity.get_roles(), set([ROLE2]))
 
     def test_grant_read(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
         entity.grant_read()
-        self.assertEqual(entity.get_roles(), set([ACL.READER_ROLE]))
+        self.assertEqual(entity.get_roles(), set([entity.READER_ROLE]))
 
     def test_grant_write(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
         entity.grant_write()
-        self.assertEqual(entity.get_roles(), set([ACL.WRITER_ROLE]))
+        self.assertEqual(entity.get_roles(), set([entity.WRITER_ROLE]))
 
     def test_grant_owner(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
         entity.grant_owner()
-        self.assertEqual(entity.get_roles(), set([ACL.OWNER_ROLE]))
+        self.assertEqual(entity.get_roles(), set([entity.OWNER_ROLE]))
 
     def test_revoke_read(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
-        entity.grant(ACL.READER_ROLE)
+        entity.grant(entity.READER_ROLE)
         entity.revoke_read()
         self.assertEqual(entity.get_roles(), set())
 
     def test_revoke_write(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
-        entity.grant(ACL.WRITER_ROLE)
+        entity.grant(entity.WRITER_ROLE)
         entity.revoke_write()
         self.assertEqual(entity.get_roles(), set())
 
     def test_revoke_owner(self):
-        from gcloud.storage.acl import ACL
         TYPE = 'type'
         entity = self._makeOne(TYPE)
-        entity.grant(ACL.OWNER_ROLE)
+        entity.grant(entity.OWNER_ROLE)
         entity.revoke_owner()
         self.assertEqual(entity.get_roles(), set())
 
@@ -208,10 +202,10 @@ def test_has_entity_miss_str(self):
         self.assertFalse(acl.has_entity('nonesuch'))
 
     def test_has_entity_miss_entity(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         TYPE = 'type'
         ID = 'id'
-        entity = ACL.Entity(TYPE, ID)
+        entity = _ACLEntity(TYPE, ID)
         acl = self._makeOne()
         self.assertFalse(acl.has_entity(entity))
 
@@ -234,10 +228,10 @@ def test_get_entity_miss_str_no_default(self):
         self.assertEqual(acl.get_entity('nonesuch'), None)
 
     def test_get_entity_miss_entity_no_default(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         TYPE = 'type'
         ID = 'id'
-        entity = ACL.Entity(TYPE, ID)
+        entity = _ACLEntity(TYPE, ID)
         acl = self._makeOne()
         self.assertEqual(acl.get_entity(entity), None)
 
@@ -247,11 +241,11 @@ def test_get_entity_miss_str_w_default(self):
         self.assertTrue(acl.get_entity('nonesuch', DEFAULT) is DEFAULT)
 
     def test_get_entity_miss_entity_w_default(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         DEFAULT = object()
         TYPE = 'type'
         ID = 'id'
-        entity = ACL.Entity(TYPE, ID)
+        entity = _ACLEntity(TYPE, ID)
         acl = self._makeOne()
         self.assertTrue(acl.get_entity(entity, DEFAULT) is DEFAULT)
 
@@ -270,11 +264,11 @@ def test_get_entity_hit_entity(self):
         self.assertTrue(acl.has_entity(entity))
 
     def test_add_entity_miss(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         TYPE = 'type'
         ID = 'id'
         ROLE = 'role'
-        entity = ACL.Entity(TYPE, ID)
+        entity = _ACLEntity(TYPE, ID)
         entity.grant(ROLE)
         acl = self._makeOne()
         acl.add_entity(entity)
@@ -283,12 +277,12 @@ def test_add_entity_miss(self):
         self.assertEqual(list(acl.get_entities()), [entity])
 
     def test_add_entity_hit(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         TYPE = 'type'
         ID = 'id'
         KEY = '%s-%s' % (TYPE, ID)
         ROLE = 'role'
-        entity = ACL.Entity(TYPE, ID)
+        entity = _ACLEntity(TYPE, ID)
         entity.grant(ROLE)
         acl = self._makeOne()
         before = acl.entity(TYPE, ID)
diff --git a/gcloud/storage/test_bucket.py b/gcloud/storage/test_bucket.py
--- a/gcloud/storage/test_bucket.py
+++ b/gcloud/storage/test_bucket.py
@@ -793,10 +793,10 @@ def test_clear_default_object_acl(self):
         self.assertEqual(kw[1]['query_params'], {'projection': 'full'})
 
     def test_make_public_defaults(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         NAME = 'name'
         before = {'acl': [], 'defaultObjectAcl': []}
-        permissive = [{'entity': 'allUsers', 'role': ACL.READER_ROLE}]
+        permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}]
         after = {'acl': permissive, 'defaultObjectAcl': []}
         connection = _Connection(after)
         bucket = self._makeOne(connection, NAME, before)
@@ -812,10 +812,10 @@ def test_make_public_defaults(self):
         self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
 
     def test_make_public_w_future(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         NAME = 'name'
         before = {'acl': [], 'defaultObjectAcl': []}
-        permissive = [{'entity': 'allUsers', 'role': ACL.READER_ROLE}]
+        permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}]
         after1 = {'acl': permissive, 'defaultObjectAcl': []}
         after2 = {'acl': permissive, 'defaultObjectAcl': permissive}
         connection = _Connection(after1, after2)
@@ -838,7 +838,7 @@ def test_make_public_w_future(self):
         self.assertEqual(kw[1]['query_params'], {'projection': 'full'})
 
     def test_make_public_recursive(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         from gcloud._testing import _Monkey
         from gcloud.storage import iterator
         from gcloud.storage import bucket as MUT
@@ -867,10 +867,11 @@ class _KeyIterator(iterator.KeyIterator):
             def get_items_from_response(self, response):
                 for item in response.get('items', []):
                     yield _Key(self.bucket, item['name'])
+
         NAME = 'name'
         KEY = 'key'
         before = {'acl': [], 'defaultObjectAcl': []}
-        permissive = [{'entity': 'allUsers', 'role': ACL.READER_ROLE}]
+        permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}]
         after = {'acl': permissive, 'defaultObjectAcl': []}
         connection = _Connection(after, {'items': [{'name': KEY}]})
         bucket = self._makeOne(connection, NAME, before)
diff --git a/gcloud/storage/test_key.py b/gcloud/storage/test_key.py
--- a/gcloud/storage/test_key.py
+++ b/gcloud/storage/test_key.py
@@ -572,10 +572,10 @@ def test_clear_acl(self):
         self.assertEqual(kw[0]['query_params'], {'projection': 'full'})
 
     def test_make_public(self):
-        from gcloud.storage.acl import ACL
+        from gcloud.storage.acl import _ACLEntity
         KEY = 'key'
         before = {'acl': []}
-        permissive = [{'entity': 'allUsers', 'role': ACL.READER_ROLE}]
+        permissive = [{'entity': 'allUsers', 'role': _ACLEntity.READER_ROLE}]
         after = {'acl': permissive}
         connection = _Connection(after)
         bucket = _Bucket(connection)