Re: [sqlalchemy] converting date @ hybrid property

2015-08-24 Thread Mehdi
After reading more documents i ended up using comparator for my hybrid 
property instead of expression. like:
class JalaliDateComparator(Comparator):

def operate(self, op, other):
input_date = self.__clause_element__()
g_date = other.togregorian()

return op(input_date, g_date)

So far it seems working, but i'll consider your solution too. i'm not sure 
which way is best practice but i'm happy that i have two solutions :)
Thanks for your reply.


On Monday, August 24, 2015 at 7:24:26 AM UTC+4:30, Michael Bayer wrote:


 On 8/22/15 4:30 PM, Mehdi wrote:

 Hi
 I'm using latest sqlalchemy with an Oracle db backend.
 I have a Date column which presents a *Gregorian date* in db. but i want 
 to query my table by a *Jalali date*.
 So the hybrid_property to convert gregorian date into jalali date should 
 be like this, i think:
 @hybrid_property
 def jalali_date(self):
 return jdatetime.date.fromgregorian(year=self.input_date.year,
 month=self.input_date,
 day=self.input_date.day)


 i've tried different ways, but all of them ends with errors like:
 AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' 
 object associated with MeasureData.input_date has an attribute 'year'
 or
 TypeError: an integer is required (got type InstrumentedAttribute)

 So i guess i have to get access to *instance value* of 
 *MeasureDate.input_date* at hybrid_property definition, but How?
 Do i have to completely change my approach?


 the hybrid allows a Python representation at the object level and a SQL 
 representation at the class level.  Your error message involves the term 
 InstrumentedAttribute, which suggests you are attempting to use this 
 hybrid at the class level (please provide full stack traces to make this 
 clearer). Your hybrid as defined only illustrates instance-level 
 conversions and there's not a simple way to do this conversion at the SQL 
 level especially in Oracle, unless you had some stored procedure which does 
 so. 

 Therefore, you are probably looking for an in-Python value of a Jalali 
 date to be converted from the alternate calendar to the gregorian 
 (SQL-persisted) calendar *in python*, before it is sent to the database, 
 and converted back to Jalali *in Python* after being received from the 
 database as a result.  For this, you want to build a custom type similar to 
 the MyEpochType illustrated at 
 http://docs.sqlalchemy.org/en/rel_1_0/core/custom_types.html#augmenting-existing-types
  
 - using this type will cause expressions like equality comparisons to 
 coerce the value side of the expression, e.g. the raw datetime object, as 
 according to your rules.  You can then cause this particular type to be 
 used with your hybrid using type_coerce.Here's an example using most 
 features of hybrids:

 from sqlalchemy import *
 from sqlalchemy.orm import *
 from sqlalchemy.ext.declarative import declarative_base
 from sqlalchemy.ext.hybrid import hybrid_property
 import jdatetime
 import datetime

 Base = declarative_base()


 class JDate(TypeDecorator):
 impl = Date

 def process_bind_param(self, value, dialect):
 if value is not None:
 value = jdatetime.date.togregorian(value)
 return value

 def process_result_value(self, value, dialect):
 if value is not None:
 value = jdatetime.date.fromgregorian(
 year=value.year,
 month=value.month,
 day=value.day)
 return value


 class A(Base):
 __tablename__ = 'a'
 id = Column(Integer, primary_key=True)

 input_date = Column(Date)

 @hybrid_property
 def jalali_date(self):
 return jdatetime.date.fromgregorian(
 year=self.input_date.year,
 month=self.input_date.month,
 day=self.input_date.day)

 @jalali_date.expression
 def jalali_date(cls):
 return type_coerce(cls.input_date, JDate)

 @jalali_date.setter
 def jalali_date(self, value):
 self.input_date = jdatetime.date.togregorian(value)


 e = create_engine(postgresql://scott:tiger@localhost/test, echo=True)
 Base.metadata.drop_all(e)
 Base.metadata.create_all(e)


 a1 = A(jalali_date=jdatetime.date(1380, 8, 2))
 a2 = A(input_date=datetime.date(2001, 10, 24))

 s = Session(e)
 s.add_all([a1, a2])
 s.commit()
 s.close()

 a1, a2 = s.query(A).filter_by(jalali_date=jdatetime.date(1380, 8, 2)).all()

 print a1.jalali_date, a2.jalali_date
 print a1.input_date, a2.input_date



 in the output, we can see that jalali_date and input_date are consistent 
 from both ways of setting, both ways of matching:

 1380-08-02 1380-08-02
 2001-10-24 2001-10-24








 Thanks.
 -- 
 You received this message because you are subscribed to the Google Groups 
 sqlalchemy group.
 To unsubscribe from this group and stop receiving emails from it, send an 
 email to 

Re: [sqlalchemy] converting date @ hybrid property

2015-08-23 Thread Mike Bayer


On 8/22/15 4:30 PM, Mehdi wrote:

Hi
I'm using latest sqlalchemy with an Oracle db backend.
I have a Date column which presents a /Gregorian date/ in db. but i 
want to query my table by a /Jalali date/.
So the hybrid_property to convert gregorian date into jalali date 
should be like this, i think:

|
@hybrid_property
defjalali_date(self):
returnjdatetime.date.fromgregorian(year=self.input_date.year,
month=|self.input_date|,
day=|self.input_date.day|)

|

i've tried different ways, but all of them ends with errors like:
|
AttributeError: Neither 'InstrumentedAttribute' object nor 
'Comparator' object associated with MeasureData.input_date has an 
attribute 'year'

or
TypeError: an integer is required (got type InstrumentedAttribute)
|

So i guess i have to get access to *instance value* of 
/MeasureDate.input_date/ at hybrid_property definition, but How?

Do i have to completely change my approach?


the hybrid allows a Python representation at the object level and a SQL 
representation at the class level.  Your error message involves the term 
InstrumentedAttribute, which suggests you are attempting to use this 
hybrid at the class level (please provide full stack traces to make this 
clearer). Your hybrid as defined only illustrates instance-level 
conversions and there's not a simple way to do this conversion at the 
SQL level especially in Oracle, unless you had some stored procedure 
which does so.


Therefore, you are probably looking for an in-Python value of a Jalali 
date to be converted from the alternate calendar to the gregorian 
(SQL-persisted) calendar *in python*, before it is sent to the database, 
and converted back to Jalali *in Python* after being received from the 
database as a result.  For this, you want to build a custom type similar 
to the MyEpochType illustrated at 
http://docs.sqlalchemy.org/en/rel_1_0/core/custom_types.html#augmenting-existing-types 
- using this type will cause expressions like equality comparisons to 
coerce the value side of the expression, e.g. the raw datetime object, 
as according to your rules.  You can then cause this particular type to 
be used with your hybrid using type_coerce. Here's an example using most 
features of hybrids:


from sqlalchemy import *
from sqlalchemy.orm import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.ext.hybrid import hybrid_property
import jdatetime
import datetime

Base = declarative_base()


class JDate(TypeDecorator):
impl = Date

def process_bind_param(self, value, dialect):
if value is not None:
value = jdatetime.date.togregorian(value)
return value

def process_result_value(self, value, dialect):
if value is not None:
value = jdatetime.date.fromgregorian(
year=value.year,
month=value.month,
day=value.day)
return value


class A(Base):
__tablename__ = 'a'
id = Column(Integer, primary_key=True)

input_date = Column(Date)

@hybrid_property
def jalali_date(self):
return jdatetime.date.fromgregorian(
year=self.input_date.year,
month=self.input_date.month,
day=self.input_date.day)

@jalali_date.expression
def jalali_date(cls):
return type_coerce(cls.input_date, JDate)

@jalali_date.setter
def jalali_date(self, value):
self.input_date = jdatetime.date.togregorian(value)


e = create_engine(postgresql://scott:tiger@localhost/test, echo=True)
Base.metadata.drop_all(e)
Base.metadata.create_all(e)


a1 = A(jalali_date=jdatetime.date(1380, 8, 2))
a2 = A(input_date=datetime.date(2001, 10, 24))

s = Session(e)
s.add_all([a1, a2])
s.commit()
s.close()

a1, a2 = s.query(A).filter_by(jalali_date=jdatetime.date(1380, 8, 2)).all()

print a1.jalali_date, a2.jalali_date
print a1.input_date, a2.input_date



in the output, we can see that jalali_date and input_date are consistent 
from both ways of setting, both ways of matching:


1380-08-02 1380-08-02
2001-10-24 2001-10-24









Thanks.
--
You received this message because you are subscribed to the Google 
Groups sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send 
an email to sqlalchemy+unsubscr...@googlegroups.com 
mailto:sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com 
mailto:sqlalchemy@googlegroups.com.

Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.


--
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit 

[sqlalchemy] converting date @ hybrid property

2015-08-22 Thread Mehdi
Hi
I'm using latest sqlalchemy with an Oracle db backend.
I have a Date column which presents a *Gregorian date* in db. but i want to 
query my table by a *Jalali date*.
So the hybrid_property to convert gregorian date into jalali date should be 
like this, i think:
@hybrid_property
def jalali_date(self):
return jdatetime.date.fromgregorian(year=self.input_date.year,
month=self.input_date,
day=self.input_date.day)


i've tried different ways, but all of them ends with errors like:
AttributeError: Neither 'InstrumentedAttribute' object nor 'Comparator' 
object associated with MeasureData.input_date has an attribute 'year'
or
TypeError: an integer is required (got type InstrumentedAttribute)

So i guess i have to get access to *instance value* of 
*MeasureDate.input_date* at hybrid_property definition, but How?
Do i have to completely change my approach?

Thanks.

-- 
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.