PYTHON-1467 - PyMongo no longer supports Python 2.6
This commit is contained in:
parent
c2fde81d60
commit
749c1a2f0b
@ -855,10 +855,11 @@ axes:
|
||||
- id: os-fully-featured
|
||||
display_name: OS
|
||||
values:
|
||||
- id: linux-64-amzn-test
|
||||
display_name: "Amazon Linux (Enterprise)"
|
||||
run_on: linux-64-amzn-test
|
||||
batchtime: 10080 # 7 days
|
||||
# https://jira.mongodb.org/browse/BUILD-5453
|
||||
#- id: linux-64-amzn-test
|
||||
# display_name: "Amazon Linux (Enterprise)"
|
||||
# run_on: linux-64-amzn-test
|
||||
# batchtime: 10080 # 7 days
|
||||
|
||||
- id: ubuntu-14.04
|
||||
display_name: "Ubuntu 14.04"
|
||||
@ -1013,10 +1014,6 @@ axes:
|
||||
- id: python-version
|
||||
display_name: "Python"
|
||||
values:
|
||||
- id: "2.6"
|
||||
display_name: "Python 2.6"
|
||||
variables:
|
||||
PYTHON_BINARY: "/opt/python/2.6/bin/python"
|
||||
- id: "2.7"
|
||||
display_name: "Python 2.7"
|
||||
variables:
|
||||
@ -1061,10 +1058,6 @@ axes:
|
||||
- id: mod-wsgi-version
|
||||
display_name: "mod_wsgi version"
|
||||
values:
|
||||
- id: "2"
|
||||
display_name: "mod_wsgi 2.8"
|
||||
variables:
|
||||
MOD_WSGI_VERSION: "2"
|
||||
- id: "3"
|
||||
display_name: "mod_wsgi 3.5"
|
||||
variables:
|
||||
@ -1122,11 +1115,7 @@ axes:
|
||||
values:
|
||||
# There is (currently) no vs2008 distro. The Microsoft Visual
|
||||
# C++ Compiler for Python 2.7 has been installed, with CPython
|
||||
# 2.6 and 2.7, on the vs2015 distro.
|
||||
- id: "2.6"
|
||||
display_name: "Python 2.6"
|
||||
variables:
|
||||
PYTHON_BINARY: "/cygdrive/c/python/Python26/python.exe"
|
||||
# 2.7, on the vs2015 distro.
|
||||
- id: "2.7"
|
||||
display_name: "Python 2.7"
|
||||
variables:
|
||||
@ -1339,9 +1328,6 @@ buildvariants:
|
||||
# on Windows with the Microsoft Visual C++ Compiler for Python 2.7 or Visual Studio 2015.
|
||||
- matrix_name: "tests-windows-vs2015-python-version-27plus"
|
||||
matrix_spec: {windows-vs2015-python-version: "*", auth-ssl: "*"}
|
||||
exclude_spec:
|
||||
- windows-vs2015-python-version: "2.6"
|
||||
auth-ssl: "*"
|
||||
display_name: "Windows 64 Visual Studio 2015 ${windows-vs2015-python-version} ${auth-ssl}"
|
||||
run_on: windows-64-vs2015-test
|
||||
tasks:
|
||||
@ -1353,51 +1339,6 @@ buildvariants:
|
||||
- ".3.0"
|
||||
- ".2.6"
|
||||
|
||||
# Test CPython 2.6 against all versions on MongoDB >= 2.6
|
||||
# on Windows with the Microsoft Visual C++ Compiler for Python 2.7.
|
||||
# Python 2.6.6 (the last 2.6 version with Windows installers) bundles
|
||||
# OpenSSL 0.9.8, which doesn't support TLS 1.1+. MongoDB 4.0+ requires
|
||||
# TLS 1.1+ by default.
|
||||
- matrix_name: "tests-windows-vs2015-python-version-26"
|
||||
matrix_spec: {windows-vs2015-python-version: "2.6", auth: "*", ssl: "*"}
|
||||
exclude_spec:
|
||||
- windows-vs2015-python-version: "*"
|
||||
auth: "noauth"
|
||||
ssl: "ssl"
|
||||
display_name: "Windows 64 Visual Studio 2015 ${windows-vs2015-python-version} ${auth} ${ssl}"
|
||||
run_on: windows-64-vs2015-test
|
||||
rules:
|
||||
- if:
|
||||
windows-vs2015-python-version: "*"
|
||||
auth: "*"
|
||||
ssl: "nossl"
|
||||
then:
|
||||
add_tasks:
|
||||
- ".latest"
|
||||
- ".4.0"
|
||||
- if:
|
||||
windows-vs2015-python-version: "*"
|
||||
auth: "noauth"
|
||||
ssl: "nossl"
|
||||
then:
|
||||
add_tasks:
|
||||
- ".3.6"
|
||||
- ".3.4"
|
||||
- ".3.2"
|
||||
- ".3.0"
|
||||
- ".2.6"
|
||||
- if:
|
||||
windows-vs2015-python-version: "*"
|
||||
auth: "auth"
|
||||
ssl: "ssl"
|
||||
then:
|
||||
add_tasks:
|
||||
- ".3.6"
|
||||
- ".3.4"
|
||||
- ".3.2"
|
||||
- ".3.0"
|
||||
- ".2.6"
|
||||
|
||||
# Storage engine tests on RHEL 6.2 (x86_64) with Python 2.7.
|
||||
- matrix_name: "tests-storage-engines"
|
||||
matrix_spec: {storage-engine: "*", python-version: "2.7"}
|
||||
@ -1453,11 +1394,7 @@ buildvariants:
|
||||
- name: "test-enterprise-auth"
|
||||
|
||||
- matrix_name: "tests-mod-wsgi"
|
||||
matrix_spec: {"python-version": ["2.6", "2.7", "3.4", "3.6"], "mod-wsgi-version": "*"}
|
||||
exclude_spec:
|
||||
# mod_wsgi 2.8 segfaults with the toolchain python 2.7, regardless of distro
|
||||
python-version: ["2.7", "3.4", "3.6"]
|
||||
mod-wsgi-version: ["2"]
|
||||
matrix_spec: {"python-version": ["2.7", "3.4", "3.6"], "mod-wsgi-version": "*"}
|
||||
display_name: "${mod-wsgi-version} ${python-version}"
|
||||
run_on: rhel62-small
|
||||
tasks:
|
||||
@ -1479,7 +1416,7 @@ buildvariants:
|
||||
- name: "doctests"
|
||||
|
||||
- matrix_name: "cdecimal"
|
||||
matrix_spec: {python-version: ["2.6", "2.7"]}
|
||||
matrix_spec: {python-version: ["2.7"]}
|
||||
display_name: "cdecimal ${python-version}"
|
||||
batchtime: 10080 # 7 days
|
||||
run_on:
|
||||
|
||||
@ -7,24 +7,16 @@ export JAVA_HOME=/opt/java/jdk8
|
||||
|
||||
IMPL=$(${PYTHON_BINARY} -c "import platform, sys; sys.stdout.write(platform.python_implementation())")
|
||||
PYTHON_VERSION=$(${PYTHON_BINARY} -c "import sys; print('.'.join(map(str, sys.version_info[:2])))")
|
||||
if [ $PYTHON_VERSION = "2.6" -o $IMPL = "Jython" ]; then
|
||||
# TODO - When Jython has its own virtualenv install use it instead.
|
||||
/opt/python/2.6/bin/virtualenv -p ${PYTHON_BINARY} --never-download --no-wheel atlastest
|
||||
. atlastest/bin/activate
|
||||
trap "deactivate; rm -rf atlastest" EXIT HUP
|
||||
pip install certifi
|
||||
if [ $PYTHON_VERSION = "2.6" ]; then
|
||||
pip install unittest2
|
||||
fi
|
||||
PYTHON=python
|
||||
elif [ $IMPL = "PyPy" -a $PYTHON_VERSION = "3.2" ]; then
|
||||
if [ $IMPL = "Jython" -o $IMPL = "PyPy" ]; then
|
||||
$PYTHON_BINARY -m virtualenv --never-download --no-wheel atlastest
|
||||
. atlastest/bin/activate
|
||||
trap "deactivate; rm -rf atlastest" EXIT HUP
|
||||
pip install certifi
|
||||
# Portable pypy3.2 can't load CA certs from the system.
|
||||
# https://github.com/squeaky-pl/portable-pypy/issues/15
|
||||
export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())")
|
||||
if [ $PYTHON_VERSION = "3.2" ]; then
|
||||
# Portable pypy3.2 can't load CA certs from the system.
|
||||
# https://github.com/squeaky-pl/portable-pypy/issues/15
|
||||
export SSL_CERT_FILE=$(python -c "import certifi; print(certifi.where())")
|
||||
fi
|
||||
PYTHON=python
|
||||
else
|
||||
PYTHON=$PYTHON_BINARY
|
||||
|
||||
@ -44,10 +44,7 @@ if [ -z "$PYTHON_BINARY" ]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
# wheel and pip are dropping support for Python 2.6. Avoid virtualenv
|
||||
# automatically upgrading its bundled versions to new versions that
|
||||
# might fail in 2.6.
|
||||
$VIRTUALENV --no-download pymongotestvenv || $VIRTUALENV pymongotestvenv
|
||||
$VIRTUALENV pymongotestvenv
|
||||
. pymongotestvenv/bin/activate
|
||||
PYTHON=python
|
||||
trap "deactivate; rm -rf pymongotestvenv" EXIT HUP
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
language: python
|
||||
|
||||
python:
|
||||
- 2.6
|
||||
- 2.7
|
||||
- 3.4
|
||||
- 3.5
|
||||
|
||||
@ -19,7 +19,7 @@ that might not be of interest or that has already been addressed.
|
||||
Supported Interpreters
|
||||
----------------------
|
||||
|
||||
PyMongo supports CPython 2.6, 2.7, 3.4+, PyPy, and PyPy3. Language
|
||||
PyMongo supports CPython 2.7, 3.4+, PyPy, and PyPy3. Language
|
||||
features not supported by all interpreters can not be used.
|
||||
|
||||
Style Guide
|
||||
|
||||
@ -88,7 +88,7 @@ is incompatible with PyMongo.
|
||||
Dependencies
|
||||
============
|
||||
|
||||
PyMongo supports CPython 2.6, 2.7, 3.4+, PyPy, and PyPy3.
|
||||
PyMongo supports CPython 2.7, 3.4+, PyPy, and PyPy3.
|
||||
|
||||
Optional dependencies:
|
||||
|
||||
@ -136,7 +136,6 @@ Other optional packages:
|
||||
Additional dependencies are:
|
||||
|
||||
- (to generate documentation) sphinx_
|
||||
- (to run the tests under Python 2.6) unittest2_
|
||||
|
||||
Examples
|
||||
========
|
||||
@ -188,8 +187,7 @@ Testing
|
||||
=======
|
||||
|
||||
The easiest way to run the tests is to run **python setup.py test** in
|
||||
the root of the distribution. Note that you will need unittest2_ to
|
||||
run the tests under Python 2.6.
|
||||
the root of the distribution.
|
||||
|
||||
To verify that PyMongo works with Gevent's monkey-patching::
|
||||
|
||||
@ -200,4 +198,3 @@ Or with Eventlet's::
|
||||
$ python green_framework_test.py eventlet
|
||||
|
||||
.. _sphinx: http://sphinx.pocoo.org/
|
||||
.. _unittest2: https://pypi.python.org/pypi/unittest2
|
||||
|
||||
@ -31,9 +31,9 @@ that changes the major version number.
|
||||
Doing a Release
|
||||
---------------
|
||||
|
||||
1. Test releases on Python 2.6-2.7 and 3.4+ on Windows, Linux and OSX,
|
||||
1. Test releases on Python 2.7 and 3.4+ on Windows, Linux and OSX,
|
||||
with and without the C extensions. It's generally enough to just run the
|
||||
tests on 2.6, 2.7, 3.4 and the latest 3.x version with and without the
|
||||
tests on 2.7, 3.4 and the latest 3.x version with and without the
|
||||
extensions on a single platform, and then just test any version on the
|
||||
other platforms as a sanity check. `python setup.py test` will build the
|
||||
extensions and test. `python tools/clean.py` will remove the extensions,
|
||||
|
||||
@ -35,21 +35,6 @@ else:
|
||||
"An implementation of int.from_bytes for python 2.x."
|
||||
return _int(_hexlify(value), 16)
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
def _bit_length(num):
|
||||
"""bit_length for python 2.6"""
|
||||
if num:
|
||||
# bin() was new in 2.6. Note that this won't work
|
||||
# for values less than 0, which we never have here.
|
||||
return len(bin(num)) - 2
|
||||
# bit_length(0) is 0, but len(bin(0)) - 2 is 1
|
||||
return 0
|
||||
else:
|
||||
def _bit_length(num):
|
||||
"""bit_length for python >= 2.7"""
|
||||
# num could be int or long in python 2.7
|
||||
return num.bit_length()
|
||||
|
||||
|
||||
_PACK_64 = struct.Struct("<Q").pack
|
||||
_UNPACK_64 = struct.Struct("<Q").unpack
|
||||
@ -126,7 +111,7 @@ def _decimal_to_128(value):
|
||||
return _NNAN if value.is_signed() else _PNAN
|
||||
|
||||
significand = int("".join([str(digit) for digit in digits]))
|
||||
bit_length = _bit_length(significand)
|
||||
bit_length = significand.bit_length()
|
||||
|
||||
high = 0
|
||||
low = 0
|
||||
@ -298,10 +283,9 @@ class Decimal128(object):
|
||||
mask = 0x0001000000000000
|
||||
arr[0] = (high & mask) >> 48
|
||||
|
||||
# Have to convert bytearray to bytes for python 2.6.
|
||||
# cdecimal only accepts a tuple for digits.
|
||||
digits = tuple(
|
||||
int(digit) for digit in str(_from_bytes(bytes(arr), 'big')))
|
||||
int(digit) for digit in str(_from_bytes(arr, 'big')))
|
||||
|
||||
with decimal.localcontext(_DEC128_CTX) as ctx:
|
||||
return ctx.create_decimal((sign, digits, exponent))
|
||||
|
||||
@ -107,21 +107,12 @@ but it will be faster as there is less recursion.
|
||||
|
||||
import base64
|
||||
import datetime
|
||||
import json
|
||||
import math
|
||||
import re
|
||||
import sys
|
||||
import uuid
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
# In Python 2.6, json does not include object_pairs_hook. Use simplejson
|
||||
# instead.
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
else:
|
||||
import json
|
||||
|
||||
from pymongo.errors import ConfigurationError
|
||||
|
||||
import bson
|
||||
@ -143,13 +134,6 @@ from bson.timestamp import Timestamp
|
||||
from bson.tz_util import utc
|
||||
|
||||
|
||||
try:
|
||||
json.loads("{}", object_pairs_hook=dict)
|
||||
_HAS_OBJECT_PAIRS_HOOK = True
|
||||
except TypeError:
|
||||
_HAS_OBJECT_PAIRS_HOOK = False
|
||||
|
||||
|
||||
_RE_OPT_TABLE = {
|
||||
"i": re.I,
|
||||
"l": re.L,
|
||||
@ -245,10 +229,6 @@ class JSONMode:
|
||||
class JSONOptions(CodecOptions):
|
||||
"""Encapsulates JSON options for :func:`dumps` and :func:`loads`.
|
||||
|
||||
Raises :exc:`~pymongo.errors.ConfigurationError` on Python 2.6 if
|
||||
`simplejson >= 2.1.0 <https://pypi.python.org/pypi/simplejson>`_ is not
|
||||
installed and document_class is not the default (:class:`dict`).
|
||||
|
||||
:Parameters:
|
||||
- `strict_number_long`: If ``True``, :class:`~bson.int64.Int64` objects
|
||||
are encoded to MongoDB Extended JSON's *Strict mode* type
|
||||
@ -301,11 +281,6 @@ class JSONOptions(CodecOptions):
|
||||
"JSONOptions.datetime_representation must be one of LEGACY, "
|
||||
"NUMBERLONG, or ISO8601 from DatetimeRepresentation.")
|
||||
self = super(JSONOptions, cls).__new__(cls, *args, **kwargs)
|
||||
if not _HAS_OBJECT_PAIRS_HOOK and self.document_class != dict:
|
||||
raise ConfigurationError(
|
||||
"Support for JSONOptions.document_class on Python 2.6 "
|
||||
"requires simplejson >= 2.1.0"
|
||||
"(https://pypi.python.org/pypi/simplejson) to be installed.")
|
||||
if json_mode not in (JSONMode.LEGACY,
|
||||
JSONMode.RELAXED,
|
||||
JSONMode.CANONICAL):
|
||||
@ -430,11 +405,8 @@ def loads(s, *args, **kwargs):
|
||||
Accepts optional parameter `json_options`. See :class:`JSONOptions`.
|
||||
"""
|
||||
json_options = kwargs.pop("json_options", DEFAULT_JSON_OPTIONS)
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(
|
||||
pairs, json_options)
|
||||
else:
|
||||
kwargs["object_hook"] = lambda obj: object_hook(obj, json_options)
|
||||
kwargs["object_pairs_hook"] = lambda pairs: object_pairs_hook(
|
||||
pairs, json_options)
|
||||
return json.loads(s, *args, **kwargs)
|
||||
|
||||
|
||||
|
||||
@ -36,7 +36,7 @@ if PY3:
|
||||
def b(s):
|
||||
# BSON and socket operations deal in binary data. In
|
||||
# python 3 that means instances of `bytes`. In python
|
||||
# 2.6 and 2.7 you can create an alias for `bytes` using
|
||||
# 2.7 you can create an alias for `bytes` using
|
||||
# the b prefix (e.g. b'foo').
|
||||
# See http://python3porting.com/problems.html#nicer-solutions
|
||||
return codecs.latin_1_encode(s)[0]
|
||||
|
||||
@ -1,6 +1,23 @@
|
||||
Changelog
|
||||
=========
|
||||
|
||||
Changes in Version 3.8.0
|
||||
------------------------
|
||||
|
||||
.. warning:: PyMongo no longer supports Python 2.6. RHEL 6 users should install
|
||||
Python 2.7 or newer from `Red Hat Software Collections
|
||||
<https://www.softwarecollections.org>`_. CentOS 6 users should install Python
|
||||
2.7 or newer from `SCL
|
||||
<https://wiki.centos.org/AdditionalResources/Repositories/SCL>`_
|
||||
|
||||
Issues Resolved
|
||||
...............
|
||||
|
||||
See the `PyMongo 3.8 release notes in JIRA`_ for the list of resolved issues
|
||||
in this release.
|
||||
|
||||
.. _PyMongo 3.8 release notes in JIRA: https://jira.mongodb.org/secure/ReleaseNote.jspa?projectId=10004&version=19904
|
||||
|
||||
Changes in Version 3.7.0
|
||||
------------------------
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ To upgrade do::
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
PyMongo supports CPython 2.6, 2.7, 3.4+, PyPy, and PyPy3.
|
||||
PyMongo supports CPython 2.7, 3.4+, PyPy, and PyPy3.
|
||||
|
||||
Optional dependencies:
|
||||
|
||||
@ -135,13 +135,12 @@ OSX and Xcode versions.
|
||||
**Snow Leopard (10.6)** - Xcode 3 with 'UNIX Development Support'.
|
||||
|
||||
**Snow Leopard Xcode 4**: The Python versions shipped with OSX 10.6.x
|
||||
are universal binaries. They support i386, PPC, and (in the case of python2.6)
|
||||
x86_64. Xcode 4 removed support for PPC, causing the distutils version shipped
|
||||
with Apple's builds of Python to fail to build the C extensions if you have
|
||||
Xcode 4 installed. There is a workaround::
|
||||
are universal binaries. They support i386, PPC, and x86_64. Xcode 4 removed
|
||||
support for PPC, causing the distutils version shipped with Apple's builds of
|
||||
Python to fail to build the C extensions if you have Xcode 4 installed. There
|
||||
is a workaround::
|
||||
|
||||
# For Apple-supplied Python2.6 (installed at /usr/bin/python2.6) and
|
||||
# some builds from python.org
|
||||
# For some Python builds from python.org
|
||||
$ env ARCHFLAGS='-arch i386 -arch x86_64' python -m easy_install pymongo
|
||||
|
||||
See `http://bugs.python.org/issue11623 <http://bugs.python.org/issue11623>`_
|
||||
@ -185,8 +184,8 @@ requirements apply to both CPython and ActiveState's ActivePython:
|
||||
For Python 3.5 and newer install Visual Studio 2015. For Python 3.4
|
||||
install Visual Studio 2010. You must use the full version of Visual Studio
|
||||
2010 as Visual C++ Express does not provide 64-bit compilers. Make sure that
|
||||
you check the "x64 Compilers and Tools" option under Visual C++. For Python 2.6
|
||||
and 2.7 install the `Microsoft Visual C++ Compiler for Python 2.7`_.
|
||||
you check the "x64 Compilers and Tools" option under Visual C++. For Python 2.7
|
||||
install the `Microsoft Visual C++ Compiler for Python 2.7`_.
|
||||
|
||||
32-bit Windows
|
||||
~~~~~~~~~~~~~~
|
||||
@ -195,7 +194,7 @@ For Python 3.5 and newer install Visual Studio 2015.
|
||||
|
||||
For Python 3.4 install Visual C++ 2010 Express.
|
||||
|
||||
For Python 2.6 and 2.7 install the `Microsoft Visual C++ Compiler for Python 2.7`_
|
||||
For Python 2.7 install the `Microsoft Visual C++ Compiler for Python 2.7`_
|
||||
|
||||
.. _`Microsoft Visual C++ Compiler for Python 2.7`: https://www.microsoft.com/en-us/download/details.aspx?id=44266
|
||||
|
||||
|
||||
@ -97,8 +97,8 @@ Python 3 you must pass ``encoding='latin-1'`` to pickle.loads::
|
||||
If you need to pickle ObjectIds using Python 3 and unpickle them using Python 2
|
||||
you must use ``protocol <= 2``::
|
||||
|
||||
Python 3.6.1 (v3.6.1:69c0db5050, Mar 21 2017, 01:21:04)
|
||||
[GCC 4.9.3] on linux
|
||||
Python 3.6.5 (default, Jun 21 2018, 15:09:09)
|
||||
[GCC 7.3.0] on linux
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> import pickle
|
||||
>>> from bson.objectid import ObjectId
|
||||
@ -108,8 +108,8 @@ you must use ``protocol <= 2``::
|
||||
>>> pickle.dumps(oid, protocol=2)
|
||||
b'\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...'
|
||||
|
||||
Python 2.6.9 (unknown, Feb 26 2014, 12:39:10)
|
||||
[GCC 4.7.3] on linux2
|
||||
Python 2.7.15 (default, Jun 21 2018, 15:00:48)
|
||||
[GCC 7.3.0] on linux2
|
||||
Type "help", "copyright", "credits" or "license" for more information.
|
||||
>>> import pickle
|
||||
>>> pickle.loads('\x80\x02cbson.objectid\nObjectId\nq\x00)\x81q\x01c_codecs\nencode\...')
|
||||
|
||||
@ -284,10 +284,7 @@ class ServerListener(_EventListener):
|
||||
|
||||
def _to_micros(dur):
|
||||
"""Convert duration 'dur' to microseconds."""
|
||||
if hasattr(dur, 'total_seconds'):
|
||||
return int(dur.total_seconds() * 10e5)
|
||||
# Python 2.6
|
||||
return dur.microseconds + (dur.seconds + dur.days * 24 * 3600) * 1000000
|
||||
return int(dur.total_seconds() * 10e5)
|
||||
|
||||
|
||||
def _validate_event_listeners(option, listeners):
|
||||
|
||||
@ -101,7 +101,7 @@ except ImportError:
|
||||
# ':' is not a valid character for a hostname. If we get
|
||||
# here a few things have to be true:
|
||||
# - We're on a recent version of python 2.7 (2.7.9+).
|
||||
# 2.6 and older 2.7 versions don't support SNI.
|
||||
# Older 2.7 versions don't support SNI.
|
||||
# - We're on Windows XP or some unusual Unix that doesn't
|
||||
# have inet_pton.
|
||||
# - The application is using IPv6 literals with TLS, which
|
||||
@ -272,7 +272,7 @@ def _raise_connection_failure(address, error, msg_prefix=None):
|
||||
if isinstance(error, socket.timeout):
|
||||
raise NetworkTimeout(msg)
|
||||
elif isinstance(error, SSLError) and 'timed out' in str(error):
|
||||
# CPython 2.6, 2.7, PyPy 2.x, and PyPy3 do not distinguish network
|
||||
# CPython 2.7, PyPy 2.x, and PyPy3 do not distinguish network
|
||||
# timeouts from other SSLErrors (https://bugs.python.org/issue10272).
|
||||
# Luckily, we can work around this limitation because the phrase
|
||||
# 'timed out' appears in all the timeout related SSLErrors raised
|
||||
@ -766,7 +766,7 @@ def _create_connection(address, options):
|
||||
|
||||
Can raise socket.error.
|
||||
|
||||
This is a modified version of create_connection from CPython >= 2.6.
|
||||
This is a modified version of create_connection from CPython >= 2.7.
|
||||
"""
|
||||
host, port = address
|
||||
|
||||
|
||||
@ -20,16 +20,6 @@ from pymongo.ismaster import IsMaster
|
||||
from pymongo.monotonic import time as _time
|
||||
|
||||
|
||||
def _total_seconds(delta):
|
||||
"""Total seconds in the duration."""
|
||||
if hasattr(delta, 'total_seconds'):
|
||||
return delta.total_seconds()
|
||||
|
||||
# Python 2.6.
|
||||
return ((delta.days * 86400 + delta.seconds) * 10 ** 6 +
|
||||
delta.microseconds) / 10.0 ** 6
|
||||
|
||||
|
||||
class ServerDescription(object):
|
||||
"""Immutable representation of one server.
|
||||
|
||||
@ -82,7 +72,7 @@ class ServerDescription(object):
|
||||
if ismaster.last_write_date:
|
||||
# Convert from datetime to seconds.
|
||||
delta = ismaster.last_write_date - EPOCH_NAIVE
|
||||
self._last_write_date = _total_seconds(delta)
|
||||
self._last_write_date = delta.total_seconds()
|
||||
else:
|
||||
self._last_write_date = None
|
||||
|
||||
|
||||
@ -25,7 +25,7 @@ class SSLContext(object):
|
||||
|
||||
This implements an API similar to ssl.SSLContext from python 3.2
|
||||
but does not implement methods or properties that would be
|
||||
incompatible with ssl.wrap_socket from python 2.6.
|
||||
incompatible with ssl.wrap_socket from python 2.7 < 2.7.9.
|
||||
|
||||
You must pass protocol which must be one of the PROTOCOL_* constants
|
||||
defined in the ssl module. ssl.PROTOCOL_SSLv23 is recommended for maximum
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
# Backport of the match_hostname logic from python 3.5, with small
|
||||
# changes to support IP address matching on python 2.6, 2.7, 3.3, and 3.4.
|
||||
# changes to support IP address matching on python 2.7 and 3.4.
|
||||
|
||||
import re
|
||||
import sys
|
||||
|
||||
try:
|
||||
# Python 3.3+, or the ipaddress module from pypi.
|
||||
# Python 3.4+, or the ipaddress module from pypi.
|
||||
from ipaddress import ip_address
|
||||
except ImportError:
|
||||
ip_address = lambda address: None
|
||||
|
||||
@ -123,7 +123,7 @@ if HAVE_SSL:
|
||||
# up to date versions of MongoDB 2.4 and above already disable
|
||||
# SSLv2 and SSLv3, python disables SSLv2 by default in >= 2.7.7
|
||||
# and >= 3.3.4 and SSLv3 in >= 3.4.3. There is no way for us to do
|
||||
# any of this explicitly for python 2.6 or 2.7 before 2.7.9.
|
||||
# any of this explicitly for python 2.7 before 2.7.9.
|
||||
ctx.options |= getattr(ssl, "OP_NO_SSLv2", 0)
|
||||
ctx.options |= getattr(ssl, "OP_NO_SSLv3", 0)
|
||||
# OpenSSL >= 1.0.0
|
||||
|
||||
31
setup.py
31
setup.py
@ -97,21 +97,16 @@ class test(Command):
|
||||
if self.distribution.tests_require:
|
||||
self.distribution.fetch_build_eggs(self.distribution.tests_require)
|
||||
if self.xunit_output:
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
self.distribution.fetch_build_eggs(
|
||||
["unittest-xml-reporting>=1.14.0,<2.0.0a0"])
|
||||
else:
|
||||
self.distribution.fetch_build_eggs(["unittest-xml-reporting"])
|
||||
self.distribution.fetch_build_eggs(["unittest-xml-reporting"])
|
||||
self.run_command('egg_info')
|
||||
build_ext_cmd = self.reinitialize_command('build_ext')
|
||||
build_ext_cmd.inplace = 1
|
||||
self.run_command('build_ext')
|
||||
|
||||
# Construct a TextTestRunner directly from the unittest imported from
|
||||
# test (this will be unittest2 under Python 2.6), which creates a
|
||||
# TestResult that supports the 'addSkip' method. setuptools will by
|
||||
# default create a TextTestRunner that uses the old TestResult class,
|
||||
# resulting in DeprecationWarnings instead of skipping tests under 2.6.
|
||||
# test, which creates a TestResult that supports the 'addSkip' method.
|
||||
# setuptools will by default create a TextTestRunner that uses the old
|
||||
# TestResult class.
|
||||
from test import unittest, PymongoTestRunner, test_cases
|
||||
if self.test_suite is None:
|
||||
all_tests = unittest.defaultTestLoader.discover(self.test_module)
|
||||
@ -223,8 +218,8 @@ class doc(Command):
|
||||
" %s/\n" % (mode, path))
|
||||
|
||||
|
||||
if sys.platform == 'win32' and sys.version_info > (2, 6):
|
||||
# 2.6's distutils.msvc9compiler can raise an IOError when failing to
|
||||
if sys.platform == 'win32':
|
||||
# distutils.msvc9compiler can raise an IOError when failing to
|
||||
# find the compiler
|
||||
build_errors = (CCompilerError, DistutilsExecError,
|
||||
DistutilsPlatformError, IOError)
|
||||
@ -294,7 +289,7 @@ http://api.mongodb.org/python/current/installation.html#osx
|
||||
|
||||
def build_extension(self, ext):
|
||||
name = ext.name
|
||||
if sys.version_info[:3] >= (2, 6, 0):
|
||||
if sys.version_info[:3] >= (2, 7, 0):
|
||||
try:
|
||||
build_ext.build_extension(self, ext)
|
||||
except build_errors:
|
||||
@ -310,7 +305,7 @@ http://api.mongodb.org/python/current/installation.html#osx
|
||||
warnings.warn(self.warning_message % ("The %s extension "
|
||||
"module" % (name,),
|
||||
"PyMongo supports python "
|
||||
">= 2.6."))
|
||||
">= 2.7."))
|
||||
|
||||
ext_modules = [Extension('bson._cbson',
|
||||
include_dirs=['bson'],
|
||||
@ -343,15 +338,6 @@ else:
|
||||
extra_opts = {
|
||||
"packages": ["bson", "pymongo", "gridfs"]
|
||||
}
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
try:
|
||||
import unittest2
|
||||
except ImportError:
|
||||
# The setuptools version on Solaris 11 is incapable
|
||||
# of recognizing if unittest2 is already installed.
|
||||
# It's also incapable of installing any version of
|
||||
# unittest2 newer than 0.8.0
|
||||
extra_opts['tests_require'] = "unittest2<=0.8.0"
|
||||
|
||||
if "--no_ext" in sys.argv:
|
||||
sys.argv.remove("--no_ext")
|
||||
@ -388,7 +374,6 @@ setup(
|
||||
"Operating System :: Microsoft :: Windows",
|
||||
"Operating System :: POSIX",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.6",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
|
||||
@ -20,6 +20,7 @@ import socket
|
||||
import sys
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
import warnings
|
||||
|
||||
try:
|
||||
@ -28,14 +29,8 @@ try:
|
||||
except ImportError:
|
||||
HAVE_IPADDRESS = False
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
import unittest2 as unittest
|
||||
from unittest2 import SkipTest
|
||||
else:
|
||||
import unittest
|
||||
from unittest import SkipTest
|
||||
|
||||
from functools import wraps
|
||||
from unittest import SkipTest
|
||||
|
||||
import pymongo
|
||||
import pymongo.errors
|
||||
|
||||
@ -17,13 +17,7 @@
|
||||
import os
|
||||
import ssl
|
||||
import sys
|
||||
|
||||
# Don't drag in PyMongo's entire test suite
|
||||
# just to get the right unittest module.
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
import unittest2 as unittest
|
||||
else:
|
||||
import unittest
|
||||
import unittest
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
|
||||
@ -38,7 +38,7 @@ Compile mod_wsgi
|
||||
................
|
||||
|
||||
Compile mod_wsgi for each combination for Python and mod_wsgi version in the
|
||||
test matrix. For example, to compile mod_wsgi 3.4 for Python 2.6 on a
|
||||
test matrix. For example, to compile mod_wsgi 3.4 for Python 2.7 on a
|
||||
RedHat-like Linux::
|
||||
|
||||
sudo yum install -y httpd httpd-devel
|
||||
|
||||
@ -18,19 +18,12 @@ import binascii
|
||||
import codecs
|
||||
import functools
|
||||
import glob
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
from decimal import DecimalException
|
||||
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
try:
|
||||
import simplejson as json
|
||||
except ImportError:
|
||||
import json
|
||||
else:
|
||||
import json
|
||||
|
||||
sys.path[0:0] = [""]
|
||||
|
||||
from bson import BSON, json_util
|
||||
@ -92,17 +85,11 @@ to_bson_uuid_04 = functools.partial(BSON.encode,
|
||||
codec_options=codec_options_uuid_04)
|
||||
to_bson = functools.partial(BSON.encode, codec_options=codec_options)
|
||||
decode_bson = lambda bbytes: BSON(bbytes).decode(codec_options=codec_options)
|
||||
if json_util._HAS_OBJECT_PAIRS_HOOK:
|
||||
decode_extjson = functools.partial(
|
||||
json_util.loads,
|
||||
json_options=json_util.JSONOptions(json_mode=JSONMode.CANONICAL,
|
||||
document_class=SON))
|
||||
loads = functools.partial(json.loads, object_pairs_hook=SON)
|
||||
else:
|
||||
decode_extjson = functools.partial(
|
||||
json_util.loads,
|
||||
json_options=json_util.CANONICAL_JSON_OPTIONS)
|
||||
loads = json.loads
|
||||
decode_extjson = functools.partial(
|
||||
json_util.loads,
|
||||
json_options=json_util.JSONOptions(json_mode=JSONMode.CANONICAL,
|
||||
document_class=SON))
|
||||
loads = functools.partial(json.loads, object_pairs_hook=SON)
|
||||
|
||||
|
||||
class TestBSONCorpus(unittest.TestCase):
|
||||
@ -177,7 +164,7 @@ def create_test(case_spec):
|
||||
# Test round-tripping canonical extended json.
|
||||
decoded_json = decode_extjson(cEJ)
|
||||
self.assertJsonEqual(encode_extjson(decoded_json), cEJ)
|
||||
if not lossy and json_util._HAS_OBJECT_PAIRS_HOOK:
|
||||
if not lossy:
|
||||
self.assertEqual(encode_bson(decoded_json), cB)
|
||||
|
||||
# Test round-tripping degenerate bson.
|
||||
@ -190,9 +177,6 @@ def create_test(case_spec):
|
||||
decoded_json = decode_extjson(dEJ)
|
||||
self.assertJsonEqual(encode_extjson(decoded_json), cEJ)
|
||||
if not lossy:
|
||||
# We don't need to check json_util._HAS_OBJECT_PAIRS_HOOK
|
||||
# because degenerate_extjson is always a single key so
|
||||
# the order cannot be changed.
|
||||
self.assertEqual(encode_bson(decoded_json), cB)
|
||||
|
||||
# Test round-tripping relaxed extended json.
|
||||
|
||||
@ -911,9 +911,6 @@ class TestClient(IntegrationTest):
|
||||
@client_context.require_ipv6
|
||||
def test_ipv6(self):
|
||||
if client_context.ssl:
|
||||
# http://bugs.python.org/issue13034
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
raise SkipTest("Python 2.6 can't parse SANs")
|
||||
if not HAVE_IPADDRESS:
|
||||
raise SkipTest("Need the ipaddress module to test with SSL")
|
||||
|
||||
|
||||
@ -131,11 +131,9 @@ def run_operation(collection, test):
|
||||
else:
|
||||
for arg_name in list(arguments):
|
||||
c2s = camel_to_snake(arg_name)
|
||||
# PyMongo accepts sort as list of tuples. Asserting len=1
|
||||
# because ordering dicts from JSON in 2.6 is unwieldy.
|
||||
# PyMongo accepts sort as list of tuples.
|
||||
if arg_name == "sort":
|
||||
sort_dict = arguments[arg_name]
|
||||
assert len(sort_dict) == 1, 'test can only have 1 sort key'
|
||||
arguments[arg_name] = list(iteritems(sort_dict))
|
||||
# Named "key" instead not fieldName.
|
||||
if arg_name == "fieldName":
|
||||
|
||||
@ -26,8 +26,7 @@ from pymongo.errors import ConfigurationError
|
||||
|
||||
from bson import json_util, EPOCH_AWARE, EPOCH_NAIVE, SON
|
||||
from bson.json_util import (DatetimeRepresentation,
|
||||
STRICT_JSON_OPTIONS,
|
||||
_HAS_OBJECT_PAIRS_HOOK)
|
||||
STRICT_JSON_OPTIONS)
|
||||
from bson.binary import (ALL_UUID_REPRESENTATIONS, Binary, MD5_SUBTYPE,
|
||||
USER_DEFINED_SUBTYPE, JAVA_LEGACY, CSHARP_LEGACY,
|
||||
STANDARD)
|
||||
@ -64,11 +63,10 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.round_trip({"ref": DBRef("foo", 5, "db")})
|
||||
self.round_trip({"ref": DBRef("foo", ObjectId())})
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$ref": "collection", "$id": 1, "$db": "db"}',
|
||||
json_util.dumps(DBRef('collection', 1, 'db')))
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$ref": "collection", "$id": 1, "$db": "db"}',
|
||||
json_util.dumps(DBRef('collection', 1, 'db')))
|
||||
|
||||
def test_datetime(self):
|
||||
# only millis, not micros
|
||||
@ -226,15 +224,14 @@ class TestJsonUtil(unittest.TestCase):
|
||||
json_util.loads(
|
||||
'{"r": {"$regex": ".*", "$options": "ilm"}}')['r'])
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(Regex('.*', re.M | re.X)))
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(Regex('.*', re.M | re.X)))
|
||||
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(re.compile(b'.*', re.M | re.X)))
|
||||
self.assertEqual(
|
||||
'{"$regex": ".*", "$options": "mx"}',
|
||||
json_util.dumps(re.compile(b'.*', re.M | re.X)))
|
||||
|
||||
def test_minkey(self):
|
||||
self.round_trip({"m": MinKey()})
|
||||
@ -247,9 +244,7 @@ class TestJsonUtil(unittest.TestCase):
|
||||
res = json_util.dumps(dct, default=json_util.default)
|
||||
rtdct = json_util.loads(res)
|
||||
self.assertEqual(dct, rtdct)
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
self.assertEqual('{"ts": {"$timestamp": {"t": 4, "i": 13}}}', res)
|
||||
self.assertEqual('{"ts": {"$timestamp": {"t": 4, "i": 13}}}', res)
|
||||
|
||||
def test_uuid(self):
|
||||
doc = {'uuid': uuid.UUID('f47ac10b-58cc-4372-a567-0e02b2c3d479')}
|
||||
@ -257,33 +252,30 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
'{"uuid": {"$uuid": "f47ac10b58cc4372a5670e02b2c3d479"}}',
|
||||
json_util.dumps(doc))
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
self.assertEqual(
|
||||
self.assertEqual(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
json_util.dumps(
|
||||
doc, json_options=json_util.STRICT_JSON_OPTIONS))
|
||||
self.assertEqual(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_util.dumps(
|
||||
doc, json_options=json_util.JSONOptions(
|
||||
strict_uuid=True, uuid_representation=STANDARD)))
|
||||
self.assertEqual(
|
||||
doc, json_util.loads(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}',
|
||||
json_util.dumps(
|
||||
doc, json_options=json_util.STRICT_JSON_OPTIONS))
|
||||
self.assertEqual(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_util.dumps(
|
||||
doc, json_options=json_util.JSONOptions(
|
||||
strict_uuid=True, uuid_representation=STANDARD)))
|
||||
self.assertEqual(
|
||||
doc, json_util.loads(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}'))
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "03"}}'))
|
||||
for uuid_representation in ALL_UUID_REPRESENTATIONS:
|
||||
options = json_util.JSONOptions(
|
||||
strict_uuid=True, uuid_representation=uuid_representation)
|
||||
self.round_trip(doc, json_options=options)
|
||||
# Ignore UUID representation when decoding BSON binary subtype 4.
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
self.assertEqual(doc, json_util.loads(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_options=options))
|
||||
self.assertEqual(doc, json_util.loads(
|
||||
'{"uuid": '
|
||||
'{"$binary": "9HrBC1jMQ3KlZw4CssPUeQ==", "$type": "04"}}',
|
||||
json_options=options))
|
||||
|
||||
def test_binary(self):
|
||||
if PY3:
|
||||
@ -312,24 +304,22 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.assertTrue('"$type": "00"' in json_bin_dump)
|
||||
self.assertEqual(bin_type_dict,
|
||||
json_util.loads('{"bin": {"$type": 0, "$binary": "AAECAwQ="}}'))
|
||||
json_bin_dump = json_util.dumps(md5_type_dict)
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==",'
|
||||
+ ' "$type": "05"}}',
|
||||
json_bin_dump)
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
json_bin_dump = json_util.dumps(md5_type_dict)
|
||||
# Check order.
|
||||
self.assertEqual(
|
||||
'{"md5": {"$binary": "IG43GK8JL9HRL4DK53HMrA==",'
|
||||
+ ' "$type": "05"}}',
|
||||
json_bin_dump)
|
||||
self.assertEqual(md5_type_dict,
|
||||
json_util.loads('{"md5": {"$type": 5, "$binary":'
|
||||
' "IG43GK8JL9HRL4DK53HMrA=="}}'))
|
||||
|
||||
self.assertEqual(md5_type_dict,
|
||||
json_util.loads('{"md5": {"$type": 5, "$binary":'
|
||||
' "IG43GK8JL9HRL4DK53HMrA=="}}'))
|
||||
|
||||
json_bin_dump = json_util.dumps(custom_type_dict)
|
||||
self.assertTrue('"$type": "80"' in json_bin_dump)
|
||||
self.assertEqual(custom_type_dict,
|
||||
json_util.loads('{"custom": {"$type": 128, "$binary":'
|
||||
' "aGVsbG8="}}'))
|
||||
json_bin_dump = json_util.dumps(custom_type_dict)
|
||||
self.assertTrue('"$type": "80"' in json_bin_dump)
|
||||
self.assertEqual(custom_type_dict,
|
||||
json_util.loads('{"custom": {"$type": 128, "$binary":'
|
||||
' "aGVsbG8="}}'))
|
||||
|
||||
# Handle mongoexport where subtype >= 128
|
||||
self.assertEqual(128,
|
||||
@ -347,13 +337,12 @@ class TestJsonUtil(unittest.TestCase):
|
||||
res = json_util.dumps(code)
|
||||
self.assertEqual(code, json_util.loads(res))
|
||||
|
||||
if _HAS_OBJECT_PAIRS_HOOK:
|
||||
# Check order.
|
||||
self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res)
|
||||
# Check order.
|
||||
self.assertEqual('{"$code": "return z", "$scope": {"z": 2}}', res)
|
||||
|
||||
no_scope = Code('function() {}')
|
||||
self.assertEqual(
|
||||
'{"$code": "function() {}"}', json_util.dumps(no_scope))
|
||||
no_scope = Code('function() {}')
|
||||
self.assertEqual(
|
||||
'{"$code": "function() {}"}', json_util.dumps(no_scope))
|
||||
|
||||
def test_undefined(self):
|
||||
jsn = '{"name": {"$undefined": true}}'
|
||||
@ -375,13 +364,9 @@ class TestJsonUtil(unittest.TestCase):
|
||||
self.assertEqual({"foo": "bar"}, json_util.loads(
|
||||
'{"foo": "bar"}',
|
||||
json_options=json_util.JSONOptions(document_class=dict)))
|
||||
if not _HAS_OBJECT_PAIRS_HOOK:
|
||||
self.assertRaises(
|
||||
ConfigurationError, json_util.JSONOptions, document_class=SON)
|
||||
else:
|
||||
self.assertEqual(SON([("foo", "bar"), ("b", 1)]), json_util.loads(
|
||||
'{"foo": "bar", "b": 1}',
|
||||
json_options=json_util.JSONOptions(document_class=SON)))
|
||||
self.assertEqual(SON([("foo", "bar"), ("b", 1)]), json_util.loads(
|
||||
'{"foo": "bar", "b": 1}',
|
||||
json_options=json_util.JSONOptions(document_class=SON)))
|
||||
|
||||
|
||||
class TestJsonUtilRoundtrip(IntegrationTest):
|
||||
|
||||
@ -196,9 +196,6 @@ class TestReplicaSetClient(TestReplicaSetClientBase):
|
||||
@client_context.require_ipv6
|
||||
def test_ipv6(self):
|
||||
if client_context.ssl:
|
||||
# http://bugs.python.org/issue13034
|
||||
if sys.version_info[:2] == (2, 6):
|
||||
raise SkipTest("Python 2.6 can't parse SANs")
|
||||
if not HAVE_IPADDRESS:
|
||||
raise SkipTest("Need the ipaddress module to test with SSL")
|
||||
|
||||
|
||||
@ -257,9 +257,7 @@ class TestSSL(IntegrationTest):
|
||||
|
||||
self.assertClientWorks(client)
|
||||
|
||||
# Python 2.6 often can't read SANs from the peer cert.
|
||||
# http://bugs.python.org/issue13034
|
||||
if HAVE_IPADDRESS and sys.version_info[:2] > (2, 6):
|
||||
if HAVE_IPADDRESS:
|
||||
client = MongoClient('127.0.0.1',
|
||||
ssl=True,
|
||||
ssl_certfile=CLIENT_PEM,
|
||||
|
||||
@ -247,11 +247,9 @@ class TestTransactions(IntegrationTest):
|
||||
|
||||
for arg_name in list(arguments):
|
||||
c2s = camel_to_snake(arg_name)
|
||||
# PyMongo accepts sort as list of tuples. Asserting len=1
|
||||
# because ordering dicts from JSON in 2.6 is unwieldy.
|
||||
# PyMongo accepts sort as list of tuples.
|
||||
if arg_name == "sort":
|
||||
sort_dict = arguments[arg_name]
|
||||
assert len(sort_dict) == 1, 'test can only have 1 sort key'
|
||||
arguments[arg_name] = list(iteritems(sort_dict))
|
||||
# Named "key" instead not fieldName.
|
||||
if arg_name == "fieldName":
|
||||
|
||||
6
tox.ini
6
tox.ini
@ -4,13 +4,9 @@
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = py26, py27, py33, py34, py35, pypy, pypy3
|
||||
envlist = py27, py34, py35, py36, pypy, pypy3
|
||||
skip_missing_interpreters = True
|
||||
|
||||
[testenv]
|
||||
commands =
|
||||
{envpython} setup.py --no_ext test
|
||||
|
||||
[testenv:py26]
|
||||
deps =
|
||||
unittest2
|
||||
|
||||
Loading…
Reference in New Issue
Block a user