diff --git a/.gitignore b/.gitignore index 2452aab..608847c 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ .pytest_cache .tox .venv +.vscode /build/ /dist/ diff --git a/.travis.yml b/.travis.yml index 250247c..7789878 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,28 +1,22 @@ language: python +sudo: false +python: + - 2.7 + - 3.5 + - 3.6 + - 3.7 + - 3.8 + - 3.9-dev + - pypy + - pypy3 matrix: include: - - python: "3.7" - env: TOX_ENV=black,flake8,mypy,py37 - - python: "3.6" - env: TOX_ENV=py36 - - python: "3.5" - env: TOX_ENV=py35 - - python: "2.7" - env: TOX_ENV=py27 - - python: pypy3 - env: TOX_ENV=pypy3 - - python: pypy - env: TOX_ENV=pypy -cache: - directories: - - "$HOME/.cache/pip" - - "$TRAVIS_BUILD_DIR/.tox" -install: - - pip install tox codecov -script: - - tox -e $TOX_ENV -- --cov-report term-missing --cov=graphql_server -after_success: - - codecov + - python: 3.6 + env: TOXENV=flake8,black,import-order,mypy,manifest +cache: pip +install: pip install tox-travis codecov +script: tox +after_success: codecov deploy: provider: pypi on: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..c573f21 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,93 @@ +# Contributing + +Thanks for helping to make graphql-server-core awesome! + +We welcome all kinds of contributions: + +- Bug fixes +- Documentation improvements +- New features +- Refactoring & tidying + + +## Getting started + +If you have a specific contribution in mind, be sure to check the [issues](https://github.com/graphql-python/graphql-server-core/issues) and [pull requests](https://github.com/graphql-python/graphql-server-core/pulls) in progress - someone could already be working on something similar and you can help out. + + +## Project setup + +### Development with virtualenv (recommended) + +After cloning this repo, create a virtualenv: + +```console +virtualenv graphql-server-core-dev +``` + +Activate the virtualenv and install dependencies by running: + +```console +python pip install -e ".[test]" +``` + +If you are using Linux or MacOS, you can make use of Makefile command +`make dev-setup`, which is a shortcut for the above python command. + +### Development on Conda + +You must create a new env (e.g. `graphql-sc-dev`) with the following command: + +```sh +conda create -n graphql-sc-dev python=3.8 +``` + +Then activate the environment with `conda activate graphql-sc-dev`. + +Proceed to install all dependencies by running: + +```console +pip install -e ".[dev]" +``` + +And you ready to start development! + +## Running tests + +After developing, the full test suite can be evaluated by running: + +```sh +pytest tests --cov=graphql-server-core -vv +``` + +If you are using Linux or MacOS, you can make use of Makefile command +`make tests`, which is a shortcut for the above python command. + +You can also test on several python environments by using tox. + +### Running tox on virtualenv + +Install tox: + +```console +pip install tox +``` + +Run `tox` on your virtualenv (do not forget to activate it!) +and that's it! + +### Running tox on Conda + +In order to run `tox` command on conda, install +[tox-conda](https://github.com/tox-dev/tox-conda): + +```sh +conda install -c conda-forge tox-conda +``` + +This install tox underneath so no need to install it before. + +Then uncomment the `requires = tox-conda` line on `tox.ini` file. + +Run `tox` and you will see all the environments being created +and all passing tests. :rocket: diff --git a/MANIFEST.in b/MANIFEST.in index 04f196a..12b4ad7 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,2 +1,13 @@ +include MANIFEST.in + include README.md include LICENSE +include CONTRIBUTING.md + +include codecov.yml +include tox.ini + +graft tests +prune bin + +global-exclude *.py[co] __pycache__ diff --git a/README.md b/README.md index ec7e022..fdb3d40 100644 --- a/README.md +++ b/README.md @@ -42,3 +42,6 @@ You can also use one of the existing integrations listed above as blueprint to build your own integration or GraphQL server implementations. Please let us know when you have built something new, so we can list it here. + +## Contributing +See [CONTRIBUTING.md](CONTRIBUTING.md) diff --git a/graphql_server/__init__.py b/graphql_server/__init__.py index 1895a41..cb802ee 100644 --- a/graphql_server/__init__.py +++ b/graphql_server/__init__.py @@ -13,7 +13,7 @@ import six -from promise import promisify, is_thenable +from promise import promisify, is_thenable, Promise from graphql import get_default_backend from graphql.error import format_error as default_format_error @@ -266,6 +266,7 @@ def execute_graphql_request( backend=None, # type: GraphQLBackend **kwargs # type: Any ): + # type: (...) -> ExecutionResult """Execute a GraphQL request and return an ExecutionResult. You need to pass the GraphQL schema and the GraphQLParams that you can get @@ -318,18 +319,20 @@ def get_response( allow_only_query=False, # type: bool **kwargs # type: Any ): - # type: (...) -> Optional[ExecutionResult] + # type: (...) -> Optional[Union[ExecutionResult, Promise[ExecutionResult]]] """Get an individual execution result as response, with option to catch errors. This does the same as execute_graphql_request() except that you can catch errors that belong to an exception class that you need to pass as a parameter. """ - # noinspection PyBroadException + # Note: PyCharm will display a error due to the triple dot being used on Callable. execute = ( - execute_graphql_request_as_promise - if kwargs.get("return_promise", False) - else execute_graphql_request - ) + execute_graphql_request + ) # type: Callable[..., Union[Promise[ExecutionResult], ExecutionResult]] + if kwargs.get("return_promise", False): + execute = execute_graphql_request_as_promise + + # noinspection PyBroadException try: execution_result = execute(schema, params, allow_only_query, **kwargs) except catch_exc: @@ -350,11 +353,10 @@ def format_execution_result( """ status_code = 200 + response = None if execution_result: if execution_result.invalid: status_code = 400 response = execution_result.to_dict(format_error=format_error) - else: - response = None return FormattedResult(response, status_code) diff --git a/setup.cfg b/setup.cfg index ea8cbd3..70e1f4a 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,7 @@ max-line-length = 88 known_first_party=graphql_server [tool:pytest] -norecursedirs = venv .venv .tox .git .cache .mypy_cache .pytest_cache +norecursedirs = venv .venv .tox .git .cache .mypy_cache .pytest_cache [bdist_wheel] universal=1 diff --git a/setup.py b/setup.py index 75f12f5..11a6634 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,22 @@ from setuptools import setup, find_packages -required_packages = ["graphql-core>=2.3,<3", "promise>=2.3,<3"] -tests_require = ["pytest==4.6.9", "pytest-cov==2.8.1"] +install_requires = [ + "graphql-core>=2.3,<3", + "promise>=2.3,<3", +] + +tests_requires = [ + "pytest==4.6.9", + "pytest-cov==2.8.1" +] + +dev_requires = [ + 'flake8==3.7.9', + 'isort<4.0.0', + 'black==19.10b0', + 'mypy==0.761', + 'check-manifest>=0.40,<1', +] + tests_requires setup( name="graphql-server-core", @@ -30,9 +45,12 @@ ], keywords="api graphql protocol rest", packages=find_packages(exclude=["tests"]), - install_requires=required_packages, - tests_require=tests_require, - extras_require={"test": tests_require}, + install_requires=install_requires, + tests_require=tests_requires, + extras_require={ + 'test': tests_requires, + 'dev': dev_requires, + }, include_package_data=True, zip_safe=False, platforms="any", diff --git a/tests/test_asyncio.py b/tests/test_asyncio.py index 9ee4386..db8fc02 100644 --- a/tests/test_asyncio.py +++ b/tests/test_asyncio.py @@ -1,15 +1,10 @@ -import asyncio - -from promise import Promise - from graphql.execution.executors.asyncio import AsyncioExecutor -from graphql.type.definition import ( - GraphQLField, - GraphQLNonNull, - GraphQLObjectType, -) +from graphql.type.definition import GraphQLField, GraphQLNonNull, GraphQLObjectType from graphql.type.scalars import GraphQLString from graphql.type.schema import GraphQLSchema +from promise import Promise + +import asyncio from graphql_server import RequestParams, run_http_query from .utils import as_dicts diff --git a/tests/test_helpers.py b/tests/test_helpers.py index 53e9965..fc4b73e 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -3,6 +3,7 @@ from graphql.error import GraphQLError from graphql.execution import ExecutionResult from graphql.language.location import SourceLocation +from pytest import raises from graphql_server import ( HttpQueryError, @@ -12,7 +13,6 @@ json_encode_pretty, load_json_body, ) -from pytest import raises def test_json_encode(): diff --git a/tests/test_query.py b/tests/test_query.py index 73c1674..e5bbb79 100644 --- a/tests/test_query.py +++ b/tests/test_query.py @@ -1,11 +1,9 @@ import json -from pytest import raises - -from promise import Promise - from graphql.error import GraphQLError, GraphQLSyntaxError from graphql.execution import ExecutionResult +from promise import Promise +from pytest import raises from graphql_server import ( HttpQueryError, diff --git a/tox.ini b/tox.ini index f759b87..77a2bb6 100644 --- a/tox.ini +++ b/tox.ini @@ -1,38 +1,47 @@ [tox] -envlist = black,flake8,mypy,py{38,37,36,35,py27,py3,py} -skipsdist = true +envlist = + black,flake8,import-order,mypy,manifest, + py{27,35,36,37,38,39-dev,py,py3} +; requires = tox-conda [testenv] +passenv = * setenv = PYTHONPATH = {toxinidir} -deps = - .[test] +install_command = python -m pip install --ignore-installed {opts} {packages} +deps = -e.[test] +whitelist_externals = + python commands = - pytest tests {posargs} + pip install -U setuptools + pytest --cov-report=term-missing --cov=graphql_server tests {posargs} [testenv:black] -basepython=python3.7 -deps = black==19.10b0 +basepython=python3.6 +deps = -e.[dev] commands = black --check graphql_server tests [testenv:flake8] -basepython=python3.7 -deps = flake8==3.7.9 +basepython=python3.6 +deps = -e.[dev] commands = flake8 setup.py graphql_server tests -[testenv:isort] -basepython=python3.7 -deps = - isort - graphql-core>=2.3,<3 +[testenv:import-order] +basepython=python3.6 +deps = -e.[dev] commands = isort -rc graphql_server/ tests/ [testenv:mypy] -basepython=python3.7 -deps = mypy==0.761 +basepython=python3.6 +deps = -e.[dev] commands = mypy graphql_server tests --ignore-missing-imports +[testenv:manifest] +basepython = python3.6 +deps = -e.[dev] +commands = + check-manifest -v