Giter Site home page Giter Site logo

maps's People

Contributors

jmaroeder avatar pcattori avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

Forkers

xgid

maps's Issues

What about __slots__

Mapping from standart collections has empty __slots__ = ().
I think it'll be fine to add slots for FrozenMap and others.
For FrozenMap:

__slots__ = [
    '_data',
    '_hash'
]

exec can't handle certain field names beyond keywords

The way namedfixedkeymap and namedfrozenmap are created in the current version of code, there are a couple additional field names that aren't supported beyond what are already accounted for in the _validate_name method.

The template code is:

def __init__(self, {args}):
    super(type(self), self).__init__()
    self._data = collections.OrderedDict({kwargs})

Because each of the field names gets inserted into {args}, the following field names are forbidden but not currently caught:

  • type
  • self
  • collections

Here's code demonstrating each of the errors:

>>> Foo = maps.namedfrozen('Foo', ['type'])

>>> foo = Foo('abc')
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-58-eb714c1f9e6f> in <module>()
----> 1 foo = Foo('abc')

<string> in __init__(self, type)

TypeError: 'str' object is not callable

>>> Bar = maps.namedfrozen('Bar', ['self'])
Traceback (most recent call last):

  File "/Users/jamesallen/.pyenv/versions/3.6.1/envs/cf2-local/lib/python3.6/site-packages/IPython/core/interactiveshell.py", line 2862, in run_code
    exec(code_obj, self.user_global_ns, self.user_ns)

  File "<ipython-input-59-53de955fd15f>", line 1, in <module>
    Bar = maps.namedfrozen('Bar', ['self'])

  File "/Users/jamesallen/.pyenv/versions/3.6.1/envs/cf2-local/lib/python3.6/site-packages/maps/__init__.py", line 29, in namedfrozen
    return NamedFrozenMapMeta(typename, fields)

  File "/Users/jamesallen/.pyenv/versions/3.6.1/envs/cf2-local/lib/python3.6/site-packages/maps/namedfrozenmap.py", line 104, in __new__
    exec(template.format(args=args, kwargs=kwargs), namespace)

  File "<string>", line 1
SyntaxError: duplicate argument 'self' in function definition


>>> Baz = maps.namedfrozen('Baz', ['collections'])

>>> baz = Baz('abc')
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-61-10871cae25dc> in <module>()
----> 1 baz = Baz('abc')

<string> in __init__(self, collections)

AttributeError: 'str' object has no attribute 'OrderedDict'

The simplest fix is to disallow these field names, but it also shouldn't be much more work to come up with unique identifiers for self, type, and collections. I'll look into it and submit a PR shortly

user-defined defaults for fields

maybe like this:


import maps
# namedfrozen(typename, fields, defaults)
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue', 'alpha'], defaults=dict(alpha=0))
...
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue', 'alpha'], defaults={'alpha': 0})

but this could break the rule of "positional args first, then key word args" eg. if you define defaults with gaps between them


  1. or a little more DRY
import maps
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue'], dict(alpha=0))

but need to be careful about ordering of kwargs
^ actually, this is again similar to function def notation, where order of kwargs is not that important. though the issue is that the user may not know in what order those kwargs got defined. In Python 3, we can avoid this via the bare * are keyword-only params. But in python 2, this is trickier

# in python3.6+ kwargs order is preserved
import collections
import maps
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue'], defaults=collections.OrderedDict(alpha=0))
# or without depending on collections.OrderedDict
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue'], defaults=[('alpha', 0)])

^ this is similar to function definition notation where positional args come before keyword args.


import maps
# namedfrozen(typename, fields) where fields can specify defaults
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue', ('alpha', 0)])

  1. or simply let the user define a function:
import maps
# namedfrozen(typename, fields) where fields can specify defaults
RGB = maps.namedfrozen('RGB', ['red', 'green', 'blue', 'alpha'])
def rgb(red, green, blue, alpha=0):
    return RGB(red, green, blue, alpha)

tag releases on github

it's way easier for package maintainers in distros to take archive from github than from PyPI

Subclassing NamedDict leads to infinite recursion in __repr__

Attempting to subclass NamedDict leads to an infinite recursion error when attempting to print out the repr of an instance of the class. This is due to the use of type(self) in the super call.

The docs address this (http://maps.readthedocs.io/en/latest/user/design.html#class-vs-function), but I think there is a use case for being able to subclass NamedDict - specifically, if you want to be able to distinguish between types of NamedDict using isinstance, and/or if you want to add specific functionality to a bag of data.

NamedDict is a trivial fix - just change the occurrences of super(type(self), self) to super(NamedDict, self).

However, the metaclasses NamedFrozenMapMeta and NamedFixedKeyMapMeta still contain occurrences of super(type(self), self). Due to the way the subclasses are created (using exec), it's not immediately apparent to me how one would address this issue - there seems to be a chicken and egg problem in we need to pass a reference to the class into the namespace, but we don't have that reference until it's created. I tried attaching __init__ to the class after creation via type.__new__, but that led to other issues:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 2, in __init__
  File "/Users/jamesallen/src/github.com/jamesmallen/maps/maps/frozenmap.py", line 28, in __init__
    self._data = dict(*args, **kwargs)
  File "/Users/jamesallen/src/github.com/jamesmallen/maps/maps/namedfrozenmap.py", line 66, in _setattr
    super(NamedFrozenMapMeta, self).__setattr__(name, value)
TypeError: super(type, obj): obj must be an instance or subtype of type

recursive?

I was wondering if you can export a recursive version that can handle recurse into dicts and lists.

Here is an example structure I am working with:
screen shot 2017-03-27 at 3 59 36 pm

I envision this to be similar to the fromJS function from immutableJS: http://facebook.github.io/immutable-js/docs/#/fromJS

EDIT: I meant to use FrozenMap in the screenshot above.

collections.defaultdict causes FrozenMap.recurse() to fail

$ python
Python 3.7.3 (default, Apr  3 2019, 19:16:38) 
[GCC 8.0.1 20180414 (experimental) [trunk revision 259383]] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import maps
>>> from collections import defaultdict
>>> maps.FrozenMap.recurse({'a': {'b': 'c'}})
FrozenMap({'a': FrozenMap({'b': 'c'})})
>>> d = defaultdict(dict)
>>> d['a']['b'] = 'c'
>>> d
defaultdict(<class 'dict'>, {'a': {'b': 'c'}})
>>> maps.FrozenMap.recurse(d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/crushingismybusiness/.local/share/virtualenvs/sample_service-cH3G9tDP/lib/python3.7/site-packages/maps/frozenmap.py", line 44, in recurse
    return utils._recurse(obj, map_fn=cls, list_fn=list_fn, object_fn=object_fn)
  File "/home/crushingismybusiness/.local/share/virtualenvs/sample_service-cH3G9tDP/lib/python3.7/site-packages/maps/utils.py", line 52, in _recurse
    return map_fn(**cls((k, _recurse(v, **kwargs)) for k,v in obj.items()))
TypeError: first argument must be callable or None

[Feature Request] FrozenMap.update

Hi,
Would it be possible to add a binary operation between FrozenMap instances that merges them?
For example, it would be nice for the following code to work:

import maps
x = maps.FrozenMap({'a': 2, 'b': 4})
y = maps.FrozenMap({'b': 5, 'c': 6})
assert x.update(y) == maps.FrozenMap({'a': 2, 'b': 5, 'c': 6})
assert x['b'] == 4
assert 'c' not in x

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.