diff --git a/setup.py b/setup.py index 55fe9f853..7ffcbc204 100755 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ import subprocess import sys import warnings -# Hack to silence atexit traceback in newer python versions. +# Hack to silence atexit traceback in some Python versions try: import multiprocessing except ImportError: @@ -191,8 +191,11 @@ ext_modules = [Extension('bson._cbson', extra_opts = { "packages": ["bson", "pymongo", "gridfs"], - "test_suite": "nose.collector" + "test_suite": "test.test_suite" } +if sys.version_info[:2] == (2, 6): + extra_opts['tests_require'] = "unittest2" + if "--no_ext" in sys.argv: sys.argv.remove("--no_ext") elif (sys.platform.startswith("java") or @@ -228,7 +231,6 @@ setup( keywords=["mongo", "mongodb", "pymongo", "gridfs", "bson"], install_requires=[], license="Apache License, Version 2.0", - tests_require=["nose"], classifiers=[ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", diff --git a/test/__init__.py b/test/__init__.py index 1f3fe3e23..67ddc9bbd 100644 --- a/test/__init__.py +++ b/test/__init__.py @@ -12,15 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. -"""Clean up databases after running `nosetests`. +"""Test suite for pymongo, bson, and gridfs. """ import os +import sys +if sys.version_info[:2] == (2, 6): + import unittest2 as unittest + from unittest2.case import SkipTest +else: + import unittest + from unittest import SkipTest import warnings -from bson.py3compat import _unicode import pymongo -from pymongo.errors import ConnectionFailure + +from bson.py3compat import _unicode # hostnames retrieved by MongoReplicaSetClient from isMaster will be of unicode # type in Python 2, so ensure these hostnames are unicodes, too. It makes tests @@ -35,9 +42,10 @@ port2 = int(os.environ.get("DB_PORT2", 27018)) host3 = _unicode(os.environ.get("DB_IP3", 'localhost')) port3 = int(os.environ.get("DB_PORT3", 27019)) -# Make sure warnings are always raised, regardless of -# python version. + def setup(): + # Make sure warnings are always raised, regardless of + # python version. warnings.resetwarnings() warnings.simplefilter("always") @@ -45,7 +53,7 @@ def setup(): def teardown(): try: c = pymongo.MongoClient(host, port) - except ConnectionFailure: + except pymongo.errors.ConnectionFailure: # Tests where ssl=True can cause connection failures here. # Ignore and continue. return @@ -56,3 +64,21 @@ def teardown(): c.drop_database("pymongo_test2") c.drop_database("pymongo_test_mike") c.drop_database("pymongo_test_bernie") + + +class PymongoTestSuite(unittest.TestSuite): + """Run package-level setup and teardown functions. + + This functionality was built into nose, but doesn't exist in + unittest. + """ + def run(self, result): + setup() + super(PymongoTestSuite, self).run(result) + teardown() + + +class PymongoTestLoader(unittest.TestLoader): + suiteClass = PymongoTestSuite + +test_suite = PymongoTestLoader().discover('.') diff --git a/test/high_availability/test_ha.py b/test/high_availability/test_ha.py index 638aa0bce..197d42a64 100644 --- a/test/high_availability/test_ha.py +++ b/test/high_availability/test_ha.py @@ -20,12 +20,10 @@ # given replica-set configuration. import time -import unittest import ha_tools from ha_tools import use_greenlets -from nose.plugins.skip import SkipTest from pymongo.errors import (AutoReconnect, OperationFailure, ConnectionFailure, @@ -36,7 +34,7 @@ from pymongo.mongo_replica_set_client import MongoReplicaSetClient from pymongo.mongo_client import MongoClient, _partition_node from pymongo.read_preferences import ReadPreference -from test import utils, version +from test import SkipTest, unittest, utils, version from test.utils import one diff --git a/test/test_auth.py b/test/test_auth.py index 6f4b37946..b7d432b9a 100644 --- a/test/test_auth.py +++ b/test/test_auth.py @@ -17,7 +17,6 @@ import os import sys import threading -import unittest try: from urllib.parse import quote_plus @@ -27,13 +26,11 @@ except ImportError: sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from pymongo import MongoClient, MongoReplicaSetClient from pymongo.auth import HAVE_KERBEROS from pymongo.errors import OperationFailure, ConfigurationError from pymongo.read_preferences import ReadPreference -from test import version, host, port +from test import host, port, SkipTest, unittest, version from test.utils import is_mongos, server_started_with_auth # YOU MUST RUN KINIT BEFORE RUNNING GSSAPI TESTS. diff --git a/test/test_binary.py b/test/test_binary.py index 08a514747..9e6470dc6 100644 --- a/test/test_binary.py +++ b/test/test_binary.py @@ -18,7 +18,6 @@ import base64 import copy import pickle import sys -import unittest import uuid sys.path[0:0] = [""] @@ -28,10 +27,11 @@ import bson from bson.binary import * from bson.py3compat import u from bson.son import SON -from nose.plugins.skip import SkipTest +from test import unittest from test.test_client import get_client from pymongo.mongo_client import MongoClient + class TestBinary(unittest.TestCase): def test_binary(self): a_string = "hello world" diff --git a/test/test_bson.py b/test/test_bson.py index c4e27e33b..07f2d90c5 100644 --- a/test/test_bson.py +++ b/test/test_bson.py @@ -20,13 +20,10 @@ import datetime import re import sys import traceback -import unittest import uuid sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - import bson from bson import (BSON, decode_all, @@ -47,7 +44,7 @@ from bson.min_key import MinKey from bson.tz_util import (FixedOffset, utc) -from test import qcheck +from test import qcheck, SkipTest, unittest if PY3: long = int diff --git a/test/test_bulk.py b/test/test_bulk.py index ee2163f60..ce3f611eb 100644 --- a/test/test_bulk.py +++ b/test/test_bulk.py @@ -15,22 +15,20 @@ """Test the bulk API.""" import sys -import unittest - -from nose.plugins.skip import SkipTest sys.path[0:0] = [""] from bson import InvalidDocument, SON from bson.py3compat import string_type from pymongo.errors import BulkWriteError, InvalidOperation, OperationFailure -from test import version +from test import SkipTest, unittest, version from test.test_client import get_client from test.utils import (oid_generated_on_client, remove_all_users, server_started_with_auth, server_started_with_nojournal) + class BulkTestBase(unittest.TestCase): def setUp(self): diff --git a/test/test_client.py b/test/test_client.py index 5f554504e..ad7b9ace8 100644 --- a/test/test_client.py +++ b/test/test_client.py @@ -20,12 +20,9 @@ import threading import socket import sys import time -import unittest sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.py3compat import thread, u from bson.son import SON from bson.tz_util import utc @@ -39,7 +36,7 @@ from pymongo.errors import (AutoReconnect, InvalidName, OperationFailure, PyMongoError) -from test import version, host, port, pair +from test import host, pair, port, SkipTest, unittest, version from test.pymongo_mocks import MockClient from test.utils import (assertRaisesExactly, delay, diff --git a/test/test_code.py b/test/test_code.py index c01fb26ba..02d524b3b 100644 --- a/test/test_code.py +++ b/test/test_code.py @@ -14,12 +14,12 @@ """Tests for the Code wrapper.""" -import unittest import sys sys.path[0:0] = [""] from bson.code import Code from bson.py3compat import u +from test import unittest class TestCode(unittest.TestCase): diff --git a/test/test_collection.py b/test/test_collection.py index 5f1da7f52..439d49e1f 100644 --- a/test/test_collection.py +++ b/test/test_collection.py @@ -21,12 +21,9 @@ import re import sys import threading import time -import unittest import uuid import warnings -from nose.plugins.skip import SkipTest - sys.path[0:0] = [""] from bson.binary import Binary @@ -54,8 +51,7 @@ from pymongo.errors import (DocumentTooLarge, from test.test_client import get_client from test.utils import (is_mongos, joinall, enable_text_search, get_pool, oid_generated_on_client) -from test import (qcheck, - version) +from test import qcheck, SkipTest, unittest, version class TestCollection(unittest.TestCase): diff --git a/test/test_common.py b/test/test_common.py index aaa960d16..a4d8a7904 100644 --- a/test/test_common.py +++ b/test/test_common.py @@ -15,14 +15,11 @@ """Test the pymongo common module.""" import sys -import unittest import uuid import warnings sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.binary import UUIDLegacy, OLD_UUID_SUBTYPE, UUID_SUBTYPE from bson.code import Code from bson.objectid import ObjectId @@ -30,7 +27,7 @@ from bson.son import SON from pymongo.mongo_client import MongoClient from pymongo.mongo_replica_set_client import MongoReplicaSetClient from pymongo.errors import ConfigurationError, OperationFailure -from test import host, port, pair, version +from test import pair, unittest, SkipTest, version from test.utils import drop_collections diff --git a/test/test_cursor.py b/test/test_cursor.py index 4cf6c3db7..af5c61c25 100644 --- a/test/test_cursor.py +++ b/test/test_cursor.py @@ -18,11 +18,8 @@ import itertools import random import re import sys -import unittest sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.code import Code from bson.py3compat import u, PY3 from bson.son import SON @@ -36,7 +33,7 @@ from pymongo.database import Database from pymongo.errors import (InvalidOperation, OperationFailure, ExecutionTimeout) -from test import version +from test import SkipTest, unittest, version from test.test_client import get_client from test.utils import is_mongos, get_command_line, server_started_with_auth diff --git a/test/test_database.py b/test/test_database.py index 031dd0201..2762c57bb 100644 --- a/test/test_database.py +++ b/test/test_database.py @@ -21,9 +21,6 @@ import sys import warnings sys.path[0:0] = [""] -import unittest - -from nose.plugins.skip import SkipTest from bson.code import Code from bson.regex import Regex @@ -47,7 +44,7 @@ from pymongo.errors import (CollectionInvalid, from pymongo.son_manipulator import (AutoReference, NamespaceInjector, ObjectIdShuffler) -from test import version +from test import SkipTest, unittest, version from test.utils import (get_command_line, is_mongos, remove_all_users, server_started_with_auth) from test.test_client import get_client diff --git a/test/test_dbref.py b/test/test_dbref.py index f4b3adee9..72ac5f908 100644 --- a/test/test_dbref.py +++ b/test/test_dbref.py @@ -15,13 +15,13 @@ """Tests for the dbref module.""" import pickle -import unittest import sys sys.path[0:0] = [""] from bson.dbref import DBRef from bson.objectid import ObjectId from bson.py3compat import u +from test import unittest from copy import deepcopy diff --git a/test/test_errors.py b/test/test_errors.py index 59416e521..5a8931d0a 100644 --- a/test/test_errors.py +++ b/test/test_errors.py @@ -14,12 +14,12 @@ """Test the errors module.""" -import unittest import sys sys.path[0:0] = [""] from pymongo import MongoClient from pymongo.errors import PyMongoError +from test import unittest class TestErrors(unittest.TestCase): diff --git a/test/test_grid_file.py b/test/test_grid_file.py index ec8dca925..3fa535abc 100644 --- a/test/test_grid_file.py +++ b/test/test_grid_file.py @@ -19,11 +19,8 @@ import datetime import sys -import unittest sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.objectid import ObjectId from bson.py3compat import u, StringIO from gridfs import GridFS @@ -39,7 +36,7 @@ from gridfs.errors import (NoFile, from pymongo import MongoClient from pymongo.errors import ConnectionFailure from test.test_client import get_client -from test import qcheck +from test import qcheck, unittest class TestGridFile(unittest.TestCase): diff --git a/test/test_gridfs.py b/test/test_gridfs.py index 2c6a80912..99888bf18 100644 --- a/test/test_gridfs.py +++ b/test/test_gridfs.py @@ -25,7 +25,6 @@ from pymongo.read_preferences import ReadPreference from test.test_replica_set_client import TestReplicaSetClientBase import datetime -import unittest import threading import time import gridfs @@ -33,6 +32,7 @@ import gridfs from bson.py3compat import u, StringIO, string_type from gridfs.errors import (FileExists, NoFile) +from test import unittest from test.test_client import get_client from test.utils import joinall diff --git a/test/test_json_util.py b/test/test_json_util.py index 07be715ef..ed022e773 100644 --- a/test/test_json_util.py +++ b/test/test_json_util.py @@ -14,14 +14,11 @@ """Test some utilities for working with JSON and PyMongo.""" -import unittest import datetime import re import sys import uuid -from nose.plugins.skip import SkipTest - sys.path[0:0] = [""] from bson import json_util @@ -36,6 +33,7 @@ from bson.son import RE_TYPE from bson.timestamp import Timestamp from bson.tz_util import utc +from test import SkipTest, unittest from test.test_client import get_client PY3 = sys.version_info[0] == 3 diff --git a/test/test_mongos_ha.py b/test/test_mongos_ha.py index 3032f5a37..3bfb480f6 100644 --- a/test/test_mongos_ha.py +++ b/test/test_mongos_ha.py @@ -16,11 +16,11 @@ import sys import threading -import unittest sys.path[0:0] = [""] from pymongo.errors import AutoReconnect +from test import unittest from test.pymongo_mocks import MockClient diff --git a/test/test_objectid.py b/test/test_objectid.py index 37f39a9bc..a8271cb75 100644 --- a/test/test_objectid.py +++ b/test/test_objectid.py @@ -16,18 +16,16 @@ import datetime import pickle -import unittest import sys import time sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.errors import InvalidId from bson.objectid import ObjectId from bson.py3compat import PY3, u, _unicode from bson.tz_util import (FixedOffset, utc) +from test import SkipTest, unittest def oid(x): diff --git a/test/test_pooling.py b/test/test_pooling.py index 28bbf0e2b..c09e1e046 100644 --- a/test/test_pooling.py +++ b/test/test_pooling.py @@ -16,14 +16,12 @@ import sys import time -import unittest sys.path[0:0] = [""] from bson.py3compat import thread -from nose.plugins.skip import SkipTest -from test import host, port +from test import host, port, SkipTest, unittest from test.test_pooling_base import ( _TestPooling, _TestMaxPoolSize, _TestMaxOpenSockets, _TestPoolSocketSharing, _TestWaitQueueMultiple, one) diff --git a/test/test_pooling_base.py b/test/test_pooling_base.py index 3d1130427..ac8850471 100644 --- a/test/test_pooling_base.py +++ b/test/test_pooling_base.py @@ -24,15 +24,13 @@ import time sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - import pymongo.pool from bson.py3compat import thread from pymongo.mongo_client import MongoClient from pymongo.pool import Pool, NO_REQUEST, NO_SOCKET_YET, SocketInfo from pymongo.errors import ConfigurationError, ConnectionFailure from pymongo.errors import ExceededMaxWaiters -from test import version, host, port +from test import version, host, port, SkipTest from test.test_client import get_client from test.utils import delay, is_mongos, one, get_pool @@ -311,7 +309,7 @@ class CreateAndReleaseSocketNoRendezvous(MongoThread): class _TestPoolingBase(object): """Base class for all client-pool tests. Doesn't inherit from unittest.TestCase, and its name is prefixed with "_" to avoid being - run by nose. Real tests double-inherit from this base and from TestCase. + run by unittest. Real tests double-inherit from this base and from TestCase. """ use_greenlets = False diff --git a/test/test_pooling_gevent.py b/test/test_pooling_gevent.py index 88bb2c083..276cc4f2a 100644 --- a/test/test_pooling_gevent.py +++ b/test/test_pooling_gevent.py @@ -17,13 +17,10 @@ import gc import sys import time -import unittest - -from nose.plugins.skip import SkipTest from pymongo import pool from pymongo.errors import ConfigurationError -from test import host, port +from test import host, port, SkipTest, unittest from test.utils import looplet from test.test_pooling_base import ( _TestPooling, _TestMaxPoolSize, _TestMaxOpenSockets, diff --git a/test/test_pymongo.py b/test/test_pymongo.py index a861b1f78..fe499eda6 100644 --- a/test/test_pymongo.py +++ b/test/test_pymongo.py @@ -14,13 +14,13 @@ """Test the pymongo module itself.""" -import unittest import os import sys sys.path[0:0] = [""] import pymongo -from test import host, port +from test import host, port, unittest + class TestPyMongo(unittest.TestCase): def test_mongo_client_alias(self): diff --git a/test/test_read_preferences.py b/test/test_read_preferences.py index cf4826ab6..a296695c0 100644 --- a/test/test_read_preferences.py +++ b/test/test_read_preferences.py @@ -16,9 +16,6 @@ import random import sys -import unittest - -from nose.plugins.skip import SkipTest sys.path[0:0] = [""] @@ -35,7 +32,7 @@ from pymongo.errors import ConfigurationError from test.test_replica_set_client import TestReplicaSetClientBase from test.test_client import get_client -from test import version, utils, host, port +from test import host, port, SkipTest, unittest, utils, version class TestReadPreferencesBase(TestReplicaSetClientBase): diff --git a/test/test_replica_set_client.py b/test/test_replica_set_client.py index 326bd56cc..624db2b7e 100644 --- a/test/test_replica_set_client.py +++ b/test/test_replica_set_client.py @@ -23,12 +23,9 @@ import sys import time import threading import traceback -import unittest sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from bson.py3compat import thread, u, _unicode from bson.son import SON from bson.tz_util import utc @@ -43,7 +40,7 @@ from pymongo.errors import (AutoReconnect, ConnectionFailure, InvalidName, OperationFailure, InvalidOperation) -from test import version, port, pair +from test import pair, port, SkipTest, unittest, version from test.pymongo_mocks import MockReplicaSetClient from test.utils import ( delay, assertReadFrom, assertReadFromAll, read_from_which_host, diff --git a/test/test_replica_set_reconfig.py b/test/test_replica_set_reconfig.py index aeabf3e13..157a8d3f2 100644 --- a/test/test_replica_set_reconfig.py +++ b/test/test_replica_set_reconfig.py @@ -15,12 +15,12 @@ """Test clients and replica set configuration changes, using mocks.""" import sys -import unittest sys.path[0:0] = [""] from pymongo.errors import ConfigurationError, ConnectionFailure from pymongo import ReadPreference +from test import unittest from test.pymongo_mocks import MockClient, MockReplicaSetClient diff --git a/test/test_son.py b/test/test_son.py index 1d41cb97d..1b97f81b5 100644 --- a/test/test_son.py +++ b/test/test_son.py @@ -18,13 +18,12 @@ import copy import pickle import re import sys -import unittest -sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest +sys.path[0:0] = [""] from bson.py3compat import b from bson.son import SON +from test import SkipTest, unittest class TestSON(unittest.TestCase): diff --git a/test/test_son_manipulator.py b/test/test_son_manipulator.py index a3eebf7b2..9ed87dd15 100644 --- a/test/test_son_manipulator.py +++ b/test/test_son_manipulator.py @@ -15,7 +15,6 @@ """Tests for SONManipulators. """ -import unittest import sys sys.path[0:0] = [""] @@ -26,7 +25,7 @@ from pymongo.son_manipulator import (NamespaceInjector, ObjectIdShuffler, SONManipulator) from test.test_client import get_client -from test import qcheck +from test import qcheck, unittest class TestSONManipulator(unittest.TestCase): diff --git a/test/test_ssl.py b/test/test_ssl.py index b24c0a857..e510c2426 100644 --- a/test/test_ssl.py +++ b/test/test_ssl.py @@ -17,7 +17,6 @@ import os import socket import sys -import unittest try: from ssl import CertificateError @@ -33,14 +32,12 @@ except ImportError: # Python 2 from urllib import quote_plus -from nose.plugins.skip import SkipTest - from pymongo import MongoClient, MongoReplicaSetClient from pymongo.common import HAS_SSL from pymongo.errors import (ConfigurationError, ConnectionFailure, OperationFailure) -from test import host, port, pair, version +from test import host, pair, port, SkipTest, unittest, version from test.utils import server_started_with_auth, remove_all_users diff --git a/test/test_thread_util.py b/test/test_thread_util.py index 4e746a7b1..942c3b18a 100644 --- a/test/test_thread_util.py +++ b/test/test_thread_util.py @@ -18,18 +18,16 @@ import gc import sys import threading import time -import unittest sys.path[0:0] = [""] -from nose.plugins.skip import SkipTest - from pymongo import thread_util if thread_util.have_gevent: import greenlet # Plain greenlets. import gevent.greenlet # Gevent's enhanced Greenlets. import gevent.hub +from test import SkipTest, unittest from test.utils import looplet, my_partial, RendezvousThread diff --git a/test/test_threads.py b/test/test_threads.py index 0c95a4443..77443356a 100644 --- a/test/test_threads.py +++ b/test/test_threads.py @@ -14,12 +14,10 @@ """Test that pymongo is thread safe.""" -import unittest import threading import traceback -from nose.plugins.skip import SkipTest - +from test import SkipTest, unittest from test.utils import (joinall, remove_all_users, server_started_with_auth, RendezvousThread) from test.test_client import get_client @@ -161,10 +159,11 @@ class FindPauseFind(RendezvousThread): class BaseTestThreads(object): """ - Base test class for TestThreads and TestThreadsReplicaSet. (This is not - itself a unittest.TestCase, otherwise it'd be run twice -- once when nose - imports this module, and once when nose imports - test_threads_replica_set_connection.py, which imports this module.) + Base test class for TestThreads and TestThreadsReplicaSet. (This + is not itself a unittest.TestCase, otherwise it'd be run twice -- + once when unittest imports this module, and once when unittest + imports test_threads_replica_set_connection.py, which imports this + module.) """ def setUp(self): self.db = self._get_client().pymongo_test @@ -303,7 +302,7 @@ class BaseTestThreadsAuth(object): """ Base test class for TestThreadsAuth and TestThreadsAuthReplicaSet. (This is not itself a unittest.TestCase, otherwise it'd be run twice -- once when - nose imports this module, and once when nose imports + unittest imports this module, and once when unittest imports test_threads_replica_set_connection.py, which imports this module.) """ def _get_client(self): diff --git a/test/test_threads_replica_set_client.py b/test/test_threads_replica_set_client.py index 23b517670..42e050b0f 100644 --- a/test/test_threads_replica_set_client.py +++ b/test/test_threads_replica_set_client.py @@ -14,10 +14,9 @@ """Test that pymongo is thread safe.""" -import unittest - from pymongo.mongo_replica_set_client import MongoReplicaSetClient +from test import unittest from test.test_threads import BaseTestThreads, BaseTestThreadsAuth from test.test_replica_set_client import TestReplicaSetClientBase, pair diff --git a/test/test_timestamp.py b/test/test_timestamp.py index 5a4930c3e..6636f3814 100644 --- a/test/test_timestamp.py +++ b/test/test_timestamp.py @@ -15,7 +15,6 @@ """Tests for the Timestamp class.""" import datetime -import unittest import sys import copy import pickle @@ -23,6 +22,7 @@ sys.path[0:0] = [""] from bson.timestamp import Timestamp from bson.tz_util import utc +from test import unittest class TestTimestamp(unittest.TestCase): diff --git a/test/test_uri_parser.py b/test/test_uri_parser.py index bd4759056..e36a9ec55 100644 --- a/test/test_uri_parser.py +++ b/test/test_uri_parser.py @@ -15,7 +15,6 @@ """Test the pymongo uri_parser module.""" import copy -import unittest import sys sys.path[0:0] = [""] @@ -30,6 +29,7 @@ from pymongo.errors import ConfigurationError, InvalidURI from pymongo import ReadPreference from bson.binary import JAVA_LEGACY from bson.py3compat import string_type, _unicode +from test import unittest class TestURI(unittest.TestCase): diff --git a/test/utils.py b/test/utils.py index 67faf55a3..b31288963 100644 --- a/test/utils.py +++ b/test/utils.py @@ -20,11 +20,10 @@ import struct import sys import threading -from nose.plugins.skip import SkipTest from pymongo import MongoClient, MongoReplicaSetClient from pymongo.errors import AutoReconnect from pymongo.pool import NO_REQUEST, NO_SOCKET_YET, SocketInfo -from test import host, port, version +from test import host, port, SkipTest, version try: