Уведомления

Jabber-конференция сообщества: pythonua@conference.jabber.ru

#1 Июнь 26, 2007 13:02:54

Нави Гатор
От:
Зарегистрирован: 2007-03-14
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

как работать с dictproxy?

Помогите, пожалуйста.
Я переопределил метод __setattr__ для класса следующим образом:

class SomeClass(SomeMetaClass):
def _setattr(cls,name,val):
try:
cls.__getattribute__(name)
except:
cls.__dict__[name]=val
SomeMetaClass.__setattr__=_setattr
В результате при вызове SomeClass.someattr='value' вылезает ошибка:

TypeError: Error when calling the metaclass bases
‘dictproxy’ object does not support item assignment

Что сдесь можно сделать?



Офлайн

#2 Июнь 26, 2007 13:56:59

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

как работать с dictproxy?

нужен полный пример. Что за SomeMetaClass?



Офлайн

#3 Июнь 26, 2007 14:59:01

Нави Гатор
От:
Зарегистрирован: 2007-03-14
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

как работать с dictproxy?

Да без разницы, пусть будет:

class SomeMetaClass(object):
pass
Вопрос в том, как переопределить __setattr__. SomeMetaClass трогать нельзя, SomeClass.__dict__ должен показывать правильные аттрибуты

Вообще, речь идет о скюэльалхемовской примочке elixir. На класс SomeClass процедурой setattr() внутри elixir навешиваются методы, один из которых очень нужно переопределить. Для этого я этот метод объявляю внутри класса SomeClass, а потом делаю умный __setattr__, который устанавливает новые аттрибуты только если они не существуют.
Полный код:
from elixir import * 
class BigClass(Entity):
def _setattr(cls,name,val):
if not cls.__dict__.has_key(name):
cls.__dict__[name]=val
EntityMeta.__setattr__=_setattr
@classmethod
def select_by(*args,**kwargs):
cls=args[0]
kwargs[type]=cls.type
return cls[0].__class__.select_by(**kwargs)
class SomeClass(BigClass):
type=1
#EntityMeta и Entity для данной задачи можно считать одним и тем же классом



Отредактировано (Июнь 26, 2007 15:48:36)

Офлайн

#4 Июнь 26, 2007 19:11:22

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

как работать с dictproxy?

Скажу сразу: с Эликсиром не работал. В отличие от алхимии.
Но, как я вижу из его сорцов, select_by он сам не навешивает.
И уж тем более не совсем через setattr.
elixir/entity.py: 167 - прикладывается assign_mapper к entity, который, используя assignmapper extension инструментирует entity.

Посмотри на sqlalchemy/ext/assign_mapper.py: 4 monkeypatch_query_method. Им же и твою реализацию прикрутить можно.

Если, конечно, я правильно понял цель - в select_by один из критериев выборки жестко зашивать в самом entity

Алхимия 0.3.9, Эликсир 0.3.0

Если я совсем тебя не понял - попытайся по другому сформировать вопрос.

Кстати, assingmapper - кривоватая штука, рудимент от первой бородатой версии



Отредактировано (Июнь 26, 2007 19:12:26)

Офлайн

#5 Июнь 27, 2007 13:19:06

Нави Гатор
От:
Зарегистрирован: 2007-03-14
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

как работать с dictproxy?

Спасибо. Про monkeypatch_query_method то я знаю, именно из него вызывается setattr, но насколько я понял метод select_by он вытаскивает прямо из Query. А как бы его заставить цеплять свой select_by? Все-таки сырцы sqlalchemy менять как-то не хочется.



Офлайн

#6 Июнь 28, 2007 13:35:11

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

как работать с dictproxy?

Нави Гатор
Спасибо. Про monkeypatch_query_method то я знаю, именно из него вызывается setattr, но насколько я понял метод select_by он вытаскивает прямо из Query. А как бы его заставить цеплять свой select_by? Все-таки сырцы sqlalchemy менять как-то не хочется.
Это то, что ты хотел?

from elixir import *
from elixir.entity import EntityMeta

metadata.connect(“sqlite:///sample.sqlite”)


class SelectDescr(object):
def __init__(self, cls, fixed_name):
self._cls = cls
self._old_select_by = cls.select_by
self._fixed_name = fixed_name

def __get__(self, instance, owner):
def f(*args, **kwargs):
new_kw = dict()
new_kw.update(kwargs)
if self._fixed_name is not None:
new_kw = self._fixed_name
return self._old_select_by(instance, *args, **new_kw)
return f


class PersonMeta(EntityMeta):
def __init__(cls, name, bases, dict_):
EntityMeta.__init__(cls, name, bases, dict_)
cls.select_by = SelectDescr(cls, getattr(cls, ‘fixed_name’, None))


class Person(Entity):
__metaclass__ = PersonMeta
has_field('name', Unicode(255))

def __repr__(self):
return ‘Person @ 0x%08x (%s)’%(id(self), self.name)

#instrument(Person)
#Person.select_by = SelectDescr(Person)


drop_all()
create_all()

def fill():
p = Person(name='Jack')
p2 = Person(name='John')

objectstore.flush()

fill()

print Person.select_by()

print Person.select_by(name='Jack')

class Jack(Person):
fixed_name = ‘Jack’

print Jack.select_by()


Если нет - давай отталкиваться от примера и выяснять, что таки нужно.



Офлайн

#7 Июнь 29, 2007 12:11:35

Нави Гатор
От:
Зарегистрирован: 2007-03-14
Сообщения: 11
Репутация: +  0  -
Профиль   Отправить e-mail  

как работать с dictproxy?

Пасиибаа!
Как раз то, что надо



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version