Unfortunately still getting the same result: http://paste.pocoo.org/show/249801/
The test snippet shows that the modified set is not actually saved to the database. On Aug 13, 3:29 pm, Michael Bayer <mike...@zzzcomputing.com> wrote: > On Aug 13, 2010, at 10:24 AM, Dan wrote: > > > > > > > On Aug 13, 3:17 pm, Michael Bayer <mike...@zzzcomputing.com> wrote: > >> On Aug 13, 2010, at 10:01 AM, Dan wrote: > > >>> I have created a custom type in order to store denormalized PKs in a > >>> TEXT field. The idea is that the text is converted back and forth from > >>> a set of integers: > > >>>http://paste.pocoo.org/show/249784/ > > >> this is unrelated, but the code is incorrect there, should be > > >> def process(value): > >> if value is not None: > >> items = [str(item).strip() for item in value] > >> value = self.separator.join(item for item in items if item) > > >> otherwise, you must implement copy_value() on your type. Here, the value > >> isn't being copied so there's nothing to compare to. > > > Yes, sorry for the typo. Realized myself once I'd posted. > > >> Usually you're supposed to mixin MutableType which will raise > >> notimplemented for copy_value(). I guess still more docs are needed > >> since you were misled by the is_mutable() method. > > > I've tried the same thing with the MutableType mixin with the same > > result, i.e: > > > class DenormalizedText(types.TypeDecorator, types.MutableType): > > MutableType would be first. But again this only just so the > NotImplementedError lets you know copy_value() is needed. I could make the > default copy_value() raise if is_mutable() is true...though it pains me to > add more method calls... > > from sqlalchemy import * > > from sqlalchemy.ext.declarative import declarative_base > from sqlalchemy.orm import * > > Base = declarative_base() > metadata = Base.metadata > engine = create_engine('sqlite://', echo=True) > > from sqlalchemy import types > > class DenormalizedText(types.TypeDecorator): > """ > Stores denormalized primary keys that can be > accessed as a set. > > :param coerce: coercion function that ensures correct > type is returned > > :param separator: separator character > """ > > impl = types.Text > > def __init__(self, coerce=int, separator=" ", **kwargs): > > self.coerce = coerce > self.separator = separator > > super(DenormalizedText, self).__init__(**kwargs) > > def bind_processor(self, dialect): > > def process(value): > if value is not None: > items = [str(item).strip() for item in value] > value = self.separator.join(item for item in items if item) > return value > return process > > def result_processor(self, dialect, coltype): > def process(value): > if not value: > return set() > return set(self.coerce(item) \ > for item in value.split(self.separator)) > return process > > def copy_value(self, value): > return set(value) > > def is_mutable(self): > > return True > > class Post(Base): > __tablename__ = "posts" > id = Column(Integer, primary_key=True) > votes = Column(DenormalizedText) > > def __init__(self, *args, **kwargs): > super(Post, self).__init__(*args, **kwargs) > self.votes = self.votes or set() > > Base.metadata.create_all(engine) > > session = sessionmaker(engine)() > > post = Post() > post.votes.add(3) > > session.add(post) > session.commit() > > print "-----------------------" > post.votes.add(5) > session.commit() > > > > > -- > > You received this message because you are subscribed to the Google Groups > > "sqlalchemy" group. > > To post to this group, send email to sqlalch...@googlegroups.com. > > To unsubscribe from this group, send email to > > sqlalchemy+unsubscr...@googlegroups.com. > > For more options, visit this group > > athttp://groups.google.com/group/sqlalchemy?hl=en. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To post to this group, send email to sqlalch...@googlegroups.com. To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en.