From b52ff101535218cbf2f6e203dac6dc86b173d4f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miro=20Hron=C4=8Dok?= Date: Fri, 18 May 2018 12:12:09 +0200 Subject: [PATCH 01/14] Travis CI: Run tests on Python 3.7 Also, switch to wheel, because eggs caused problems on 3.7: ValueError: bad marshal data (unknown type code) --- .travis.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2fbf7010..51cba9a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,12 +6,14 @@ language: python python: - 2.7 + - 3.7-dev - 3.6 - 3.5 - 3.4 install: - - python setup.py install + - pip install -U pip setuptools wheel + - pip install . - rm -rf psycopg2.egg-info - sudo scripts/travis_prepare.sh From b5e4a040f8e50928aefc4f3dc9717bbcf3520cd0 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Mon, 14 May 2018 02:38:44 +0100 Subject: [PATCH 02/14] Fixed adaptation of arrays of arrays of nulls Close #325, close #706. --- NEWS | 1 + psycopg/adapter_list.c | 113 +++++++++++++++++++++++++++----------- tests/test_types_basic.py | 29 +++++++--- 3 files changed, 104 insertions(+), 39 deletions(-) diff --git a/NEWS b/NEWS index 09b19e5f..3bce91c6 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,7 @@ Other changes: What's new in psycopg 2.7.5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Fixed adaptation of arrays of arrays of nulls (:ticket:`#325`). - Fixed building on Solaris 11 and derivatives such as SmartOS and illumos (:ticket:`#677`). - Maybe fixed building on MSYS2 (as reported in :ticket:`#658`). diff --git a/psycopg/adapter_list.c b/psycopg/adapter_list.c index dec17b4c..3fdff76a 100644 --- a/psycopg/adapter_list.c +++ b/psycopg/adapter_list.c @@ -38,13 +38,14 @@ list_quote(listObject *self) { /* adapt the list by calling adapt() recursively and then wrapping everything into "ARRAY[]" */ - PyObject *tmp = NULL, *str = NULL, *joined = NULL, *res = NULL; + PyObject *res = NULL; + PyObject **qs = NULL; + Py_ssize_t bufsize = 0; + char *buf = NULL, *ptr; /* list consisting of only NULL don't work with the ARRAY[] construct - * so we use the {NULL,...} syntax. Note however that list of lists where - * some element is a list of only null still fails: for that we should use - * the '{...}' syntax uniformly but we cannot do it in the current - * infrastructure. TODO in psycopg3 */ + * so we use the {NULL,...} syntax. The same syntax is also necessary + * to convert array of arrays containing only nulls. */ int all_nulls = 1; Py_ssize_t i, len; @@ -53,47 +54,95 @@ list_quote(listObject *self) /* empty arrays are converted to NULLs (still searching for a way to insert an empty array in postgresql */ - if (len == 0) return Bytes_FromString("'{}'"); + if (len == 0) { + res = Bytes_FromString("'{}'"); + goto exit; + } - tmp = PyTuple_New(len); + if (!(qs = PyMem_New(PyObject *, len))) { + PyErr_NoMemory(); + goto exit; + } + memset(qs, 0, len * sizeof(PyObject *)); - for (i=0; iwrapped, i); if (wrapped == Py_None) { Py_INCREF(psyco_null); - quoted = psyco_null; + qs[i] = psyco_null; } else { - quoted = microprotocol_getquoted(wrapped, - (connectionObject*)self->connection); - if (quoted == NULL) goto error; - all_nulls = 0; + if (!(qs[i] = microprotocol_getquoted( + wrapped, (connectionObject*)self->connection))) { + goto exit; + } + + /* Lists of arrays containing only nulls are also not supported + * by the ARRAY construct so we should do some special casing */ + if (!PyList_Check(wrapped) || Bytes_AS_STRING(qs[i])[0] == 'A') { + all_nulls = 0; + } } - - /* here we don't loose a refcnt: SET_ITEM does not change the - reference count and we are just transferring ownership of the tmp - object to the tuple */ - PyTuple_SET_ITEM(tmp, i, quoted); + bufsize += Bytes_GET_SIZE(qs[i]) + 1; /* this, and a comma */ } - /* now that we have a tuple of adapted objects we just need to join them - and put "ARRAY[] around the result */ - str = Bytes_FromString(", "); - joined = PyObject_CallMethod(str, "join", "(O)", tmp); - if (joined == NULL) goto error; + /* Create an array literal, usually ARRAY[...] but if the contents are + * all NULL or array of NULL we must use the '{...}' syntax + */ + if (!(ptr = buf = PyMem_Malloc(bufsize + 8))) { + PyErr_NoMemory(); + goto exit; + } - /* PG doesn't like ARRAY[NULL..] */ if (!all_nulls) { - res = Bytes_FromFormat("ARRAY[%s]", Bytes_AsString(joined)); - } else { - res = Bytes_FromFormat("'{%s}'", Bytes_AsString(joined)); + strcpy(ptr, "ARRAY["); + ptr += 6; + for (i = 0; i < len; i++) { + Py_ssize_t sl; + sl = Bytes_GET_SIZE(qs[i]); + memcpy(ptr, Bytes_AS_STRING(qs[i]), sl); + ptr += sl; + *ptr++ = ','; + } + *(ptr - 1) = ']'; + } + else { + *ptr++ = '\''; + *ptr++ = '{'; + for (i = 0; i < len; i++) { + /* in case all the adapted things are nulls (or array of nulls), + * the quoted string is either NULL or an array of the form + * '{NULL,...}', in which case we have to strip the extra quotes */ + char *s; + Py_ssize_t sl; + s = Bytes_AS_STRING(qs[i]); + sl = Bytes_GET_SIZE(qs[i]); + if (s[0] != '\'') { + memcpy(ptr, s, sl); + ptr += sl; + } + else { + memcpy(ptr, s + 1, sl - 2); + ptr += sl - 2; + } + *ptr++ = ','; + } + *(ptr - 1) = '}'; + *ptr++ = '\''; } - error: - Py_XDECREF(tmp); - Py_XDECREF(str); - Py_XDECREF(joined); + res = Bytes_FromStringAndSize(buf, ptr - buf); + +exit: + if (qs) { + for (i = 0; i < len; i++) { + PyObject *q = qs[i]; + Py_XDECREF(q); + } + PyMem_Free(qs); + } + PyMem_Free(buf); + return res; } diff --git a/tests/test_types_basic.py b/tests/test_types_basic.py index a93265d9..76b9aa3f 100755 --- a/tests/test_types_basic.py +++ b/tests/test_types_basic.py @@ -224,16 +224,31 @@ class TypesBasicTests(ConnectingTestCase): curs.execute("insert into na (boola) values (%s)", ([True, None],)) curs.execute("insert into na (boola) values (%s)", ([None, None],)) - # TODO: array of array of nulls are not supported yet - # curs.execute("insert into na (textaa) values (%s)", ([[None]],)) + curs.execute("insert into na (textaa) values (%s)", ([[None]],)) curs.execute("insert into na (textaa) values (%s)", ([['a', None]],)) - # curs.execute("insert into na (textaa) values (%s)", ([[None, None]],)) - # curs.execute("insert into na (intaa) values (%s)", ([[None]],)) + curs.execute("insert into na (textaa) values (%s)", ([[None, None]],)) + + curs.execute("insert into na (intaa) values (%s)", ([[None]],)) curs.execute("insert into na (intaa) values (%s)", ([[42, None]],)) - # curs.execute("insert into na (intaa) values (%s)", ([[None, None]],)) - # curs.execute("insert into na (boolaa) values (%s)", ([[None]],)) + curs.execute("insert into na (intaa) values (%s)", ([[None, None]],)) + + curs.execute("insert into na (boolaa) values (%s)", ([[None]],)) curs.execute("insert into na (boolaa) values (%s)", ([[True, None]],)) - # curs.execute("insert into na (boolaa) values (%s)", ([[None, None]],)) + curs.execute("insert into na (boolaa) values (%s)", ([[None, None]],)) + + @testutils.skip_before_postgres(8, 2) + def testNestedArrays(self): + curs = self.conn.cursor() + for a in [ + [[1]], + [[None]], + [[None, None, None]], + [[None, None], [1, None]], + [[None, None], [None, None]], + [[[None, None], [None, None]]], + ]: + curs.execute("select %s::int[]", (a,)) + self.assertEqual(curs.fetchone()[0], a) @testutils.skip_from_python(3) def testTypeRoundtripBuffer(self): From 8dd00ee87469d908dfa800d50d87e09ab97ed90f Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Mon, 14 May 2018 03:04:57 +0100 Subject: [PATCH 03/14] Hstore test fixed after adapting arrays dropped space after commas --- tests/test_types_extras.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_types_extras.py b/tests/test_types_extras.py index 5cb13534..cda163b6 100755 --- a/tests/test_types_extras.py +++ b/tests/test_types_extras.py @@ -179,8 +179,8 @@ class HstoreTestCase(ConnectingTestCase): m = re.match(br'hstore\(ARRAY\[([^\]]+)\], ARRAY\[([^\]]+)\]\)', q) self.assert_(m, repr(q)) - kk = m.group(1).split(b", ") - vv = m.group(2).split(b", ") + kk = m.group(1).split(b",") + vv = m.group(2).split(b",") ii = list(zip(kk, vv)) ii.sort() From bc84b6233eaa1e7a6302b51f8ab8950534ff1813 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 13 May 2018 23:51:21 +0100 Subject: [PATCH 04/14] Allow non-ascii chars in namedtuple fields They can be valid chars in Python 3. Or maybe not? In which case Python will throw an exception, but that's fine. Fix regression introduced fixing #211 --- NEWS | 2 ++ lib/extras.py | 9 ++++++--- tests/test_extras_dictcursor.py | 9 ++++++++- 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 09b19e5f..a264c907 100644 --- a/NEWS +++ b/NEWS @@ -17,6 +17,8 @@ Other changes: What's new in psycopg 2.7.5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +- Allow non-ascii chars in namedtuple fields (regression introduced fixing + :ticket':`#211`). - Fixed building on Solaris 11 and derivatives such as SmartOS and illumos (:ticket:`#677`). - Maybe fixed building on MSYS2 (as reported in :ticket:`#658`). diff --git a/lib/extras.py b/lib/extras.py index 1f85d532..9c26ccba 100644 --- a/lib/extras.py +++ b/lib/extras.py @@ -363,12 +363,15 @@ class NamedTupleCursor(_cursor): return def _make_nt(self): + # ascii except alnum and underscore + nochars = ' !"#$%&\'()*+,-./:;<=>?@[\\]^`{|}~' + re_clean = _re.compile('[' + _re.escape(nochars) + ']') + def f(s): - # NOTE: Python 3 actually allows unicode chars in fields - s = _re.sub('[^a-zA-Z0-9_]', '_', s) + s = re_clean.sub('_', s) # Python identifier cannot start with numbers, namedtuple fields # cannot start with underscore. So... - if _re.match('^[0-9_]', s): + if s[0] == '_' or '0' <= s[0] <= '9': s = 'f' + s return s diff --git a/tests/test_extras_dictcursor.py b/tests/test_extras_dictcursor.py index 99bdeee6..2a46fbaf 100755 --- a/tests/test_extras_dictcursor.py +++ b/tests/test_extras_dictcursor.py @@ -19,7 +19,7 @@ from datetime import timedelta import psycopg2 import psycopg2.extras import unittest -from .testutils import ConnectingTestCase, skip_before_postgres +from .testutils import ConnectingTestCase, skip_before_postgres, skip_before_python class ExtrasDictCursorTests(ConnectingTestCase): @@ -357,6 +357,13 @@ class NamedTupleCursorTest(ConnectingTestCase): self.assertEqual(rv.f_column_, 2) self.assertEqual(rv.f3, 3) + @skip_before_python(3) + def test_nonascii_name(self): + curs = self.conn.cursor() + curs.execute('select 1 as \xe5h\xe9') + rv = curs.fetchone() + self.assertEqual(getattr(rv, '\xe5h\xe9'), 1) + def test_minimal_generation(self): # Instrument the class to verify it gets called the minimum number of times. from psycopg2.extras import NamedTupleCursor From eb570488a40ce67fb1df3ed548bda1c57d585084 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Mon, 14 May 2018 02:41:32 +0100 Subject: [PATCH 05/14] Test databases from newest to oldest This way we can spot when a feature was not supported yet by the first test failing. --- scripts/travis_test.sh | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scripts/travis_test.sh b/scripts/travis_test.sh index 0320654a..342e24cc 100755 --- a/scripts/travis_test.sh +++ b/scripts/travis_test.sh @@ -56,15 +56,15 @@ fi # Unsupported postgres versions that we still support # Images built by https://github.com/psycopg/psycopg2-wheels/tree/build-dinosaurs if [[ -n "$TEST_PAST" ]]; then - run_test 7.4 - run_test 8.0 - run_test 8.1 - run_test 8.2 - run_test 8.3 - run_test 8.4 - run_test 9.0 - run_test 9.1 run_test 9.2 + run_test 9.1 + run_test 9.0 + run_test 8.4 + run_test 8.3 + run_test 8.2 + run_test 8.1 + run_test 8.0 + run_test 7.4 fi # Postgres built from master From dd7e5c906fc37c50852619d68d6a347ab5928371 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Mon, 14 May 2018 03:11:11 +0100 Subject: [PATCH 06/14] Skipped test on db version not supporting unicode identifiers --- tests/test_extras_dictcursor.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_extras_dictcursor.py b/tests/test_extras_dictcursor.py index 2a46fbaf..d43980af 100755 --- a/tests/test_extras_dictcursor.py +++ b/tests/test_extras_dictcursor.py @@ -358,6 +358,7 @@ class NamedTupleCursorTest(ConnectingTestCase): self.assertEqual(rv.f3, 3) @skip_before_python(3) + @skip_before_postgres(8) def test_nonascii_name(self): curs = self.conn.cursor() curs.execute('select 1 as \xe5h\xe9') From 3f389593f54a6ad3354140b77d9a6ce725c0516f Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 20 May 2018 13:22:38 +0100 Subject: [PATCH 07/14] Raise NotSupportedError fetching iso_8601 intervals Previously it would have failed parsing and resulted in ValueError Close #707 --- psycopg/typecast_datetime.c | 5 +++++ tests/test_dates.py | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/psycopg/typecast_datetime.c b/psycopg/typecast_datetime.c index f24223cb..e34117dd 100644 --- a/psycopg/typecast_datetime.c +++ b/psycopg/typecast_datetime.c @@ -406,6 +406,11 @@ typecast_PYINTERVAL_cast(const char *str, Py_ssize_t len, PyObject *curs) } break; + case 'P': + PyErr_SetString(NotSupportedError, + "iso_8601 intervalstyle currently not supported"); + return NULL; + default: break; } diff --git a/tests/test_dates.py b/tests/test_dates.py index 74dfc9ab..85216f87 100755 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -438,6 +438,13 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin): r = cur.fetchone()[0] self.assertEqual(r, v, "%s -> %s != %s" % (s, r, v)) + def test_interval_iso_8601_not_supported(self): + # We may end up supporting, but no pressure for it + cur = self.conn.cursor() + cur.execute("set local intervalstyle to iso_8601") + cur.execute("select '1 day 2 hours'::interval") + self.assertRaises(psycopg2.NotSupportedError, cur.fetchone) + # Only run the datetime tests if psycopg was compiled with support. if not hasattr(psycopg2.extensions, 'PYDATETIME'): From 49d9edce01c64dadba4fcdcd8ddeb563cd2cff63 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 20 May 2018 13:40:57 +0100 Subject: [PATCH 08/14] Set minimal postgres version for intervalstyle test --- tests/test_dates.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/test_dates.py b/tests/test_dates.py index 85216f87..bb5aee30 100755 --- a/tests/test_dates.py +++ b/tests/test_dates.py @@ -438,6 +438,7 @@ class DatetimeTests(ConnectingTestCase, CommonDatetimeTestsMixin): r = cur.fetchone()[0] self.assertEqual(r, v, "%s -> %s != %s" % (s, r, v)) + @skip_before_postgres(8, 4) def test_interval_iso_8601_not_supported(self): # We may end up supporting, but no pressure for it cur = self.conn.cursor() From c4da939909ea9bef99bcdef805b68dca6131eac0 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 20 May 2018 13:56:59 +0100 Subject: [PATCH 09/14] Don't raise an exception closing an unused named cursor Close #716 --- NEWS | 1 + psycopg/cursor_type.c | 18 ++++++++++++------ tests/test_cursor.py | 5 +++++ tests/test_with.py | 7 ++++++- 4 files changed, 24 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 5dc4ae04..cb1b5813 100644 --- a/NEWS +++ b/NEWS @@ -24,6 +24,7 @@ What's new in psycopg 2.7.5 (:ticket:`#677`). - Maybe fixed building on MSYS2 (as reported in :ticket:`#658`). - Allow string subclasses in connection and other places (:ticket:`#679`). +- Don't raise an exception closing an unused named cursor (:ticket:`#716`). What's new in psycopg 2.7.4 diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index b7fd1870..d73bc3a4 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -59,6 +59,11 @@ psyco_curs_close(cursorObject *self) char buffer[128]; PGTransactionStatusType status; + if (!self->query) { + Dprintf("skipping named cursor close because unused"); + goto close; + } + if (self->conn) { status = PQtransactionStatus(self->conn->pgconn); } @@ -66,17 +71,18 @@ psyco_curs_close(cursorObject *self) status = PQTRANS_UNKNOWN; } - if (!(status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR)) { - EXC_IF_NO_MARK(self); - PyOS_snprintf(buffer, 127, "CLOSE %s", self->qname); - if (pq_execute(self, buffer, 0, 0, 1) == -1) return NULL; - } - else { + if (status == PQTRANS_UNKNOWN || status == PQTRANS_INERROR) { Dprintf("skipping named curs close because tx status %d", (int)status); + goto close; } + + EXC_IF_NO_MARK(self); + PyOS_snprintf(buffer, 127, "CLOSE %s", self->qname); + if (pq_execute(self, buffer, 0, 0, 1) == -1) return NULL; } +close: self->closed = 1; Dprintf("psyco_curs_close: cursor at %p closed", self); diff --git a/tests/test_cursor.py b/tests/test_cursor.py index cc8db0f4..b3e03d9b 100755 --- a/tests/test_cursor.py +++ b/tests/test_cursor.py @@ -435,6 +435,11 @@ class CursorTests(ConnectingTestCase): self.assertEqual([(2,), (3,), (4,)], cur2.fetchmany(3)) self.assertEqual([(5,), (6,), (7,)], cur2.fetchall()) + @skip_before_postgres(8, 0) + def test_named_noop_close(self): + cur = self.conn.cursor('test') + cur.close() + @skip_before_postgres(8, 0) def test_scroll(self): cur = self.conn.cursor() diff --git a/tests/test_with.py b/tests/test_with.py index 1392d85f..f26f8f9c 100755 --- a/tests/test_with.py +++ b/tests/test_with.py @@ -26,7 +26,7 @@ import psycopg2 import psycopg2.extensions as ext import unittest -from .testutils import ConnectingTestCase +from .testutils import ConnectingTestCase, skip_before_postgres class WithTestCase(ConnectingTestCase): @@ -215,6 +215,11 @@ class WithCursorTestCase(WithTestCase): else: self.fail("where is my exception?") + @skip_before_postgres(8, 0) + def test_named_with_noop(self): + with self.conn.cursor('named') as cur: + pass + def test_suite(): return unittest.TestLoader().loadTestsFromName(__name__) From 3f0a7f9af410ebec0ca231e31abeebf4c49b3d33 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 20 May 2018 17:03:08 +0100 Subject: [PATCH 10/14] Added license to the docs Includes other docs improvements, such as the ones proposed in #711. --- LICENSE | 10 +++++----- NEWS | 2 +- doc/src/index.rst | 1 + doc/src/install.rst | 12 +++++++++--- doc/src/license.rst | 7 +++++++ doc/src/news.rst | 4 ++++ 6 files changed, 27 insertions(+), 9 deletions(-) create mode 100644 doc/src/license.rst diff --git a/LICENSE b/LICENSE index 360a44f6..bdeaf9c4 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ psycopg2 and the LGPL -===================== +--------------------- psycopg2 is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published @@ -29,15 +29,15 @@ If not, see . Alternative licenses -==================== +-------------------- If you prefer you can use the Zope Database Adapter ZPsycopgDA (i.e., -every file inside the ZPsycopgDA directory) user the ZPL license as +every file inside the ZPsycopgDA directory) using the ZPL license as published on the Zope web site, http://www.zope.org/Resources/ZPL. Also, the following BSD-like license applies (at your option) to the -files following the pattern psycopg/adapter*.{h,c} and -psycopg/microprotocol*.{h,c}: +files following the pattern ``psycopg/adapter*.{h,c}`` and +``psycopg/microprotocol*.{h,c}``: Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it diff --git a/NEWS b/NEWS index cb1b5813..c44639da 100644 --- a/NEWS +++ b/NEWS @@ -18,7 +18,7 @@ What's new in psycopg 2.7.5 ^^^^^^^^^^^^^^^^^^^^^^^^^^^ - Allow non-ascii chars in namedtuple fields (regression introduced fixing - :ticket':`#211`). + :ticket:`#211`). - Fixed adaptation of arrays of arrays of nulls (:ticket:`#325`). - Fixed building on Solaris 11 and derivatives such as SmartOS and illumos (:ticket:`#677`). diff --git a/doc/src/index.rst b/doc/src/index.rst index 852bbc2c..7ae073d7 100644 --- a/doc/src/index.rst +++ b/doc/src/index.rst @@ -48,6 +48,7 @@ Psycopg 2 is both Unicode and Python 3 friendly. errorcodes faq news + license .. ifconfig:: builder != 'text' diff --git a/doc/src/install.rst b/doc/src/install.rst index a858cbe3..9afb0bc3 100644 --- a/doc/src/install.rst +++ b/doc/src/install.rst @@ -45,7 +45,9 @@ Build prerequisites ^^^^^^^^^^^^^^^^^^^ The build prerequisites are to be met in order to install Psycopg from source -code, either from a source distribution package or from PyPI. +code, from a source distribution package, GitHub_ or from PyPI. + +.. _GitHub: https://github.com/psycopg/psycopg2 Psycopg is a C wrapper around the libpq_ PostgreSQL client library. To install it from sources you will need: @@ -302,10 +304,14 @@ Try the following. *In order:* - Google for `!psycopg2` *your error message*. Especially useful the week after the release of a new OS X version. -- Write to the `Mailing List`__. +- Write to the `Mailing List`_. + +- If you think that you have discovered a bug, test failure or missing feature + please raise a ticket in the `bug tracker`_. - Complain on your blog or on Twitter that `!psycopg2` is the worst package ever and about the quality time you have wasted figuring out the correct :envvar:`ARCHFLAGS`. Especially useful from the Starbucks near you. -.. __: https://lists.postgresql.org/mj/mj_wwwusr?func=lists-long-full&extra=psycopg +.. _mailing list: https://lists.postgresql.org/mj/mj_wwwusr?func=lists-long-full&extra=psycopg +.. _bug tracker: https://github.com/psycopg/psycopg2/issues diff --git a/doc/src/license.rst b/doc/src/license.rst new file mode 100644 index 00000000..53a4e724 --- /dev/null +++ b/doc/src/license.rst @@ -0,0 +1,7 @@ +.. index:: + single: License + +License +======= + +.. include:: ../../LICENSE diff --git a/doc/src/news.rst b/doc/src/news.rst index d5b11a69..053d6464 100644 --- a/doc/src/news.rst +++ b/doc/src/news.rst @@ -1,3 +1,7 @@ +.. index:: + single: Release notes + single: News + Release notes ============= From a110d7dd7056ebb8ba7bb60b868971d7fb176000 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 25 Feb 2018 18:11:17 +0000 Subject: [PATCH 11/14] Intersphinx urls to generate Python links updated Previous urls warn about a redirect, so they are probably to go. --- doc/src/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/src/conf.py b/doc/src/conf.py index a27d6cf4..2c52a568 100644 --- a/doc/src/conf.py +++ b/doc/src/conf.py @@ -61,8 +61,8 @@ except ImportError: release = version intersphinx_mapping = { - 'py': ('http://docs.python.org/2', None), - 'py3': ('http://docs.python.org/3', None), + 'py': ('https://docs.python.org/2', None), + 'py3': ('https://docs.python.org/3', None), } # Pattern to generate links to the bug tracker From 10caf1bd74f172fe0adb2c301894a239443a65d8 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sun, 25 Feb 2018 18:13:29 +0000 Subject: [PATCH 12/14] Command to upload docs on pythonhosted dropped altogether --- doc/Makefile | 2 -- 1 file changed, 2 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 2903b9d0..558d0a75 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -29,8 +29,6 @@ doctest: upload: # this command requires ssh configured to the proper target tar czf - -C html . | ssh psycoweb tar xzvf - -C docs/current - # this command requires a .pypirc with the right privileges - # python src/tools/pypi_docs_upload.py psycopg2 $$(pwd)/html clean: $(MAKE) $(SPHOPTS) -C src $@ From 9ceffa1cc641d4bc04a714558cd4ad6852f407e5 Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Thu, 26 Apr 2018 05:52:41 -0700 Subject: [PATCH 13/14] Update all pypi.python.org URLs to pypi.org For details on the new PyPI, see the blog post: https://pythoninsider.blogspot.ca/2018/04/new-pypi-launched-legacy-pypi-shutting.html --- README.rst | 4 ++-- doc/release.rst | 2 +- doc/src/advanced.rst | 2 +- doc/src/install.rst | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/README.rst b/README.rst index b5b048d4..a9785e3a 100644 --- a/README.rst +++ b/README.rst @@ -54,8 +54,8 @@ external libraries, by installing the `psycopg2-binary`_ package from PyPI:: The binary package is a practical choice for development and testing but in production it is advised to use the package built from sources. -.. _PyPI: https://pypi.python.org/pypi/psycopg2 -.. _psycopg2-binary: https://pypi.python.org/pypi/psycopg2-binary +.. _PyPI: https://pypi.org/project/psycopg2/ +.. _psycopg2-binary: https://pypi.org/project/psycopg2-binary/ .. _install: http://initd.org/psycopg/docs/install.html#install-from-source .. _faq: http://initd.org/psycopg/docs/faq.html#faq-compile diff --git a/doc/release.rst b/doc/release.rst index 3576cdc9..3ea4a9fa 100644 --- a/doc/release.rst +++ b/doc/release.rst @@ -100,5 +100,5 @@ Test packages may be uploaded on the `PyPI testing site`__ using:: assuming `proper configuration`__ of ``~/.pypirc``. -.. __: https://testpypi.python.org/pypi/psycopg2 +.. __: https://test.pypi.org/project/psycopg2/ .. __: https://wiki.python.org/moin/TestPyPI diff --git a/doc/src/advanced.rst b/doc/src/advanced.rst index d1683b8b..724cb281 100644 --- a/doc/src/advanced.rst +++ b/doc/src/advanced.rst @@ -485,7 +485,7 @@ details. You can check the `psycogreen`_ project for further informations and resources about the topic. .. _coroutine: http://en.wikipedia.org/wiki/Coroutine -.. _greenlet: http://pypi.python.org/pypi/greenlet +.. _greenlet: https://pypi.org/project/greenlet/ .. _green threads: http://en.wikipedia.org/wiki/Green_threads .. _Eventlet: http://eventlet.net/ .. _gevent: http://www.gevent.org/ diff --git a/doc/src/install.rst b/doc/src/install.rst index 9afb0bc3..f5524a56 100644 --- a/doc/src/install.rst +++ b/doc/src/install.rst @@ -142,7 +142,7 @@ Make sure to use an up-to-date version of :program:`pip` (you can upgrade it using something like ``pip install -U pip``) .. __: PyPI-binary_ -.. _PyPI-binary: https://pypi.python.org/pypi/psycopg2-binary/ +.. _PyPI-binary: https://pypi.org/project/psycopg2-binary/ .. _wheel: http://pythonwheels.com/ .. note:: From a8d4f37b191399639ce80df0b5316702ca9f7e5f Mon Sep 17 00:00:00 2001 From: Jon Dufresne Date: Wed, 7 Mar 2018 05:12:39 -0800 Subject: [PATCH 14/14] Complete tox testing matrix Now tests all supported Python environments as well. Allows testing the full matrix of Python version with a single command. Include the command make in the whitelist_externals configuration to avoid the runtime warning: WARNING:test command found but not installed in testenv cmd: /usr/bin/make env: .../psycopg2/.tox/flake8 Maybe you forgot to specify a dependency? See also the whitelist_externals envconfig setting. --- tox.ini | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tox.ini b/tox.ini index 17612e25..a0eafa4d 100644 --- a/tox.ini +++ b/tox.ini @@ -1,13 +1,9 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - [tox] -envlist = py27 +envlist = py{27,34,35,36} [testenv] commands = make check +whitelist_externals = make [flake8] max-line-length = 85