Commit Graph

2603 Commits

Author SHA1 Message Date
Jon Dufresne
6df60ad588 Remove support for mxDateTime
The mxDateTime support has a number of issues:

- The mxDateTime is Python 2 only. There is no support for Python 3 nor
  talk of adding it AFAICT.

- Package mxDateTime support is not tested by Travis CI. New changes,
  especially around date/time interactions, could break it.

- Running psycopg2 tests with mxDateTime support results in the failures
  below.

- Installing egenix-mx-base (to install mxDateTime) with pip fails with
  the error:

    gcc: error: mx/DateTime/mxDateTime/mxDateTime.c: No such file or directory

- All of this to say, it looks like the mxDateTime package is
  unmaintained. It hasn't had a release since 2015.

The datetime module has long been a part of the Python stdlib. All
psycopg2 supported Python environments have date/time support, so
mxDateTime may not be as necessary as it was in the past.

Given the above, I recommend removing mxDateTime support. There are a
number of other items being removed with 2.8, so it is a good
opportunity for backwards incompatible changes.

Alternatively, we could look at:

1. Deprecating mxDateTime for a period (perhaps until Python 2 support is
  dropped).

Or

1. Fixing the unit test failures
2. Find a workaround for the pip install failure
3. Running mxDateTime as part of Travis

---

Failures:

======================================================================
ERROR: test_iter_named_cursor_efficient (tests.test_cursor.CursorTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/testutils.py", line 433, in slow_
    return f(self)
  File "tests/testutils.py", line 282, in skip_before_postgres__
    return f(self)
  File "tests/test_cursor.py", line 349, in test_iter_named_cursor_efficient
    self.assert_((t2 - t1).microseconds * 1e-6 < 0.1,
AttributeError: microseconds

======================================================================
ERROR: test_adapt_infinity_tz (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 405, in test_adapt_infinity_tz
    self.assert_(t.tzinfo is None)
AttributeError: tzinfo

======================================================================
ERROR: test_interval_overflow (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 396, in test_interval_overflow
    self.assertRaises(OverflowError, f, '100000000000000000:00:00')
  File "/usr/lib64/python2.7/unittest/case.py", line 511, in assertRaises
    callableObj(*args, **kwargs)
  File "tests/test_dates.py", line 394, in f
    return cur.fetchone()[0]
RangeError: DateTimeDelta value out of range

======================================================================
ERROR: test_large_interval (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/testutils.py", line 282, in skip_before_postgres__
    return f(self)
  File "tests/test_dates.py", line 350, in test_large_interval
    self.assertEqual(total_seconds(t), 999999 * 60 * 60)
  File "tests/test_dates.py", line 34, in total_seconds
    return d.days * 24 * 60 * 60 + d.seconds + d.microseconds / 1000000.0
AttributeError: microseconds

======================================================================
ERROR: test_micros_rounding (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 369, in test_micros_rounding
    self.assertEqual(total_seconds(t), 0.1)
  File "tests/test_dates.py", line 34, in total_seconds
    return d.days * 24 * 60 * 60 + d.seconds + d.microseconds / 1000000.0
AttributeError: microseconds

======================================================================
ERROR: test_time_value_error_sec_59_99 (tests.test_dates.FromTicksTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 647, in test_time_value_error_sec_59_99
    self.assertEqual(s.adapted.replace(hour=0),
AttributeError: replace

======================================================================
FAIL: test_interval_iso_8601_not_supported (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/testutils.py", line 282, in skip_before_postgres__
    return f(self)
  File "tests/test_dates.py", line 447, in test_interval_iso_8601_not_supported
    self.assertRaises(psycopg2.NotSupportedError, cur.fetchone)
AssertionError: NotSupportedError not raised

======================================================================
FAIL: test_redshift_day (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 439, in test_redshift_day
    self.assertEqual(r, v, "%s -> %s != %s" % (s, r, v))
AssertionError: 1 -> 00:00:00.00 != 0:00:00.000001

======================================================================
FAIL: test_type_roundtrip_date (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 279, in test_type_roundtrip_date
    self._test_type_roundtrip(date(2010, 5, 3))
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.date'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_date_array (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 315, in test_type_roundtrip_date_array
    self._test_type_roundtrip_array(date(2010, 5, 3))
  File "tests/test_dates.py", line 275, in _test_type_roundtrip_array
    self.assertEqual(type(o1[0]), type(o2[0]))
AssertionError: <type 'datetime.date'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_datetime (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 283, in test_type_roundtrip_datetime
    dt = self._test_type_roundtrip(datetime(2010, 5, 3, 10, 20, 30))
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.datetime'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_datetime_array (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 319, in test_type_roundtrip_datetime_array
    self._test_type_roundtrip_array(datetime(2010, 5, 3, 10, 20, 30))
  File "tests/test_dates.py", line 275, in _test_type_roundtrip_array
    self.assertEqual(type(o1[0]), type(o2[0]))
AssertionError: <type 'datetime.datetime'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_datetimetz (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 291, in test_type_roundtrip_datetimetz
    dt2 = self._test_type_roundtrip(dt1)
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.datetime'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_datetimetz_array (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 324, in test_type_roundtrip_datetimetz_array
    datetime(2010, 5, 3, 10, 20, 30, tzinfo=FixedOffsetTimezone(0)))
  File "tests/test_dates.py", line 275, in _test_type_roundtrip_array
    self.assertEqual(type(o1[0]), type(o2[0]))
AssertionError: <type 'datetime.datetime'> != <type 'mx.DateTime.DateTime'>

======================================================================
FAIL: test_type_roundtrip_interval (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 311, in test_type_roundtrip_interval
    self._test_type_roundtrip(timedelta(seconds=30))
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.timedelta'> != <type 'mx.DateTime.DateTimeDelta'>

======================================================================
FAIL: test_type_roundtrip_interval_array (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 332, in test_type_roundtrip_interval_array
    self._test_type_roundtrip_array(timedelta(seconds=30))
  File "tests/test_dates.py", line 275, in _test_type_roundtrip_array
    self.assertEqual(type(o1[0]), type(o2[0]))
AssertionError: <type 'datetime.timedelta'> != <type 'mx.DateTime.DateTimeDelta'>

======================================================================
FAIL: test_type_roundtrip_time (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 297, in test_type_roundtrip_time
    tm = self._test_type_roundtrip(time(10, 20, 30))
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.time'> != <type 'mx.DateTime.DateTimeDelta'>

======================================================================
FAIL: test_type_roundtrip_time_array (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 328, in test_type_roundtrip_time_array
    self._test_type_roundtrip_array(time(10, 20, 30))
  File "tests/test_dates.py", line 275, in _test_type_roundtrip_array
    self.assertEqual(type(o1[0]), type(o2[0]))
AssertionError: <type 'datetime.time'> != <type 'mx.DateTime.DateTimeDelta'>

======================================================================
FAIL: test_type_roundtrip_timetz (tests.test_dates.DatetimeTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 305, in test_type_roundtrip_timetz
    tm2 = self._test_type_roundtrip(tm1)
  File "tests/test_dates.py", line 269, in _test_type_roundtrip
    self.assertEqual(type(o1), type(o2))
AssertionError: <type 'datetime.time'> != <type 'mx.DateTime.DateTimeDelta'>

======================================================================
FAIL: test_date_value_error_sec_59_99 (tests.test_dates.FromTicksTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 642, in test_date_value_error_sec_59_99
    self.assert_(s.adapted in [date(2010, 5, 6), date(2010, 5, 7)])
AssertionError: False is not true

======================================================================
FAIL: test_timestamp_value_error_sec_59_99 (tests.test_dates.FromTicksTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/test_dates.py", line 636, in test_timestamp_value_error_sec_59_99
    tzinfo=FixedOffsetTimezone(-5 * 60)))
AssertionError: <mx.DateTime.DateTime object for '2010-05-06 12:11:59.99' at 7fcbb03cc348> != datetime.datetime(2010, 5, 6, 14, 11, 59, 999920, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=-300, name=None))

======================================================================
FAIL: test_adapt_date_range (tests.test_types_extras.RangeCasterTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/testutils.py", line 282, in skip_before_postgres__
    return f(self)
  File "tests/test_types_extras.py", line 1627, in test_adapt_date_range
    self.assertEqual(r1.lower, ts1)
AssertionError: <mx.DateTime.DateTime object for '1999-12-31 06:00:00.00' at 7fcbb03cc300> != datetime.datetime(2000, 1, 1, 0, 0, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=600, name=None))

======================================================================
FAIL: test_cast_timestamptz (tests.test_types_extras.RangeCasterTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "tests/testutils.py", line 282, in skip_before_postgres__
    return f(self)
  File "tests/test_types_extras.py", line 1535, in test_cast_timestamptz
    self.assertEqual(r.lower, ts1)
AssertionError: <mx.DateTime.DateTime object for '1999-12-31 06:00:00.00' at 7fcbb03cc348> != datetime.datetime(2000, 1, 1, 0, 0, tzinfo=psycopg2.tz.FixedOffsetTimezone(offset=600, name=None))
2019-03-13 20:51:17 -07:00
Jon Dufresne
ad4c6a4673 Use unittest 'skip' feature to skip mxDateTimeTests
Rather than deleting, the class, use the skip feature. Provides a more
informative message during test output.

Never skip DatetimeTests as all supported Python environments have the
datetime module builtin.
2019-03-13 15:01:34 +00:00
Jon Dufresne
d411dc3a73 Remove unused use_pydatetime from setup.py
Looks to have been mistakenly reintroduced in
b537404487.
2019-03-13 15:00:25 +00:00
Jon Dufresne
6db347b5d7 Remove unused use_pg_dll from setup.py
Unused since 3076046b3f.
2019-03-13 11:20:27 +00:00
Jon Dufresne
3f890f8bbe Use True/False instead of 1/0 to represent bool values
Slightly more modern, readable, and Pythonic.
2019-03-13 11:13:36 +00:00
Jon Dufresne
afbbdd18b6 Remove unused variable
The variable i is immediately overwritten by the next line.
2019-03-13 11:13:24 +00:00
Jon Dufresne
03bb44dd2c Convert while 1: statements to while True:
A slightly more readable and modern syntax.
2019-03-13 11:13:05 +00:00
Jon Dufresne
18f5d5ad05 Remove unused imports from tests/test_ipaddress.py 2019-03-13 11:12:48 +00:00
Daniele Varrazzo
f2654d3573 Advertise openssl 1.0.2r and libpq 11.2 in wheels 2019-03-13 11:12:17 +00:00
Daniele Varrazzo
92ac3ba4fc Bumped to version 2.8 2019-03-05 17:33:16 +00:00
Daniele Varrazzo
3ae9dfd545 Better link from docs to "json and jsonb" data types 2019-03-05 17:31:45 +00:00
Daniele Varrazzo
c929f20048 Fixed building with Python 3.8
Not released yet, and using an internal API, so for the moment better
not declare it supported.

Close #854
2019-03-05 17:30:52 +00:00
Daniele Varrazzo
be7e1916d7 Dropped outdated setup.py comment 2019-02-26 23:48:20 +00:00
Grey Baker
7fadb75097 Add project_urls to setup.py, with links to source and documentation 2019-02-26 23:44:32 +00:00
David Fischer
147ff65e4a Fix typo 2019-02-26 11:33:48 +01:00
Daniele Varrazzo
b17670a27e Merge branch 'info-dsn-params' 2019-02-17 10:55:12 +00:00
Daniele Varrazzo
a68df50c7b Added ConnectionInfo.dsn_parameters attribute 2019-02-17 02:37:09 +00:00
Daniele Varrazzo
0eb4560771 Don't use versions such as 2.8.0 in docs
Use 2.8.
2019-02-17 01:51:06 +00:00
Daniele Varrazzo
599432552a Copyright year updated
ag -l Copyright | xargs sed -i \
        "s/\(.*copyright (C) [0-9]\+\)\(-[0-9]\+\)\?\(.*\)/\1-$(date +%Y)\3/I"
2019-02-17 01:36:36 +00:00
Daniele Varrazzo
d177fa9bd0 Allow building docs with Python 3
Use a .pth file to simplify finding the just-built psycopg package into the
docs building env.
2019-02-17 01:36:36 +00:00
Daniele Varrazzo
63ce5ca94f Fixed title level of sqlsate errors table in docs 2019-02-17 01:07:47 +00:00
Daniele Varrazzo
f70d6fd0ed Dropped text docs generation 2019-02-17 00:58:27 +00:00
Daniele Varrazzo
e5e8cec350 Added table of sqlstate exceptions in the docs
Note that the column-spanning cells break text docs. I don't think
anybody cares about them, so going to drop them.
2019-02-17 01:55:14 +01:00
Daniele Varrazzo
d08be18671 Merge branch 'libpq-ptrs' 2019-02-17 00:17:43 +01:00
Daniele Varrazzo
6bbfce7b89 Skip password encryption test if libpq < 10 2019-02-16 22:57:16 +01:00
Daniele Varrazzo
80b7b845d2 Added docs about pgconn_ptr, pgresult_ptr 2019-02-16 18:12:52 +01:00
Daniele Varrazzo
3b7c083c3d Skip tests involving ctypes on Windows
No idea about how to import libpq.
2019-02-16 18:12:52 +01:00
Daniele Varrazzo
7c7bbb9742 Added connection.pgconn_ptr and cursor.pgresult_ptr
Allow interacting with libpq in Python via ctypes.

See #782.
2019-02-16 18:12:52 +01:00
Daniele Varrazzo
1dd8c7435f Mention binary packages no longer installed by default in NEWS
Also fixed an unrelated typo.

[skip ci]
2019-02-16 16:10:03 +01:00
Daniele Varrazzo
495ff79f23 Preparing 2.8 beta release 2019-02-16 14:06:18 +01:00
Daniele Varrazzo
16b35ac77b Merge remote-tracking branch 'origin/errors-module-c' 2019-02-16 13:05:20 +01:00
Daniele Varrazzo
7c148ecee4 Improvements to errors module docs 2019-02-11 01:20:21 +00:00
Daniele Varrazzo
3de4d17519 Fixed use of StandardError in test
In Py3 it's gone.
2019-02-11 00:26:01 +00:00
Daniele Varrazzo
99f680b6fe Allow importing _psycopg even if the 'errors' module is not available 2019-02-10 04:25:06 +00:00
Daniele Varrazzo
30c1befa64 SQLSTATE error classes implemented in C
The module is only used to export them to Python.
2019-02-10 03:45:14 +00:00
Daniele Varrazzo
f1e73507d0 Merge remote-tracking branch 'origin/fast-namedtuple'
Close #838
2019-02-06 02:42:10 +00:00
Daniele Varrazzo
35ec7ad9c1 Use a proper LRU cache for namedtuples
Previous one didn't refresh by last use. Use the stdlib version for py3
and one of our own for py2.

Max size set to 512, which should be fine for everyone (tweaking is
still possible by monkeypatching, as the tests do, but I don't want to
make an interface of it).
2019-02-02 19:29:20 +00:00
Daniele Varrazzo
805527fcd6 Added caching of types generated by NamedTupleCursor
see #838
2019-02-02 14:22:25 +00:00
Daniele Varrazzo
3f20f7934a Merge branch 'drop-display-size' 2019-01-25 17:31:55 +00:00
Daniele Varrazzo
4298718978 Dropped PSYCOPG_DISPLAY_SIZE build parameter
Big and complex _pq_fetch_tuples simplified by moving per-column
calculation to a separate function.
2019-01-25 17:31:39 +00:00
Daniele Varrazzo
00cb2636f5 Merge branch 'module-init-cleanup' 2019-01-23 14:17:07 +00:00
Daniele Varrazzo
65a2a18a1b General cleanup of module init shenanigans
Pass around the module instead of its dict (getting the latter is fast
if needed), mark function raising with negative results, check all errors,
consistent names...
2019-01-23 09:46:18 +00:00
Daniele Varrazzo
66d5c6da07 Incref an object which will be held forever in a static var 2019-01-23 09:46:18 +00:00
Daniele Varrazzo
e9c476266c Decrement the refcount of temporary objects in module init failed
We are going to die anyway, but let's do it in style.
2019-01-22 19:40:42 +00:00
Daniele Varrazzo
63040e5134 Mention new OpenSSL version in wheel package 2019-01-22 12:25:03 +00:00
Daniele Varrazzo
1e6d5fb32d Merge branch 'execute-locks' 2019-01-22 12:24:41 +00:00
Daniele Varrazzo
c34c99aa7f Mention cursor locks cleanup in news file 2019-01-22 11:20:36 +00:00
Daniele Varrazzo
92e615a1a4 Assign the PGresult to the cursor in the execute critical section
Possible cause of the issue reported in #346 (in concurrent
environments).
2019-01-22 11:02:09 +00:00
Daniele Varrazzo
37891500d9 Split pq_execute into sync/async parts 2019-01-22 10:51:27 +00:00
Daniele Varrazzo
eab5d5d93f Date/time modules initialized in separate functions 2019-01-22 09:09:07 +00:00