-
Couldn't load subscription status.
- Fork 4
Add spec test functionality #15
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
Changes from 20 commits
de6f2cc
a597592
59525cd
ef6c5a1
803e27a
b8ffa0f
16fe2a5
c8f973b
3ebe9b0
e6aa287
6ed0717
8cc3923
4f230bb
e332c4e
dd09b41
3bd6bdf
69ad0d9
075c0c1
618ae94
756c4fc
9248101
12ea3c0
f7b03b6
12aaf05
5a419d9
83063cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -20,15 +20,20 @@ | |
|
|
||
| from bson.son import SON | ||
| from pymongo.collection import Collection | ||
| from pymongo.helpers import _index_document, _fields_list_to_dict | ||
| from pymongo.collation import validate_collation_or_none | ||
| from .utils import convert_to_camelcase | ||
|
|
||
|
|
||
| Document = Union[dict, SON] | ||
|
|
||
|
|
||
| class BaseCommand(): | ||
| def __init__(self, collection): | ||
| def __init__(self, collection, collation): | ||
| self.command_document = {} | ||
| collation = validate_collation_or_none(collation) | ||
| if collation is not None: | ||
| self.command_document["collation"] = collation | ||
| self.collection = collection | ||
|
|
||
| @property | ||
|
|
@@ -44,29 +49,51 @@ def get_SON(self): | |
|
|
||
| class UpdateCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, filter, update, | ||
| kwargs): | ||
| super().__init__(collection.name) | ||
| return_document = {"updates":[{"q": filter, "u": update}]} | ||
| for key in kwargs: | ||
| value = kwargs[key] | ||
| if key == "bypass_document_validation": | ||
| return_document[key] = value | ||
| else: | ||
| return_document["updates"][0][key] = value | ||
| self.command_document = convert_to_camelcase(return_document) | ||
| upsert=None, multi=None, collation=None, array_filters=None, | ||
| hint=None, ordered=None, write_concern=None, | ||
| bypass_document_validation=None, comment=None): | ||
| super().__init__(collection.name, collation) | ||
| update_doc = {"q": filter, "u": update} | ||
| self.command_document["updates"] = [update_doc] | ||
| if upsert is not None: | ||
| self.command_document["updates"][0]["upsert"] = upsert | ||
|
||
|
|
||
| if multi is not None: | ||
| self.command_document["updates"][0]["multi"] = multi | ||
|
|
||
| if array_filters is not None: | ||
| self.command_document["updates"][0]["array_filters"] = array_filters | ||
|
|
||
| if hint is not None: | ||
| self.command_document["updates"][0]["hint"] = hint if \ | ||
| isinstance(hint, str) else _index_document(hint) | ||
|
|
||
| if ordered is not None: | ||
| self.command_document["ordered"] = ordered | ||
|
|
||
| if write_concern is not None: | ||
| self.command_document["write_concern"] = write_concern | ||
|
|
||
| if bypass_document_validation is not None and \ | ||
| bypass_document_validation is not False: | ||
| self.command_document["bypass_document_validation"] = bypass_document_validation | ||
|
|
||
| if comment is not None: | ||
| self.command_document["comment"] = comment | ||
|
|
||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
||
| @property | ||
| def command_name(self): | ||
| return "update" | ||
|
|
||
|
|
||
| class DistinctCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, key, filter, session, | ||
| def __init__(self, collection: Collection, key, filter, | ||
| kwargs): | ||
| super().__init__(collection.name) | ||
| self.command_document = {"key": key, "query": filter} | ||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| self.command_document.update({"key": key, "query": filter}) | ||
|
|
||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
||
| @property | ||
|
|
@@ -75,26 +102,34 @@ def command_name(self): | |
|
|
||
|
|
||
| class AggregateCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, pipeline, session, | ||
| def __init__(self, collection: Collection, pipeline, | ||
| cursor_options, | ||
| kwargs, exclude_keys = []): | ||
| super().__init__(collection.name) | ||
| self.command_document = {"pipeline": pipeline, "cursor": cursor_options} | ||
| kwargs): | ||
|
|
||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| self.command_document.update({"pipeline": pipeline, "cursor": | ||
| cursor_options}) | ||
|
|
||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| if key == "batchSize": | ||
| if value == 0: | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to check for None too? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. None values are already removed in the converting to snakecase step |
||
| continue | ||
| self.command_document["cursor"]["batchSize"] = value | ||
| else: | ||
| self.command_document[key] = value | ||
|
|
||
| self.command_document = convert_to_camelcase( | ||
| self.command_document, exclude_keys=exclude_keys) | ||
| self.command_document) | ||
|
|
||
| @property | ||
| def command_name(self): | ||
| return "aggregate" | ||
|
|
||
|
|
||
| class CountCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, filter, | ||
| kwargs): | ||
| super().__init__(collection.name) | ||
| self.command_document = {"query": filter} | ||
| def __init__(self, collection: Collection, filter, kwargs): | ||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| self.command_document.update({"query": filter}) | ||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
@@ -107,21 +142,37 @@ def command_name(self): | |
| class FindCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, | ||
| kwargs): | ||
| super().__init__(collection.name) | ||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| if key == "projection" and value is not None: | ||
| self.command_document["projection"] = _fields_list_to_dict( | ||
| value, "projection") | ||
| elif key == "sort": | ||
| self.command_document["sort"] = _index_document( | ||
| value) | ||
| else: | ||
| self.command_document[key] = value | ||
|
|
||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
||
| @property | ||
| def command_name(self): | ||
| return "find" | ||
|
|
||
|
|
||
| class FindAndModifyCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, | ||
| kwargs): | ||
| super().__init__(collection.name) | ||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| if key == "hint": | ||
| self.command_document["hint"] = value if \ | ||
| isinstance(value, str) else _index_document(value) | ||
| elif key == "sort" and value is not None: | ||
| self.command_document["sort"] = _index_document( | ||
| value) | ||
| else: | ||
| self.command_document[key] = value | ||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
||
| @property | ||
|
|
@@ -132,10 +183,16 @@ def command_name(self): | |
| class DeleteCommand(BaseCommand): | ||
| def __init__(self, collection: Collection, filter, | ||
| limit, collation, kwargs): | ||
| super().__init__(collection.name) | ||
| self.command_document = {"deletes": [SON({"q": filter, "limit": limit})]} | ||
| super().__init__(collection.name, kwargs.pop("collation", None)) | ||
| self.command_document["deletes"] = [{"q": filter, "limit": | ||
| limit}] | ||
| for key, value in kwargs.items(): | ||
| self.command_document[key] = value | ||
| if key == "hint": | ||
| self.command_document["deletes"][0]["hint"] = value if \ | ||
| isinstance(value, str) else _index_document(value) | ||
| else: | ||
| self.command_document[key] = value | ||
|
|
||
| self.command_document = convert_to_camelcase(self.command_document) | ||
|
|
||
| @property | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -16,26 +16,17 @@ | |
| """Utility functions""" | ||
|
|
||
|
|
||
| def convert_to_camelcase(d, exclude_keys=[]): | ||
| def convert_to_camelcase(d): | ||
| if not isinstance(d, dict): | ||
| return d | ||
| ret = dict() | ||
| for key in d.keys(): | ||
| if d[key] is None: | ||
| continue | ||
| if key in exclude_keys: | ||
| ret[key] = d[key] | ||
| continue | ||
| new_key = key | ||
| if "_" in key and key[0] != "_": | ||
| new_key = key.split("_")[0] + ''.join( | ||
| [i.capitalize() for i in key.split("_")[1:]]) | ||
| if isinstance(d[key], list): | ||
| ret[new_key] = [convert_to_camelcase( | ||
| i, exclude_keys=exclude_keys) for i in d[key]] | ||
| elif isinstance(d[key], dict): | ||
| ret[new_key] = convert_to_camelcase(d[key], | ||
| exclude_keys=exclude_keys) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! I think we can remove the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
| else: | ||
| ret[new_key] = d[key] | ||
| return ret | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though we maintain pymongo we can't rely on any private methods (in python names starting with
_mean private). Could you vendor (copy) these two methods instead?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.