diff --git a/.coveragerc b/.coveragerc deleted file mode 100644 index 95760a9a..00000000 --- a/.coveragerc +++ /dev/null @@ -1,2 +0,0 @@ -[run] -omit = graphene/pyutils/*,*/tests/* diff --git a/.gitignore b/.gitignore index 9148845f..f5b54686 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ dist/ downloads/ eggs/ .eggs/ +_version.py lib/ lib64/ parts/ diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index 76c6f842..00000000 --- a/.isort.cfg +++ /dev/null @@ -1,2 +0,0 @@ -[settings] -known_third_party = aniso8601,graphql,graphql_relay,promise,pytest,pytz,pyutils,setuptools,snapshottest,sphinx_graphene_theme diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c9ffc21e..61a9a4de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,28 +1,31 @@ repos: -- repo: git://github.com/pre-commit/pre-commit-hooks - rev: v2.1.0 - hooks: - - id: check-merge-conflict - - id: check-json - - id: check-yaml - - id: debug-statements - - id: end-of-file-fixer - exclude: ^docs/.*$ - - id: pretty-format-json - args: - - --autofix - - id: trailing-whitespace - exclude: README.md -- repo: https://github.com/asottile/pyupgrade - rev: v1.12.0 - hooks: - - id: pyupgrade -- repo: https://github.com/ambv/black - rev: 19.10b0 - hooks: - - id: black - language_version: python3 -- repo: https://github.com/PyCQA/flake8 - rev: 3.7.8 - hooks: - - id: flake8 + - repo: git://github.com/pre-commit/pre-commit-hooks + rev: v3.4.0 + hooks: + - id: check-merge-conflict + - id: check-json + - id: check-yaml + - id: debug-statements + - id: end-of-file-fixer + exclude: ^docs/.*$ + - id: pretty-format-json + args: + - --autofix + - id: trailing-whitespace + exclude: README.md + - repo: https://github.com/asottile/pyupgrade + rev: v2.9.0 + hooks: + - id: pyupgrade + - repo: https://github.com/psf/black + rev: 20.8b1 + hooks: + - id: black + - repo: https://github.com/PyCQA/flake8 + rev: 3.8.4 + hooks: + - id: flake8 + - repo: https://github.com/pycqa/isort + rev: 5.6.4 + hooks: + - id: isort diff --git a/.travis.yml b/.travis.yml index e1e55119..d55e0dc2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,12 @@ language: python -dist: xenial +dist: focal python: - "3.6" - "3.7" - "3.8" + - "3.9" + - "nightly" install: - pip install tox tox-travis @@ -13,9 +15,7 @@ after_success: - pip install coveralls - coveralls cache: - directories: - - $HOME/.cache/pip - - $HOME/.cache/pre-commit + - pip stages: - test @@ -23,6 +23,8 @@ stages: if: tag IS present jobs: + allow_failures: + - python: "nightly" fast_finish: true include: - env: TOXENV=pre-commit diff --git a/MANIFEST.in b/MANIFEST.in index 9f92821d..a049403b 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -1,5 +1,4 @@ global-exclude tests/* recursive-exclude tests * -recursive-exclude tests_py35 * recursive-exclude examples * include LICENSE diff --git a/README.md b/README.md index 85849a3d..118c77f2 100644 --- a/README.md +++ b/README.md @@ -24,11 +24,11 @@ Graphene has multiple integrations with different frameworks: -| integration | Package | -| ----------------- | --------------------------------------------------------------------------------------- | -| Django | [graphene-django](https://github.com/graphql-python/graphene-django/) | -| SQLAlchemy | [graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy/) | -| Google App Engine | [graphene-gae](https://github.com/graphql-python/graphene-gae/) | +| integration | Package | +| ----------------- | ----------------------------------------------------------------------------- | +| Django | [graphene-django](https://github.com/graphql-python/graphene-django/) | +| SQLAlchemy | [graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy/) | +| Google App Engine | [graphene-gae](https://github.com/graphql-python/graphene-gae/) | Also, Graphene is fully compatible with the GraphQL spec, working seamlessly with all GraphQL clients, such as [Relay](https://github.com/facebook/relay), [Apollo](https://github.com/apollographql/apollo-client) and [gql](https://github.com/graphql-python/gql). diff --git a/README.rst b/README.rst deleted file mode 100644 index 243215e4..00000000 --- a/README.rst +++ /dev/null @@ -1,179 +0,0 @@ -**We are looking for contributors**! Please check the -`ROADMAP `__ -to see how you can help ❤️ - --------------- - -|Graphene Logo| `Graphene `__ |Build Status| |PyPI version| |Coverage Status| -========================================================================================================= - - -Introduction ------------- - -`Graphene `__ is a Python library for -building GraphQL schemas/types fast and easily. - -- **Easy to use:** Graphene helps you use GraphQL in Python without - effort. -- **Relay:** Graphene has builtin support for Relay. -- **Data agnostic:** Graphene supports any kind of data source: SQL - (Django, SQLAlchemy), NoSQL, custom Python objects, etc. We believe - that by providing a complete API you could plug Graphene anywhere - your data lives and make your data available through GraphQL. - -Integrations ------------- - -Graphene has multiple integrations with different frameworks: - -+---------------------+----------------------------------------------------------------------------------------------+ -| integration | Package | -+=====================+==============================================================================================+ -| Django | `graphene-django `__ | -+---------------------+----------------------------------------------------------------------------------------------+ -| SQLAlchemy | `graphene-sqlalchemy `__ | -+---------------------+----------------------------------------------------------------------------------------------+ -| Google App Engine | `graphene-gae `__ | -+---------------------+----------------------------------------------------------------------------------------------+ -| Peewee | *In progress* (`Tracking Issue `__) | -+---------------------+----------------------------------------------------------------------------------------------+ - -Also, Graphene is fully compatible with the GraphQL spec, working -seamlessly with all GraphQL clients, such as -`Relay `__, -`Apollo `__ and -`gql `__. - -Installation ------------- - -For instaling graphene, just run this command in your shell - -.. code:: bash - - pip install "graphene>=2.0" - -2.0 Upgrade Guide ------------------ - -Please read `UPGRADE-v2.0.md `__ to learn how to -upgrade. - -Examples --------- - -Here is one example for you to get started: - -.. code:: python - - import graphene - - class Query(graphene.ObjectType): - hello = graphene.String(description='A typical hello world') - - def resolve_hello(self, info): - return 'World' - - schema = graphene.Schema(query=Query) - -Then Querying ``graphene.Schema`` is as simple as: - -.. code:: python - - query = ''' - query SayHello { - hello - } - ''' - result = schema.execute(query) - -If you want to learn even more, you can also check the following -`examples `__: - -- **Basic Schema**: `Starwars example `__ -- **Relay Schema**: `Starwars Relay - example `__ - -Documentation -------------- - -Documentation and links to additional resources are available at -https://docs.graphene-python.org/en/latest/ - -Contributing ------------- - -After cloning this repo, create a -`virtualenv `__ and ensure -dependencies are installed by running: - -.. code:: sh - - virtualenv venv - source venv/bin/activate - pip install -e ".[test]" - -Well-written tests and maintaining good test coverage is important to -this project. While developing, run new and existing tests with: - -.. code:: sh - - py.test graphene/relay/tests/test_node.py # Single file - py.test graphene/relay # All tests in directory - -Add the ``-s`` flag if you have introduced breakpoints into the code for -debugging. Add the ``-v`` ("verbose") flag to get more detailed test -output. For even more detailed output, use ``-vv``. Check out the -`pytest documentation `__ for more -options and test running controls. - -You can also run the benchmarks with: - -.. code:: sh - - py.test graphene --benchmark-only - -Graphene supports several versions of Python. To make sure that changes -do not break compatibility with any of those versions, we use ``tox`` to -create virtualenvs for each Python version and run tests with that -version. To run against all Python versions defined in the ``tox.ini`` -config file, just run: - -.. code:: sh - - tox - -If you wish to run against a specific version defined in the ``tox.ini`` -file: - -.. code:: sh - - tox -e py36 - -Tox can only use whatever versions of Python are installed on your -system. When you create a pull request, Travis will also be running the -same tests and report the results, so there is no need for potential -contributors to try to install every single version of Python on their -own system ahead of time. We appreciate opening issues and pull requests -to make graphene even more stable & useful! - -Building Documentation -~~~~~~~~~~~~~~~~~~~~~~ - -The documentation is generated using the excellent -`Sphinx `__ and a custom theme. - -An HTML version of the documentation is produced by running: - -.. code:: sh - - make docs - -.. |Graphene Logo| image:: http://graphene-python.org/favicon.png -.. |Build Status| image:: https://travis-ci.org/graphql-python/graphene.svg?branch=master - :target: https://travis-ci.org/graphql-python/graphene -.. |PyPI version| image:: https://badge.fury.io/py/graphene.svg - :target: https://badge.fury.io/py/graphene -.. |Coverage Status| image:: https://coveralls.io/repos/graphql-python/graphene/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/graphql-python/graphene?branch=master diff --git a/bin/autolinter b/bin/autolinter deleted file mode 100755 index 0fc3ccae..00000000 --- a/bin/autolinter +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash - -# Install the required scripts with -# pip install autoflake autopep8 isort -autoflake ./examples/ ./graphene/ -r --remove-unused-variables --remove-all-unused-imports --in-place -autopep8 ./examples/ ./graphene/ -r --in-place --experimental --aggressive --max-line-length 120 -isort -rc ./examples/ ./graphene/ diff --git a/bin/convert_documentation b/bin/convert_documentation deleted file mode 100755 index b55d5dab..00000000 --- a/bin/convert_documentation +++ /dev/null @@ -1,3 +0,0 @@ -#!/bin/bash - -pandoc README.md --from markdown --to rst -s -o README.rst diff --git a/graphene/__init__.py b/graphene/__init__.py index 34729de0..8a506298 100644 --- a/graphene/__init__.py +++ b/graphene/__init__.py @@ -1,4 +1,4 @@ -from .pyutils.version import get_version +from ._version import __version__ from .relay import ( ClientIDMutation, Connection, @@ -41,11 +41,6 @@ from .types import ( from .utils.module_loading import lazy_import from .utils.resolve_only_args import resolve_only_args -VERSION = (3, 0, 0, "beta", 7) - - -__version__ = get_version(VERSION) - __all__ = [ "__version__", "Argument", diff --git a/graphene/pyutils/version.py b/graphene/pyutils/version.py deleted file mode 100644 index f2005442..00000000 --- a/graphene/pyutils/version.py +++ /dev/null @@ -1,81 +0,0 @@ -from __future__ import unicode_literals - -import datetime -import os -import subprocess - - -def get_version(version=None): - "Returns a PEP 440-compliant version number from VERSION." - version = get_complete_version(version) - - # Now build the two parts of the version number: - # main = X.Y[.Z] - # sub = .devN - for pre-alpha releases - # | {a|b|rc}N - for alpha, beta, and rc releases - - main = get_main_version(version) - - sub = "" - if version[3] == "alpha" and version[4] == 0: - git_changeset = get_git_changeset() - if git_changeset: - sub = ".dev%s" % git_changeset - else: - sub = ".dev" - elif version[3] != "final": - mapping = {"alpha": "a", "beta": "b", "rc": "rc"} - sub = mapping[version[3]] + str(version[4]) - - return str(main + sub) - - -def get_main_version(version=None): - "Returns main version (X.Y[.Z]) from VERSION." - version = get_complete_version(version) - parts = 2 if version[2] == 0 else 3 - return ".".join(str(x) for x in version[:parts]) - - -def get_complete_version(version=None): - """Returns a tuple of the graphene version. If version argument is non-empty, - then checks for correctness of the tuple provided. - """ - if version is None: - from graphene import VERSION as version - else: - assert len(version) == 5 - assert version[3] in ("alpha", "beta", "rc", "final") - - return version - - -def get_docs_version(version=None): - version = get_complete_version(version) - if version[3] != "final": - return "dev" - else: - return "%d.%d" % version[:2] - - -def get_git_changeset(): - """Returns a numeric identifier of the latest git changeset. - The result is the UTC timestamp of the changeset in YYYYMMDDHHMMSS format. - This value isn't guaranteed to be unique, but collisions are very unlikely, - so it's sufficient for generating the development version numbers. - """ - repo_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - try: - git_log = subprocess.Popen( - "git log --pretty=format:%ct --quiet -1 HEAD", - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - shell=True, - cwd=repo_dir, - universal_newlines=True, - ) - timestamp = git_log.communicate()[0] - timestamp = datetime.datetime.utcfromtimestamp(int(timestamp)) - except: - return None - return timestamp.strftime("%Y%m%d%H%M%S") diff --git a/graphene/types/objecttype.py b/graphene/types/objecttype.py index f4a0f5a0..f2ac9247 100644 --- a/graphene/types/objecttype.py +++ b/graphene/types/objecttype.py @@ -1,13 +1,10 @@ +from dataclasses import field, make_dataclass + from .base import BaseOptions, BaseType, BaseTypeMeta from .field import Field from .interface import Interface from .utils import yank_fields_from_attrs -try: - from dataclasses import make_dataclass, field -except ImportError: - from ..pyutils.dataclasses import make_dataclass, field # type: ignore - # For static type checking with Mypy MYPY = False if MYPY: @@ -28,7 +25,11 @@ class ObjectTypeMeta(BaseTypeMeta): pass base_cls = super().__new__( - cls, name_, (InterObjectType,) + bases, namespace, **options, + cls, + name_, + (InterObjectType,) + bases, + namespace, + **options, ) if base_cls._meta: fields = [ diff --git a/mypy.ini b/mypy.ini deleted file mode 100644 index bbb37b77..00000000 --- a/mypy.ini +++ /dev/null @@ -1,17 +0,0 @@ -[mypy] -ignore_missing_imports = True - -[mypy-graphene.pyutils.*] -ignore_errors = True - -[mypy-graphene.types.scalars] -ignore_errors = True - -[mypy-graphene.types.generic] -ignore_errors = True - -[mypy-graphene.types.tests.*] -ignore_errors = True - -[mypy-graphene.relay.tests.*] -ignore_errors = True diff --git a/setup.cfg b/setup.cfg index 2037bc1b..7a4de508 100644 --- a/setup.cfg +++ b/setup.cfg @@ -6,7 +6,26 @@ max-line-length = 120 omit = graphene/pyutils/*,*/tests/*,graphene/types/scalars.py [isort] +profile = black known_first_party=graphene +[mypy] +ignore_missing_imports = True + +[mypy-graphene.pyutils.*] +ignore_errors = True + +[mypy-graphene.types.scalars] +ignore_errors = True + +[mypy-graphene.types.generic] +ignore_errors = True + +[mypy-graphene.types.tests.*] +ignore_errors = True + +[mypy-graphene.relay.tests.*] +ignore_errors = True + [bdist_wheel] universal=1 diff --git a/setup.py b/setup.py index 48d7d285..1f0b46aa 100644 --- a/setup.py +++ b/setup.py @@ -1,48 +1,6 @@ -import ast -import codecs -import re -import sys +from pathlib import Path from setuptools import find_packages, setup -from setuptools.command.test import test as TestCommand - -_version_re = re.compile(r"VERSION\s+=\s+(.*)") - -with open("graphene/__init__.py", "rb") as f: - version = ast.literal_eval(_version_re.search(f.read().decode("utf-8")).group(1)) - -path_copy = sys.path[:] - -sys.path.append("graphene") -try: - from pyutils.version import get_version - - version = get_version(version) -except Exception: - version = ".".join([str(v) for v in version]) - -sys.path[:] = path_copy - - -class PyTest(TestCommand): - user_options = [("pytest-args=", "a", "Arguments to pass to py.test")] - - def initialize_options(self): - TestCommand.initialize_options(self) - self.pytest_args = [] - - def finalize_options(self): - TestCommand.finalize_options(self) - self.test_args = [] - self.test_suite = True - - def run_tests(self): - # import here, cause outside the eggs aren't loaded - import pytest - - errno = pytest.main(self.pytest_args) - sys.exit(errno) - tests_require = [ "pytest>=5.3,<6", @@ -55,38 +13,43 @@ tests_require = [ "promise>=2.3,<3", "mock>=4.0,<5", "pytz==2019.3", - "iso8601>=0.1,<2", ] -dev_requires = ["black==19.10b0", "flake8>=3.7,<4"] + tests_require +dev_requires = ["black==20.8b1", "flake8>=3.7,<4"] + tests_require setup( name="graphene", - version=version, description="GraphQL Framework for Python", - long_description=codecs.open( - "README.rst", "r", encoding="ascii", errors="replace" - ).read(), + long_description=Path("README.md").read_text(encoding="utf-8"), + long_description_content_type="text/markdown", url="https://github.com/graphql-python/graphene", author="Syrus Akbary", author_email="me@syrusakbary.com", license="MIT", classifiers=[ - "Development Status :: 3 - Alpha", + "Development Status :: 3 - Beta", "Intended Audience :: Developers", "Topic :: Software Development :: Libraries", + "Programming Language :: Python ", + "Programming Language :: Python :: Only", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", ], keywords="api graphql protocol rest relay graphene", - packages=find_packages(exclude=["examples*"]), + packages=find_packages(exclude=["examples"]), install_requires=[ "graphql-core>=3.1.2,<4", "graphql-relay>=3.0,<4", "aniso8601>=8,<9", + "dataclasses>=0.8;python_version<'3.7'", ], + use_scm_version={ + "write_to": "graphene/_version.py", + "write_to_template": "__version__ = '{version}'\n", + }, + setup_requires=["setuptools_scm", "wheel"], tests_require=tests_require, extras_require={"test": tests_require, "dev": dev_requires}, - cmdclass={"test": PyTest}, ) diff --git a/tox.ini b/tox.ini index dd922c46..d94e3e72 100644 --- a/tox.ini +++ b/tox.ini @@ -1,14 +1,10 @@ [tox] -envlist = flake8,py36,py37,py38,pre-commit,mypy -skipsdist = true +envlist = flake8, py36, py37, py38, py39, pre-commit, mypy [testenv] -deps = - .[test] -setenv = - PYTHONPATH = .:{envdir} +extras = test commands = - py{36,37,38}: pytest --cov=graphene graphene examples {posargs} + py{36,37,38,39}: pytest --cov=graphene graphene examples {posargs} [testenv:pre-commit] basepython=python3.7 @@ -17,21 +13,18 @@ deps = setenv = LC_CTYPE=en_US.UTF-8 commands = - pre-commit {posargs:run --all-files} + pre-commit {posargs:run --all-files --show-diff-on-failure} [testenv:mypy] basepython=python3.7 deps = - mypy>=0.761,<1 + mypy>=0.800,<1 commands = mypy graphene [testenv:flake8] basepython=python3.7 deps = - flake8>=3.7,<4 + flake8>=3.8,<4 commands = - pip install --pre -e . flake8 graphene - -[pytest]