[sqlalchemy] Re: Creating a custom type

2009-01-01 Thread Kless

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

2009-01-01 Thread Michael Bayer

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

2009-01-01 Thread Kless

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

2009-01-01 Thread Kless

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

2009-01-01 Thread Jonathan LaCour

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

2009-01-01 Thread Kless

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

2008-12-22 Thread Kless

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

2008-12-22 Thread Kless

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

2008-12-21 Thread Michael Bayer


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

2008-12-21 Thread Kless

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

2008-12-21 Thread Michael Bayer

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
-~--~~~~--~~--~--~---