Files
DataLogger-Generic/web_db/mysql-connector-python-2.1.4/tests/test_conversion.py
2016-11-01 16:56:22 -05:00

515 lines
17 KiB
Python

# -*- coding: utf-8 -*-
# MySQL Connector/Python - MySQL driver written in Python.
# Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved.
# MySQL Connector/Python is licensed under the terms of the GPLv2
# <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most
# MySQL Connectors. There are special exceptions to the terms and
# conditions of the GPLv2 as it is applied to this software, see the
# FOSS License Exception
# <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
"""Unittests for mysql.connector.conversion
"""
from decimal import Decimal
import datetime
import time
import uuid
import tests
from mysql.connector import conversion, constants
from mysql.connector.catch23 import PY2
class MySQLConverterBaseTests(tests.MySQLConnectorTests):
def test_init(self):
cnv = conversion.MySQLConverterBase()
self.assertEqual('utf8', cnv.charset)
self.assertEqual(True, cnv.use_unicode)
def test_init2(self):
cnv = conversion.MySQLConverterBase(charset='latin1',
use_unicode=False)
self.assertEqual('latin1', cnv.charset)
self.assertEqual(False, cnv.use_unicode)
def test_set_charset(self):
cnv = conversion.MySQLConverterBase()
cnv.set_charset('latin2')
self.assertEqual('latin2', cnv.charset)
def test_set_useunicode(self):
cnv = conversion.MySQLConverterBase()
cnv.set_unicode(False)
self.assertEqual(False, cnv.use_unicode)
def test_to_mysql(self):
cnv = conversion.MySQLConverterBase()
self.assertEqual('a value', cnv.to_mysql('a value'))
def test_to_python(self):
cnv = conversion.MySQLConverterBase()
self.assertEqual('a value', cnv.to_python('nevermind', 'a value'))
def test_escape(self):
cnv = conversion.MySQLConverterBase()
self.assertEqual("'a value'", cnv.escape("'a value'"))
def test_quote(self):
cnv = conversion.MySQLConverterBase()
self.assertEqual("'a value'", cnv.escape("'a value'"))
class MySQLConverterTests(tests.MySQLConnectorTests):
_to_python_data = [
(b'3.14', ('float', constants.FieldType.FLOAT)),
(b'128', ('int', constants.FieldType.TINY)),
(b'1281288', ('long', constants.FieldType.LONG)),
(b'3.14', ('decimal', constants.FieldType.DECIMAL)),
(b'2008-05-07', ('date', constants.FieldType.DATE)),
(b'45:34:10', ('time', constants.FieldType.TIME)),
(b'2008-05-07 22:34:10',
('datetime', constants.FieldType.DATETIME)),
(b'val1,val2', ('set', constants.FieldType.SET, None,
None, None, None, True, constants.FieldFlag.SET)),
('2008', ('year', constants.FieldType.YEAR)),
(b'\x80\x00\x00\x00', ('bit', constants.FieldType.BIT)),
(b'\xc3\xa4 utf8 string', ('utf8', constants.FieldType.STRING,
None, None, None, None, True, 0)),
]
_to_python_exp = (
float(_to_python_data[0][0]),
int(_to_python_data[1][0]),
int(_to_python_data[2][0]),
Decimal('3.14'),
datetime.date(2008, 5, 7),
datetime.timedelta(hours=45, minutes=34, seconds=10),
datetime.datetime(2008, 5, 7, 22, 34, 10),
set(['val1', 'val2']),
int(_to_python_data[8][0]),
2147483648,
unicode(b'\xc3\xa4 utf8 string', 'utf8') if PY2 \
else str(b'\xc3\xa4 utf8 string', 'utf8')
)
def setUp(self):
self.cnv = conversion.MySQLConverter()
def tearDown(self):
pass
def test_init(self):
pass
def test_escape(self):
"""Making strings ready for MySQL operations"""
data = (
None, # should stay the same
int(128), # should stay the same
int(1281288), # should stay the same
float(3.14), # should stay the same
Decimal('3.14'), # should stay a Decimal
r'back\slash',
'newline\n',
'return\r',
"'single'",
'"double"',
'windows\032',
)
exp = (
None,
128,
1281288,
float(3.14),
Decimal("3.14"),
'back\\\\slash',
'newline\\n',
'return\\r',
"\\'single\\'",
'\\"double\\"',
'windows\\\x1a'
)
res = tuple([self.cnv.escape(v) for v in data])
self.assertTrue(res, exp)
def test_quote(self):
"""Quote values making them ready for MySQL operations."""
data = [
None,
int(128),
int(1281288),
float(3.14),
Decimal('3.14'),
b'string A',
b"string B",
]
exp = (
b'NULL',
b'128',
b'1281288',
repr(float(3.14)) if PY2 else b'3.14',
b'3.14',
b"'string A'",
b"'string B'",
)
res = tuple([self.cnv.quote(value) for value in data])
self.assertEqual(res, exp)
def test_to_mysql(self):
"""Convert Python types to MySQL types using helper method"""
st_now = time.localtime()
data = (
128, # int
1281288, # long
float(3.14), # float
'Strings are sexy',
r'\u82b1',
None,
datetime.datetime(2008, 5, 7, 20, 0o1, 23),
datetime.date(2008, 5, 7),
datetime.time(20, 0o3, 23),
st_now,
datetime.timedelta(hours=40, minutes=30, seconds=12),
Decimal('3.14'),
)
exp = (
data[0],
data[1],
data[2],
self.cnv._str_to_mysql(data[3]),
self.cnv._str_to_mysql(data[4]),
None,
b'2008-05-07 20:01:23',
b'2008-05-07',
b'20:03:23',
time.strftime('%Y-%m-%d %H:%M:%S', st_now).encode('ascii'),
b'40:30:12',
b'3.14',
)
res = tuple([self.cnv.to_mysql(value) for value in data])
self.assertEqual(res, exp)
self.assertRaises(TypeError, self.cnv.to_mysql, uuid.uuid4())
def test__str_to_mysql(self):
"""A Python string becomes bytes."""
data = 'This is a string'
exp = data.encode()
res = self.cnv._str_to_mysql(data)
self.assertEqual(exp, res)
def test__bytes_to_mysql(self):
"""A Python bytes stays bytes."""
data = b'This is a bytes'
exp = data
res = self.cnv._bytes_to_mysql(data)
self.assertEqual(exp, res)
def test__bytearray_to_mysql(self):
"""A Python bytearray becomes bytes."""
data = bytearray(b'This is a bytearray',)
exp = bytes(data)
res = self.cnv._bytearray_to_mysql(data)
self.assertEqual(exp, res)
def test__nonetype_to_mysql(self):
"""Python None stays None for MySQL."""
data = None
res = self.cnv._nonetype_to_mysql(data)
self.assertEqual(data, res)
def test__datetime_to_mysql(self):
"""A datetime.datetime becomes formatted like Y-m-d H:M:S[.f]"""
cases = [
(datetime.datetime(2008, 5, 7, 20, 1, 23),
b'2008-05-07 20:01:23'),
(datetime.datetime(2012, 5, 2, 20, 1, 23, 10101),
b'2012-05-02 20:01:23.010101')
]
for data, exp in cases:
self.assertEqual(exp, self.cnv._datetime_to_mysql(data))
def test__date_to_mysql(self):
"""A datetime.date becomes formatted like Y-m-d"""
data = datetime.date(2008, 5, 7)
res = self.cnv._date_to_mysql(data)
exp = data.strftime('%Y-%m-%d').encode('ascii')
self.assertEqual(exp, res)
def test__time_to_mysql(self):
"""A datetime.time becomes formatted like Y-m-d H:M:S[.f]"""
cases = [
(datetime.time(20, 3, 23), b'20:03:23'),
(datetime.time(20, 3, 23, 10101), b'20:03:23.010101'),
]
for data, exp in cases:
self.assertEqual(exp, self.cnv._time_to_mysql(data))
def test__struct_time_to_mysql(self):
"""A time.struct_time becomes formatted like Y-m-d H:M:S"""
data = time.localtime()
res = self.cnv._struct_time_to_mysql(data)
exp = time.strftime('%Y-%m-%d %H:%M:%S', data).encode('ascii')
self.assertEqual(exp, res)
def test__timedelta_to_mysql(self):
"""A datetime.timedelta becomes format like 'H:M:S[.f]'"""
cases = [
(datetime.timedelta(hours=40, minutes=30, seconds=12),
b'40:30:12'),
(datetime.timedelta(hours=-40, minutes=30, seconds=12),
b'-39:29:48'),
(datetime.timedelta(hours=40, minutes=-1, seconds=12),
b'39:59:12'),
(datetime.timedelta(hours=-40, minutes=60, seconds=12),
b'-38:59:48'),
(datetime.timedelta(hours=40, minutes=30, seconds=12,
microseconds=10101),
b'40:30:12.010101'),
(datetime.timedelta(hours=-40, minutes=30, seconds=12,
microseconds=10101),
b'-39:29:47.989899'),
(datetime.timedelta(hours=40, minutes=-1, seconds=12,
microseconds=10101),
b'39:59:12.010101'),
(datetime.timedelta(hours=-40, minutes=60, seconds=12,
microseconds=10101),
b'-38:59:47.989899'),
]
for i, case in enumerate(cases):
data, exp = case
self.assertEqual(exp, self.cnv._timedelta_to_mysql(data),
"Case {0} failed: {1}; got {2}".format(
i + 1, repr(data),
self.cnv._timedelta_to_mysql(data)))
def test__decimal_to_mysql(self):
"""A decimal.Decimal becomes a string."""
data = Decimal('3.14')
self.assertEqual(b'3.14', self.cnv._decimal_to_mysql(data))
def test_to_python(self):
"""Convert MySQL data to Python types using helper method"""
res = tuple(
[self.cnv.to_python(v[1], v[0]) for v in self._to_python_data])
self.assertEqual(res, tuple(self._to_python_exp))
def test_row_to_python(self):
data = [v[0] for v in self._to_python_data]
description = [v[1] for v in self._to_python_data]
res = self.cnv.row_to_python(data, description)
self.assertEqual(res, self._to_python_exp)
def test__FLOAT_to_python(self):
"""Convert a MySQL FLOAT/DOUBLE to a Python float type"""
data = b'3.14'
exp = float(data)
res = self.cnv._FLOAT_to_python(data)
self.assertEqual(exp, res)
self.assertEqual(self.cnv._FLOAT_to_python,
self.cnv._DOUBLE_to_python)
def test__INT_to_python(self):
"""Convert a MySQL TINY/SHORT/INT24/INT to a Python int type"""
data = b'128'
exp = int(data)
res = self.cnv._INT_to_python(data)
self.assertEqual(exp, res)
self.assertEqual(self.cnv._INT_to_python, self.cnv._TINY_to_python)
self.assertEqual(self.cnv._INT_to_python, self.cnv._SHORT_to_python)
self.assertEqual(self.cnv._INT_to_python, self.cnv._INT24_to_python)
def test__LONG_to_python(self):
"""Convert a MySQL LONG/LONGLONG to a Python long type"""
data = b'1281288'
exp = int(data)
res = self.cnv._LONG_to_python(data)
self.assertEqual(exp, res)
self.assertEqual(self.cnv._LONG_to_python,
self.cnv._LONGLONG_to_python)
def test__DECIMAL_to_python(self):
"""Convert a MySQL DECIMAL to a Python decimal.Decimal type"""
data = b'3.14'
exp = Decimal('3.14')
res = self.cnv._DECIMAL_to_python(data)
self.assertEqual(exp, res)
self.assertEqual(self.cnv._DECIMAL_to_python,
self.cnv._NEWDECIMAL_to_python)
def test__BIT_to_python(self):
"""Convert a MySQL BIT to Python int"""
data = [
b'\x80',
b'\x80\x00',
b'\x80\x00\x00',
b'\x80\x00\x00\x00',
b'\x80\x00\x00\x00\x00',
b'\x80\x00\x00\x00\x00\x00',
b'\x80\x00\x00\x00\x00\x00\x00',
b'\x80\x00\x00\x00\x00\x00\x00\x00',
]
exp = [128, 32768, 8388608, 2147483648, 549755813888,
140737488355328, 36028797018963968, 9223372036854775808]
for i, buf in enumerate(data):
self.assertEqual(self.cnv._BIT_to_python(buf), exp[i])
def test__DATE_to_python(self):
"""Convert a MySQL DATE to a Python datetime.date type"""
data = b'2008-05-07'
exp = datetime.date(2008, 5, 7)
res = self.cnv._DATE_to_python(data)
self.assertEqual(exp, res)
res = self.cnv._DATE_to_python(b'0000-00-00')
self.assertEqual(None, res)
res = self.cnv._DATE_to_python(b'1000-00-00')
self.assertEqual(None, res)
def test__TIME_to_python(self):
"""Convert a MySQL TIME to a Python datetime.time type"""
cases = [
(b'45:34:10',
datetime.timedelta(hours=45, minutes=34, seconds=10)),
(b'-45:34:10',
datetime.timedelta(-2, 8750)),
(b'45:34:10.010101',
datetime.timedelta(hours=45, minutes=34, seconds=10,
microseconds=10101)),
(b'-45:34:10.010101',
datetime.timedelta(-2, 8749, 989899)),
]
for i, case in enumerate(cases):
data, exp = case
self.assertEqual(exp, self.cnv._TIME_to_python(data),
"Case {0} failed: {1}; got {2}".format(
i + 1, repr(data),
repr(self.cnv._TIME_to_python(data))))
def test__DATETIME_to_python(self):
"""Convert a MySQL DATETIME to a Python datetime.datetime type"""
cases = [
(b'2008-05-07 22:34:10',
datetime.datetime(2008, 5, 7, 22, 34, 10)),
(b'2008-05-07 22:34:10.010101',
datetime.datetime(2008, 5, 7, 22, 34, 10, 10101)),
(b'0000-00-00 00:00:00', None),
(b'1000-00-00 00:00:00', None),
]
for data, exp in cases:
self.assertEqual(exp, self.cnv._DATETIME_to_python(data))
def test__YEAR_to_python(self):
"""Convert a MySQL YEAR to Python int"""
data = '2008'
exp = 2008
self.assertEqual(exp, self.cnv._YEAR_to_python(data))
data = 'foobar'
self.assertRaises(ValueError, self.cnv._YEAR_to_python, data)
def test__SET_to_python(self):
"""Convert a MySQL SET type to a Python sequence
This actually calls hte _STRING_to_python() method since a SET is
returned as string by MySQL. However, the description of the field
has in it's field flags that the string is a SET.
"""
data = b'val1,val2'
exp = set(['val1', 'val2'])
desc = ('foo', constants.FieldType.STRING,
2, 3, 4, 5, 6, constants.FieldFlag.SET)
res = self.cnv._STRING_to_python(data, desc)
self.assertEqual(exp, res)
def test__STRING_to_python_utf8(self):
"""Convert a UTF-8 MySQL STRING/VAR_STRING to a Python Unicode type"""
self.cnv.set_charset('utf8') # default
data = b'\xc3\xa4 utf8 string'
exp = data.decode('utf-8')
res = self.cnv._STRING_to_python(data)
self.assertEqual(exp, res)
def test__STRING_to_python_latin1(self):
"""Convert a ISO-8859-1 MySQL STRING/VAR_STRING to a Python str"""
self.cnv.set_charset('latin1')
self.cnv.set_unicode(False)
data = b'\xe4 latin string'
exp = data
res = self.cnv._STRING_to_python(data)
self.assertEqual(exp, res)
exp = data.decode('latin1')
self.cnv.set_unicode(True)
res = self.cnv._STRING_to_python(data)
self.assertEqual(exp, res)
self.cnv.set_charset('utf8')
self.cnv.set_unicode(True)
def test__STRING_to_python_binary(self):
"""Convert a STRING BINARY to Python bytes type"""
data = b'\x33\xfd\x34\xed'
desc = ('foo', constants.FieldType.STRING,
2, 3, 4, 5, 6, constants.FieldFlag.BINARY)
res = self.cnv._STRING_to_python(data, desc)
self.assertEqual(data, res)
def test__BLOB_to_python_binary(self):
"""Convert a BLOB BINARY to Python bytes type"""
data = b'\x33\xfd\x34\xed'
desc = ('foo', constants.FieldType.BLOB,
2, 3, 4, 5, 6, constants.FieldFlag.BINARY)
res = self.cnv._BLOB_to_python(data, desc)
self.assertEqual(data, res)