[sqlalchemy] Re: Creating a custom type
I've been trying create the extension. Here is the code with a test: http://paste.pocoo.org/show/97502/ - Extension http://paste.pocoo.org/show/97503/ - Test I need help to solve this little issue: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) AttributeError: 'str' object has no attribute '_descriptor' Does could review the extension code? On 22 dic 2008, 03:40, Michael Bayer mike...@zzzcomputing.com wrote: oh, yeah for that recipe you'd have to use a flag on the mapper() called batch=False. But don't use that, its inefficient. So you can also create your type to detect a special value from the mapper extension: def before_insert(self, ): instance.password = (instance.password, True) class MyType(...): ... def process_bind_param(self, value, dialect): if isinstance(value, tuple): return hasher.create(value[0], value[1]) But since this is really an instance-level business rule, a straight descriptor and no custom type is definitely how I'd go on this one. On Dec 21, 2008, at 6:47 PM, Kless wrote: Thank you for detailed answer. Here are any thoughts: 1) The before_insert was being omitted while I was inserting records using an insert statement --that's logical because it was bypassing the ORM--. 2) It's necessary to use *session.commit()* after of each record because else it will have the value of 'instance.admin' of the last record which will be used for all records to commit. 3) I believe that it isn't necessary use *after_insert*. On 21 dic, 17:00, Michael Bayer mike...@zzzcomputing.com wrote: On Dec 21, 2008, at 6:53 AM, Kless wrote: I'm trying to build a custom type [1] to manage the bcrypt hashes [2]. --- from bcrypt_wrap import password from sqlalchemy import types class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String #(60) hasher = password.Password() def process_bind_param(self, value, dialect): return hasher.create(value) --- And I've any doubts: 1) Since that the hash length is always 60, is there that use the next? impl = types.String(60) 2) The bcryptWrap API [3] (line 53) lets call to 'create' with arguments 'cost' and 'admin' (boolean). Then, a) I would that the cost could be passed from the column definition, i.e. password = sqlalchemy.Column(types.Bcrypt, cost=12) or password = sqlalchemy.Column(types.Bcrypt(cost=12)) b) This would be more hard, but I would to pass the 'admin' argument when an object is created u = model.User() u.login = u'foo' u.password = u'bar' u.admin = True And sou could be call: return hasher.create(value, admin=True) the TypeDecorator's __init__ method just calls the impl class immediately, so the best approach is like: class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String hasher = password.Password() def __init__(self, cost): self.cost = cost types.TypeDecorator.__init__(self, 60) def process_bind_param(self, value, dialect): return hasher.create(value) then you can instantate like: Column('foo', Bcrypt(cost=12)) For b, the type object and the ExecutionContext which ultimately calls its process_bind_param method are unaware of the ORM or the ORM- specific context in which its called during INSERT/UPDATE. If you wanted to keep the logic within your type like that you'd have to integrate to a thread-local variable that is configured within an ORM plugin, something like: hasher_status = threading.local() class MyMapperExt(MapperExtension): def before_insert(self, ...): hasher_status.admin = instance.admin def after_insert(self, ...) del hasher_status.admin mapper(MyClass, table, ext=MyMapperExt) class Bcrypt(types.TypeDecorator): ... def process_bind_param(self, value, dialect): return hasher.create(value, getattr(hasher_status, 'admin', False)) Alternatively, you could keep the logic within the ORM using either a valdiator or a descriptor, as described athttp://www.sqlalchemy.org/docs/05/mappers.html#changing-attribute-beh ... . It depends on if you'd like your Bcrypt type to work with direct SQL expression language use or not. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
mapper extensions are established during the mapper() phase: mapper(someclass, sometable, extension=BycryptMapperExtension()) On Jan 1, 2009, at 1:35 PM, Kless wrote: I've been trying create the extension. Here is the code with a test: http://paste.pocoo.org/show/97502/ - Extension http://paste.pocoo.org/show/97503/ - Test I need help to solve this little issue: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) AttributeError: 'str' object has no attribute '_descriptor' Does could review the extension code? On 22 dic 2008, 03:40, Michael Bayer mike...@zzzcomputing.com wrote: oh, yeah for that recipe you'd have to use a flag on the mapper() called batch=False.But don't use that, its inefficient. So you can also create your type to detect a special value from the mapper extension: def before_insert(self, ): instance.password = (instance.password, True) class MyType(...): ... def process_bind_param(self, value, dialect): if isinstance(value, tuple): return hasher.create(value[0], value[1]) But since this is really an instance-level business rule, a straight descriptor and no custom type is definitely how I'd go on this one. On Dec 21, 2008, at 6:47 PM, Kless wrote: Thank you for detailed answer. Here are any thoughts: 1) The before_insert was being omitted while I was inserting records using an insert statement --that's logical because it was bypassing the ORM--. 2) It's necessary to use *session.commit()* after of each record because else it will have the value of 'instance.admin' of the last record which will be used for all records to commit. 3) I believe that it isn't necessary use *after_insert*. On 21 dic, 17:00, Michael Bayer mike...@zzzcomputing.com wrote: On Dec 21, 2008, at 6:53 AM, Kless wrote: I'm trying to build a custom type [1] to manage the bcrypt hashes [2]. --- from bcrypt_wrap import password from sqlalchemy import types class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String #(60) hasher = password.Password() def process_bind_param(self, value, dialect): return hasher.create(value) --- And I've any doubts: 1) Since that the hash length is always 60, is there that use the next? impl = types.String(60) 2) The bcryptWrap API [3] (line 53) lets call to 'create' with arguments 'cost' and 'admin' (boolean). Then, a) I would that the cost could be passed from the column definition, i.e. password = sqlalchemy.Column(types.Bcrypt, cost=12) or password = sqlalchemy.Column(types.Bcrypt(cost=12)) b) This would be more hard, but I would to pass the 'admin' argument when an object is created u = model.User() u.login = u'foo' u.password = u'bar' u.admin = True And sou could be call: return hasher.create(value, admin=True) the TypeDecorator's __init__ method just calls the impl class immediately, so the best approach is like: class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String hasher = password.Password() def __init__(self, cost): self.cost = cost types.TypeDecorator.__init__(self, 60) def process_bind_param(self, value, dialect): return hasher.create(value) then you can instantate like: Column('foo', Bcrypt(cost=12)) For b, the type object and the ExecutionContext which ultimately calls its process_bind_param method are unaware of the ORM or the ORM- specific context in which its called during INSERT/UPDATE. If you wanted to keep the logic within your type like that you'd have to integrate to a thread-local variable that is configured within an ORM plugin, something like: hasher_status = threading.local() class MyMapperExt(MapperExtension): def before_insert(self, ...): hasher_status.admin = instance.admin def after_insert(self, ...) del hasher_status.admin mapper(MyClass, table, ext=MyMapperExt) class Bcrypt(types.TypeDecorator): ... def process_bind_param(self, value, dialect): return hasher.create(value, getattr(hasher_status, 'admin', False)) Alternatively, you could keep the logic within the ORM using either a valdiator or a descriptor, as described athttp://www.sqlalchemy.org/docs/05/mappers.html#changing-attribute-beh ... . It depends on if you'd like your Bcrypt type to work with direct SQL expression language use or not. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to sqlalchemy+unsubscr...@googlegroups.com For more options, visit this group at
[sqlalchemy] Re: Creating a custom type
It's being passed from the IsBcrypt constructor, so: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) On 1 ene, 19:48, Michael Bayer mike...@zzzcomputing.com wrote: mapper extensions are established during the mapper() phase: mapper(someclass, sometable, extension=BycryptMapperExtension()) On Jan 1, 2009, at 1:35 PM, Kless wrote: I've been trying create the extension. Here is the code with a test: http://paste.pocoo.org/show/97502/- Extension http://paste.pocoo.org/show/97503/- Test I need help to solve this little issue: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) AttributeError: 'str' object has no attribute '_descriptor' Does anybody could review the extension code? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
I just see that will be by a problem of change in API AttributeError: 'str' object has no attribute '_descriptor' Kless ha escrito: It's being passed from the IsBcrypt constructor, so: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) On 1 ene, 19:48, Michael Bayer mike...@zzzcomputing.com wrote: mapper extensions are established during the mapper() phase: mapper(someclass, sometable, extension=BycryptMapperExtension()) On Jan 1, 2009, at 1:35 PM, Kless wrote: I've been trying create the extension. Here is the code with a test: �http://paste.pocoo.org/show/97502/- Extension �http://paste.pocoo.org/show/97503/- Test I need help to solve this little issue: entity._descriptor.add_mapper_extension(BcryptMapperExtension()) AttributeError: 'str' object has no attribute '_descriptor' Does anybody could review the extension code? --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
Kless wrote: I just see that will be by a problem of change in API AttributeError: 'str' object has no attribute '_descriptor' As I indicated to you over on the Elixir list, you seem to have used the Elixir encryption extension as a starting point. The _descriptor and the concept of an entity are Elixir concepts, not SQLAlchemy concepts. You need to base your work on other mapper extensions, not on the Elixir extension, which is designed to only work with Elixir models, not plain-SQLAlchemy models. I'd suggest starting over, and using the following documentation references: Mapper Extension API reference: http://tinyurl.com/8wfkgl Applying Mapper Extensions: http://tinyurl.com/7a3b5c Good luck. -- Jonathan LaCour http://cleverdevil.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
Thanks. This was your message on the Elixir list: It looks to me like you are using SQLAlchemy without Elixir, and therefore this isn't the proper place to be asking this question. You should ask over on the SQLAlchemy mailing list. If you would like help creating an elixir extension, I can help you with that here. Good luck. On 1 ene, 21:01, Jonathan LaCour jonathan-li...@cleverdevil.org wrote: Kless wrote: I just see that will be by a problem of change in API AttributeError: 'str' object has no attribute '_descriptor' As I indicated to you over on the Elixir list, you seem to have used the Elixir encryption extension as a starting point. The _descriptor and the concept of an entity are Elixir concepts, not SQLAlchemy concepts. You need to base your work on other mapper extensions, not on the Elixir extension, which is designed to only work with Elixir models, not plain-SQLAlchemy models. I'd suggest starting over, and using the following documentation references: Mapper Extension API reference:http://tinyurl.com/8wfkgl Applying Mapper Extensions:http://tinyurl.com/7a3b5c Good luck. -- Jonathan LaCourhttp://cleverdevil.org --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
Thank you. Your aid is incalculable as always. I'll use a descriptor for this case as you well advise. On 22 dic, 03:40, Michael Bayer mike...@zzzcomputing.com wrote: oh, yeah for that recipe you'd have to use a flag on the mapper() called batch=False. But don't use that, its inefficient. So you can also create your type to detect a special value from the mapper extension: def before_insert(self, ): instance.password = (instance.password, True) class MyType(...): ... def process_bind_param(self, value, dialect): if isinstance(value, tuple): return hasher.create(value[0], value[1]) But since this is really an instance-level business rule, a straight descriptor and no custom type is definitely how I'd go on this one. On Dec 21, 2008, at 6:47 PM, Kless wrote: 2) It's necessary to use *session.commit()* after of each record because else it will have the value of 'instance.admin' of the last record which will be used for all records to commit. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
Although it's necessary to consider that continues being necessary a custom type to add a new argument (in this case is 'cost'). And I prefer a custom type before that a subclass of Column for this one. Now well, to get the another argument which is at instance-level surely will be better make it thorught a descriptor, as you said. On 22 dic, 09:37, Kless jonas@googlemail.com wrote: Thank you. Your aid is incalculable as always. I'll use a descriptor for this case as you well advise. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
On Dec 21, 2008, at 6:53 AM, Kless wrote: I'm trying to build a custom type [1] to manage the bcrypt hashes [2]. --- from bcrypt_wrap import password from sqlalchemy import types class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String #(60) hasher = password.Password() def process_bind_param(self, value, dialect): return hasher.create(value) --- And I've any doubts: 1) Since that the hash length is always 60, is there that use the next? impl = types.String(60) 2) The bcryptWrap API [3] (line 53) lets call to 'create' with arguments 'cost' and 'admin' (boolean). Then, a) I would that the cost could be passed from the column definition, i.e. password = sqlalchemy.Column(types.Bcrypt, cost=12) or password = sqlalchemy.Column(types.Bcrypt(cost=12)) b) This would be more hard, but I would to pass the 'admin' argument when an object is created u = model.User() u.login = u'foo' u.password = u'bar' u.admin = True And sou could be call: return hasher.create(value, admin=True) the TypeDecorator's __init__ method just calls the impl class immediately, so the best approach is like: class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String hasher = password.Password() def __init__(self, cost): self.cost = cost types.TypeDecorator.__init__(self, 60) def process_bind_param(self, value, dialect): return hasher.create(value) then you can instantate like: Column('foo', Bcrypt(cost=12)) For b, the type object and the ExecutionContext which ultimately calls its process_bind_param method are unaware of the ORM or the ORM- specific context in which its called during INSERT/UPDATE. If you wanted to keep the logic within your type like that you'd have to integrate to a thread-local variable that is configured within an ORM plugin, something like: hasher_status = threading.local() class MyMapperExt(MapperExtension): def before_insert(self, ...): hasher_status.admin = instance.admin def after_insert(self, ...) del hasher_status.admin mapper(MyClass, table, ext=MyMapperExt) class Bcrypt(types.TypeDecorator): ... def process_bind_param(self, value, dialect): return hasher.create(value, getattr(hasher_status, 'admin', False)) Alternatively, you could keep the logic within the ORM using either a valdiator or a descriptor, as described at http://www.sqlalchemy.org/docs/05/mappers.html#changing-attribute-behavior . It depends on if you'd like your Bcrypt type to work with direct SQL expression language use or not. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
Thank you for detailed answer. Here are any thoughts: 1) The before_insert was being omitted while I was inserting records using an insert statement --that's logical because it was bypassing the ORM--. 2) It's necessary to use *session.commit()* after of each record because else it will have the value of 'instance.admin' of the last record which will be used for all records to commit. 3) I believe that it isn't necessary use *after_insert*. On 21 dic, 17:00, Michael Bayer mike...@zzzcomputing.com wrote: On Dec 21, 2008, at 6:53 AM, Kless wrote: I'm trying to build a custom type [1] to manage the bcrypt hashes [2]. --- from bcrypt_wrap import password from sqlalchemy import types class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String #(60) hasher = password.Password() def process_bind_param(self, value, dialect): return hasher.create(value) --- And I've any doubts: 1) Since that the hash length is always 60, is there that use the next? impl = types.String(60) 2) The bcryptWrap API [3] (line 53) lets call to 'create' with arguments 'cost' and 'admin' (boolean). Then, a) I would that the cost could be passed from the column definition, i.e. password = sqlalchemy.Column(types.Bcrypt, cost=12) or password = sqlalchemy.Column(types.Bcrypt(cost=12)) b) This would be more hard, but I would to pass the 'admin' argument when an object is created u = model.User() u.login = u'foo' u.password = u'bar' u.admin = True And sou could be call: return hasher.create(value, admin=True) the TypeDecorator's __init__ method just calls the impl class immediately, so the best approach is like: class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String hasher = password.Password() def __init__(self, cost): self.cost = cost types.TypeDecorator.__init__(self, 60) def process_bind_param(self, value, dialect): return hasher.create(value) then you can instantate like: Column('foo', Bcrypt(cost=12)) For b, the type object and the ExecutionContext which ultimately calls its process_bind_param method are unaware of the ORM or the ORM- specific context in which its called during INSERT/UPDATE. If you wanted to keep the logic within your type like that you'd have to integrate to a thread-local variable that is configured within an ORM plugin, something like: hasher_status = threading.local() class MyMapperExt(MapperExtension): def before_insert(self, ...): hasher_status.admin = instance.admin def after_insert(self, ...) del hasher_status.admin mapper(MyClass, table, ext=MyMapperExt) class Bcrypt(types.TypeDecorator): ... def process_bind_param(self, value, dialect): return hasher.create(value, getattr(hasher_status, 'admin', False)) Alternatively, you could keep the logic within the ORM using either a valdiator or a descriptor, as described athttp://www.sqlalchemy.org/docs/05/mappers.html#changing-attribute-beh... . It depends on if you'd like your Bcrypt type to work with direct SQL expression language use or not. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: Creating a custom type
oh, yeah for that recipe you'd have to use a flag on the mapper() called batch=False.But don't use that, its inefficient. So you can also create your type to detect a special value from the mapper extension: def before_insert(self, ): instance.password = (instance.password, True) class MyType(...): ... def process_bind_param(self, value, dialect): if isinstance(value, tuple): return hasher.create(value[0], value[1]) But since this is really an instance-level business rule, a straight descriptor and no custom type is definitely how I'd go on this one. On Dec 21, 2008, at 6:47 PM, Kless wrote: Thank you for detailed answer. Here are any thoughts: 1) The before_insert was being omitted while I was inserting records using an insert statement --that's logical because it was bypassing the ORM--. 2) It's necessary to use *session.commit()* after of each record because else it will have the value of 'instance.admin' of the last record which will be used for all records to commit. 3) I believe that it isn't necessary use *after_insert*. On 21 dic, 17:00, Michael Bayer mike...@zzzcomputing.com wrote: On Dec 21, 2008, at 6:53 AM, Kless wrote: I'm trying to build a custom type [1] to manage the bcrypt hashes [2]. --- from bcrypt_wrap import password from sqlalchemy import types class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String #(60) hasher = password.Password() def process_bind_param(self, value, dialect): return hasher.create(value) --- And I've any doubts: 1) Since that the hash length is always 60, is there that use the next? impl = types.String(60) 2) The bcryptWrap API [3] (line 53) lets call to 'create' with arguments 'cost' and 'admin' (boolean). Then, a) I would that the cost could be passed from the column definition, i.e. password = sqlalchemy.Column(types.Bcrypt, cost=12) or password = sqlalchemy.Column(types.Bcrypt(cost=12)) b) This would be more hard, but I would to pass the 'admin' argument when an object is created u = model.User() u.login = u'foo' u.password = u'bar' u.admin = True And sou could be call: return hasher.create(value, admin=True) the TypeDecorator's __init__ method just calls the impl class immediately, so the best approach is like: class Bcrypt(types.TypeDecorator): Stores a bcrypt hash of a password. impl = types.String hasher = password.Password() def __init__(self, cost): self.cost = cost types.TypeDecorator.__init__(self, 60) def process_bind_param(self, value, dialect): return hasher.create(value) then you can instantate like: Column('foo', Bcrypt(cost=12)) For b, the type object and the ExecutionContext which ultimately calls its process_bind_param method are unaware of the ORM or the ORM- specific context in which its called during INSERT/UPDATE. If you wanted to keep the logic within your type like that you'd have to integrate to a thread-local variable that is configured within an ORM plugin, something like: hasher_status = threading.local() class MyMapperExt(MapperExtension): def before_insert(self, ...): hasher_status.admin = instance.admin def after_insert(self, ...) del hasher_status.admin mapper(MyClass, table, ext=MyMapperExt) class Bcrypt(types.TypeDecorator): ... def process_bind_param(self, value, dialect): return hasher.create(value, getattr(hasher_status, 'admin', False)) Alternatively, you could keep the logic within the ORM using either a valdiator or a descriptor, as described athttp://www.sqlalchemy.org/docs/05/mappers.html#changing-attribute-beh ... . It depends on if you'd like your Bcrypt type to work with direct SQL expression language use or not. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---