Skip to content

Commit 2a094fc

Browse files
abhinand-cAdithyanJothiradarshdigievoarunsureshkumarmak626
authored
v0.4.0 - Async BugFixes & Optimisations (#225)
* Fix(register): updated register_enum function support custom classes Use isinstance instead of type to support instances of enum class in addition to exact same type. * Support Async * Convert: get_node to async * Fix: Test Case * Bug Fix on connection_resolver * Support Async * Fix: connection_resolver * Support Async, Test Case Added * Bump Version : 0.4.0 * Add asgiref to dependency * Add pytest-asyncio to dependency * Fix: Test Case * Update: README.md * Blocking Threaded to Async * Bug Fix: Argument Parser * (Deprecated) get_resolver to wrap_resolve * Fix: Count Performance * Fix: Queryset Check * Optimise: Lazy Reference Resolver * Fix: DeprecationWarnings * Fix: Queryset evaluation * feat: add support for mongo date field * refactor: change logging level * fix(connection_field): respects non_filter_fields when argument name is same as field name * refact: sync to async wrapper * chore: add ruff formatting * fix: inconsistent has_next_page when pk is not sorted * fix: self.get_queryset not being async * fix[pipeline]: add ruff remove flake8 * refact: filter connection * refact: has_next_page logic * fix: has_next_page using limit * fix: ci change flake8 to ruff * fix: convert | syntax to union type for backward compatibility * chore: add support for python 12 * chore: drop support for python 3.7, add support python 3.12 * refact: add typings * fix: ruff lint * chore: add setup tools for python 12 to fix mongomock ImportError: No module named pkg_resources --------- Co-authored-by: Adithyan Jothir <[email protected]> Co-authored-by: Adarsh D <[email protected]> Co-authored-by: Arun Suresh Kumar <[email protected]> Co-authored-by: M Aswin Kishore <[email protected]> Co-authored-by: Edwin Jose George <[email protected]> Co-authored-by: Roshan R Chandar <[email protected]>
1 parent 615adb3 commit 2a094fc

38 files changed

+3172
-919
lines changed

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ jobs:
1717
strategy:
1818
matrix:
1919
os: [ubuntu-latest, macos-latest, windows-latest]
20-
python: ["3.7", "3.8", "3.9", "3.10", "3.11"]
20+
python: ["3.8", "3.9", "3.10", "3.11","3.12"]
2121
runs-on: ${{ matrix.os }}
2222
steps:
2323
- uses: actions/checkout@v3
2424
- name: Set up Python ${{ matrix.python }}
2525
uses: actions/setup-python@v3
2626
with:
2727
python-version: ${{ matrix.python }}
28-
- name: Lint with flake8
28+
- name: Lint with ruff
2929
run: |
30-
python -m pip install flake8
30+
python -m pip install ruff
3131
make lint
3232
- name: Install dependencies
3333
run: |

.github/workflows/lint.yml

+4-6
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,15 @@ jobs:
1111
build:
1212
strategy:
1313
matrix:
14-
python: ["3.11"]
14+
python: ["3.12"]
1515
runs-on: ubuntu-latest
1616
steps:
1717
- uses: actions/checkout@v3
1818
- name: Set up Python
1919
uses: actions/setup-python@v3
2020
with:
2121
python-version: ${{ matrix.python }}
22-
- name: Install dependencies
22+
- name: Lint with ruff
2323
run: |
24-
python -m pip install --upgrade pip
25-
pip install flake8
26-
- name: Lint with flake8
27-
run: make lint
24+
python -m pip install ruff
25+
make lint

Makefile

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ clean:
1111
@find . -name "__pycache__" -delete
1212

1313
lint:
14-
@flake8 graphene_mongo --count --show-source --statistics
14+
@ruff check graphene_mongo
15+
@ruff format . --check
1516

1617
test: clean
1718
pytest graphene_mongo/tests --cov=graphene_mongo --cov-report=html --cov-report=term

README.md

+49-5
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
A [Mongoengine](https://mongoengine-odm.readthedocs.io/) integration for [Graphene](http://graphene-python.org/).
88

9-
109
## Installation
1110

1211
For installing graphene-mongo, just run this command in your shell
@@ -23,13 +22,14 @@ Here is a simple Mongoengine model as `models.py`:
2322
from mongoengine import Document
2423
from mongoengine.fields import StringField
2524

25+
2626
class User(Document):
2727
meta = {'collection': 'user'}
2828
first_name = StringField(required=True)
2929
last_name = StringField(required=True)
3030
```
3131

32-
To create a GraphQL schema for it you simply have to write the following:
32+
To create a GraphQL schema and sync executor; for it you simply have to write the following:
3333

3434
```python
3535
import graphene
@@ -38,15 +38,60 @@ from graphene_mongo import MongoengineObjectType
3838

3939
from .models import User as UserModel
4040

41+
4142
class User(MongoengineObjectType):
4243
class Meta:
4344
model = UserModel
4445

46+
4547
class Query(graphene.ObjectType):
4648
users = graphene.List(User)
47-
49+
4850
def resolve_users(self, info):
49-
return list(UserModel.objects.all())
51+
return list(UserModel.objects.all())
52+
53+
54+
schema = graphene.Schema(query=Query)
55+
```
56+
57+
Then you can simply query the schema:
58+
59+
```python
60+
query = '''
61+
query {
62+
users {
63+
firstName,
64+
lastName
65+
}
66+
}
67+
'''
68+
result = await schema.execute(query)
69+
```
70+
71+
To create a GraphQL schema and async executor; for it you simply have to write the following:
72+
73+
```python
74+
import graphene
75+
76+
from graphene_mongo import AsyncMongoengineObjectType
77+
from asgiref.sync import sync_to_async
78+
from concurrent.futures import ThreadPoolExecutor
79+
80+
from .models import User as UserModel
81+
82+
83+
class User(AsyncMongoengineObjectType):
84+
class Meta:
85+
model = UserModel
86+
87+
88+
class Query(graphene.ObjectType):
89+
users = graphene.List(User)
90+
91+
async def resolve_users(self, info):
92+
return await sync_to_async(list, thread_sensitive=False,
93+
executor=ThreadPoolExecutor())(UserModel.objects.all())
94+
5095

5196
schema = graphene.Schema(query=Query)
5297
```
@@ -71,7 +116,6 @@ To learn more check out the following [examples](examples/):
71116
* [Django MongoEngine example](examples/django_mongoengine)
72117
* [Falcon MongoEngine example](examples/falcon_mongoengine)
73118

74-
75119
## Contributing
76120

77121
After cloning this repo, ensure dependencies are installed by running:

docs/conf.py

+8-12
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,18 @@
6060
master_doc = "index"
6161

6262
# General information about the project.
63-
project = u"Graphene Mongo"
64-
copyright = u"Graphene 2018"
65-
author = u"Abaw Chen"
63+
project = "Graphene Mongo"
64+
copyright = "Graphene 2018"
65+
author = "Abaw Chen"
6666

6767
# The version info for the project you're documenting, acts as replacement for
6868
# |version| and |release|, also used in various other places throughout the
6969
# built documents.
7070
#
7171
# The short X.Y version.
72-
version = u"0.1"
72+
version = "0.1"
7373
# The full version, including alpha/beta/rc tags.
74-
release = u"0.1.2"
74+
release = "0.1.2"
7575

7676
# The language for content autogenerated by Sphinx. Refer to documentation
7777
# for a list of supported languages.
@@ -275,9 +275,7 @@
275275
# Grouping the document tree into LaTeX files. List of tuples
276276
# (source start file, target name, title,
277277
# author, documentclass [howto, manual, or own class]).
278-
latex_documents = [
279-
(master_doc, "Graphene.tex", u"Graphene Documentation", u"Syrus Akbary", "manual")
280-
]
278+
latex_documents = [(master_doc, "Graphene.tex", "Graphene Documentation", "Syrus Akbary", "manual")]
281279

282280
# The name of an image file (relative to this directory) to place at the top of
283281
# the title page.
@@ -316,9 +314,7 @@
316314

317315
# One entry per manual page. List of tuples
318316
# (source start file, name, description, authors, manual section).
319-
man_pages = [
320-
(master_doc, "graphene_django", u"Graphene Django Documentation", [author], 1)
321-
]
317+
man_pages = [(master_doc, "graphene_django", "Graphene Django Documentation", [author], 1)]
322318

323319
# If true, show URL addresses after external links.
324320
#
@@ -334,7 +330,7 @@
334330
(
335331
master_doc,
336332
"Graphene-Django",
337-
u"Graphene Django Documentation",
333+
"Graphene Django Documentation",
338334
author,
339335
"Graphene Django",
340336
"One line description of project.",

examples/django_mongoengine/bike/urls.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,5 @@
33
from graphene_django.views import GraphQLView
44

55
urlpatterns = [
6-
path(
7-
"graphql", csrf_exempt(GraphQLView.as_view(graphiql=True)), name="graphql-query"
8-
)
6+
path("graphql", csrf_exempt(GraphQLView.as_view(graphiql=True)), name="graphql-query")
97
]

examples/django_mongoengine/bike_catalog/settings.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,7 @@
8585
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators
8686

8787
AUTH_PASSWORD_VALIDATORS = [
88-
{
89-
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"
90-
},
88+
{"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator"},
9189
{"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator"},
9290
{"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator"},
9391
{"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator"},
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
11
from .settings import * # flake8: noqa
22

3-
mongoengine.connect(
4-
"graphene-mongo-test", host="mongomock://localhost", alias="default"
5-
)
3+
mongoengine.connect("graphene-mongo-test", host="mongomock://localhost", alias="default")

examples/falcon_mongoengine/api.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@
33
from .schema import schema
44

55

6-
def set_graphql_allow_header(
7-
req: falcon.Request, resp: falcon.Response, resource: object
8-
):
6+
def set_graphql_allow_header(req: falcon.Request, resp: falcon.Response, resource: object):
97
resp.set_header("Allow", "GET, POST, OPTIONS")
108

119

examples/falcon_mongoengine/tests/tests.py

+13-9
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
import mongoengine
22
from graphene.test import Client
3+
34
from examples.falcon_mongoengine.schema import schema
45
from .fixtures import fixtures_data
56

6-
mongoengine.connect(
7-
"graphene-mongo-test", host="mongomock://localhost", alias="default"
8-
)
7+
mongoengine.connect("graphene-mongo-test", host="mongomock://localhost", alias="default")
98

109

1110
def test_category_last_1_item_query(fixtures_data):
@@ -23,7 +22,16 @@ def test_category_last_1_item_query(fixtures_data):
2322

2423
expected = {
2524
"data": {
26-
"categories": {"edges": [{"node": {"name": "Work", "color": "#1769ff"}}]}
25+
"categories": {
26+
"edges": [
27+
{
28+
"node": {
29+
"name": "Work",
30+
"color": "#1769ff",
31+
}
32+
}
33+
]
34+
}
2735
}
2836
}
2937

@@ -45,11 +53,7 @@ def test_category_filter_item_query(fixtures_data):
4553
}
4654
}"""
4755

48-
expected = {
49-
"data": {
50-
"categories": {"edges": [{"node": {"name": "Work", "color": "#1769ff"}}]}
51-
}
52-
}
56+
expected = {"data": {"categories": {"edges": [{"node": {"name": "Work", "color": "#1769ff"}}]}}}
5357

5458
client = Client(schema)
5559
result = client.execute(query)

examples/falcon_mongoengine/types.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1-
import graphene
21
from graphene import relay
3-
from graphene_mongo import MongoengineObjectType
42

5-
from .models import Category, Bookmark
3+
from graphene_mongo import MongoengineObjectType
4+
from .models import Bookmark, Category
65

76

87
class CategoryType(MongoengineObjectType):

examples/flask_mongoengine/app.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,7 @@
4242
}
4343
}""".strip()
4444

45-
app.add_url_rule(
46-
"/graphql", view_func=GraphQLView.as_view("graphql", schema=schema, graphiql=True)
47-
)
45+
app.add_url_rule("/graphql", view_func=GraphQLView.as_view("graphql", schema=schema, graphiql=True))
4846

4947
if __name__ == "__main__":
5048
init_db()

examples/flask_mongoengine/models.py

-4
Original file line numberDiff line numberDiff line change
@@ -10,25 +10,21 @@
1010

1111

1212
class Department(Document):
13-
1413
meta = {"collection": "department"}
1514
name = StringField()
1615

1716

1817
class Role(Document):
19-
2018
meta = {"collection": "role"}
2119
name = StringField()
2220

2321

2422
class Task(EmbeddedDocument):
25-
2623
name = StringField()
2724
deadline = DateTimeField(default=datetime.now)
2825

2926

3027
class Employee(Document):
31-
3228
meta = {"collection": "employee"}
3329
name = StringField()
3430
hired_on = DateTimeField(default=datetime.now)

examples/flask_mongoengine/schema.py

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import graphene
22
from graphene.relay import Node
3-
from graphene_mongo.tests.nodes import PlayerNode, ReporterNode
43

54
from graphene_mongo import MongoengineConnectionField, MongoengineObjectType
65
from .models import Department as DepartmentModel
@@ -20,7 +19,11 @@ class Meta:
2019
model = RoleModel
2120
interfaces = (Node,)
2221
filter_fields = {
23-
'name': ['exact', 'icontains', 'istartswith']
22+
"name": [
23+
"exact",
24+
"icontains",
25+
"istartswith",
26+
]
2427
}
2528

2629

@@ -35,7 +38,11 @@ class Meta:
3538
model = EmployeeModel
3639
interfaces = (Node,)
3740
filter_fields = {
38-
'name': ['exact', 'icontains', 'istartswith']
41+
"name": [
42+
"exact",
43+
"icontains",
44+
"istartswith",
45+
]
3946
}
4047

4148

graphene_mongo/__init__.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
from .fields import MongoengineConnectionField
2+
from .fields_async import AsyncMongoengineConnectionField
23

34
from .types import MongoengineObjectType, MongoengineInputType, MongoengineInterfaceType
5+
from .types_async import AsyncMongoengineObjectType
46

57
__version__ = "0.1.1"
68

79
__all__ = [
810
"__version__",
911
"MongoengineObjectType",
12+
"AsyncMongoengineObjectType",
1013
"MongoengineInputType",
1114
"MongoengineInterfaceType",
12-
"MongoengineConnectionField"
13-
]
15+
"MongoengineConnectionField",
16+
"AsyncMongoengineConnectionField",
17+
]

0 commit comments

Comments
 (0)