Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pymongo3 compatibility #946

Merged
merged 30 commits into from
May 11, 2015
Merged

Conversation

MRigal
Copy link
Member

@MRigal MRigal commented Apr 9, 2015

Hi guys,

Now everything is fixed and is fully compatible for both PyMongo 2.X and 3.X

I'm awaiting some feedback for:

  1. The way I introduced differential behaviour based on PyMongo version
  2. The behaviour for save() when a document is created with a given primary key, source of 5 of remaining issues. Here particularly, I have removed the check for self._created since we used to modify this why changing/switching db on the fly. This whole behaviour has changed in PyMongo3 and IMHO doesn't make sense anymore.
  3. Your opinion if the test_hint failure could point to a bug in PyMongo3
  4. A hand on the other error on test_geo_indexes_recursion
  5. A problem with binary field used as primary index that was always there and only discovered now by a better test that became mandatory by the use of a work-around concerning a PyMongo 3.0 bug already fixed in the upcoming 3.0.1

Cheers,
Matthieu

Review on Reviewable

@landscape-bot
Copy link

Code Health
Repository health increased by 0.36% when pulling e5daf8c on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.47%) to 73.55% when pulling e5daf8c on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@thedrow
Copy link
Contributor

thedrow commented Apr 9, 2015

I think we should extract the PyMongo major version to a constant somewhere.
This looks good as a start but I'd like to see the build passing in order to merge it.
Also, please use Github/Reviewable for comments like MRigal@9cd934b#diff-b3cd585db6ec2d41acd04ddd897c23e8R291.
If the comments don't clarify the code they shouldn't exist in the repo.

@thedrow
Copy link
Contributor

thedrow commented Apr 9, 2015

Ref #948

@@ -7,6 +7,10 @@


DEFAULT_CONNECTION_NAME = 'default'
if pymongo.version_tuple[0] >= 3:
READ_PREFERENCE = ReadPreference.SECONDARY_PREFERRED
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be PRIMARY by default.

SECONDARY_PREFERRED as a default with no other configuration will break many applications - as it introduces an inherent race conditions for replica set systems. Imagine adding a User to the database and then on the next request trying to read from a secondary to get that User - it might not have been replicated to the secondary node.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fully right ! Sorry, it was late yesterday when I finished...

@rozza
Copy link
Contributor

rozza commented Apr 9, 2015

Looks great @MRigal a couple of comments / observations to help get this into merged

@rozza
Copy link
Contributor

rozza commented Apr 9, 2015

Sorry @thedrow I just saw the use reviewable comment :(

@@ -491,6 +509,9 @@ class BlogPost(Document):

self.assertEqual(BlogPost.objects.count(), 10)
self.assertEqual(BlogPost.objects.hint().count(), 10)
# here we seem to have find a bug in PyMongo 3.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(GitHub comment in order to remove it from code)
Seems to be a PyMongo3 bug
The cursor first makes a SON out of the list of tuples
Then later reuses it and wonders why is it not a list of tuples

@rozza
Copy link
Contributor

rozza commented Apr 9, 2015

test_hint confirmed as a pymongo 3.0 bug (https://jira.mongodb.org/browse/PYTHON-875)

@MRigal
Copy link
Member Author

MRigal commented Apr 9, 2015

Thanks @rozza ! I'll push a new commit with some of your suggestions !

Concerning Point 1: Everything is up with the @thedrow ? We make a global constant IS_PYMONGO_3 in mongoengine/init.py Which I set to a boolean? Or a PYMONGO_MAJOR which I set to an integer?

I would still ask for support for point 2, please checkout yourself and give me your opinion on the changes there #946 (diff) Try to comment the self._created check and see yourself, digging with pdb

@landscape-bot
Copy link

Code Health
Repository health increased by 0.36% when pulling 27aa15c on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@thedrow
Copy link
Contributor

thedrow commented Apr 9, 2015

I think that IS_PYMONGO_3 is better since there's no need to calculate if the version is equal to 3.x every time.

@MRigal
Copy link
Member Author

MRigal commented Apr 9, 2015

There is no significant performance difference between True != False and 3 != 2

I think it should more be based on "human-readability". I still don't know what's best... Let's wait for one or two more comments

@coveralls
Copy link

Coverage Status

Coverage increased (+0.53%) to 73.6% when pulling 27aa15c on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@MRigal
Copy link
Member Author

MRigal commented Apr 9, 2015

(sorry by the bug introduced by a revert introduced to the wrong place)

@landscape-bot
Copy link

Code Health
Repository health increased by 0.36% when pulling ac25074 on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.79%) to 74.86% when pulling ac25074 on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@rozza
Copy link
Contributor

rozza commented Apr 10, 2015

+1 on IS_PYMONGO_3 does exactly what it says on the tin :)

@MRigal
Copy link
Member Author

MRigal commented Apr 10, 2015

OK for IS_PYMONGO_3. I couldn't put it into mongoengine/init.py because of circular imports. I hope the current location is appropriate, else I can move it again easily

@landscape-bot
Copy link

Code Health
Repository health increased by 0.36% when pulling 022674d on MRigal:fix/pymongo3-connection into 1ce6a7f on MongoEngine:master.

@mmellison
Copy link
Contributor

mongoengine/queryset/transform.py, line 138 [r15] (raw file):
The max_wire_version attribute was removed in PyMongo 3+

We should probably just do this:

        elif key in mongo_query:
            if key in mongo_query and isinstance(mongo_query[key], dict):
                mongo_query[key].update(value)
                # $maxDistance needs to come last - convert to SON
                value_dict = mongo_query[key]
                if ('$maxDistance' in value_dict and '$near' in value_dict):
                    value_son = SON()
                    if isinstance(value_dict['$near'], dict):
                        for k, v in value_dict.iteritems():
                            if k == '$maxDistance':
                                continue
                            value_son[k] = v
                        value_son['$near'] = SON(value_son['$near'])
                        value_son['$near']['$maxDistance'] = value_dict['$maxDistance']
                    else:
                        for k, v in value_dict.iteritems():
                            if k == '$maxDistance':
                                continue
                            value_son[k] = v
                        value_son['$maxDistance'] = value_dict['$maxDistance']

                    mongo_query[key] = value_son

That seems to work on both MongoDB 2.4.x and 2.6.x (tested locally). However, other tests do fail with 2.4 so we should really start looking at adding different MongoDB version to Travis (and discuss when do we deprecate 2.4, etc.).

Here is why it is failing in Python 3 and not in Python 2:

When you call get_connection().max_wire_version it returns a Database object (since getitem on MongoClient returns a Database if the request name is not an attribute). Now how does Python 2 handle integer comparisons to classes?

In [2]: class Test:
   ...:     pass
   ...: 

In [3]: Test() < 1
Out[3]: True

Let's try that again with Python 3:

In [1]: class Test:
   ...:     pass
   ...: 

In [2]: Test() < 1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-2-ec09b1796211> in <module>()
----> 1 Test() < 1

TypeError: unorderable types: Test() < int()

So its a combination of PyMongo 3 and Python 3 behavior causing this problem.

Since we can no longer check the wire version of the server with PyMongo, if we need to support version checking in the future, we should check the version from get_server_info() or some other method.

You will also have to remove the max_wire_version checks from the tests in tests/queryset/queryset.py.


Comments from the review on Reviewable.io

@MRigal
Copy link
Member Author

MRigal commented May 7, 2015

Excellent @seglberg ! Fast and precise! I'll do my best with it, and also give you owner access to my repository, since we are working close together on many issues, it might be better to directly commit some things on the PR of the other ;) 👍

@landscape-bot
Copy link

Code Health
Repository health increased by 0.24% when pulling 7941016 on MRigal:fix/pymongo3-connection into d6b2d8d on MongoEngine:master.

@coveralls
Copy link

Coverage Status

Coverage decreased (-0.53%) to 91.18% when pulling 7941016 on MRigal:fix/pymongo3-connection into d6b2d8d on MongoEngine:master.

@MRigal
Copy link
Member Author

MRigal commented May 7, 2015

Halleluja! Finally green! 🎱

But the price for enabling Pymongo 3.0 and Dev: :-(

Duration: 1 hr 55 min 46 sec

@MRigal
Copy link
Member Author

MRigal commented May 7, 2015

I let any other maintainer have a latest eye on it and (eventually) merge it

@mmellison
Copy link
Contributor

I will give it one more look and pull it down locally again to test things out.

Even though this will extend the Travis times, if you notice, Travis is not so "continuous" lately. It will complete the first 4-8 jobs then sit and wait for 20 minutes before it starts anymore, the entire time, the total duration keeps going up.

@DavidBord
Copy link
Contributor

I reviewed it as well and it looks good
@seglberg, do you have additional input or can I merge?

@mmellison
Copy link
Contributor

Had it go through a soak test over the weekend and nothing failed.

👍 🍻

DavidBord added a commit that referenced this pull request May 11, 2015
@DavidBord DavidBord merged commit 94eac1e into MongoEngine:master May 11, 2015
@thedrow
Copy link
Contributor

thedrow commented May 11, 2015

:shipit:

@rturk
Copy link

rturk commented May 11, 2015

Not sure if is related. This PR breaks Flask-Mongoengine Pagination
AttributeError: 'Cursor' object has no attribute '_Cursor__snapshot'

edit: That's probably because snapshot was deprecated

@MRigal
Copy link
Member Author

MRigal commented May 12, 2015

Yep, it definitely is related, snapshot was removed in PyMongo3 and is not
available anymore (it was never consistent from MongoDB side). I think it
was also simply ignored with MongoDB3+, even with PyMongo 2.X. Someone
should adapt Flask-Mongoengine and any other similar consequences...

2015-05-11 23:50 GMT+02:00 rat notifications@github.com:

Not sure if is related. This PR breaks Flask-Mongoengine Pagination
AttributeError: 'Cursor' object has no attribute '_Cursor__snapshot'


Reply to this email directly or view it on GitHub
#946 (comment)
.

@thedrow
Copy link
Contributor

thedrow commented May 13, 2015

Should I release?

@MRigal
Copy link
Member Author

MRigal commented May 13, 2015

@thedrow I wouldn't. I think we should decide what should go into the next release, also how to name it, but at least integrate #980 .
As I wrote in a couple tickets and on the wiki, I would call it 0.10, since removing Django support is a breaking change. What do you think?
We may have a look at what is from the wiki and the milestone planned for the 0.10, eventually remove some things and prepare the release. Be my guest to remove or edit things there.

@thedrow
Copy link
Contributor

thedrow commented May 13, 2015

Yeh I think you're right.
But I think we should at least release 0.9.0.1 that will limit the pymongo version.

@mmellison
Copy link
Contributor

Yes, I think we should take 0.9.0 and create 1 additional commit on top of
it to limit the PyMongo version (and bump version to 0.9.1 or 0.9.0.1, etc)
so people stop downloading 3.0 before 0.10 is released.

On Wed, May 13, 2015 at 10:50 AM, Omer Katz notifications@github.com
wrote:

Yeh I think you're right.
But I think we should at least release 0.9.0.1 that will limit the pymongo
version.


Reply to this email directly or view it on GitHub
#946 (comment)
.

@MRigal
Copy link
Member Author

MRigal commented May 13, 2015

I am perfectly fine with it. A pity it wasn't done earlier, but better now
than never :-)
Am 13.05.2015 20:10 schrieb "Matthew Ellison" notifications@github.com:

Yes, I think we should take 0.9.0 and create 1 additional commit on top of
it to limit the PyMongo version (and bump version to 0.9.1 or 0.9.0.1, etc)
so people stop downloading 3.0 before 0.10 is released.

On Wed, May 13, 2015 at 10:50 AM, Omer Katz notifications@github.com
wrote:

Yeh I think you're right.
But I think we should at least release 0.9.0.1 that will limit the
pymongo
version.


Reply to this email directly or view it on GitHub
<
#946 (comment)

.


Reply to this email directly or view it on GitHub
#946 (comment)
.

@blakev
Copy link

blakev commented May 14, 2015

Lovely how pymongo < 3.0 was nuked from pypi. Suggestions now?

@mmellison
Copy link
Contributor

As far as I can see, it is still on PyPI: https://pypi.python.org/pypi/pymongo/2.8

I even tested with pip and it still works just fine. pip install pymongo==2.8

@jaraco
Copy link

jaraco commented Jun 6, 2015

For what it's worth, I'd really like to see a release with this change. An 0.9.1 wouldn't help me as I've got a system which has been ported to Pymongo3 (and without compatibility shims). I saw mention of wanting to incorporate other unrelated changes. My preference would be for releases to be made often and whenever the codebase can be made stable. I see 15 open tickets on the milestone. I hate to think that all of those have to be addressed before a release can be made to address this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.