Skip to content

Instantly share code, notes, and snippets.

@effigies
Created July 30, 2015 22:31
Show Gist options
  • Select an option

  • Save effigies/9c64e743f8c60a22bc70 to your computer and use it in GitHub Desktop.

Select an option

Save effigies/9c64e743f8c60a22bc70 to your computer and use it in GitHub Desktop.

Revisions

  1. effigies created this gist Jul 30, 2015.
    68 changes: 68 additions & 0 deletions TypedDict.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    #!python3

    class TypedDict(dict):
    keytype = valtype = keymap = valmap = valid_keys = typemap = None
    def __init__(self, mapping=None, **kwargs):
    if self.typemap is not None and self.valid_keys is None:
    self.valid_keys = set(self.typemap)

    super(TypedDict, self).__init__()
    if mapping is None:
    mapping = kwargs.items()
    elif isinstance(mapping, dict):
    mapping = mapping.items()

    for k, v in mapping:
    self[k] = v

    def __setitem__(self, key, val):
    if self.keytype is not None and type(key) is not self.keytype:
    if self.keymap is not None and type(key) in self.keymap:
    key = self.keymap[type(key)](key)
    else:
    try:
    key = self.keytype(key)
    except TypeError:
    raise TypeError('Keys must be of type {!r}'.format(
    self.keytype))
    if self.valtype is not None and type(val) is not self.valtype:
    if self.valmap is not None and type(val) in self.valmap:
    val = self.valmap[type(val)](val)
    else:
    try:
    val = self.valtype(val)
    except TypeError:
    raise TypeError('Values must be of type {!r}'.format(
    self.valtype))

    if self.typemap is not None and key in self.typemap:
    val = self.typemap[key](val)

    if self.valid_keys is not None and key not in self.valid_keys:
    raise KeyError('Invalid key')
    super(TypedDict, self).__setitem__(key, val)


    class BytesIntMap(TypedDict):
    keytype = bytes
    valtype = int
    keymap = {str: str.encode}


    class ExampleModel(TypedDict):
    class File(TypedDict):
    class Permission(TypedDict):
    valid_keys = {'r', 'w', 'x'}
    valtype = bool
    keytype = str
    typemap = {'mtime': int, 'perm': Permission}
    class User(TypedDict):
    keytype = str
    valid_keys = {'groups'}
    valtype = list
    typemap = {'files': File, 'users': User}

    model = ExampleModel(
    files={'/home': {'mtime': 0, 'perm': {'r': True, 'w': False}},
    '/tmp': {'mtime': 0, 'perm': {'r': True, 'w': True}}},
    users={'root': {'groups': ['root', 'wheel']}})