def to_decimal(value): if value is None: return None elif isinstance(value, decimal.Decimal): return value else: return decimal.Decimal(fstring % value)
def round_decimal(value, prec): if isinstance(value, float): return round(value, prec) # can also use shift() here but that is 2.6 only return (value * decimal.Decimal("1" + "0" * prec)).to_integral(decimal.ROUND_FLOOR) / \ pow(10, prec)
def test_return_type_detection(self): for fn in [func.coalesce, func.max, func.min, func.sum]: for args, type_ in [ ((datetime.date(2007, 10, 5), datetime.date(2005, 10, 15)), sqltypes.Date), ((3, 5), sqltypes.Integer), ((decimal.Decimal(3), decimal.Decimal(5)), sqltypes.Numeric), (("foo", "bar"), sqltypes.String), ((datetime.datetime(2007, 10, 5, 8, 3, 34), datetime.datetime(2005, 10, 15, 14, 45, 33)), sqltypes.DateTime) ]: assert isinstance(fn(*args).type, type_), "%s / %s" % (fn(), type_) assert isinstance(func.concat("foo", "bar").type, sqltypes.String)
def _test_decimal(self, tabledef): """Checks a variety of FIXED usages. This is primarily for SERIAL columns, which can be FIXED (scale-less) or (SMALL)INT. Ensures that FIXED id columns are converted to integers and that are assignable as such. Also exercises general decimal assignment and selection behavior. """ meta = MetaData(testing.db) try: if isinstance(tabledef, basestring): # run textual CREATE TABLE testing.db.execute(tabledef) else: _t = tabledef.tometadata(meta) _t.create() t = Table('dectest', meta, autoload=True) vals = [ decimal.Decimal('2.2'), decimal.Decimal('23'), decimal.Decimal('2.4'), 25 ] cols = ['d1', 'd2', 'n1', 'i1'] t.insert().execute(dict(zip(cols, vals))) roundtrip = list(t.select().execute()) eq_(roundtrip, [tuple([1] + vals)]) t.insert().execute( dict(zip(['id'] + cols, [2] + list(roundtrip[0][1:])))) roundtrip2 = list(t.select(order_by=t.c.id).execute()) eq_(roundtrip2, [tuple([1] + vals), tuple([2] + vals)]) finally: try: testing.db.execute("DROP TABLE dectest") except exc.DatabaseError: pass
def _detect_decimal_char(self, connection): """detect if the decimal separator character is not '.', as is the case with european locale settings for NLS_LANG. cx_oracle itself uses similar logic when it formats Python Decimal objects to strings on the bind side (as of 5.0.3), as Oracle sends/receives string numerics only in the current locale. """ if self.cx_oracle_ver < (5, ): # no output type handlers before version 5 return cx_Oracle = self.dbapi conn = connection.connection # override the output_type_handler that's # on the cx_oracle connection with a plain # one on the cursor def output_type_handler(cursor, name, defaultType, size, precision, scale): return cursor.var(cx_Oracle.STRING, 255, arraysize=cursor.arraysize) cursor = conn.cursor() cursor.outputtypehandler = output_type_handler cursor.execute("SELECT 0.1 FROM DUAL") val = cursor.fetchone()[0] cursor.close() char = re.match(r"([\.,])", val).group(1) if char != '.': _detect_decimal = self._detect_decimal self._detect_decimal = \ lambda value: _detect_decimal(value.replace(char, '.')) self._to_decimal = \ lambda value: decimal.Decimal(value.replace(char, '.'))
def _detect_decimal(self, value): if "." in value: return decimal.Decimal(value) else: return int(value)