Changeset 585


Ignore:
Timestamp:
Nov 21, 2015, 11:00:14 PM (4 years ago)
Author:
cito
Message:

Make non-ascii query results work with Python 3

Location:
trunk/module
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/module/TEST_PyGreSQL_classic_connection.py

    r580 r585  
    3131except NameError:  # Python >= 3.0
    3232    long = int
     33
     34unicode_strings = str is not bytes
    3335
    3436# We need a database to test against.  If LOCAL_PyGreSQL.py exists we will
     
    400402        num_cols = 100
    401403        num_rows = 100
    402         q = "select " + ','.join(map(str, xrange(num_cols)))
     404        q = "select " + ','.join(map(str, range(num_cols)))
    403405        q = ' union all '.join((q,) * num_rows)
    404406        r = self.c.query(q).getresult()
     
    569571        self.assertEqual(query("select $1::integer+$2", [1, 2]
    570572            ).getresult(), [(3,)])
    571         self.assertEqual(query("select 0+$1+$2+$3+$4+$5+$6", range(6)
     573        self.assertEqual(query("select 0+$1+$2+$3+$4+$5+$6", list(range(6))
    572574            ).getresult(), [(15,)])
    573575
     
    595597        query('set client_encoding = utf8')
    596598        self.assertEqual(query("select $1||', '||$2||'!'",
    597             ('Hello', u'w\xf6rld')).getresult(), [('Hello, w\xc3\xb6rld!',)])
     599            ('Hello', u'wörld')).getresult(), [('Hello, wörld!',)])
    598600        self.assertEqual(query("select $1||', '||$2||'!'",
    599             ('Hello', u'\u043c\u0438\u0440')).getresult(),
    600             [('Hello, \xd0\xbc\xd0\xb8\xd1\x80!',)])
     601            ('Hello', u'ЌОр')).getresult(),
     602            [('Hello, ЌОр!',)])
    601603        query('set client_encoding = latin1')
    602         self.assertEqual(query("select $1||', '||$2||'!'",
    603             ('Hello', u'w\xf6rld')).getresult(), [('Hello, w\xf6rld!',)])
     604        r = query("select $1||', '||$2||'!'", ('Hello', u'wörld')).getresult()
     605        if unicode_strings:
     606            self.assertEqual(r, [('Hello, wörld!',)])
     607        else:
     608            self.assertEqual(r, [(u'Hello, wörld!'.encode('latin1'),)])
    604609        self.assertRaises(UnicodeError, query, "select $1||', '||$2||'!'",
    605             ('Hello', u'\u043c\u0438\u0440'))
     610            ('Hello', u'ЌОр'))
    606611        query('set client_encoding = iso_8859_1')
    607         self.assertEqual(query("select $1||', '||$2||'!'",
    608             ('Hello', u'w\xf6rld')).getresult(), [('Hello, w\xf6rld!',)])
     612        r = query("select $1||', '||$2||'!'", ('Hello', u'wörld')).getresult()
     613        if unicode_strings:
     614            self.assertEqual(r, [('Hello, wörld!',)])
     615        else:
     616            self.assertEqual(r, [(u'Hello, wörld!'.encode('latin1'),)])
    609617        self.assertRaises(UnicodeError, query, "select $1||', '||$2||'!'",
    610             ('Hello', u'\u043c\u0438\u0440'))
     618            ('Hello', u'ЌОр'))
    611619        query('set client_encoding = iso_8859_5')
    612620        self.assertRaises(UnicodeError, query, "select $1||', '||$2||'!'",
    613             ('Hello', u'w\xf6rld'))
    614         self.assertEqual(query("select $1||', '||$2||'!'",
    615             ('Hello', u'\u043c\u0438\u0440')).getresult(),
    616             [('Hello, \xdc\xd8\xe0!',)])
     621            ('Hello', u'wörld'))
     622        r = query("select $1||', '||$2||'!'", ('Hello', u'ЌОр')).getresult()
     623        if unicode_strings:
     624            self.assertEqual(r, [('Hello, ЌОр!',)])
     625        else:
     626            self.assertEqual(r, [(u'Hello, ЌОр!'.encode('cyrillic'),)])
    617627        query('set client_encoding = sql_ascii')
    618628        self.assertRaises(UnicodeError, query, "select $1||', '||$2||'!'",
    619             ('Hello', u'w\xf6rld'))
     629            ('Hello', u'wörld'))
    620630
    621631    def testQueryWithMixedParams(self):
     
    643653        query = self.c.query
    644654        self.assertEqual(query(u"select 1+1").getresult(), [(2,)])
    645         self.assertRaises(TypeError, query, u"select 'Hello, w\xf6rld!'")
     655        if unicode_strings:
     656            self.assertEqual(query("select 'Hello, wörld!'").getresult(),
     657                [('Hello, wörld!',)])
     658        else:
     659            self.assertRaises(TypeError, query, u"select 'Hello, wörld!'")
    646660
    647661
  • trunk/module/pgmodule.c

    r584 r585  
    111111static char *decimal_point = "."; /* decimal point used in money values */
    112112
     113static int pg_encoding_utf8 = 0;
     114static int pg_encoding_latin1 = 0;
     115static int pg_encoding_ascii = 0;
     116
    113117/*
    114118OBJECTS
     
    181185        PyObject_HEAD
    182186        PGresult        *result;                /* result content */
    183         int                     result_type;    /* type of previous result */
    184         long            current_pos;    /* current position in last result */
    185         long            num_rows;               /* number of (affected) rows */
     187        int                     encoding;               /* client encoding */
    186188}       queryObject;
    187189#define is_queryObject(v) (PyType(v) == &queryType)
     
    10781080        PGresult        *result;
    10791081        queryObject *npgobj;
    1080         int                     status,
     1082        const char*     encoding_name=NULL;
     1083        int                     encoding,
     1084                                status,
    10811085                                nparms = 0;
    10821086
     
    11091113        }
    11101114
     1115        encoding = PQclientEncoding(self->cnx);
     1116        if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
     1117                        && encoding != pg_encoding_ascii)
     1118                /* should be translated to Python here */
     1119                encoding_name = pg_encoding_to_char(encoding);
     1120
    11111121        /* gets result */
    11121122        if (nparms)
     
    11141124                /* prepare arguments */
    11151125                PyObject        **str, **s, *obj = PySequence_GetItem(oargs, 0);
    1116                 char            **parms, **p, *enc=NULL;
     1126                char            **parms, **p;
    11171127                int                     *lparms, *l;
    11181128                register int i;
     
    11501160                        else if (PyUnicode_Check(obj))
    11511161                        {
    1152                                 if (!enc)
    1153                                         enc = (char *)pg_encoding_to_char(
    1154                                                 PQclientEncoding(self->cnx));
    1155                                 if (!strcmp(enc, "UTF8"))
     1162                                if (encoding == pg_encoding_utf8)
    11561163                                        *s = PyUnicode_AsUTF8String(obj);
    1157                                 else if (!strcmp(enc, "LATIN1"))
     1164                                else if (encoding == pg_encoding_latin1)
    11581165                                        *s = PyUnicode_AsLatin1String(obj);
    1159                                 else if (!strcmp(enc, "SQL_ASCII"))
     1166                                else if (encoding == pg_encoding_ascii)
    11601167                                        *s = PyUnicode_AsASCIIString(obj);
    11611168                                else
    1162                                         *s = PyUnicode_AsEncodedString(obj, enc, "strict");
     1169                                        *s = PyUnicode_AsEncodedString(obj,
     1170                                                encoding_name, "strict");
    11631171                                if (*s == NULL)
    11641172                                {
     
    12851293        /* stores result and returns object */
    12861294        npgobj->result = result;
     1295        npgobj->encoding = encoding;
    12871296        return (PyObject *) npgobj;
    12881297}
     
    14201429                                *buffer,
    14211430                                *bufpt;
    1422         char            *enc=NULL;
     1431        const char *encoding_name=NULL;
     1432        int                     encoding;
    14231433        size_t          bufsiz;
    14241434        PyObject        *list,
     
    14861496                return NULL;
    14871497        }
     1498
     1499        encoding = PQclientEncoding(self->cnx);
     1500        if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
     1501                        && encoding != pg_encoding_ascii)
     1502                /* should be translated to Python here */
     1503                encoding_name = pg_encoding_to_char(encoding);
    14881504
    14891505        PQclear(result);
     
    15661582                        {
    15671583                                PyObject *s;
    1568                                 if (!enc)
    1569                                         enc = (char *)pg_encoding_to_char(
    1570                                                 PQclientEncoding(self->cnx));
    1571                                 if (!strcmp(enc, "UTF8"))
     1584                                if (encoding == pg_encoding_utf8)
    15721585                                        s = PyUnicode_AsUTF8String(item);
    1573                                 else if (!strcmp(enc, "LATIN1"))
     1586                                else if (encoding == pg_encoding_latin1)
    15741587                                        s = PyUnicode_AsLatin1String(item);
    1575                                 else if (!strcmp(enc, "SQL_ASCII"))
     1588                                else if (encoding == pg_encoding_ascii)
    15761589                                        s = PyUnicode_AsASCIIString(item);
    15771590                                else
    1578                                         s = PyUnicode_AsEncodedString(item, enc, "strict");
     1591                                        s = PyUnicode_AsEncodedString(item,
     1592                                                encoding_name, "strict");
    15791593                                const char* t = PyBytes_AsString(s);
    15801594                                while (*t && bufsiz)
     
    32063220                                n,
    32073221                           *typ;
     3222#if IS_PY3
     3223        int                     encoding;
     3224        const char *encoding_name=NULL;
     3225#endif
    32083226
    32093227        /* checks args (args == NULL for an internal call) */
     
    32143232                return NULL;
    32153233        }
     3234
     3235#if IS_PY3
     3236        encoding = self->encoding;
     3237        if (encoding != pg_encoding_utf8 && encoding != pg_encoding_latin1
     3238                        && encoding != pg_encoding_ascii)
     3239                /* should be translated to Python here */
     3240                encoding_name = pg_encoding_to_char(encoding);
     3241#endif
    32163242
    32173243        /* stores result in tuple */
     
    32553281
    32563282                                        case 3:  /* float/double */
    3257                                                 tmp_obj = PyBytes_FromString(s);
     3283                                                tmp_obj = PyStr_FromString(s);
    32583284#if IS_PY3
    32593285                                                val = PyFloat_FromString(tmp_obj);
     
    32883314                                                else
    32893315                                                {
    3290                                                         tmp_obj = PyBytes_FromString(s);
     3316                                                        tmp_obj = PyStr_FromString(s);
    32913317#if IS_PY3
    32923318                                                        val = PyFloat_FromString(tmp_obj);
     
    32993325
    33003326                                        default:
    3301                                                 val = PyStr_FromString(s);
     3327#if IS_PY3
     3328                                                if (encoding == pg_encoding_utf8)
     3329                                                        val = PyUnicode_DecodeUTF8(s, strlen(s), "strict");
     3330                                                else if (encoding == pg_encoding_latin1)
     3331                                                        val = PyUnicode_DecodeLatin1(s, strlen(s), "strict");
     3332                                                else if (encoding == pg_encoding_ascii)
     3333                                                        val = PyUnicode_DecodeASCII(s, strlen(s), "strict");
     3334                                                else
     3335                                                        val = PyUnicode_Decode(s, strlen(s),
     3336                                                                encoding_name, "strict");
     3337                                                if (!val)
     3338                                                        val = PyBytes_FromString(s);
     3339#else
     3340                                                val = PyBytes_FromString(s);
     3341#endif
    33023342                                                break;
    33033343                                }
     
    43604400#endif /* DEFAULT_VARS */
    43614401
     4402        /* store common pg encoding ids */
     4403
     4404        pg_encoding_utf8 = pg_char_to_encoding("UTF8");
     4405        pg_encoding_latin1 = pg_char_to_encoding("LATIN1");
     4406        pg_encoding_ascii = pg_char_to_encoding("SQL_ASCII");
     4407
    43624408        /* Check for errors */
    43634409        if (PyErr_Occurred())
Note: See TracChangeset for help on using the changeset viewer.