import logging
import attrdict as ad
import enum as enum
import collections as coll

class WrapperBase(ad.AttrDict):
  """
  Base for our classes.
  Enhancements over AttrDict:
    - Specifies a list of valid properties. This is definitely NOT pythonic,
      but helps with self-documenting code. Otherwise, people want to use the
      class and they have no idea what the properties are. This also enables
      the following nice properties:
        - Read-only properties. We can mark the valid properties as read-only,
          which means that we can 
        - Support inline completion in ipython (my favorite feature!).
        - Support dependencies (properties that are automatically populated
          based on other properties for precomputation)
  """
  """
    All subclasses should define:
    - name: the name to use instead of AttrDict in the string representation
    - properties: a map of valid properties, with a value indicating whether
      they are read-only or not
  """
  Access = enum.Enum("PropertyAccess", "RO RW")


  def __init__(self, *args, **kwargs):
    super(WrapperBase, self).__init__(*args, **kwargs)

  def __dir__(self):
    return dir(super) + self.props.keys()

  def __getattr__(self, key):
    if key in self.props:
        # This code is copied from the base Attr code.
        # This allows us to pass the key into _build as well instead of only the value
        if key not in self or not self._valid_name(key):
            raise AttributeError(
                "'{cls}' instance has no attribute '{name}'".format(
                    cls=self.__class__.__name__, name=key
                )
            )
        return self._build(key, self[key])
    else:
        raise AttributeError("property %s is not defined for %s" % (key, self.__class__.__name__))

  def __setattr__(self, key, value):
    if key in self.props:
        if self.props[key] == WrapperBase.Access.RW:
            return super(WrapperBase, self).__setattr__(key, value)
        else:
            raise AttributeError("property %s is read-only" % key)
    else:
        raise AttributeError("property %s is not defined for %s" % (key, self.__class__.__name__))

  def __repr__(self):
    """
    We would like to use a name for the class that is different from _AttrDict_.
    Unfortunately, the AttrDict name is hardcoded in the parent class, which
    makes sense since they don't want to do a lot of setup, but it means that we
    can't easily outgrow it.

    Out of the three options:
    1. Modify the parent class
    2. Duplicate the parent class
    3. Replace the string here, we have chosen to go with (3) for greatest cleanliness.
    """
    parentResult = super(WrapperBase, self).__repr__()
    return parentResult.replace("AttrDict", self.__class__.__name__)

  def __call__(self, key):
    print("_call called with %s, %s" % (self, key))
    return super(WrapperBase, self).__call__(key)

  @staticmethod
  def _get_class(wrapper_name):
    import importlib

    # Convention is to name the module with the wrapper name in lower case, and
    # then have a class in the module with the name.
    # e.g. The Location class will be in a module named location.
    wrapperModule = importlib.import_module("emission.core.wrapper.%s" % (wrapper_name.lower()))
    return getattr(wrapperModule, wrapper_name)

  def _build(self, key, obj):
    # print("_build called with %s, %s, %s" % (self, key, obj))
    if isinstance(obj, coll.Mapping):
        key_class = self._get_class(key)
        return key_class._constructor(obj, self._configuration())
    else:
        return super(WrapperBase, self)._build(obj)

@@ -812,94 +812,12 @@
   - 
-name: the name to use instead of AttrDict in the string representation%0A    - propertie
+prop
 s: a
@@ -906,16 +906,154 @@
  or not%0A
+    - _populateDependencies: a method to pre-populate fields based on the%0A      current field. This can be empty, and implemented by pass%0A
   %22%22%22%0A  
@@ -1193,16 +1193,49 @@
 *kwargs)
+%0A    self._populateDependencies()
 %0A%0A  def 
@@ -1318,24 +1318,86 @@
 self, key):%0A
+    # logging.debug(%22__getattr__ called for key = %25s%22 %25 key)%0A%0A
     if key i
@@ -1794,32 +1794,81 @@
 )%0A            )%0A
+        # logging.debug(%22Returning self._build%22)%0A
         return s
@@ -3466,17 +3466,16 @@
 r.%25s%22 %25 
-(
 wrapper_
@@ -3482,18 +3482,75 @@
 name
-.lower()))
+)%0A    wrapperClassName = wrapper_name%5B0%5D.upper() + wrapper_name%5B1:%5D
 %0A   
@@ -3583,26 +3583,30 @@
 ule, wrapper
-_n
+ClassN
 ame)%0A%0A  def 
@@ -3635,21 +3635,29 @@
 :%0A    # 
-print
+logging.debug
 (%22_build
@@ -3776,24 +3776,78 @@
 _class(key)%0A
+        # logging.debug(%22key_class = %25s%22 %25 key_class)%0A
         retu

Fix to the naming convention for wrapper classes