Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #85223 > unrolled thread

pymongo and attribute dictionaries

Started byTravis Griggs <travisgriggs@gmail.com>
First post2015-02-04 08:50 -0800
Last post2015-02-05 14:11 -0700
Articles 8 — 5 participants

Back to article view | Back to comp.lang.python


Contents

  pymongo and attribute dictionaries Travis Griggs <travisgriggs@gmail.com> - 2015-02-04 08:50 -0800
    Re: pymongo and attribute dictionaries Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-05 09:38 +1100
      Re: pymongo and attribute dictionaries Ian Kelly <ian.g.kelly@gmail.com> - 2015-02-04 17:19 -0700
        Re: pymongo and attribute dictionaries Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-05 12:58 +1100
      Re: pymongo and attribute dictionaries Vito De Tullio <vito.detullio@gmail.com> - 2015-02-05 06:36 +0100
        Re: pymongo and attribute dictionaries Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2015-02-05 16:43 +1100
          Re: pymongo and attribute dictionaries Anssi Saari <as@sci.fi> - 2015-02-05 15:27 +0200
            Re: pymongo and attribute dictionaries Ian Kelly <ian.g.kelly@gmail.com> - 2015-02-05 14:11 -0700

#85223 — pymongo and attribute dictionaries

FromTravis Griggs <travisgriggs@gmail.com>
Date2015-02-04 08:50 -0800
Subjectpymongo and attribute dictionaries
Message-ID<mailman.18469.1423068652.18130.python-list@python.org>
I really like pymongo. And I really like Python. But one thing my fingers really get tired of typing is

someDoc[‘_’id’]

This just does not roll of the fingers well. Too many “reach for modifier keys” in a row. I would rather use

someDoc._id

Googling shows that I’m not the first to want to do this in the general sense (e.g. http://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute-in-python).

Arguments aside of whether this should or shouldn’t be done, I want to know how I might solve this with Python. Consider it an academic pursuit.

The problem I have is not how to do the AttributeDictionary subclass, there are plenty of those examples. The problem is that the pymongo APIs already return dictionaries. In a language (Smalltalk, Objective-C, Ruby) that supports class extensions, that would be my first tool of choice to solve this problem. I’d just extend Dictionary to behave the way I want and be done with it. I can’t do that in Python though. I guess I could make my own module that subclasses the relevant pymongo classes, and do super() calling implementations of all of the relevant methods, coercing the return type. That is a maintenance headache though.

What are my options, if any?

[toc] | [next] | [standalone]


#85236

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-02-05 09:38 +1100
Message-ID<54d29f63$0$12986$c3e8da3$5496439d@news.astraweb.com>
In reply to#85223
Travis Griggs wrote:

> I really like pymongo. And I really like Python. But one thing my fingers
> really get tired of typing is
> 
> someDoc[‘_’id’]

I've never used pymongo, so can't comment from experience, but surely any
library which encourages, if not requires, that you access private data _id
doesn't inspire me with confidence.

Also, the above is a syntax error, but you probably know that.


> This just does not roll of the fingers well. Too many “reach for modifier
> keys” in a row.

*One* modifier key in a row is too many? 

s o m e SHIFT D o c [ ' SHIFT _ i d ' ]


You can cut that by 50% by changing your naming convention:

somedoc['_id']

While you're at it, you can cut the total number of keystrokes too:

doc['_id']


If there are a fixed set of key names that you use repeatedly, you can do
this:


ID, FE, FI, FO, FUM = '_id', '_fe', '_fi', '_fo', '_fum'
# later
someDoc[ID]


Ah, but that needs the shiftkey... well, I guess that PEP 8 naming
conventions aren't compulsory, and so long as you don't need the built-in
`id` function, it's okay to shadow it (consenting adults and all that), so:

id, fe, fi, fo, fum = '_id', '_fe', '_fi', '_fo', '_fum'
# later
someDoc[id]


> I would rather use
> someDoc._id

That has exactly the same number of modifier keys as your original example.
I'm starting to sense that you don't actually care about the SHIFT key...


[...]
> The problem I have is not how to do the AttributeDictionary subclass,
> there are plenty of those examples. The problem is that the pymongo APIs
> already return dictionaries. In a language (Smalltalk, Objective-C, Ruby)
> that supports class extensions, that would be my first tool of choice to
> solve this problem. I’d just extend Dictionary to behave the way I want
> and be done with it. I can’t do that in Python though. I guess I could
> make my own module that subclasses the relevant pymongo classes, and do
> super() calling implementations of all of the relevant methods, coercing
> the return type. That is a maintenance headache though.
> 
> What are my options, if any?

HingTFU comes to mind :-)

But as "an academic exercise" *nudge nudge, wink wink* there's always the
Adaptor design pattern. Import as much or as little of pymongo as you need,
wrap it in an adaptor, and use that. There are lots of different ways that
you could do this, some more monkey-patchy than others.


# pymongo adaptor module (untested)
from pymongo import *

import functools

def wrap(name):
    """Wrap function called `name` so it returns an AttrDict instead 
    of dict. May the gods have mercy on your soul."""
    func = globals()[name]
    @functools.wraps(func)
    def inner(*args, **kwargs):
        result = func(*args, **kwargs)
        if isinstance(result, dict):
            result = AttrDict(result)
        return result
    globals()[name] = func


FUNCTIONS_THAT_RETURN_DICTS = ['this', 'that', 'another']
for name in FUNCTIONS_THAT_RETURN_DICTS:
    wrap(name)



Extending this to use introspection to automatically detect the pymongo
functions instead of having to list them manually is left as an exercise.
(Hint: import pymongo; for obj in vars(pymongo): ...).

Extending this to wrap methods of classes is also left as an exercise.
(Hint: don't subclass. Search the ActiveState Python recipes for "automatic
delegation" by Alex Martelli.)

And now just use the adaptor module instead of the original.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#85242

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-02-04 17:19 -0700
Message-ID<mailman.18481.1423099055.18130.python-list@python.org>
In reply to#85236
On Wed, Feb 4, 2015 at 3:38 PM, Steven D'Aprano
<steve+comp.lang.python@pearwood.info> wrote:
> Travis Griggs wrote:
>> This just does not roll of the fingers well. Too many “reach for modifier
>> keys” in a row.
>
> *One* modifier key in a row is too many?
>
> s o m e SHIFT D o c [ ' SHIFT _ i d ' ]

I think the point was meant to be the number of keys that need to be
reached for, not just the number of times Shift needs to be pressed.

> Extending this to wrap methods of classes is also left as an exercise.
> (Hint: don't subclass. Search the ActiveState Python recipes for "automatic
> delegation" by Alex Martelli.)

Do you mean this one?

http://code.activestate.com/recipes/52295-automatic-delegation-as-an-alternative-to-inherita/

That's based on old-style classes. With new-style classes it fails to
delegate dunder methods like __str__. That recipe should be considered
obsolete.

[toc] | [prev] | [next] | [standalone]


#85243

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-02-05 12:58 +1100
Message-ID<54d2ce40$0$21718$c3e8da3@news.astraweb.com>
In reply to#85242
Ian Kelly wrote:

>> Extending this to wrap methods of classes is also left as an exercise.
>> (Hint: don't subclass. Search the ActiveState Python recipes for
>> "automatic delegation" by Alex Martelli.)
> 
> Do you mean this one?
> 
> http://code.activestate.com/recipes/52295-automatic-delegation-as-an-
alternative-to-inherita/
> 
> That's based on old-style classes. With new-style classes it fails to
> delegate dunder methods like __str__. That recipe should be considered
> obsolete.

I'm aware of the problem with dunder methods. But that's not an 
insurmountable problem, if you need your delegation recipe to support 
dunders (and you may not), it's fiddly and annoying to do so, but not 
impossible. There are at least two approaches:

- manually delegate to the dunders that you care about with hand-
  written dunder methods:

    def __str__(self):
        return type(self.proxied_object).__str__(self.proxied_object)
        # or for people who prefer simplicity over correctness
        # return self.proxied_object.__str__()


- write a decorator which inspects the class and automatically adds 
  explicit dunders for you. (There's a recipe on ActiveState for 
  that one too.)

Regardless of whether you start with Alex's recipe or not, the idea is to 
make a proxy for the pymongo classes, and delegate to it rather than 
subclass or re-invent the wheel. That's a basic design pattern, and if 
dunders are a problem in Python that Ruby or Java doesn't have, oh well, 
life wasn't meant to be easy.



-- 
Steven

[toc] | [prev] | [next] | [standalone]


#85249

FromVito De Tullio <vito.detullio@gmail.com>
Date2015-02-05 06:36 +0100
Message-ID<mailman.18487.1423114638.18130.python-list@python.org>
In reply to#85236
Steven D'Aprano wrote:

>> This just does not roll of the fingers well. Too many “reach for modifier
>> keys” in a row.
> 
> *One* modifier key in a row is too many?
> 
> s o m e SHIFT D o c [ ' SHIFT _ i d ' ]

I'm not OP, but as side note... not everyone has "[" as a direct character 
on the keyboard. I need to press "AltGr" + "è" (and "AltGr" + "+" to get 
"]"), so I can feel the OP lamenting :)

s o m e SHIFT D o c ALTGR è ' SHIFT - i d ' ALTRG +

-- 
By ZeD

[toc] | [prev] | [next] | [standalone]


#85250

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2015-02-05 16:43 +1100
Message-ID<54d302fc$0$11096$c3e8da3@news.astraweb.com>
In reply to#85249
Vito De Tullio wrote:

> Steven D'Aprano wrote:
> 
>>> This just does not roll of the fingers well. Too many “reach for
>>> modifier keys” in a row.
>> 
>> *One* modifier key in a row is too many?
>> 
>> s o m e SHIFT D o c [ ' SHIFT _ i d ' ]
> 
> I'm not OP, but as side note... not everyone has "[" as a direct character
> on the keyboard. I need to press "AltGr" + "è" (and "AltGr" + "+" to get
> "]"), so I can feel the OP lamenting :)

Point taken. Thank you.


-- 
Steven

[toc] | [prev] | [next] | [standalone]


#85270

FromAnssi Saari <as@sci.fi>
Date2015-02-05 15:27 +0200
Message-ID<vg3wq3wnlbu.fsf@coffee.modeemi.fi>
In reply to#85250
Steven D'Aprano <steve+comp.lang.python@pearwood.info> writes:

> Vito De Tullio wrote:
>
>> Steven D'Aprano wrote:
>> 
>>>> This just does not roll of the fingers well. Too many “reach for
>>>> modifier keys” in a row.
>>> 
>>> *One* modifier key in a row is too many?
>>> 
>>> s o m e SHIFT D o c [ ' SHIFT _ i d ' ]
>> 
>> I'm not OP, but as side note... not everyone has "[" as a direct character
>> on the keyboard. I need to press "AltGr" + "è" (and "AltGr" + "+" to get
>> "]"), so I can feel the OP lamenting :)
>
> Point taken. Thank you.

What I find surprising is that so many people cling so hard to their
localized keyboard layouts. I think none of those were created by
engineers and should be avoided by technical people. Or, in fact,
everyone. Even Microsoft seems to understand this and so Windows
installs the US English layout by default as an alternative.

[toc] | [prev] | [next] | [standalone]


#85281

FromIan Kelly <ian.g.kelly@gmail.com>
Date2015-02-05 14:11 -0700
Message-ID<mailman.18503.1423210712.18130.python-list@python.org>
In reply to#85270
On Thu, Feb 5, 2015 at 6:27 AM, Anssi Saari <as@sci.fi> wrote:
> What I find surprising is that so many people cling so hard to their
> localized keyboard layouts. I think none of those were created by
> engineers and should be avoided by technical people. Or, in fact,
> everyone. Even Microsoft seems to understand this and so Windows
> installs the US English layout by default as an alternative.

Speaking as a user of both Dvorak and Qwerty, switching between
layouts frequently can be confusing. In particular the pain points are
the places where the two layouts are similar. I haven't done this so
much recently, but in the past I have often been typing away in one
layout, then come to an A or an M (which happen to be in the same
position in both layouts) at which point my brain would inadvertently
"switch" and I would suddenly find myself typing in the wrong layout.
I would expect that a localized layout with more similarity than what
there is between Dvorak and Qwerty would cause even more of these
types of problems.

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web