<commit_before>import pytest
from datetime import datetime
from bson import ObjectId
from pymongo import MongoClient

from ..common import BaseDBTest, get_pymongo_version, TEST_DB
from ..fixtures import classroom_model, instance

from umongo import (Document, EmbeddedDocument, fields, exceptions, Reference,
                    Instance, PyMongoInstance, NoDBDefinedError)


# Check if the required dependancies are met to run this driver's tests
major, minor, _ = get_pymongo_version()
if int(major) != 3 or int(minor) < 2:
    dep_error = "pymongo driver requires pymongo>=3.2.0"
else:
    dep_error = None
    from pymongo.results import InsertOneResult, UpdateResult, DeleteResult

if not dep_error:  # Make sure the module is valid by importing it
    from umongo.frameworks import pymongo as framework_pymongo


# Helper to sort indexes by name in order to have deterministic comparison
def name_sorted(indexes):
    return sorted(indexes, key=lambda x: x['name'])


@pytest.fixture
def db():
    return MongoClient()[TEST_DB]


@pytest.mark.skipif(dep_error is not None, reason=dep_error)
class TestPymongo(BaseDBTest):

    def test_auto_instance(self, db):
        instance = Instance(db)

        class Doc(Document):
            pass

        doc_impl_cls = instance.register(Doc)
        assert doc_impl_cls.collection == db['doc']
        assert issubclass(doc_impl_cls, framework_pymongo.PyMongoDocument)

    def test_lazy_loader_instance(self, db):
        instance = PyMongoInstance()

        class Doc(Document):
            pass

        doc_impl_cls = instance.register(Doc)
        assert issubclass(doc_impl_cls, framework_pymongo.PyMongoDocument)
        with pytest.raises(NoDBDefinedError):
            doc_impl_cls.collection
        instance.init(db)
        assert doc_impl_cls.collection == db['doc']

    def test_create(self, classroom_model):
        Student = classroom_model.Student
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        ret = john.commit()
        assert isinstance(ret, InsertOneResult)
        assert john.to_mongo() == {
            '_id': john.id,
            'name': '<NAME>',
            'birthday': datetime(1995, 12, 12)
        }
        john2 = Student.find_one(john.id)
        assert john2._data == john._data
        # Double commit should do nothing
        assert john.commit() is None

    def test_update(self, classroom_model):
        Student = classroom_model.Student
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        john.commit()
        john.name = '<NAME>'
        assert john.to_mongo(update=True) == {'$set': {'name': '<NAME>'}}
        ret = john.commit()
        assert isinstance(ret, UpdateResult)
        assert john.to_mongo(update=True) is None
        john2 = Student.find_one(john.id)
        assert john2._data == john._data
        # Update without changing anything
        john.name = john.name
        john.commit()
        # Test conditional commit
        john.name = '<NAME>'
        with pytest.raises(exceptions.UpdateError):
            john.commit(conditions={'name': 'Bad Name'})
        john.commit(conditions={'name': '<NAME>'})
        john.reload()
        assert john.name == '<NAME>'
        # Cannot use conditions when creating document
        with pytest.raises(RuntimeError):
            Student(name='Joe').commit(conditions={'name': 'dummy'})

    def test_delete(self, classroom_model):
        Student = classroom_model.Student
        Student.collection.drop()
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        with pytest.raises(exceptions.NotCreatedError):
            john.delete()
        john.commit()
        assert Student.collection.find().count() == 1
        ret = john.delete()
        assert isinstance(ret, DeleteResult)
        assert not john.is_created
        assert Student.collection.find().count() == 0
        with pytest.raises(exceptions.NotCreatedError):
            john.delete()
        # Can re-commit the document in database
        john.commit()
        assert john.is_created
        assert Student.collection.find().count() == 1
        # Finally try to delete a doc no longer in database
        Student.find_one(john.id).delete()
        with pytest.raises(exceptions.DeleteError):
            john.delete()

    def test_reload(self, classroom_model):
        Student = classroom_model.Student
        Student(name='Other dude').commit()
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        with pytest.raises(exceptions.NotCreatedError):
            john.reload()
        john.commit()
        john2 = Student.find_one(john.id)
        john2.name = '<NAME>'
        john2.commit()
        john.reload()
        assert john.name == '<NAME>'

    def test_cursor(self, classroom_model):
        Student = classroom_model.Student
        Student.collection.drop()
        for i in range(10):
            Student(name='student-%s' % i).commit()
        cursor = Student.find(limit=5, skip=6)
        assert cursor.count() == 10
        assert cursor.count(with_limit_and_skip=True) == 4
        names = []
        for elem in cursor:
            assert isinstance(elem, Student)
            names.append(elem.name)
        assert sorted(names) == ['student-%s' % i for i in range(6, 10)]

        cursor = Student.find(limit=5, skip=6)
        elem0 = cursor[0]
        assert isinstance(elem0, Student)
        assert next(cursor) == elem0

        # Make sure this kind of notation doesn't create new cursor
        cursor = Student.find()
        cursor_limit = cursor.limit(5)
        cursor_skip = cursor.skip(6)
        assert cursor is cursor_limit is cursor_skip

    def test_classroom(self, classroom_model):
        student = classroom_model.Student(name='<NAME>', birthday=datetime(1968, 6, 9))
        student.commit()
        teacher = classroom_model.Teacher(name='<NAME>')
        teacher.commit()
        course = classroom_model.Course(name='Hoverboard 101', teacher=teacher)
        course.commit()
        assert student.courses == []
        student.courses.append(course)
        student.commit()
        assert student.to_mongo() == {
            '_id': student.pk,<commit_msg>Add test for PyMongo WrappedCursor slicing<commit_after>import pytest
from datetime import datetime
from bson import ObjectId
from pymongo import MongoClient

from ..common import BaseDBTest, get_pymongo_version, TEST_DB
from ..fixtures import classroom_model, instance

from umongo import (Document, EmbeddedDocument, fields, exceptions, Reference,
                    Instance, PyMongoInstance, NoDBDefinedError)


# Check if the required dependancies are met to run this driver's tests
major, minor, _ = get_pymongo_version()
if int(major) != 3 or int(minor) < 2:
    dep_error = "pymongo driver requires pymongo>=3.2.0"
else:
    dep_error = None
    from pymongo.results import InsertOneResult, UpdateResult, DeleteResult

if not dep_error:  # Make sure the module is valid by importing it
    from umongo.frameworks import pymongo as framework_pymongo


# Helper to sort indexes by name in order to have deterministic comparison
def name_sorted(indexes):
    return sorted(indexes, key=lambda x: x['name'])


@pytest.fixture
def db():
    return MongoClient()[TEST_DB]


@pytest.mark.skipif(dep_error is not None, reason=dep_error)
class TestPymongo(BaseDBTest):

    def test_auto_instance(self, db):
        instance = Instance(db)

        class Doc(Document):
            pass

        doc_impl_cls = instance.register(Doc)
        assert doc_impl_cls.collection == db['doc']
        assert issubclass(doc_impl_cls, framework_pymongo.PyMongoDocument)

    def test_lazy_loader_instance(self, db):
        instance = PyMongoInstance()

        class Doc(Document):
            pass

        doc_impl_cls = instance.register(Doc)
        assert issubclass(doc_impl_cls, framework_pymongo.PyMongoDocument)
        with pytest.raises(NoDBDefinedError):
            doc_impl_cls.collection
        instance.init(db)
        assert doc_impl_cls.collection == db['doc']

    def test_create(self, classroom_model):
        Student = classroom_model.Student
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        ret = john.commit()
        assert isinstance(ret, InsertOneResult)
        assert john.to_mongo() == {
            '_id': john.id,
            'name': '<NAME>',
            'birthday': datetime(1995, 12, 12)
        }
        john2 = Student.find_one(john.id)
        assert john2._data == john._data
        # Double commit should do nothing
        assert john.commit() is None

    def test_update(self, classroom_model):
        Student = classroom_model.Student
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        john.commit()
        john.name = '<NAME>'
        assert john.to_mongo(update=True) == {'$set': {'name': '<NAME>'}}
        ret = john.commit()
        assert isinstance(ret, UpdateResult)
        assert john.to_mongo(update=True) is None
        john2 = Student.find_one(john.id)
        assert john2._data == john._data
        # Update without changing anything
        john.name = john.name
        john.commit()
        # Test conditional commit
        john.name = '<NAME>'
        with pytest.raises(exceptions.UpdateError):
            john.commit(conditions={'name': 'Bad Name'})
        john.commit(conditions={'name': '<NAME>'})
        john.reload()
        assert john.name == '<NAME>'
        # Cannot use conditions when creating document
        with pytest.raises(RuntimeError):
            Student(name='Joe').commit(conditions={'name': 'dummy'})

    def test_delete(self, classroom_model):
        Student = classroom_model.Student
        Student.collection.drop()
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        with pytest.raises(exceptions.NotCreatedError):
            john.delete()
        john.commit()
        assert Student.collection.find().count() == 1
        ret = john.delete()
        assert isinstance(ret, DeleteResult)
        assert not john.is_created
        assert Student.collection.find().count() == 0
        with pytest.raises(exceptions.NotCreatedError):
            john.delete()
        # Can re-commit the document in database
        john.commit()
        assert john.is_created
        assert Student.collection.find().count() == 1
        # Finally try to delete a doc no longer in database
        Student.find_one(john.id).delete()
        with pytest.raises(exceptions.DeleteError):
            john.delete()

    def test_reload(self, classroom_model):
        Student = classroom_model.Student
        Student(name='Other dude').commit()
        john = Student(name='<NAME>', birthday=datetime(1995, 12, 12))
        with pytest.raises(exceptions.NotCreatedError):
            john.reload()
        john.commit()
        john2 = Student.find_one(john.id)
        john2.name = '<NAME>'
        john2.commit()
        john.reload()
        assert john.name == '<NAME>'

    def test_cursor(self, classroom_model):
        Student = classroom_model.Student
        Student.collection.drop()
        for i in range(10):
            Student(name='student-%s' % i).commit()
        cursor = Student.find(limit=5, skip=6)
        assert cursor.count() == 10
        assert cursor.count(with_limit_and_skip=True) == 4
        names = []
        for elem in cursor:
            assert isinstance(elem, Student)
            names.append(elem.name)
        assert sorted(names) == ['student-%s' % i for i in range(6, 10)]

        cursor = Student.find(limit=5, skip=6)
        elem0 = cursor[0]
        assert isinstance(elem0, Student)
        assert next(cursor) == elem0

        # Make sure this kind of notation doesn't create new cursor
        cursor = Student.find()
        cursor_limit = cursor.limit(5)
        cursor_skip = cursor.skip(6)
        assert cursor is cursor_limit is cursor_skip

        # Cursor slicing
        cursor = Student.find()
        names = (elem.name for elem in cursor[2:5])
        assert sorted(names) == ['student-%s' % i for i in range(2, 5)]

    def test_classroom(self, classroom_model):
        student = classroom_model.Student(name='<NAME>', birthday=datetime(1968, 6, 9))
        student.commit()
        teacher = classroom_model.Teacher(name='<NAME>')
        teacher.commit()
        course = classroom_model.Course(name='Hoverboard 101', teacher=teacher)
        course.commit()
        assert student.courses == []
        student.courses.append(course)
        student.commit()
        assert student.to_mongo() == {
            '_id': student.pk,
{'fraction_non_alphanumeric': 0.10890233362143474, 'fraction_numerical': 0.013200282863204212, 'mean_word_length': 2.6344945745288406, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5265066', 'n_tokens_mistral': 3809, 'n_tokens_neox': 3618, 'n_words': 905}