Compare commits

...

1179 Commits

Author SHA1 Message Date
Erik Wrede
8290326308
release: 3.4.3 2024-11-09 21:43:17 +01:00
Philipp Hagemeister
4a274b8424
fix: raise proper error when UUID parsing fails (#1582)
* Do not raise AttributeError when parsing non-string UUIDs

When a user sends a dictionary or other object as a UUID variable like `{[123]}`, previously graphene crashed with an `AttributeError`, like this:

```
(…)
  File "…/lib/python3.12/site-packages/graphql/utils/is_valid_value.py", line 78, in is_valid_value
    parse_result = type.parse_value(value)
                   ^^^^^^^^^^^^^^^^^^^^^^^
  File "…/lib/python3.12/site-packages/graphene/types/uuid.py", line 33, in parse_value
    return _UUID(value)
           ^^^^^^^^^^^^
  File "/usr/lib/python3.12/uuid.py", line 175, in __init__
    hex = hex.replace('urn:', '').replace('uuid:', '')
          ^^^^^^^^^^^
AttributeError: 'dict' object has no attribute 'replace'
```

But an `AttributeError` makes it seem like this is the server's fault, when it's obviously the client's.

Report a proper GraphQLError.

* fix: adjust exception message structure

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-11-09 21:42:51 +01:00
Erik Wrede
b3db1c0cb2
release: 3.4.2 2024-11-09 18:18:36 +01:00
Muhammed Al-Dulaimi
3ed7bf6362
chore: Make Union meta overridable (#1583)
This PR makes the Union Options configurable, similar to how it works with ObjectTypes
---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-11-09 18:17:42 +01:00
Erik Wrede
ccae7364e5
release: 3.4.1 2024-10-27 21:16:40 +01:00
Erik Wrede
cf97cbb1de
fix: use dateutil-parse for < 3.11 support (#1581)
* fix: use dateutil-parse for < 3.11 support

* chore: lint

* chore: lint

* fix mypy deps

* fix mypy deps

* chore: lint

* chore: fix test
2024-10-27 21:14:55 +01:00
Erik Wrede
dca31dc61d
release: 3.4.0 2024-10-18 13:43:07 +02:00
Erik Wrede
73df50e3dc
housekeeping: switch 3.13 to non-dev 2024-10-18 13:40:31 +02:00
Dulmandakh
821451fddc
CI: bump upload-artifact and codecov actions (#1567)
CI: bump actions/upload-artifact and codecov/codecov-action actions
2024-09-29 15:23:21 +02:00
Dulmandakh
f2e68141fd
CI: build package (#1564) 2024-09-29 13:40:19 +02:00
Dulmandakh
431826814d
lint: use ruff pre commit hook (#1566)
* lint: use ruff pre commit hook

* dont install ruff

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-09-29 13:33:10 +02:00
Dulmandakh
5b3ed2c2ba
bump pre-commit to 3.7 (#1568) 2024-09-29 13:32:26 +02:00
Erik Wrede
f95e9221bb
refactor: replace @deprecated decorator with upcoming native support (via typing-extensions), bump mypy (#1578)
* refactor: replace @deprecated decorator with upcoming native support (via typing-extensions)

* chore: fix tests

* chore: ruff fmt
2024-09-29 13:31:24 +02:00
Florian Zimmermann
48678afba4
fix: run the tests in python 3.12 and 3.13 and remove snapshottest dependency (#1572)
* actually run the tests in python 3.12 and 3.13

* remove snapshottest from the example tests

so that the tests pass in 3.12 and 3.13 again

* remove the section about snapshot testing from the testing docs

because the snapshottest package doesn't work on Python 3.12 and above

* fix assertion for badly formed JSON input on Python 3.13

* fix deprecation warning about datetime.utcfromtimestamp()
2024-08-08 11:49:26 +02:00
Dulmandakh
dc3b2e49c1
CI: fix tests on Python 3.13 (#1562) 2024-07-01 17:03:49 +02:00
Dulmandakh
d53a102b08
Lint using Ruff (#1563)
* lint using Ruff

* remove isort config, flake8 comments
2024-07-01 17:03:13 +02:00
Dulmandakh
fd9ecef36e
CI: format check using Ruff (#1557)
* CI: format check using Ruff

* precommit, setup py

* gitignore ruff_cache

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-06-28 15:05:04 +02:00
Dulmandakh
1263e9b41e
pytest 8 (#1549)
* pytest 8

* bump coveralls, pytest-cov

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-06-28 15:04:25 +02:00
Dulmandakh
74b33ae148
remove README.rst, leave only README.md (#1559)
remove README.rst
2024-06-28 15:03:48 +02:00
Dulmandakh
6834385786
support python 3.13 (#1561) 2024-06-28 15:03:34 +02:00
Dulmandakh
c335c5f529
fix lint error in SECURITY.md (#1556)
fix lint SECURITY.md
2024-06-23 18:24:34 +02:00
Erik Wrede
d90d65cafe
chore: adjust incorrect development status 2024-06-22 12:31:14 +02:00
Dulmandakh
5924cc4150
remove Python 2 (#1547)
Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-06-13 16:52:06 +02:00
Erik Wrede
6a668514de
docs: create security.md (#1554) 2024-06-13 16:51:43 +02:00
tijuca
88c3ec539b
pytest: Don't use nose like syntax in graphene/relay/tests/test_custom_global_id.py (#1539) (#1540)
pytest: Don't use nose like syntax

The tests in test_custom_global_id.py use the old nose specific method
'setup(self)' which isn't supported anymore in Pytest 8+. The tests fail
with this error message without modification.

E               pytest.PytestRemovedIn8Warning: Support for nose tests is deprecated and will be removed in a future release.
E               graphene/relay/tests/test_custom_global_id.py::TestIncompleteCustomGlobalID::test_must_define_resolve_global_id is using nose-specific method: `setup(self)`
E               To remove this warning, rename it to `setup_method(self)`
E               See docs: https://docs.pytest.org/en/stable/deprecations.html#support-for-tests-written-for-nose

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-06-13 14:38:48 +00:00
Dulmandakh
17d09c8ded
remove aniso8601, mock, iso8601 (#1548)
* remove aniso8601

* remove mock, iso8601

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2024-06-13 16:35:00 +02:00
Dulmandakh
614449e651
Python 3.12 (#1550)
* python 3.12

* update classifiers
2024-06-13 14:34:16 +00:00
Dulmandakh
44dcdad182
CI: fix deprecation warning (#1551) 2024-06-13 16:32:50 +02:00
Dulmandakh
221afaf4c4
bump pytest to 7 (#1546)
* bump pytest

* downgrade pytest-cov
2024-05-16 10:17:46 +02:00
Dulmandakh
5db1af039f
Remove Python 3.7 (#1543)
* CI: add Python 3.12

* dd

* remove python 3.12
2024-05-16 10:17:26 +02:00
Dulmandakh
82d0a68a81
remove polyfill for dataclasses (#1545)
* remove polyfill for dataclasses

* fix lint
2024-05-16 10:09:37 +02:00
Dulmandakh
3cd0c30de8
CI: bump GH actions (#1544) 2024-05-16 10:09:19 +02:00
Andrew Swait
5fb7b54377
docs: update docstring for type arg of Field (#1527) 2023-10-06 22:15:26 +02:00
wongcht
baaef0d21a
chore: remove pytz (#1520) 2023-08-30 23:41:17 +02:00
Erik Wrede
93cb33d359
housekeeping: delete outdated ROADMAP.md 2023-07-26 09:43:40 +02:00
Erik Wrede
f5aba2c027
release: 3.3.0 2023-07-26 08:26:30 +02:00
garo (they/them)
ea7ccc350e
feat(relay): add option for strict connection types (#1504)
* types: add option for strict connection types

* chore: appease linter

* chore: appease linter

* test: add test

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-07-26 08:25:57 +02:00
Dulmandakh
6b8cd2dc78
ci: drop python 3.6 (#1507)
Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-07-19 09:08:19 +02:00
Naoya Yamashita
74db349da4
docs: add get_human function (#1380)
Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-07-19 09:01:00 +02:00
Ransom Williams
99f0103e37
test: print schema with InputObjectType with DateTime field with default_value (#1293) (#1513)
* test [1293]: regression test print schema with InputObjectType with DateTime field with default_value

* chore: clarify test title and assertion

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-07-19 07:00:30 +00:00
Erik Wrede
03cf2e131e
chore: remove travis ci link 2023-06-06 20:45:01 +02:00
Jeongseok Kang
d77d0b0571
chore: Use typing.TYPE_CHECKING instead of MYPY (#1503)
Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-06-04 23:49:26 +02:00
senseysensor
c636d984c6
fix: Corrected enum metaclass to fix pickle.dumps() (#1495)
* Corrected enum metaclass to fix pickle.dumps()

* considered case with colliding class names (try to distinguish by file name)

* reverted simple solution back (without attempt to support duplicate Enum class names)

---------

Co-authored-by: sgrekov <sgrekov@lohika.com>
Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-06-04 23:10:05 +02:00
Cadu
2da8e9db5c
feat: Enable use of Undefined in InputObjectTypes (#1506)
* Changed InputObjectType's default builder-from-dict argument to be `Undefined` instead of `None`, removing ambiguity of undefined optional inputs using dot notation access syntax.

* Move `set_default_input_object_type_to_undefined()` fixture into conftest.py for sharing it between multiple test files.
2023-06-04 23:01:05 +02:00
Firas Kafri
8ede21e063
chore: default enum description to "An enumeration." (#1502)
* Default enum description to "An enumeration."

default to this string, which is used in many tests, is causing

* Use the docstring descriptions of enums when they are present

* Added tests

* chore: add missing newline

* Fix new line

---------

Co-authored-by: Erik Wrede <erikwrede@users.noreply.github.com>
2023-05-25 12:21:55 +02:00
Erik Wrede
57cbef6666
release: 3.2.2 2023-03-13 21:24:16 +01:00
Erik Wrede
d33e38a391
chore: make relay type fields extendable (#1499) 2023-03-13 21:23:28 +01:00
Roman Solomatin
b76e89c0c2
docs: remove unpair bracket (#1500) 2023-03-09 10:09:15 +01:00
Erik Wrede
81e7eee5da
Update README.md 2023-03-03 17:35:46 +01:00
Erik Wrede
969a630541
Update README.md 2023-03-03 17:35:05 +01:00
QuentinN42
8b89afeff1
docs: update sphinx to the latest version (#1497) 2023-02-28 13:21:45 +01:00
Peder Johnsen
52143473ef
docs: Remove prerelease notice (#1487) 2022-12-25 22:59:05 +01:00
Pei-Lun H
8eb2807ce5
docs: Correct the module name of custom scalar example in documentation (#1486) 2022-12-23 07:57:45 +01:00
Erik Wrede
340d5ed12f
release: 3.2.1 2022-12-11 21:05:25 +01:00
Vladyslav Hutov
19ea63b9c5
fix: Input fields and Arguments can now be deprecated (#1472)
Non-required InputFields and arguments now support deprecation via setting the `deprecation_reason` argument upon creation.
2022-12-10 12:25:07 +01:00
Erik Wrede
d5dadb7b1b
release: 3.2.0
fixes previous release number 3.1.2 due to a pending feature release
2022-12-09 10:53:50 +01:00
Erik Wrede
8596349405
release: 3.1.2 2022-12-09 10:46:24 +01:00
Mike Roberts
a141e848c3
Do not interpret Enum members called 'description' as description properties (#1478)
This is a workaround for `TypeError`s being raised when initialising schemas with
Enum members named `description` or `deprecation_reason`.


Fixes #1321
2022-12-01 11:06:24 +01:00
Erik Wrede
f09b2e5a81
housekeeping: pin ubuntu to 20.04 for python 3.6
Ubuntu:latest doesn't include py36 anymore. Keep this until we add 3.11 and drop 3.6.
See:
https://github.com/actions/setup-python/issues/544
https://github.com/rwth-i6/returnn/issues/1226
2022-11-21 15:40:05 +01:00
Mike Roberts
7f6fa16194
feat_ (#1476)
Previously, installing graphene and trying to do `from graphene.test import Client`
as recommended in the docs caused an `ImportError`, as the 'promise' library
is imported but only listed as a requirement in the 'test' section of the setup.py
file.
2022-11-16 21:38:15 +01:00
Rens Groothuijsen
0b1bfbf65b
chore: Make Graphene enums iterable like Python enums (#1473)
* Makes Graphene enums iterable like Python enums by implementing __iter__
2022-11-16 21:30:49 +01:00
Rens Groothuijsen
f891a3683d
docs: Disambiguate argument name in quickstart docs (#1474) 2022-11-16 21:27:34 +01:00
Erik Wrede
a2b63d8d84
fix: MyPy findings due to a mypy version upgrade were corrected (#1477) 2022-11-16 21:23:37 +01:00
Rens Groothuijsen
b349632a82
Clarify execution order in middleware docs (#1475) 2022-11-15 08:48:48 +01:00
Kevin Le
ccdd35b354
hashable Enum (#1461) 2022-10-27 13:55:38 +02:00
Kristian Uzhca
6969023491
Add copy function for GrapheneGraphQLType (#1463) 2022-10-24 20:06:24 +02:00
Thomas Leonard
ee1ff975d7
feat: Add support for custom global (Issue #1276) (#1428)
Co-authored-by: Thomas Leonard <thomas@loftorbital.com>
2022-09-19 10:17:31 +02:00
Erik Wrede
b20bbdcdf7
v3.1.1 2022-09-08 10:55:05 +02:00
Cadu
694c1db21e
Vendor DataLoader from aiodataloader and move get_event_loop() out of __init__ function. (#1459)
* Vendor DataLoader from aiodataloader and also move get_event_loop behavior from `__init__` to a property which only gets resolved when actually needed (this will solve PyTest-related to early get_event_loop() issues)

* Added DataLoader's specific tests

* plug `loop` parameter into `self._loop`, so that we still have the ability to pass in a custom event loop, if needed.


Co-authored-by: Erik Wrede <erikwrede2@gmail.com>
2022-09-07 20:32:53 +02:00
Erik Wrede
20219fdc1b
Update README.md
Update
2022-09-06 13:42:38 +02:00
Christian Clauss
45986b18e7
Upgrade GitHub Actions (#1457) 2022-08-28 20:25:55 +02:00
Ülgen Sarıkavak
c5ccc9502d
Upgrade base Python version to 3.10 (#1449) 2022-08-28 17:33:35 +02:00
Erik Wrede
35c281a3cd
Fix BigInt export (#1456) 2022-08-28 17:30:26 +02:00
Ülgen Sarıkavak
355601bd5c
Remove duplicate flake8 call in tox, it's covered by pre-commit (#1448) 2022-08-27 18:13:48 +02:00
Christian Clauss
cbf59a88ad
Add Python 3.11 release candidate 1 to the testing (#1450)
* Add Python 3.11 release candidate 1 to the testing

https://www.python.org/download/pre-releases

* Update tests.yml
2022-08-27 18:06:38 +02:00
Erik Wrede
24059a8b40
Merge pull request #1370 from DrewHoo/fix/ariadne-link 2022-08-20 14:59:22 +02:00
Erik Wrede
d96ec55abb
Merge branch 'master' into fix/ariadne-link 2022-08-20 14:59:02 +02:00
Erik Wrede
f1e8f4862a
Merge pull request #1447 from ulgens/update_precommit 2022-08-19 08:57:13 +02:00
Ülgen Sarıkavak
e6429c3c5b Update pre-commit hooks 2022-08-19 09:20:51 +03:00
Erik Wrede
ed1290aaba
Merge pull request #1407 from alimcmaster1/patch-1
Update quickstart.rst
2022-08-18 09:41:32 +02:00
Erik Wrede
84faf8f57c
Merge pull request #1444 from karmingc/karmingc/readme-typo
fix: use install instead of instal for consistency
2022-08-18 09:39:32 +02:00
karming
0ac4d9397e fix: use install instead of instal for consistency 2022-08-16 19:21:29 -04:00
Erik Wrede
023452a09f
Merge pull request #1442 from graphql-python/erikwrede-patch-1
Delete coveralls.yml
2022-08-14 12:42:55 +02:00
Erik Wrede
6339f489e9
Delete coveralls.yml
We are now using Codecov
2022-08-14 12:09:07 +02:00
Erik Wrede
23ca978918
Merge pull request #1414 from loft-orbital/issue-#1413_fix-invalid-input-type
Providing an invalid value to an input type will now provoke an exception.
For example if the input as the type `UUID` and that you provide the value `2` it will now fail.
2022-08-14 11:55:45 +02:00
Erik Wrede
97abb9db42
Merge pull request #1381 from belkka/patch-1
Avoid ambiguity in graphene.Mutation docstring [documentation]
2022-08-13 15:19:52 +02:00
Erik Wrede
57f3aa3ba9
Merge pull request #1190 from graphql-python/update-dataloaderdocs
Update Dataloader docs
2022-08-13 15:14:44 +02:00
Erik Wrede
8e1c3d3102
Merge branch 'master' into update-dataloaderdocs 2022-08-13 15:11:12 +02:00
Erik Wrede
13c661332e
Fix typo
Co-authored-by: Justin Miller <justinrmiller@users.noreply.github.com>
2022-08-13 15:08:34 +02:00
Erik Wrede
80e3498750
Fix Test Failure due to #1304
assert bar_graphql_type.interfaces == [foo_graphql_type] failed only on tox, because .interfaces was a tuple instead of a list. Error didn't occur using just pytest. Fixed by explicitly
converting both to list.
2022-08-13 14:51:58 +02:00
Erik Wrede
c77d87d205
Merge pull request #1304 from closeio/support-interface-implementations
Add support for interfaces on interfaces
2022-08-13 14:28:17 +02:00
Erik Wrede
8bdcec5cd7
Merge pull request #1402 from RJ722/patch-1
Docs: Highlight .get in backticks
2022-08-13 14:18:21 +02:00
Erik Wrede
dfece7f65d
Merge pull request #1437 from timgates42/bugfix_typos 2022-07-17 00:30:54 +02:00
Tim Gates
8589aaeb98
docs: Fix a few typos
There are small typos in:
- UPGRADE-v1.0.md
- UPGRADE-v2.0.md
- docs/execution/fileuploading.rst

Fixes:
- Should read `standard` rather than `stantard`.
- Should read `library` rather than `libary`.
- Should read `explicitly` rather than `explicity`.

Signed-off-by: Tim Gates <tim.gates@iress.com>
2022-07-16 14:40:00 +10:00
Thomas Leonard
72c2fd5ec3
Merge pull request #1430 from loft-orbital/feat/enable-to-provide-enum-name
feat: add ability to provide a type name to enum when using from_enum
2022-06-27 18:07:49 +02:00
Erik Wrede
69be326290
Merge pull request #1431 from erikwrede/master
Add Codecov to github actions
2022-06-27 16:41:24 +02:00
Erik Wrede
2ee23b0b2c Add codecov action 2022-06-27 16:30:01 +02:00
Thomas Leonard
8f6a8f9c4a feat: add ability to provide a type name to enum when using from_enum 2022-06-24 18:18:04 +02:00
Thomas Leonard
3bdc67c6ae fix: input with invalid types should raise an error 2022-06-20 15:15:14 +02:00
Thomas Leonard
efe4b89015
Merge pull request #1424 from ramonwenger/master
Fix typo in union comments
2022-06-20 15:14:27 +02:00
Ramon Wenger
785fcb38b6
Merge branch 'graphql-python:master' into master 2022-06-15 13:48:25 +02:00
Jonathan Kim
5475a7ad1f
v3.1.0 2022-05-30 13:57:16 +01:00
Ramon Wenger
5d4e71f463 Fix typo in union comments 2022-05-25 17:45:28 +02:00
Christoph Zwerschke
9c3e4bb7da
Merge pull request #1421 from Cito/upgrade-dev-env
Make Graphene compatible with GraphQL-Core 3.2
2022-05-07 00:53:24 +02:00
Christoph Zwerschke
9e7e08d48a
Make Graphene compatible with Core 3.2 2022-05-07 00:50:03 +02:00
Christoph Zwerschke
e37ef00ca4
Update test and dev environment 2022-05-06 22:31:31 +02:00
Christoph Zwerschke
4e8a1e6057
Merge pull request #1420
fix: add default param _variables to parse_literal #1419
2022-05-06 21:57:57 +02:00
René Birrer
181d9f76da fix: add default param _variables to parse_literal #1419
This is to match the `graphql-core` API. If it's not respected
the `parse_literal` method will produce an error event though
dealing with a valid value.
2022-05-03 13:51:14 +02:00
Jonathan Kim
03277a5512
Merge pull request #1412 from loft-orbital/issue-#1394_fix-required 2022-04-07 15:18:17 +01:00
Thomas Leonard
19ebf08339 fix: default value for argument should be Undefined (Issue #1394) and update function from_global_id exception handling (b217aefa8c) 2022-03-20 18:49:44 +01:00
Ali McMaster
bf40e6c419
Update quickstart.rst 2022-02-14 09:01:42 +00:00
Syrus Akbary
61f0d8a8e0
Merge pull request #1405 from conao3/patch-1
fix UPGRADE-v2.0.md
2022-02-13 12:57:54 -08:00
Naoya Yamashita
763910e7b5
fix UPGRADE-v2.0.md 2022-02-07 15:51:08 +09:00
Rahul Jha
beb957382d
Highlight .get in backticks
When I first read through the documentation twice, it took me two tries and looking very hard to find out the difference b/w the two. The background highlight using backticks would be helpful in this case.
2022-01-13 15:33:09 +05:30
Syrus Akbary
06eb1a3e82
Merge pull request #1401 from Cito/test-py39-and-py310
Add Python 3.9 and 3.10 to the test matrix
2022-01-11 13:22:25 +01:00
Christoph Zwerschke
e441fa72aa
Add Python 3.9 and 3.10 to the test matrix
Also update the test dependencies and adapt two tests (#1400).
2022-01-11 12:13:12 +01:00
Syrus Akbary
7ecb4e68ba
Merge pull request #1387 from GDGSNF/master
Chore: Refactor Multi Expression Code 
2021-12-13 15:02:02 +01:00
Syrus Akbary
9311d3525d
Merge pull request #1324 from justinrmiller/doc-fixes
Various spelling and grammar fixes for the documentation.
2021-12-13 14:59:53 +01:00
Yasser Tahiri
7108bc8577
Update node.py 2021-12-02 12:04:07 +01:00
Mel van Londen
a61f0a214d update README.rst using pandoc 2021-11-13 14:25:10 -08:00
Mel van Londen
27f19e5a90 release v3 stable 2021-11-13 14:15:18 -08:00
Yasser Tahiri
9e17044ddc
Chore: Refactor Multi Expression Code 2021-11-05 02:21:14 +01:00
belkka
b274a607f4
Avoid ambiguity in graphene.Mutation docstring
The code example in docstring starts with `from graphene import Mutation` and defines a `class Mutation` later. This definition would shadow previously imported name and (which is more important) confuses a reader about usage of this class — one need to keep in mind that previous usage of `Mutation` is imported from graphene and have not been overridden yet.

This PR changes an import-from statement to an import statement, so `graphene.Mutation` is used explicitly. This approach is consistent with other code examples in docs (e. g. https://docs.graphene-python.org/en/v2.1.9/types/mutations/).

Another option is to change name of example class Mutation to something more clear (maybe SchemaMutation or RootMutation), but I'm not sure what name to choose.

Only docstring is updated, no code changes.
2021-10-11 23:46:13 +03:00
Eran Kampf
0a54094f59
v3.0.0b8 2021-09-29 23:42:36 -07:00
Syrus Akbary
9c1db0f662
Merge pull request #1376 from codebyaryan/master
Fix unseen examples
2021-09-30 08:23:09 +02:00
Syrus Akbary
03aad2799a
Merge pull request #1377 from graphql-python/fix-graphql-core-dependency
Fix GraphQL-core dependency
2021-09-30 08:22:41 +02:00
Eran Kampf
b6c8931b22
Fix GraphQL-core dependency
GraphQL-core released `3.2.0rc1` with some breaking changes and
1. We should be getting RC releases in our dependencies
2. It has breaking changes, so we shouldn't get 3.2.0 unless someone fixes it explicitly
2021-09-29 17:11:16 -07:00
Aryan Iyappan
10aee710fc
Merge branch 'graphql-python:master' into master 2021-09-29 18:13:31 +05:30
Aryan Iyappan
1d6f9e984b
Mame sure to pass correct graphql schema instance 2021-09-29 18:13:08 +05:30
Aryan Iyappan
c1bd25555c
Update queryvalidation.rst 2021-09-28 06:41:54 +05:30
Drew Hoover
78973964b8
fix: update ariadne url to the new docs 2021-09-21 13:00:19 -04:00
Syrus Akbary
f039af2810
Merge pull request #1359 from codebyaryan/fix-actions
Fix actions
2021-08-23 22:07:12 -05:00
Aryan Iyappan
47696559c7 run linters locally 2021-08-24 08:30:54 +05:30
Aryan Iyappan
2e5944eb20 format code 2021-08-22 11:03:22 +05:30
Aryan Iyappan
2c66e496f7
Update tox.ini 2021-08-22 08:48:38 +05:30
Aryan Iyappan
908d5aeaeb
Update .pre-commit-config.yaml 2021-08-22 08:48:15 +05:30
Aryan Iyappan
d5d7a0e5e0
Update tox.ini 2021-08-21 21:41:47 +05:30
Aryan Iyappan
85f06fb2a6
Update tox.ini 2021-08-21 21:37:30 +05:30
Aryan Iyappan
a3a2f999aa
Update .pre-commit-config.yaml 2021-08-21 21:33:00 +05:30
Aryan Iyappan
7087710d02
Update .pre-commit-config.yaml 2021-08-21 21:17:00 +05:30
Aryan Iyappan
1c3054b7c8
Update test_connection_async.py 2021-08-21 21:01:27 +05:30
Aryan Iyappan
5896ade2dd
Update test_connection_query.py 2021-08-21 20:58:18 +05:30
Aryan Iyappan
76701e0809
Update .pre-commit-config.yaml 2021-08-21 20:53:58 +05:30
Aryan Iyappan
3b77b5f92a
Update tox.ini 2021-08-21 20:36:41 +05:30
Aryan Iyappan
16d0b32a8f
Update .pre-commit-config.yaml 2021-08-21 20:21:46 +05:30
Aryan Iyappan
d54b819552
Update .pre-commit-config.yaml 2021-08-21 18:37:44 +05:30
Aryan Iyappan
1886ec9dcb
Update schema.py 2021-08-21 18:34:39 +05:30
Aryan Iyappan
0ebff3313d
Update test_schema.py 2021-08-21 18:30:42 +05:30
Aryan Iyappan
7827219ba2
Update schema.py 2021-08-21 18:29:56 +05:30
Aryan Iyappan
ce59f1ff15
Rename .pre-commit-config.yml to .pre-commit-config.yaml 2021-08-21 17:48:33 +05:30
Aryan Iyappan
3145543386
Update tox.ini 2021-08-21 17:46:14 +05:30
Aryan Iyappan
7960b02124
Delete lint.yml 2021-08-21 17:41:12 +05:30
Aryan Iyappan
9807d6102c
Update coveralls.yml 2021-08-21 17:40:08 +05:30
Aryan Iyappan
e66d6148ab
Create lint.yml 2021-08-21 17:25:38 +05:30
Aryan Iyappan
1654d2fa29
Update coveralls.yml 2021-08-21 17:24:11 +05:30
Aryan Iyappan
772986ac83
Create lint.yml 2021-08-21 17:23:27 +05:30
Aryan Iyappan
0aef168687
Create deploy.yml 2021-08-21 17:21:48 +05:30
Aryan Iyappan
dc6b820635
Create coveralls.yml 2021-08-21 17:19:53 +05:30
Aryan Iyappan
16551369b2
Update tests.yml 2021-08-21 17:16:43 +05:30
Aryan Iyappan
e1822c9ae9
Create stale.yml 2021-08-21 17:15:28 +05:30
Aryan Iyappan
3c50fa817a
Delete stale.yml 2021-08-21 17:14:52 +05:30
Syrus Akbary
efc03533ae
Merge pull request #1357 from codebyaryan/master
add support for query validation
2021-08-20 19:40:50 -05:00
Aryan Iyappan
74a6565ea3
Update depth_limit.py 2021-08-20 21:07:57 +05:30
Aryan Iyappan
98980b53f6
Update depth_limit.py 2021-08-20 21:04:22 +05:30
Aryan Iyappan
57a4394bf3
Update depth_limit.py 2021-08-20 20:56:19 +05:30
Aryan Iyappan
ea4e6d65e9
Update schema.py 2021-08-20 16:08:58 +05:30
Aryan Iyappan
18cd3451f9
Update test_schema.py 2021-08-20 15:59:38 +05:30
Aryan Iyappan
946c2a3807
Update schema.py 2021-08-20 15:58:43 +05:30
Syrus Akbary
7d890bf915
Update graphene/validation/disable_introspection.py 2021-08-19 14:02:45 -05:00
Aryan Iyappan
0e4c14b076 update workflow: tests 2021-08-19 15:00:09 +05:30
Aryan Iyappan
8ae4369155 remove build matrix wherever not needed 2021-08-19 12:16:13 +05:30
Aryan Iyappan
c0ddbbfaf4 update workflow matrix 2021-08-19 12:13:46 +05:30
Aryan Iyappan
467b1f8e8d add workflow: tests 2021-08-19 12:03:27 +05:30
Aryan Iyappan
b4be4a686b add notice to failing tests 2021-08-19 10:59:58 +05:30
Aryan Iyappan
4e32dac251 add tests and docs for disable introspection rule 2021-08-14 08:41:24 +05:30
Aryan Iyappan
ec982ac50b update docs typo 2021-08-14 08:22:04 +05:30
Aryan Iyappan
c68071952d mention how to implement custom validators 2021-08-14 08:20:46 +05:30
Aryan Iyappan
ac5dd90f5f fix typo in docs 2021-08-14 07:54:58 +05:30
Aryan Iyappan
7be4bd6bc6 update docs 2021-08-14 07:49:09 +05:30
Aryan Iyappan
d7b474751d add depth limit validator tests 2021-08-14 07:45:34 +05:30
Aryan Iyappan
a784ef15e5 add disable introspection 2021-08-13 20:24:53 +05:30
Aryan Iyappan
5977b1648c fix typo 2021-08-13 20:04:42 +05:30
Aryan Iyappan
4259502dc3 update docs 2021-08-13 20:02:20 +05:30
Aryan Iyappan
fc2967e276 remove unused imports 2021-08-13 18:51:23 +05:30
Aryan Iyappan
aa11681048 add depth limit validator 2021-08-13 18:22:12 +05:30
Fabian Affolter
fce45ef552
Update pytz to 2021.1 (#1330) 2021-07-16 10:12:09 -07:00
Fabian Affolter
5290c9364c
Allow later aniso8601 releases (#1331) 2021-07-16 10:11:49 -07:00
Sergey Fedoseev
69b6286861
Fix typo in docstring of ObjectType (#1343) 2021-07-16 10:10:53 -07:00
kevinr-electric
485b1ed325
fix field name in execute.rst example (#1327)
fix field name in execute.rst 'Operation Name' example
2021-04-22 20:28:05 -07:00
Minh Tu Le
c08379ed85
Use argument's default_value regardless if the input field is required (#1326)
* Use argument's default value regardless if the input field is required

* Add a test

* Format code
2021-04-19 10:03:11 -07:00
Justin Miller
55cbc4d100 Merge branch 'DocFixes' of github.com:justinrmiller/graphene into DocFixes 2021-04-12 23:54:06 -07:00
Justin Miller
fbac4d5092 Fixing grammar and spelling errors across a number of files. 2021-04-12 23:53:36 -07:00
Justin Miller
002b769db4 Fixing Dataloader docs due to tox issue. 2021-04-12 23:32:11 -07:00
Justin Miller
12302b78f9
Update schema.rst 2021-04-12 23:08:42 -07:00
Justin Miller
db9d9a08f2
Update schema.rst 2021-04-12 23:01:20 -07:00
Justin Miller
3ed8273239
Update dataloader.rst 2021-04-12 22:48:53 -07:00
Justin Miller
a5fbb2e9e5
Update middleware.rst 2021-04-12 22:44:41 -07:00
Justin Miller
5acd04aa93
Update mutations.rst 2021-04-12 22:40:08 -07:00
Justin Miller
17f6a45a47
Update unions.rst 2021-04-12 22:37:32 -07:00
Justin Miller
f5321d619c
Update interfaces.rst 2021-04-12 22:33:14 -07:00
shukryzablah
f622f1f53c
Update index.rst (#1313) 2021-03-24 20:32:51 +01:00
bartenra
6f9cdb4888
Fix links to Relay docs (#1318) 2021-03-24 20:32:35 +01:00
Alec Rosenbaum
7004515f06 implement interface interfaces on TypeMap, fix failing test 2021-01-15 13:13:05 -05:00
Alec Rosenbaum
a17f63cf03 add failing type_map test, bar_graphql_type has no interfaces 2021-01-15 13:10:14 -05:00
Alec Rosenbaum
86b7e6ac86 update InterfaceOptions to fix failing test 2021-01-15 13:02:08 -05:00
Alec Rosenbaum
ae93499a37 add failing test for interface meta 2021-01-15 13:01:43 -05:00
Jonathan Kim
2e87ebe5fc
v3.0.0b7 2021-01-06 09:58:19 +00:00
Jason Kraus
e5eeb9d831
fix(Decimal): parse integers as decimal. (#1295) 2021-01-06 09:54:45 +00:00
Varun Dey
e0d4bec2d8
Remove Object Mutation dead link from Relay docs (#1272)
The official Relay project has removed 'Relay input Object Mutation' in favour of general mutation spec from their docs in [this PR](https://github.com/facebook/relay/pull/2401/files#diff-98bee0595817d7a46cd52d86e6c3db70) and is unavailable on their [official website](https://relay.dev/docs/en/graphql-server-specification#mutations) as well
2020-11-17 08:01:21 -08:00
Jonathan Kim
7d09e5b138
Update stale.yml 2020-10-27 08:51:51 +00:00
Jonathan Kim
84582eb374
v3.0.0b6 2020-10-21 10:15:38 +01:00
Alec Rosenbaum
e24ac547d6
Add UnforgivingExecutionContext (#1255) 2020-10-21 10:13:32 +01:00
Ali Reza Yahyapour
a53b782bf8
Syntax Error Fixed for Dictionary assert (#1267) 2020-09-22 17:10:01 +01:00
Paul Bailey
8c327fc4ed
add BigInt type (#1261)
* add BigInt type

* formatting

* more Int tests
2020-08-28 17:55:46 +02:00
Varun Dey
b685e109f5
Fix typo in Schema docs (#1259) 2020-08-24 17:20:33 +01:00
Daniel T. Plop
6918db1033
Fix Typo in Docs (#1252)
The example of executing a query by passing a root value had a typo for
the trailing parenthesis, namely it was '}' instead of ')'.
2020-08-12 14:44:00 -07:00
Jonathan Kim
188ce9a6cb
Fix subscribe with arguments (#1251) 2020-08-12 14:43:35 -07:00
Jonathan Kim
86b904d327
Split out the subscriptions documentation a separate file and fix it (#1245) 2020-08-07 14:37:32 -07:00
Jonathan Kim
29dd3f8391
v3.0.0b5 2020-08-06 17:19:02 +01:00
Syrus Akbary
d085c8852b
Subscription revamp (#1235)
* Integrate async tests into main code

* Added full support for subscriptions

* Fixed syntax using black

* Fixed typo
2020-07-28 13:33:21 -07:00
Redowan Delowar
2130005406
Minor grammatical fix in the schema docs (#1237) 2020-07-27 11:56:14 -07:00
Jonathan Kim
64af43748c
v3.0.0b4 2020-07-14 14:31:54 +01:00
Jonathan Kim
81fff0f1b5
Improve enum compatibility (#1153)
* Improve enum compatibility by supporting return enum as well as values and names

* Handle invalid enum values

* Rough implementation of compat middleware

* Move enum middleware into compat module

* Fix tests

* Tweak enum examples

* Add some tests for the middleware

* Clean up tests

* Add missing imports

* Remove enum compat middleware

* Use custom dedent function and pin graphql-core to >3.1.2
2020-07-13 15:40:57 -07:00
Jonathan Kim
d042d5e95a
Expose Base64 type and add custom scalar examples (#1223) 2020-07-09 17:55:27 +01:00
Eric Rodrigues Pires
c61f0f736a
Add Base64 scalar (#1221) 2020-07-02 10:52:44 -07:00
Jonathan Kim
5b2eb1109a
ObjectType meta arguments (#1219)
* Pass extra kwargs down the meta chain

* Rename name argument to allow custom name

* Reword error message

* Explicitly define kwargs

* Revert change to explicit kwargs

* name -> name_ for Enum __new__ function
2020-06-29 15:26:08 -07:00
Jonathan Kim
ecd11ccc1e
Revert 1213 update mutation docs (#1214)
* Revert "Update requirement for Query type in mutation docs (#1213)"

This reverts commit a9625dac0e.

* Add test to check that Query type must be defined
2020-06-29 07:53:53 -07:00
Jonathan Kim
324df19d3d
Set min version of graphql-core to v3.1.1 (#1215) 2020-06-28 21:54:36 -07:00
Jonathan Ehwald
bf034ca85f
Rename variables called type to type_ (#1216)
Co-authored-by: Daniel Gallagher <daniellg@yelp.com>
2020-06-27 11:18:11 +01:00
Jonathan Kim
05d96a9833 v3.0.0b3 2020-06-25 17:57:42 +01:00
Jonathan Kim
a9625dac0e
Update requirement for Query type in mutation docs (#1213) 2020-06-24 19:22:22 -07:00
Jonathan Kim
a1fc3688aa
Remove to_const function (#1212) 2020-06-24 19:21:40 -07:00
Jonathan Kim
4b70186031
Remove @staticmethod decorator in mutations doc (#1206) 2020-06-24 19:18:59 -07:00
Christoph Zwerschke
47c63f3dd7
Fix DateTime Scalar parse_literal methods (#1199) (#1200) 2020-06-04 21:30:23 -07:00
dbgb
966aba06cd
Fix typo in quickstart document (#1201) 2020-05-28 15:41:38 +02:00
Jonathan Kim
b0c8a17ec7
Fix issue with trailing whitespace (#1197) 2020-05-19 22:12:41 -07:00
Jonathan Kim
9b756bf12c
Delete CODEOWNERS 2020-05-09 13:32:52 +01:00
Jonathan Kim
d6acfc6eae
Create config.yml 2020-05-09 13:32:38 +01:00
Jonathan Kim
0723dd1d6c Update issue templates 2020-05-09 13:31:55 +01:00
Jonathan Kim
df67e69129
v3.0b2 2020-05-09 13:04:05 +01:00
Kevin Harvey
396b278aff
Fix typos (#1192) 2020-04-29 13:38:56 +01:00
Jonathan Kim
380166989d Update dataloader docs 2020-04-26 13:22:09 +01:00
Jonathan Kim
3e4305259b Add basic test for aiodataloader 2020-04-26 13:17:00 +01:00
Jonathan Kim
a0b522fa39 Add aiodataloader to test deps 2020-04-26 13:16:51 +01:00
Jonathan Kim
12ec8dc007
Don't exclude tests from distribution 2020-04-26 11:44:16 +01:00
Radosław Kowalski
133a831ab9
Update excluded packages list to properly exclude examples pack… (#1187)
* examples package will not be installed with graphene
2020-04-17 13:27:22 +01:00
Kimball Leavitt
7a1e9d7798
added graphene import to READMEs (#1183)
it's nice to just be able to copy/paste the entire example without
having to remember the import
2020-04-14 10:25:10 +01:00
Syrus Akbary
49fcf9f2e6
Allow fast ObjectType creation based on dataclasses (#1157)
* Allow fast ObjectType creation based on dataclasses

* Fixed Python 3.8 integration

* Added repr and eq methods to ObjectType containers

* Reformatted code

* Fixed mypy issue

* Removed unused __init__ for ObjectType containers

* Use black in dataclasses

* Use latest black verison on precommit
2020-04-12 17:45:46 -07:00
rrueth
37d6eaea46
Fix resolve method parameters bullet list (#1178)
The current documentation shows all of the resolve parameters on a single line as opposed to the bullet list that was intended.
2020-04-12 12:19:56 +01:00
sduthil
871c60cf46
Docs: integrations: fix FastAPI link (#1177) 2020-04-09 19:21:04 +01:00
Jonathan Kim
0051f82b5f
v3.0.0b1 2020-04-06 09:36:53 +01:00
Jonathan Kim
a2fe8dd704
Add note about the use of args (#1170)
* Add note about the use of `args`

Closes #1037

* Some improvements

* Link to correct place
2020-04-02 19:55:00 +01:00
Jonathan Kim
9fdab033a7
Add exempt labels 2020-04-01 16:24:23 +01:00
Jonathan Kim
cb3bfe011f
Use default_resolver to resolve values when using the source at… (#1155) 2020-03-16 16:20:04 +00:00
Jonathan Kim
6f2863ef6e
Add some more tests for Interface (#1154) 2020-03-16 16:19:44 +00:00
Jonathan Kim
00e36b52d5
Remove unused function (#1160) 2020-03-16 15:51:07 +00:00
Oleh Kuchuk
f9efe15973
Fixed examples, make root object explicit inside resolvers and… (#1159) 2020-03-15 18:52:56 +00:00
Syrus Akbary
60a9609b9a
Updated all str.format(…) to f-strings (#1158)
* Updated all str.format(…) to f-strings

This revamps the PR #984

* Pass black

* Fix flake8

* Updated objecttype

* Fix black version
2020-03-14 17:32:44 -07:00
Syrus Akbary
14183012a8
Remove subclass polyfill (#1156)
The subclass polyfill was only needed for Python 2.7-3.5

Python 3.6 introduced the __init_subclass__, so since Graphene now requires Python 3.6+, this is no longer needed.

https://www.python.org/dev/peps/pep-0487/
2020-03-14 20:19:28 +00:00
Rob Blackbourn
1cf303a27b
Added support for subscription (#1107)
* Added support for subscription

* Added pre-commit hooks for black and formatted changed files

* Checked with flake8

* Integrated changes from master.

Co-authored-by: Rob Blackbourn <rblackbourn@bhdgsystematic.com>
Co-authored-by: Rob Blackbourn <rtb@beast.jetblack.net>
2020-03-14 16:48:12 +00:00
Christoph Zwerschke
88f79b2850 Fix types in Schema docstring (#1100) 2020-03-04 15:26:09 +01:00
Christoph Zwerschke
5d97c848e0 Remove misleading comment
The comment originally referred to the __metaclass__ attribute which is gone now.
2020-03-04 12:44:53 +01:00
Christoph Zwerschke
5e6f68957e Use latest graphql-core 3.1.0b1 instead of 3.0.3
Adapt Schema, because there is no type reducer in core 3.1 any more.
2020-03-04 12:23:40 +01:00
Christoph Zwerschke
ffb7701466 Create another alpha release 2020-03-04 11:37:00 +01:00
Christoph Zwerschke
796880fc5c Update dependencies 2020-03-04 11:24:42 +01:00
Jonathan Kim
98e10f0db8
Replace INVALID with Undefined (#1146) 2020-02-27 20:51:59 +00:00
Jayden Windle
ac98be7836
Use Undefined instead of the now deprecated INVALID (#1143) 2020-02-26 21:18:13 +01:00
Lem Ko
ba5b7dd3d7
Fix example query in quickstart doc (#1139) 2020-02-21 11:15:51 +00:00
정유석
be97a369f7
fix typo in class 'Interface' (#1135) 2020-02-18 08:53:48 +00:00
David Sanders
03bd6984dd
fix example middleware class in docs (#1134) 2020-02-10 14:17:16 -08:00
James
23bb52a770
Add a helpful message to when a global_id fails to parse. (#1074)
* Add a helpful message to when a global_id fails to parse.

* Update test_node to have errors on test_node_query_incorrect_id

* Black the node.py file

* Remove func wrapper used in debugging get_resolver partial

* Update node.py

* Expand error messages

Co-authored-by: Jonathan Kim <jkimbo@gmail.com>
2020-02-10 14:16:11 -08:00
Jean-Louis Fuchs
ad0b3a529c
The default_value of InputField should be INVALID (#1111)
* The default_value of InputField should be INVALID

Since GraphQL 3.0 there is a distinction between None and INVALID (no value).
The tests captured the bug and are updated.

* Update minimum graphql-core version

* Use Undefined instead of INVALID

Co-authored-by: Jonathan Kim <jkimbo@gmail.com>
2020-02-08 20:24:58 +00:00
Henry Baldursson
9a19447213 Use unidecode to handle unicode characters in constant names (#1080) 2020-02-08 09:21:25 -08:00
Jonathan Kim
55a03ba716
Update readme (#1130)
* Add slack link and dev notice to the README

* Fix formatting

* Update formatting

* Add notice to documentation
2020-01-30 08:17:12 -08:00
Jonathan Kim
f82b811377
Fix example code (#1120) 2020-01-30 12:18:00 +00:00
Jonathan Kim
bd6d8d086d
Fix tests (#1119)
* Fix tests

* Add extra folders to make test command

* Update snapshots

* Add python 3.8 to test matrix

* Add black command to makefile and black dependency to setup.py

* Add lint command

* Run format

* Remove 3.8 from test matrix

* Add Python 3.8 to test matrix

* Update setup.py
2019-12-31 14:08:30 +00:00
Tom Paoletti
81d61f82c5 Fix objecttypes DefaultResolver example (#1087) (#1088)
* Create namedtuple as expected
* Access result.data instead of result['data']
* Refer to field with camel-case name
2019-12-26 20:05:14 +00:00
Jonathan Kim
482c7fcc65
Add file uploading docs (#1084) 2019-12-26 20:02:57 +00:00
Iman
c0fbcba97a Update quickstart.rst (#1090)
A miss letter
2019-12-26 20:02:28 +00:00
Yu Mochizuki
e31b93d1fd Increase the allowed version of aniso8601 (#1072) 2019-12-26 11:27:55 +00:00
TheMelter
abc2c2a784 Fix typo in execute.rst (#1115) 2019-12-19 23:02:45 -08:00
Jonathan Kim
3f6f426946
Update stale.yml 2019-10-18 10:50:54 +01:00
Theodore Diamantidis
7c7876d37c Propagate arguments of relay.NodeField to Field (#1036)
* Propagate name, deprecation_reason arguments of relay.NodeField to Field

* Allow custom description in Node.Field and move ID description to ID argument

* Add test for Node.Field with custom name

* Add tests for description, deprecation_reason arguments of NodeField

* Pass all kwargs from NodeField to Field
2019-09-27 09:54:46 +01:00
Jonathan Kim
a3b215d891
Remove AbstractType (#1053) 2019-09-27 09:54:19 +01:00
Min ho Kim
e90aa1b712 Fix typos (#1066)
Fixed typos in docs, string literals, comments, test name
2019-09-25 19:57:53 -04:00
Mel van Londen
8e7d76bbce
Graphene v3 following v3 graphql-core (#1048)
* v3.0 - remove Python 2.x from build (#983)

* Change travis to only compile for p3.6+

* Changed tox to only run Python 3.6+

* Changed library classifiers to reflect support in Python 3.6+

* Changed version to 3.0.0 development

In [15]: get_version((3, 0, 0, "alpha", 0))
Out[15]: '3.0.dev20190601212304'

* Reorganize Tests (#985)

We no longer need a dedicated folder for Python3.6+ tests
We no longer need to check six.PY3 in tests

* Upgrade black to 19.3b0 (#987)

* Remove six dependency (#986)

* No one is using func_name

* Remove six simple usages

* Remove six requirement

* Remove `six.with_metaclass` calls

* pytest-asyncio should be a regular dependency now with Py3 move

* Change dependency to graphql-core-next (#988)

* Changed dependencies to core-next

* Converted Scalars

* ResolveInfo name change

* Ignore .venv

* Make Schema compatible with GraphQL-core-next

* Ignore more venv names and mypy and pytest caches

* Remove print statements for debugging in schema test

* core-next now provides out_type and out_name

* Adapt date and time scalar types to core-next

* Ignore the non-standard result.invalid flag

* Results are named tuples in core-next (immutable)

* Enum values are returned as dict in core-next

* Fix mutation tests with promises

* Make all 345 tests pass with graphql-core-next

* Remove the compat module which was only needed for older Py version

* Remove object as base class (not needed in Py 3)

* We can assume that dicts are ordered in Py 3.6+

* Make use of the fact that dicts are iterable

* Use consistent style of importing from pytest

* Restore compatibility with graphql-relay-py v3

Add adpaters for the PageInfo and Connection args.

* Avoid various deprecation warnings

* Use graphql-core 3 instead of graphql-core-next

* Update dependencies, reformat changes with black

* Update graphene/relay/connection.py

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Run black on setup.py

* Remove trailing whitespace
2019-08-17 17:07:53 -04:00
Jonathan Kim
3d0e460be1 v2.1.8 (#1054)
Update version to v2.1.8
2019-08-17 16:52:59 -04:00
Jonathan Kim
0808e8acb3
Add stalebot (#1044) 2019-07-29 12:02:11 +02:00
Ntale Shadik
c96bd680d7 Add interfaces meta argument on Mutations (#1023) 2019-07-24 18:44:22 +01:00
Vincent Prouillet
6e4058960d Increased allowed version of aniso8601 (#1009)
Closes #1008 

The only change should not affect graphene https://bitbucket.org/nielsenb/aniso8601/issues/24/float-induced-rounding-errors-when-parsing
2019-07-24 18:43:28 +01:00
Jonathan Kim
167c8c203c Bump version 2019-07-15 21:09:41 +01:00
Jonathan Kim
6fc1a8f79d
Upgrade graphql-relay (#1032)
* Upgrade graphql-relay

* Remove pypy3 test
2019-07-15 21:02:56 +01:00
Danilo Herrera
57157ab7f4 Fix typo (#1028) 2019-07-08 22:21:50 +01:00
Mel van Londen
4170e73251
Update roadmap (#1019)
* update roadmap

* Update ROADMAP.md graphql-core-next table entry

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Update ROADMAP.md graphql-core table entry

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Update ROADMAP.md remove SDL schema creation

* Update ROADMAP.md remove connections structure

* fix trailing whitespace
2019-06-24 20:38:45 -07:00
Jonathan Kim
8dee85cc13
Trying to get codeowners to work (#996)
* Trying to get codeowners to work

* Update CODEOWNERS
2019-06-24 16:01:45 +01:00
Jonathan Kim
abe547fb4d
Fix wrong variable name (#1015)
Resolves #1014
2019-06-22 18:09:52 +02:00
Jonathan Kim
0e8a3c5063
Update travis.yml (#1010)
* Use xenial dist

* Only install coveralls after success

* Latest version of pypi

* Refactor travis.yml into stages and add travis-tox

* Drop 2.6

* Bump to python 3.7
2019-06-19 18:25:21 +01:00
Mel van Londen
ac6714e8fa Remove sponsorship text from readme (#1002)
* remove sponsorship text from readme

* remove sponsorship references in roadmap
2019-06-14 12:56:02 +01:00
Jonathan Kim
89ca4f58a2
v2.1.6 (#1005) 2019-06-14 11:41:29 +01:00
Adrián López Calvo
431e93cd68 Fix malformed version on aniso8601 requirement (#995)
* Fix malformed version on aniso8601 requirement

* 6 -> 6.0

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>
2019-06-10 21:16:28 -07:00
David Anderson
5cb7d91aaa Revise documentation (#969)
* Revise documentation

- Add missing reference to `flask-graphql` in integrations
- align documentation for resolver arguments (use root for 1st argument
instead of self)
- explore use of `parent` instead of `root` for first argument
- clarify resolvers and object type documentation
- add documentation for Meta class options for ObjectType
- expand quickstart documentation for first time users
- streamline order of documentation for first time users (broad ->
specific)
- document resolver quirks

* explict imports from graphene

* rename doc refs for resolvers

* suggestions typos and graphene import
2019-06-09 16:49:56 -07:00
David Anderson
da1359ecca expose livehtml autobuild in Makefile + Add API autodoc (#971)
* expose livehtml autobuild in Makefile

* add API documentation for schema

* document graphene core API

* fixes black lint

* Update graphene/types/union.py

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Update graphene/types/argument.py

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Update graphene/types/field.py

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* Update graphene/types/inputfield.py

Co-Authored-By: Jonathan Kim <jkimbo@gmail.com>

* add note about non-functional `interfaces` meta argument in mutation

* update with other virtual environment configuration

* pin autobuild

* format argument example code

* format enum input object and interface examples

* format enum mutation union examples

* revise documentation with imports, capitalization
2019-06-09 15:36:06 -07:00
Ambro
40229b8a73 Fix internal link on docs (#980) 2019-06-04 09:23:24 -07:00
Eran Kampf
89a352e93a Pypi doesnt allow raw directive 2019-06-03 10:29:59 -07:00
Eran Kampf
17fbcb6746 v.2.1.5 2019-06-03 10:12:50 -07:00
Eran Kampf
f0cc9268d2 Fix RST README 2019-06-03 09:44:03 -07:00
Jessamyn Hodge
4e3f46b2c9
updating codeowners to have additional reviewers for docs and example changes (#989) 2019-06-02 18:16:25 -04:00
Eran Kampf
40534bcce9 v2.1.4 2019-06-01 13:44:13 -07:00
David Anderson
ec9f76cfae Fix flaky date tests (#982)
* fix flaky datetime test with fixed values

* rename fixtures for clarity in date+time tests
2019-06-01 13:41:45 -07:00
Eran Kampf
eb7966eca7
Fix for metaclasses that use type annotation (Issue #979) (#981)
* Replicate error with test

* Fix - ignore parameters we do not recognize

* Seperate Python3.6+ tests to their own folder

* lint

* Unused import

* Black formatting
2019-05-31 14:31:17 -07:00
Mike Bobadilla
1fcdeaac65 Typo in documentation (#975) 2019-05-28 10:09:57 -07:00
cclauss
f73055f72b Drop support for Python 3.4 because it is EOL (#963) 2019-05-07 12:16:22 -07:00
Scott Crunkleton
a5162e9ae3 Update aniso8601 dependency to allow versions 4+. (#935)
* Update aniso8601 dependency to allow versions 4+.

* Upper bound to aniso8601 dependency version.
2019-05-07 09:31:30 -07:00
NyanKiyoshi
6a4091b3e4 from_enum can now take a deprecation reason (#957) 2019-05-06 10:17:33 -07:00
Minh Tu Le
abff3d75a3 Allow the connection node to be wrapped in a NonNull type (#934) 2019-04-12 16:29:53 -07:00
Ganesh Pandey
daf0d17647 fix type on docs (#939) 2019-04-09 11:29:40 -07:00
Eran Kampf
d0cfee5641
Make UUID compatible (Fixed issue #936) (#937)
* Make UUID compatible

* Fix typo

* black code formatting
2019-04-08 14:06:32 -07:00
Eran Kampf
bcbb66c025
Line too long in code sample caused docs UI to overflow (#938) 2019-04-08 13:59:39 -07:00
Eran Kampf
582ac59bf7 Another docs test 2019-04-08 12:36:35 -07:00
Eran Kampf
28f6b18f55 Small formatting fix to test docs integration 2019-04-08 12:33:29 -07:00
Andreas Sodeur
7b6dae7fa3 [863] DateTime, Date, and Time now accept datetime.datetime, datetime.date,… (#864)
* DateTime, Date, and Time now accept datetime.datetime, datetime.date, and datetime.time resp. inputs when used as variables

* Added tests and improved resilience against bad DateTime, Date, and Time inputs.

* Fixed string type checks too narrow for py2.7

* fixed some of pre-commit's complaints
2019-03-31 11:57:34 +01:00
Jonathan Kim
c5b2281e22 Update execution doc with correct way to use variables (#920)
* Fix issue #890

* Change to `root`
2019-03-27 16:44:41 -07:00
Jonathan Kim
21cccf4c96 Update object type docs (#921)
Now that the default resolver handles both objects and dicts
2019-03-17 12:43:49 -07:00
Jonathan Kim
0805436d45
Docs on changing the name of an ObjectType (#922)
Fixes https://github.com/graphql-python/graphene/issues/839
2019-03-16 21:58:49 +00:00
Jonathan Kim
ca9188a615 Dict or attr default resolver (#638)
* Add dict_or_attr resolver and set it as default

* Add some tests

* Dry up code

* Updated formatting
2019-03-11 10:24:11 -07:00
Sebastián Ramírez
bbe11c9b5e Add FastAPI and Starlette to integrations (#906) 2019-03-11 10:03:54 -07:00
Markus Holtermann
96d497c2b8 Fix docs on graphene.Int bounds (#891) 2019-03-11 09:32:23 -07:00
Jonathan Kim
a4681ce6b2
Fixes middleware documentation (#916)
Closes #812
2019-03-10 16:21:08 +01:00
Harry Moreno
d95163c61d Add Docs link to readme (#914)
* change header of contributing docs to building docs
2019-03-09 17:35:15 -08:00
Dan
9ae2359b87 Run pre-commit autoupdate to bump versions of precommit hooks, then run them on all files (#913) 2019-03-08 11:09:45 -08:00
Eran Kampf
fd0bd0ccd7
Adding Myn to CODEOWNERS (projectcheshire) 2019-03-08 09:35:48 -08:00
Eran Kampf
359753dc0f
Merge pull request #912 from graphql-python/feature/add_codeowners_file
Added CODEOWNERS
2019-03-07 18:32:56 -08:00
Eran Kampf
806b99f59d Initial CODEOWNERS file as decided in our community meeting 2019-03-07 18:29:40 -08:00
Syrus Akbary
ae7a5d71c7
Merge pull request #873 from asodeur/issue_872
Special characters in README.rst break setup.py on Windows
2019-01-07 16:10:23 -05:00
Syrus Akbary
88d68fa672
Merge pull request #874 from kiendang/fix-doc
Fix anchor link
2019-01-07 16:10:01 -05:00
kiendang
ff4fb4f86a Fix anchor link 2018-12-28 10:53:29 +08:00
Syrus Akbary
e32cbc3346
Merge pull request #883 from graphql-python/update-object-type-docs
Update documentation on ObjectTypes
2018-12-27 14:53:09 +01:00
Jonathan Kim
d1b1ad733f Ignore flake8 error 2018-12-27 09:39:18 +00:00
Jonathan Kim
e1a2eb5a35 Remove trailing whitespace 2018-12-26 20:32:22 +00:00
Jonathan Kim
349add5700 Update documentation on ObjectTypes
Resolves #798
2018-12-26 20:22:34 +00:00
as
2bc7699a98 black formatting and removed trailing whitespace 2018-12-11 15:03:10 +01:00
as
2c43a2ae0a Now setup.py works on Windows other tools have trouble with PKG-INFO. Forcing long_description to ASCII. 2018-12-06 10:38:17 +01:00
as
3aafe58d4d Special characters in README.rst break setup.py on Windows 2018-11-29 09:29:00 +01:00
Syrus Akbary
08c86f3def
Merge pull request #845 from nive/master
quickstart example improvement
2018-11-05 20:26:18 +01:00
Syrus Akbary
37a6c01839
Merge pull request #855 from cherls/default-mutation-field-description
Default mutation field description
2018-11-05 20:25:56 +01:00
cherls
8e53672a1d Add mutation field default arg test 2018-11-05 13:30:09 -05:00
cherls
4d5a091d16 Add default Field description as docstring 2018-11-05 13:30:05 -05:00
Syrus Akbary
80066e55f3
Merge pull request #854 from johanzietsman-em/master
Fixed typos.
2018-11-01 19:10:03 +01:00
Johan Zietsman
587ce5ae93
Update interfaces.rst 2018-10-30 14:23:29 +02:00
Johan Zietsman
52f54f51b2
Update objecttypes.rst 2018-10-30 14:17:44 +02:00
Johan Zietsman
95cfff8c37
Update enums.rst 2018-10-30 14:06:37 +02:00
Syrus Akbary
e07e89d2e2 Improved README 2018-10-26 19:36:12 +02:00
Syrus Akbary
a0be081fc0 Improved README 2018-10-26 19:34:58 +02:00
Syrus Akbary
49a41060a6 Improved documentation showcasing sponsors 2018-10-26 19:30:37 +02:00
Syrus Akbary
7cfc3ffe67
Merge pull request #850 from MarSoft/patch-1
Fix typo in docs
2018-10-26 19:16:03 +02:00
Syrus Akbary
83a5587d71
Merge pull request #851 from etandel/feature/dataloader-docs
Improve dataloader doc
2018-10-26 19:15:44 +02:00
Syrus Akbary
89ba0da6d7
Merge pull request #847 from patrick91/fix/precommit-py-version
Don't enforce python 3.6 on precommit
2018-10-23 21:06:25 +02:00
Syrus Akbary
984e7cebe1
Merge pull request #849 from nerdoc/patch-1
fix deprecated "Input" class
2018-10-23 21:05:58 +02:00
Elias Tandel Barrionovo
21dbaa93c4 Improve dataloader doc
Explicitly mention that loaded values must have the same order as the
given keys
2018-10-23 10:05:47 -03:00
Семён Марьясин
ca02095806
Fix typo in docs 2018-10-22 16:19:55 +03:00
Christian González
4752ec08ab
fix deprecated "Input" class 2018-10-20 11:16:29 +02:00
Patrick Arminio
7e17b92a18
Don't enforce python 3.6 on precommit 2018-10-18 12:28:12 -07:00
adroullier
85e6c3d3fb quickstart example improvement, rename name parameter of String field to argument 2018-10-16 13:59:25 +02:00
Syrus Akbary
705cad76b2
Merge pull request #844 from dschaller/make-docs
add root make target for creating html version of docs
2018-10-15 14:46:49 +02:00
Syrus Akbary
8eb23ed802
Merge pull request #843 from dschaller/easier-make-docs
inline doctstring of make targets
2018-10-15 14:46:21 +02:00
Derek Schaller
a4c812f886 add root make target for creating html version of docs 2018-10-13 11:27:57 -07:00
Derek Schaller
3df3754ae6 inline doctstring of make targets 2018-10-13 11:21:07 -07:00
Syrus Akbary
131cbebc88
Merge pull request #832 from danpalmer/patch-6
Add basic type documentation for Relay fields
2018-09-09 20:11:36 +02:00
Dan Palmer
2a3d92682a
Add descriptions to the fields as well 2018-09-09 18:44:01 +01:00
Dan Palmer
b8ecc3929d
Add basic type documentation for Relay fields
This adds documentation in the API for `PageInfo`s and `Edges`.

This is useful to include in Graphene because `PageInfo` is always the same, and Edges always have the same format, so documentation for both can be created automatically.
2018-09-09 18:19:58 +01:00
Syrus Akbary
8d5843dc21 Added BACKERS.md 2018-09-09 18:10:07 +02:00
Syrus Akbary
8d4b9cdc77
Merge pull request #830 from danpalmer/patch-4
Expose documentation for Union types
2018-09-08 20:07:18 +02:00
Dan Palmer
00d370b228
Expose documentation for Union types 2018-09-08 17:20:39 +01:00
Syrus Akbary
e043527d5e
Merge pull request #827 from alxpy/py37
Add Python3.7 to CI
2018-09-04 16:25:32 +02:00
Alex Kuzmenko
325ab0d002 Add Python3.7 to CI 2018-09-04 17:17:28 +03:00
Syrus Akbary
e748c5f048
Update ROADMAP.md 2018-09-04 14:36:17 +02:00
Syrus Akbary
563ef221d4
Merge pull request #824 from graphql-python/feature/async-relay
Abstract thenables (promise, coroutine) out of relay
2018-08-31 20:51:48 +02:00
Syrus Akbary
9512528a77 Fixed async funcs 2018-08-31 20:16:12 +02:00
Syrus Akbary
3d41a500c9 Fixed lint & imports 2018-08-31 20:01:03 +02:00
Syrus Akbary
3e5319cf70 Abstract thenables (promise, coroutine) out of relay Connections and Mutations 2018-08-31 19:53:21 +02:00
Syrus Akbary
5777d85f99 Improved docs for testing 2018-08-31 17:58:51 +02:00
Syrus Akbary
bf3a4a88a4 Added ROADMAP to the Project 2018-08-31 17:49:29 +02:00
Syrus Akbary
c40ce98bb8
Merge pull request #821 from danpalmer/patch-3
Fix grammar in error message
2018-08-30 19:06:06 +02:00
Dan Palmer
baec6249e5
Fix assertion 2018-08-29 18:10:37 +01:00
Dan Palmer
07ec419578
Fix grammar 2018-08-29 17:31:46 +01:00
Syrus Akbary
727e09105f
Merge pull request #819 from adamchainz/deprecated_arguments
Change deprecated execute() arguments to new ones
2018-08-29 13:49:58 +02:00
Adam Johnson
4f2b278e12 black reformat 2018-08-29 13:07:45 +03:00
Adam Johnson
7dd8305bdf Change deprecated execute() arguments to new ones
Changed in https://github.com/graphql-python/graphql-core/pull/185 , the docs here were out of date, as were the tests.
2018-08-29 12:35:44 +03:00
Syrus Akbary
d728b84e48
Merge pull request #726 from picturedots/issue-703
Issue 703 -- support for Decimal type
2018-07-24 09:19:58 -07:00
Mark Chackerian
00cc97875d Merge branch 'master' into issue-703 2018-07-20 10:25:46 -04:00
Syrus Akbary
d28dc68abc Updated requirements to use graphql-core >= 2.1 2018-07-19 14:44:20 -07:00
Syrus Akbary
bfd6fd7c49
Merge pull request #802 from sebdiem/sdr/fix_black_formatting
fix black formatting
2018-07-19 14:38:07 -07:00
Sébastien Diemer
1eae96fd43 fix black formatting 2018-07-19 23:28:26 +02:00
Mark Chackerian
8ca7b855ac more flake8 fixes 2018-07-16 18:31:32 -04:00
Mark Chackerian
c076412ba5 automatically generated linting fixes 2018-07-16 18:20:04 -04:00
Mark Chackerian
fc3dbf0963 Merge branch 'master' into issue-703
# Conflicts:
#	graphene/__init__.py
#	graphene/types/__init__.py
2018-07-16 17:50:41 -04:00
Mark Chackerian
0fdc2ca3eb should fix some import issues with python 2.7 2018-07-16 17:20:49 -04:00
Syrus Akbary
4346832f71
Merge pull request #788 from sebdiem/sdr/subclass_mutations
Enable mutations subclassing
2018-07-09 19:06:15 -07:00
Syrus Akbary
319605bfaf
Merge branch 'master' into sdr/subclass_mutations 2018-07-09 18:49:07 -07:00
Syrus Akbary
43aec720a8
Merge pull request #793 from dan98765/add_black_formatter_precommit_hook
Add black formatter precommit hook
2018-07-06 17:40:40 -05:00
Daniel Gallagher
142f4a58d8 Run black formatter via pre-commit on all files 2018-07-06 14:03:15 -07:00
Daniel Gallagher
086f9dda99 Run black formatter via pre-commit on all files 2018-07-06 12:09:23 -07:00
Daniel Gallagher
71bcbb8566 Go with base black formatter for now 2018-07-06 12:06:16 -07:00
Daniel Gallagher
bf0d23b584 Add pyproject.toml to configure black formatter 2018-07-06 11:18:24 -07:00
Daniel Gallagher
04782a2818 Add black formatter pre-commit hook and remove isort (since black also sorts imports) 2018-07-06 11:10:41 -07:00
Syrus Akbary
ae7395f9da
Merge pull request #737 from dan98765/pre_commit_runs_as_part_of_continuous_integration
Update .travis.yml file to use tox as script for running tests
2018-07-06 12:50:31 -05:00
Sébastien Diemer
181e75c952 Fetch fields from parent classes in mutations
The goal of this commit is to be able to subclass mutations like this:

```
    class BaseMutation(graphene.Mutation):
        class Arguments:
            name = graphene.String()

        def mutate(self, info, **kwargs):
            # do something

    class ChildMutation(BaseMutation):
        class Arguments(BaseMutation.Arguments):
            other_arg = graphene.String()

        def mutate(self, info, **kwargs):
            # do other things
```

Note:
    vars(x).get(key, gettattr(x, key)) is used instead of the
    simpler gettatrr(x, key) for python2.7 compat.
    Indeed python2 and python3 lead to different results for

    class Foo(object):
        def bar(self):
            pass
    getattr(Foo, 'bar')

    # python 2.7 : > unbound method bar
    # python 3.x : > function Foo.bar
2018-07-02 10:03:39 +02:00
Sébastien Diemer
9f366e93c6 __wip__ add failed test
Just to ease review.
TODO: merge with next commit.
2018-07-02 10:03:39 +02:00
Syrus Akbary
2e41db8d95
Merge pull request #786 from jkimbo/deduplicator
Deduplicator
2018-07-01 18:10:36 -07:00
Syrus Akbary
fa5f5b0acb
Merge pull request #787 from jkimbo/crunch
Crunch response data
2018-07-01 18:09:28 -07:00
Jonathan Kim
1e40eceab3 Convert inputs to OrderedDicts 2018-07-01 21:19:19 +01:00
Jonathan Kim
9ce78e32a5 Remove utf-8 characters 2018-07-01 21:11:00 +01:00
Jonathan Kim
1f541e4467 Add crunch utility 2018-07-01 21:09:12 +01:00
Jonathan Kim
56000394c4 Simplify code 2018-07-01 11:32:16 +01:00
Jonathan Kim
cbcaac66d0 Add deduplicator utility 2018-07-01 11:29:45 +01:00
Syrus Akbary
1b746e6460
Merge pull request #779 from benmosher/patch-1
docs: mutation 'Output' example (closes #543)
2018-06-26 10:59:31 -07:00
Ben Mosher
708278e6dc
docs: mutation 'Output' example (closes #543) 2018-06-26 07:14:46 -04:00
Syrus Akbary
9efdf4c46e
Merge pull request #771 from jkimbo/update-interface-documentation
Update interface documentation
2018-06-18 13:33:59 -07:00
Syrus Akbary
9da46e8c99
Merge pull request #770 from boidolr/master
Update documentation
2018-06-18 13:33:34 -07:00
Jonathan Kim
cc54c76a3e Improve wording 2018-06-17 12:05:34 +01:00
Jonathan Kim
e7ebb86e5a Re-order type list 2018-06-17 11:25:32 +01:00
Jonathan Kim
a2db7c5dae Remove an unnecessary field 2018-06-17 11:24:59 +01:00
Jonathan Kim
3f6c3a7a99 Clean up doc and add resolve_type documentation 2018-06-17 11:23:08 +01:00
Jonathan Kim
43e87768d2 Update interface documentation 2018-06-16 15:10:32 +01:00
Raphael Boidol
5c4736e102 Update documentation
* resolver function arguments changed in `objecttypes.rst`
* small typo in `mutations.rst`
2018-06-16 13:11:33 +02:00
Syrus Akbary
c102458808
Merge pull request #768 from graphql-python/v2.1.2-1
Update to v2.1.2
2018-06-13 10:34:15 -07:00
Jonathan Kim
81419de5bf
Update to v2.1.2 2018-06-12 21:48:52 +01:00
Dan
33f2b303de Add python3.6 classifier to setup.py (#763) 2018-06-12 21:38:16 +01:00
Dan
b72dfa87a4 Update README Contributing section to encourage use of virtualenv (#765) 2018-06-12 21:38:06 +01:00
Daniel Gallagher
400a98de92 Add tox env for running mypy and add that to .travis.yml 2018-06-11 09:12:27 -07:00
Dan
12ee52a13a Add pyupgrade pre-commit hook and run on all files (#736) 2018-06-09 14:01:29 +01:00
Daniel Gallagher
c8fba61a05 Exclude README.md from trailing-whitespace hook 2018-06-08 22:19:26 -07:00
Daniel Gallagher
b5542d4426 Run pre-commit autoupdate 2018-06-08 22:13:45 -07:00
Daniel Gallagher
0f3d786402 Run pre-commit on all files 2018-06-08 22:08:58 -07:00
Daniel Gallagher
87cf3d4b80 Try installing mypy only when python version is 3.6 2018-06-08 22:00:01 -07:00
Daniel Gallagher
1d49df033c Explicitly run on py27 2018-06-08 21:56:08 -07:00
Daniel Gallagher
dbb72ba06b Update to match graphql-core 2018-06-08 21:54:24 -07:00
Daniel Gallagher
6116901ab6 Merge branch 'master' of github.com:dan98765/graphene into pre_commit_runs_as_part_of_continuous_integration 2018-06-08 21:52:34 -07:00
Dan
1b3e7f3b96 Add flake8 pre-commit hook and manually edit files to pass flake8 validation (#746)
Add flake8 pre-commit hook and manually edit files to pass flake8 validation
2018-06-05 21:47:07 +01:00
Syrus Akbary
8bf937d1ff
Merge pull request #754 from femesq/patch-2
Fix parameter order for Relay's Root-field
2018-06-01 18:16:42 -07:00
Syrus Akbary
8802ab3c28
Merge pull request #752 from jlowin/input-meta
Don't overwrite fields on InputObject - closes #720
2018-06-01 18:15:43 -07:00
Felipe Mesquita
2fbd2c1cb6
Fix parameter order for Relay's Root-field 2018-06-01 17:15:34 -03:00
Jeremiah Lowin
00ccc2056b Don't overwrite fields on InputObject - closes #720 2018-05-31 21:52:35 -04:00
Syrus Akbary
332214ba9c
Merge pull request #751 from nxtman123/issue#750
Resolve #750 by editing assert message
2018-05-30 18:08:17 -07:00
Kurtis Jantzen
d6a81ee7ff Update tests to reflect changes 2018-05-30 17:06:43 -06:00
Kurtis Jantzen
aa0c401cb5 Resolve #750 by editing assert message 2018-05-30 16:56:42 -06:00
Syrus Akbary
7bd77a0817
Merge pull request #748 from danpalmer/patch-2
Fix warning output
2018-05-30 09:35:03 -07:00
Dan Palmer
4e59cf3ea6
Fix warning output
Warning filtering is the responsibility of the application, not a library, and this current use causes all warnings from an application (at least those after this function is evaluated the first time) to print their contents.

This makes the library a better citizen in the Python ecosystem, and more closely matches what developers would expect.

(For what it's worth, we also can't start using this library without this patch because the logging is too verbose and may obscure more important warnings. We depend on being able to accurately control warning and logging output)
2018-05-30 14:50:22 +01:00
Dan
f13e54b4a4 Update contributing docs about using tox and sync tox pytest cmd with travis (#744)
* Update pytest command run by tox to match the command used by travis. Updated README contributing section with info about using tox to run tests.

* Uppercase 'Graphene'
2018-05-30 12:53:44 +01:00
Daniel Gallagher
05a362c9b5 Merge remote-tracking branch 'upstream/master' 2018-05-28 14:06:35 -07:00
Dan
a7168ffc6e Fix: Make tox stop failing (#741)
* Tox stopped working due to recent changes; add in necessary dependencies to tox.ini so it passes again

* Run pre-commit on all files

* Switch testenv deps to .[test] instead of an explicit list so the list of test deps in setup.py becomes the single source of truth for test deps.
2018-05-28 21:25:15 +01:00
Daniel Gallagher
a554b986af Merge remote-tracking branch 'upstream/master' 2018-05-28 12:26:02 -07:00
Dan
034b5385a5 Add isort precommit hook & run on all files (#743)
* Add isort and seed-isort-config pre-commit hook

* Fix erroneous isort moving comment to the top of file
2018-05-28 19:18:54 +01:00
Dan
4787cdc200
Merge pull request #1 from graphql-python/master
sync
2018-05-25 21:25:12 -07:00
Syrus Akbary
9f678fdfe8
Merge pull request #740 from jkimbo/release-2.1.1
Updated version to 2.1.1
2018-05-25 09:53:13 -07:00
Jonathan Kim
ec9526d0cd Updated version to 2.1.1 2018-05-25 17:17:20 +01:00
Nikordaris
034765aebe Added partial support to Dynamic type (#725) 2018-05-25 16:20:22 +01:00
Daniel Gallagher
013c9e5077 Update .travis.yml file to use tox as script for running tests 2018-05-24 23:33:32 -07:00
Syrus Akbary
28f6353212
Merge pull request #732 from femesq/patch-1
Migrations docs improvement
2018-05-24 19:20:33 -07:00
Syrus Akbary
4720f7743e
Merge pull request #730 from dan98765/add_pre_commit_tool_to_repo
Add pre-commit tool to repository, and run on all files
2018-05-24 19:18:10 -07:00
Felipe Mesquita
ead24a94c2
Update UPGRADE-v2.0.md
type correction
2018-05-23 20:20:55 -03:00
Felipe Mesquita
5d084cf2ea
Update UPGRADE-v2.0.md
Migration docs improvement
2018-05-23 20:13:03 -03:00
Daniel Gallagher
9777184721 Add pre-commit tool to repository, and run on all files 2018-05-22 10:56:58 -07:00
Mark Chackerian
de050fa6db fix linting error 2018-05-15 12:09:12 -04:00
Mark Chackerian
d40ef4be2b adds Decimal to types __all__ 2018-05-15 11:42:43 -04:00
Mark Chackerian
49258193ed adds decimal type and associated tests 2018-05-15 11:36:08 -04:00
Syrus Akbary
12d4dab774
Merge pull request #711 from devArtoria/master
add Graphene-Mongo to intergrations index of docs/index.rst
2018-04-19 20:12:27 -07:00
Lewis
7d998f0844
add Graphene-Mongo to intergrations list
The Graphene-Mongo integration is missing from the intergration index. So I added the Graphene-Mongo docs to the integration index.
2018-04-12 10:38:48 +09:00
Syrus Akbary
9408ba70d1 Fields default_value are no longer dismissed. Fixed #702. 2018-04-07 15:31:04 -07:00
Syrus Akbary
05d7e61b84 Updated version to 2.1.0 2018-03-29 22:38:51 -07:00
Syrus Akbary
d8aacc3b9e
Merge pull request #701 from graphql-python/feature/date-improvements
Datetime improvements
2018-03-29 22:35:28 -07:00
Syrus Akbary
50cd43c6e5 Added Date, DateTime and Time to global exports 2018-03-29 22:31:36 -07:00
Syrus Akbary
85e354c139 Merge branch 'master' into feature/date-improvements
# Conflicts:
#	graphene/types/datetime.py
2018-03-29 22:10:18 -07:00
Syrus Akbary
b4255e55fd Use aniso8601 instead of iso8601 2018-03-29 22:05:12 -07:00
Syrus Akbary
d46d8e8c33 Allow mutations to be required. Improved testing. Fixed #694 2018-03-21 21:31:56 -07:00
Syrus Akbary
562cafc14f Fixed str on abstract types. Improved repr 2018-03-21 21:21:03 -07:00
Syrus Akbary
415b71f730
Merge pull request #679 from anisjonischkeit/patch-1
Made DateTime types return GraphQLError on fail
2018-03-20 20:26:46 -07:00
Syrus Akbary
f4d1553d48
Merge pull request #692 from abawchen/fix-deprecations-url
Fix deprecations url
2018-03-20 20:24:06 -07:00
abawchen
a96ed550bd Fix deprecations url in DeprecationWarning message. 2018-03-20 08:14:59 +08:00
abawchen
dbc2ee4da9
Merge pull request #1 from graphql-python/master
Sync with original repo.
2018-03-20 07:30:53 +08:00
Syrus Akbary
2594cdb614 Fixed Meta included in Enum members. Fixed #685 2018-03-14 22:15:24 -07:00
Syrus Akbary
d6df14923d
Updated docs template 2018-03-13 22:37:36 -07:00
Anis Jonischkeit
9973fd314f added tests for when bad input is passed into date/datetime/time fields 2018-03-14 13:06:10 +10:00
Anis Jonischkeit
2a67ffeb35 fixed function name for test to be what it is actually testing and prevent name colision 2018-03-14 12:51:34 +10:00
Anis Jonischkeit
1a1efbd77d
linting: added two lines after end of class 2018-02-27 10:21:41 +10:00
Anis Jonischkeit
84fbf5dc23
Made DateTime types return GraphQLError on fail
This change makes it so that when an incorrectly formatted date string gets passed to a Date / Time argument a GraphQLError is returned rather than a GraphQLLocatedError. Since Date / Time are types, their errors should not be in the same class as errors in your application. This is also inline with how other types work in graphene (graphene.Int, graphene.Float)
2018-02-27 10:00:20 +10:00
Syrus Akbary
5df134e096
Merge pull request #675 from jkimbo/fix-type-in-example
Fix kwarg name in example. Fixes #533
2018-02-19 19:10:17 -08:00
Syrus Akbary
c5ce04f31e
Merge pull request #676 from jkimbo/exclude-examples-module
Exclude examples module in setup.py
2018-02-19 19:10:08 -08:00
Jonathan Kim
79f7cc08e3 Exclude examples module in setup.py
Fixes #608
2018-02-18 17:21:19 +00:00
Jonathan Kim
d3b708533d Fix kwarg name in example. Fixes #533 2018-02-17 23:28:33 +00:00
Syrus Akbary
8c7ca74c6f
Merge pull request #673 from jkimbo/relay-connection-required
Fix bug when setting a Relay ConnectionField to be required
2018-02-17 14:06:39 -08:00
Jonathan Kim
c25bcb3345 Move NonNull check 2018-02-17 21:50:40 +00:00
Jonathan Kim
38baf7ab52 Handle relay connection field being required 2018-02-17 20:18:55 +00:00
Jonathan Kim
42c96a453f Added failing test 2018-02-17 20:18:49 +00:00
Syrus Akbary
0971a05b33 Improved support / assertion for graphql types in Schema 2018-02-09 10:49:08 -08:00
Syrus Akbary
a7a4ba62af
Enabled possibility of setting name, description or deprecation_reason in mutation Fields
Fixed  #634, $660 #626 and #593
2018-02-08 23:56:13 -08:00
Syrus Akbary
da0b2c6805
Merge pull request #661 from pjdelport/fix-GitHub-link-tags
Fix broken GitHub link tags: 2.0 -> v2.0.0
2018-02-07 19:45:27 -08:00
Syrus Akbary
4e5a49789b
Merge pull request #665 from pjdelport/patch-1
Update .gitignore for pytest 3.4+
2018-02-07 19:44:57 -08:00
Syrus Akbary
113cf8da38
Merge pull request #666 from pjdelport/patch-2
Tox: Add py36 to default envlist
2018-02-07 19:44:43 -08:00
Pi Delport
265719d11f
Tox: Add py36 to default envlist 2018-02-08 01:32:10 +02:00
Pi Delport
f4b21c7a75
Update .gitignore for pytest 3.4+
Pytest 3.4.0 changes the default cache directory from `.cache` to `.pytest_cache`.

Changelog: https://docs.pytest.org/en/latest/changelog.html#pytest-3-4-0-2018-01-30
2018-02-08 01:31:12 +02:00
Pi Delport
368a2a02fe (Fit line length < 120) 2018-02-08 01:26:27 +02:00
Syrus Akbary
c044b2431b
Merge pull request #664 from jkimbo/document-nonnull-list
Add documentation on NonNull lists
2018-02-07 13:58:26 -07:00
Jonathan Kim
e26c0a3717 Add documentation on NonNull lists 2018-02-07 12:06:29 -08:00
Pi Delport
4fa0df401a Fix broken GitHub link tags: 2.0 -> v2.0.0 2018-02-05 16:49:16 +02:00
Syrus Akbary
e94716d94a
Merge pull request #653 from dkleissa/master
Update middleware example to support introspection
2018-01-24 19:25:53 -08:00
Dean Kleissas
035ff7ef88 Update middleware example to support introspection
In the `timing_middleware` example, introspection queries will fail due to `Schema` and others not having `_meta` attributes. API will work and tests pass but introspection will fail, which can be quite confusing to the developer. Simple update makes sure the `root` variable has a `_meta` attribute before accessing it.
2018-01-24 16:48:14 -05:00
Syrus Akbary
a0fc843513
Merge pull request #641 from presencelearning/issue-610-connection-name
Allow ObjectType to set Connection name
2018-01-20 15:37:46 -08:00
Syrus Akbary
8123c4ad8f
Fix relay links. 2018-01-20 15:17:52 -08:00
Syrus Akbary
be1f7d72a4
Merge pull request #644 from frsv/issue-643_fields_capitalizes_incorrectly
Change .title method to .capitalize in to_camel_case() in str_convertes.py
2018-01-11 11:43:10 -08:00
Roman Fursov
9dde259f54 Change .title method to .capitalize in to_camel_case in str_convertes.py 2018-01-10 17:25:15 +03:00
Brian Chapman
a2178dc220 Allow ObjectType to set Connection name 2018-01-08 09:16:02 -08:00
Syrus Akbary
38db32e4f2
Merge pull request #630 from dfee/425-extended
extended support for subclassing with meta to Enum and InputObjectType
2017-12-26 17:50:13 +00:00
Syrus Akbary
25dab925ee
Merge pull request #629 from simonwoerpel/master
Docs: fix typos in code-example for relay nodes
2017-12-23 10:17:31 -08:00
Syrus Akbary
94d5e345a1
Merge pull request #635 from jkimbo/error-missing-type
Raise better error if type is missing from schema
2017-12-23 10:17:06 -08:00
Jonathan Kim
d6968c2e92 Raise better error if type is missing from schema 2017-12-20 18:43:51 +00:00
Devin Fee
a16c5ba00b extended support for subclassing with meta to Enum and InputObjectType 2017-12-16 21:49:23 -08:00
Simon Wörpel
7afeaa052b
Docs: fix typos in example for relay nodes 2017-12-16 00:03:36 +01:00
Syrus Akbary
5036d164b7
Merge pull request #623 from jkimbo/scalar-documentation
[Docs] Scalar documentation
2017-12-10 12:54:54 -08:00
Jonathan Kim
0a6921d2d0 Add extra documentation on base scalars 2017-12-10 16:07:48 +01:00
Jonathan Kim
76f8a35916 Add documentation for scalar type arguments 2017-12-10 15:53:28 +01:00
Syrus Akbary
92f6a496c5
Merge pull request #622 from jkimbo/docs-middleware-update
[Docs] Functional middleware example
2017-12-09 17:41:48 -08:00
Jonathan Kim
502597c5a4 Format duration 2017-12-08 15:03:20 +00:00
Jonathan Kim
27745078bc Document functional middleware 2017-12-08 14:58:03 +00:00
Syrus Akbary
6c92e25ae8
Merge pull request #615 from Prince-Leto/patch-1
Added Date scalar to documentation
2017-12-01 12:14:15 -08:00
Grégoire Chauvet
98366c6add
Added Date scalar to documentation 2017-11-29 14:32:17 +01:00
Syrus Akbary
375d1f494b
Merge pull request #606 from g--/patch-1
Relay documentation reflects api changes in 2.0
2017-11-26 17:48:43 -08:00
Syrus Akbary
e19e229710
Merge pull request #611 from danpalmer/patch-1
Use more Pythonic terminology here
2017-11-25 15:27:08 -08:00
Dan Palmer
834d52f9d3
Use more Pythonic terminology here
"Hash" in the Python world implies a cryptographic hash, or possibly a checksum. Here, I believe "hash" is being used to mean "hash map", which would be more commonly known in Python as a dictionary, or dict for short.
2017-11-25 12:51:53 +00:00
Geoff
ec32c252e7
Relay documentation reflects api changes in 2.0
Specifically, get_node_from_global_id.
2017-11-20 10:05:28 -05:00
Syrus Akbary
e71a52140a
Update __init__.py 2017-11-14 23:25:30 -08:00
Syrus Akbary
eb5108f81e Simplified inputobjecttype implementation+tests 2017-11-14 22:19:22 -08:00
Syrus Akbary
6dd9e5ff1f Merge branch 'master' into input-fixes 2017-11-14 22:08:56 -08:00
Syrus Akbary
f6697188ee Added tests for nested inputobjecttypes 2017-11-14 22:06:28 -08:00
Syrus Akbary
0fc7280154
Merge pull request #602 from freundallein/docs-unions-fix
fix unions.rst
2017-11-14 09:12:26 -08:00
Stan Zhavoronkov
3412dba31f
fix Unions.rst
fix Unions.rst docs (copy-paste sentence from interfaces.rst).
2017-11-14 13:04:47 +03:00
Nathaniel Parrish
b2151d62da Code cleanup 2017-11-07 09:10:41 -08:00
Nathaniel Parrish
9c27db7ed5 Handle complex input types 2017-11-07 09:06:36 -08:00
Nathaniel Parrish
b5abccb1dc Set all fields on input object types 2017-11-03 16:36:36 -07:00
Syrus Akbary
71d5b1d943
Merge pull request #587 from ekampf/feature/enum_docs_update
Improved docs for Enums
2017-11-02 22:00:23 -07:00
Syrus Akbary
3fe12ca611
Merge pull request #588 from ekampf/feature/doc_fix_middleware
Fix resolve arguments section according to 2.0 resolvers
2017-11-02 22:00:06 -07:00
Syrus Akbary
3ee94131ae Improved object container initialization. Fixed #585 2017-11-02 21:57:10 -07:00
Syrus Akbary
045d5fffbe Added Date type in datetime 2017-11-02 21:17:06 -07:00
Syrus Akbary
43cda1d46a Added extra test to objecttypes 2017-11-02 21:07:10 -07:00
Eran Kampf
1555c988e0 Fix resolve arguments section according to 2.0 resolvers 2017-10-30 14:31:20 -07:00
Eran Kampf
7f59a8fa7e Added docs 2017-10-30 13:05:02 -07:00
Syrus Akbary
f79eb57c06
Merge pull request #586 from ekampf/feature/enum_value_descriptions
Support from_enum description lambda
2017-10-30 11:18:42 -07:00
Eran Kampf
90272e5297 Increase test coverage 2017-10-30 10:31:13 -07:00
Eran Kampf
e1f8480b32 lint fix 2017-10-30 10:26:42 -07:00
Eran Kampf
16c80c173e Support from_enum description lambda 2017-10-30 10:24:36 -07:00
Syrus Akbary
a8a6555537
Merge pull request #584 from vpoulailleau/patch-1
fix documentation to access to the request in Django
2017-10-30 09:36:58 -07:00
Vincent Poulailleau
98c2af3fcc
fix access to the request in Django
With the current documentation, I get after execution:
"graphql.error.located_error.GraphQLLocatedError: name 'context' is not defined"

I don't get any error after the correction I made (I haven't yet tried to upload a file…)
2017-10-30 16:00:18 +01:00
Syrus Akbary
36a902fbfa
Merge pull request #581 from lucascosta/patch-1
Prevent requirement breaking changes
2017-10-28 10:44:31 -07:00
Syrus Akbary
05518a7615
Merge pull request #582 from varundey/patch-1
Fixed minor grammatical error
2017-10-28 10:43:58 -07:00
Varun Dey
ef507c7932 Fixed minor grammatical error 2017-10-27 15:58:32 +05:30
Lucas Costa
71177fe977 Prevent requirement breaking changes
I have a project still in 1.2.0 thats has been broken in my last release since it used `'graphql-core>=1.0.1'` in the `install_requires`. Since `graphql-core` has released version 2.0 with breaking changes and there was no instruction to maintain version 1, it was included as a dependency. This prevents this situation for the future.
2017-10-26 16:21:19 -02:00
Syrus Akbary
34d03a7bd2 Updated docs to use stable version of Graphene 2.0 2017-10-26 00:22:59 -07:00
Syrus Akbary
d65e431619 Bump Graphene to 2.0 🎉 2017-10-25 10:40:58 -07:00
Syrus Akbary
e405cea361 Use stable versions of graphql-core 2017-10-25 10:31:28 -07:00
Syrus Akbary
afcad8a8f0 Commented pypy until is stable on travis 2017-10-25 10:27:50 -07:00
Syrus Akbary
fcef703eb5 Fixed flake8 issues 2017-10-25 10:27:50 -07:00
Syrus Akbary
c38ffa5ffd Update setup.py 2017-10-14 12:16:09 +02:00
Syrus Akbary
88111610fb Fixed pytest requirements 2017-10-14 12:11:18 +02:00
Syrus Akbary
3ce6031192 Fixed pypy tests 2017-10-09 12:01:37 +02:00
Syrus Akbary
7b08dbd2a1 Merge pull request #560 from nikolas/patch-1
quickstart: use print function in example query
2017-10-05 11:38:06 +02:00
Syrus Akbary
9c10649045 Merge pull request #561 from frankier/add-union-types-index
Add unions doc to index
2017-10-05 11:37:53 +02:00
Frankie Robertson
a1bc7377bd Add unions doc to index 2017-10-05 11:50:09 +03:00
Nik Nyby
37fbbf55fa quickstart: use print function in example query 2017-10-04 23:09:18 -04:00
Syrus Akbary
2cc701f444 Improved is_node checks 2017-09-06 17:51:09 -07:00
Syrus Akbary
bb6dc43d4b Merge pull request #539 from daxlab/patch-1
fix typo in Enum docs
2017-09-03 14:49:28 -07:00
Mandeep Singh
b34b3091d4 fix typo in Enum docs 2017-09-03 20:38:06 +05:30
Syrus Akbary
ab5a11b399 Fixed Argument comparison. Fixed #530 2017-08-29 20:21:17 -07:00
Syrus Akbary
f68682e153 Improved mutation examples 2017-08-29 19:53:24 -07:00
Syrus Akbary
7455063728 Fixed mutation docs (adding missing info arg in mutate) 2017-08-29 09:26:20 -07:00
Syrus Akbary
1d52148b37 Update quickstart.rst 2017-08-27 16:06:35 -07:00
Syrus Akbary
0b92d3dba6 Merge pull request #500 from graphql-python/2.0
[WIP] Road to 2.0
2017-08-27 13:27:12 -07:00
Syrus Akbary
7eb3ab5747 Fixed Flake8 issues 2017-08-07 20:59:48 -07:00
Syrus Akbary
4585469425 Fixed travis 2017-08-07 20:55:05 -07:00
Syrus Akbary
7cfec55410 Added mypy static checking 2017-08-07 20:48:26 -07:00
Syrus Akbary
19bf9b3713 Update UPGRADE-v2.0.md 2017-08-07 12:28:18 -07:00
Syrus Akbary
1e20e2bff3 Update UPGRADE-v2.0.md 2017-08-07 12:27:23 -07:00
Syrus Akbary
48754046b2 Update UPGRADE-v2.0.md 2017-08-07 12:24:17 -07:00
Syrus Akbary
066e7bab05 Merge pull request #517 from picturedots/patch-1
minor spelling and grammar changes UPGRADE-v2.0.md
2017-08-03 18:14:43 -07:00
picturedots
8826d72ada minor spelling and grammar changes UPGRADE-v2.0.md 2017-08-03 15:20:11 -04:00
Syrus Akbary
0a97deaa4d Improved relay coverage 2017-08-01 23:55:39 -07:00
Syrus Akbary
7e901f83ae Improved test coverage 2017-08-01 23:39:27 -07:00
Syrus Akbary
eff882e5a5 Fixed snapshot 2017-08-01 23:12:21 -07:00
Syrus Akbary
7f33fbe638 Fixed field source tests 2017-08-01 15:24:31 -07:00
Syrus Akbary
10a3e86cc5 Fixed mutation payload name and added tests for covering it. 2017-08-01 15:24:22 -07:00
Syrus Akbary
d8fac58701 Fixed source resolver and added tests for it 2017-08-01 13:59:18 -07:00
Syrus Akbary
81018268aa Added support for wheel distributions. Fixed #505 2017-07-31 22:30:13 -07:00
Syrus Akbary
a4bcb94958 Merge pull request #514 from graphql-python/2.0-newresolvers
Use the new resolvers API
2017-07-31 22:19:16 -07:00
Syrus Akbary
3a83671669 Merge branch '2.0' into 2.0-newresolvers 2017-07-31 22:19:11 -07:00
Syrus Akbary
7f1c2a654b Fixed benchmark tests 2017-07-31 22:15:26 -07:00
Syrus Akbary
602d8866bb Updated graphql-core version 2017-07-31 22:08:05 -07:00
Syrus Akbary
6a85507325 Improved get_node API 2017-07-27 20:06:48 -07:00
Syrus Akbary
0002d42e38 Updated docs 2017-07-27 03:05:58 -07:00
Syrus Akbary
394a1beb07 Updated resolver api 2017-07-27 02:55:25 -07:00
Syrus Akbary
d85a4e4874 Update UPGRADE-v2.0.md 2017-07-27 00:13:12 -07:00
Syrus Akbary
586ea56693 Update UPGRADE-v2.0.md 2017-07-27 00:10:50 -07:00
Syrus Akbary
6ae9e51320 Update UPGRADE-v2.0.md 2017-07-27 00:10:22 -07:00
Syrus Akbary
66390554d9 Improved resolver consistency 2017-07-26 23:14:32 -07:00
Syrus Akbary
e6b0cbb3bc Merge branch 'master' into 2.0 2017-07-26 22:46:26 -07:00
Syrus Akbary
a56d5d9f77 Added union docs. Fixed #493 2017-07-26 22:43:22 -07:00
Syrus Akbary
fa512cfa50 Improved mutation docs 2017-07-26 22:36:27 -07:00
Syrus Akbary
5c58d9e686 Fixed lazy type instant resolved with NonNull. Fixed #494 2017-07-26 22:32:37 -07:00
Syrus Akbary
f3bdd7de69 Improved upgrade example. Fixed #509 2017-07-26 20:12:15 -07:00
Syrus Akbary
719acc6771 Update UPGRADE-v2.0.md 2017-07-26 20:08:30 -07:00
Syrus Akbary
711a096ec6 Update UPGRADE-v2.0.md 2017-07-26 20:08:11 -07:00
Syrus Akbary
6dde81ee65 Improved Mutation warning 2017-07-26 19:44:17 -07:00
Syrus Akbary
c7c611266b Allow types to be abstract 2017-07-26 19:26:54 -07:00
Syrus Akbary
e71b59a8c3 Fixed flake8 issues in mutation 2017-07-24 23:15:56 -07:00
Syrus Akbary
5696c5af4f Added UUID docs 2017-07-24 23:15:47 -07:00
Syrus Akbary
eabb9b202c Added UUID type 2017-07-24 23:09:59 -07:00
Syrus Akbary
ed4bcce0cf Improved Relay Mutation 2017-07-24 23:09:52 -07:00
Syrus Akbary
7ca5c2225f Added create_type. Support for Meta as dict 2017-07-24 21:33:08 -07:00
Syrus Akbary
33a30db5f1 Improved quickstart docs 2017-07-24 00:01:44 -07:00
Syrus Akbary
dba6256578 Changed version to 2.0.dev 2017-07-23 23:43:08 -07:00
Syrus Akbary
df58b9a48b Remove _is_annotated flag from annotate decorator 2017-07-23 23:30:56 -07:00
Syrus Akbary
0e355ee296 Improved documentation examples 2017-07-23 23:29:27 -07:00
Syrus Akbary
9769612a44 Make resolvers simple again 2017-07-23 23:10:15 -07:00
Syrus Akbary
800fbdf820 Use dev version of graphql-core and promise 2017-07-23 21:47:23 -07:00
Syrus Akbary
40a15bdd21 Improved test coverage 2017-07-23 20:56:00 -07:00
Syrus Akbary
66468e3ea5 Improved Upgrade guide 2017-07-23 20:29:35 -07:00
Syrus Akbary
907a3d9915 Fixed Python 3.5 issues 2017-07-23 19:43:58 -07:00
Syrus Akbary
6c4f4624e3 Fixed Python 2/3 issues and flake syntax issues 2017-07-23 19:30:13 -07:00
Syrus Akbary
f8561fa5c4 Fixed travis 2017-07-23 19:20:19 -07:00
Syrus Akbary
8c3a933bd9 Fixed test 425 url 2017-07-23 19:18:29 -07:00
Syrus Akbary
287a7a814d Added package test requirements into travis excluding setup 2017-07-23 19:15:51 -07:00
Syrus Akbary
85d3145862 Improved abstract type 2017-07-23 19:13:33 -07:00
Syrus Akbary
8bac3dc9e5 Use latest graphql-core and promise lib 2017-07-23 19:02:41 -07:00
Syrus Akbary
6ae9717415 Improved automatic resolver args from annotations 2017-07-23 18:57:17 -07:00
Syrus Akbary
fb4b4df500 Added auto resolver function 2017-07-23 17:55:26 -07:00
Syrus Akbary
b185f4cae7 Improved mutation with thenable check 2017-07-23 17:36:20 -07:00
Syrus Akbary
b892eee0ae Removed unnecessary files 2017-07-23 17:22:12 -07:00
Syrus Akbary
d2f1024d81 Added annotated resolver and context 2017-07-23 17:19:45 -07:00
Syrus Akbary
f7fdc9aa3d Initial version of function annotations 2017-07-23 16:08:48 -07:00
Syrus Akbary
26686da30e Added inputobjecttype containers 2017-07-23 15:17:10 -07:00
Syrus Akbary
8ff3380291 Removed testing in Python 3.4 and start testing in 3.6 2017-07-12 21:58:05 -07:00
Syrus Akbary
ec5697b185 Fixed Connection side effects and add into breaking changes. 2017-07-12 21:53:35 -07:00
Syrus Akbary
f1624af08a Fixed Flake issues 2017-07-12 21:45:06 -07:00
Syrus Akbary
3fbc3281a2 Fixed Python 3.5 issues with Enum 2017-07-12 21:41:57 -07:00
Syrus Akbary
6321c52bd2 Fixed Connection tests 2017-07-12 21:21:16 -07:00
Syrus Akbary
557ec44a13 Merge pull request #502 from Thibaut-Fatus/patch-1
Doc was missing for using variables in queries
2017-07-12 10:36:54 -07:00
Thibaut Fatus
c155b7a56e Doc was missing for using variables in queries
added an example
2017-07-12 18:52:46 +02:00
Syrus Akbary
a023aeba62 Simplified Node type 2017-07-12 01:58:32 -07:00
Syrus Akbary
7a6d741531 Fixed relay ClientIDMutation 2017-07-12 01:36:44 -07:00
Syrus Akbary
4820a7fede Improved Mutation 2017-07-12 00:33:50 -07:00
Syrus Akbary
563ca23d00 Make init_subclass work in Python 3.5 2017-07-12 00:04:37 -07:00
Syrus Akbary
e38007868e Fixed upgrade doc title 2017-07-11 23:52:24 -07:00
Syrus Akbary
58b04dfcf5 Updated Readme docs 2017-07-11 23:10:02 -07:00
Syrus Akbary
28c987bdd1 Improved docs for extending Option attrs 2017-07-11 23:07:20 -07:00
Syrus Akbary
e86f73d30c Added class arguments example for Python 3 2017-07-11 22:52:58 -07:00
Syrus Akbary
9ce1288e12 Improved Enum implementation 2017-07-11 22:33:30 -07:00
Syrus Akbary
3604c8f172 Improved mutation class 2017-07-11 21:43:25 -07:00
Syrus Akbary
858343a8f6 Removed unused functions 2017-07-11 21:33:03 -07:00
Syrus Akbary
02c203f748 Simplified Union implementation 2017-07-11 21:31:38 -07:00
Syrus Akbary
b78b8c4134 Removed unused code 2017-07-11 21:27:20 -07:00
Syrus Akbary
f0edcb224a Removed AbstractType 2017-07-11 21:23:39 -07:00
Syrus Akbary
2d557d6ed7 Simplified mutation 2017-07-11 21:16:41 -07:00
Syrus Akbary
d8b42dd1ca Simplified InputObjectType 2017-07-11 20:59:44 -07:00
Syrus Akbary
5ee6e2b8e7 Simplified Scalar 2017-07-11 20:59:02 -07:00
Syrus Akbary
e487206818 Simplified ObjectType logic 2017-07-11 20:53:49 -07:00
Syrus Akbary
c98d91ba1c Simplified Interface code 2017-07-11 20:33:03 -07:00
Syrus Akbary
3e62fcf0cc Merge pull request #498 from XatMassacrE/master
Fix doc typo
2017-07-10 21:33:40 -07:00
XatMassacrE
dc5de1f503 Fix doc typo 2017-07-11 11:08:39 +08:00
XatMassacrE
93fc03d9e0 Fix doc typo 2017-07-11 10:27:36 +08:00
Syrus Akbary
f22504c2fc Improved Mutation with custom Field and output 2017-06-29 23:46:58 -07:00
Syrus Akbary
078230ad49 Updated version to 1.4.1 2017-06-27 22:00:56 -07:00
Syrus Akbary
985252920c Fixed argument output name. Fixed #490 2017-06-24 12:46:51 -07:00
Syrus Akbary
c41b183fad Fixed lint in graphene.test 2017-06-24 12:24:20 -07:00
Syrus Akbary
6c2b940a03 Improved ClientIDMutation tests for thenables 2017-06-24 12:23:56 -07:00
Syrus Akbary
645bfddfe9 Improved Test Framework to support promises as returned GraphQL execution 2017-06-16 11:09:36 -07:00
Syrus Akbary
fccc22b651 Merge pull request #467 from affablebloke/master
Added type consistency between Field and Argument
2017-06-05 19:44:34 -07:00
Syrus Akbary
8622989da9 Merge pull request #471 from vincentfretin/patch-1
Fix typo Grapehne -> Graphene
2017-05-23 21:49:47 -07:00
Syrus Akbary
ba04abfea8 Merge pull request #475 from pmlandwehr/patch-1
Include license in manifest for source bundles
2017-05-22 16:21:52 -07:00
Peter M. Landwehr
d7dff53f46 Include license in manifest for source bundles 2017-05-22 16:18:33 -07:00
Vincent Fretin
9d30136095 Fix typo Grapehne -> Graphene 2017-05-17 11:05:53 +02:00
Syrus Akbary
cb0adcb0fe Merge pull request #470 from ryanashcraft/patch-1
Fix typo in dataloader docs
2017-05-16 21:00:47 -07:00
Ryan Ashcraft
0a9dbb608a Fix typo in dataloader docs 2017-05-15 19:06:23 -07:00
Daniel Johnston
83857bfcfe Fixed typo. 2017-05-05 14:38:46 -07:00
Daniel Johnston
388253ede4 Added type consistency. 2017-05-05 14:27:46 -07:00
Daniel Johnston
7642644d82 Removed white space. 2017-05-05 14:23:51 -07:00
Daniel Johnston
59f4ddcd94 Removed white space. 2017-05-05 14:23:21 -07:00
Syrus Akbary
606575a2b0 Merge pull request #465 from ryanwilsonperkin/patch-1
Update UPGRADE-v1.0.md
2017-05-03 11:24:58 -07:00
Ryan Wilson-Perkin
b5d15b635e Update UPGRADE-v1.0.md
Hoping to help out by fixing a few small grammatical mistakes. Thanks for the upgrade guide!
2017-05-03 10:58:56 -04:00
Syrus Akbary
23e028fe72 Merge pull request #460 from yixizhang/typo
fix typo in docs/execution
2017-04-26 23:58:17 -07:00
Syrus Akbary
342b3a703a Merge pull request #459 from MikeTYChen/update-relay-doc-link
Update Relay Documentation Link
2017-04-26 23:58:05 -07:00
Yixi Zhang
bad6f5a188 fix typo in docs/execution 2017-04-26 16:27:44 -07:00
Michael Chen
5052536787 Update Relay Documentation Link
Update the link of Relay Specification to Facebook Relay Specifications
2017-04-26 11:45:36 -07:00
Syrus Akbary
8cae7bd16f Updated version to 1.4.0 2017-04-20 00:55:13 -07:00
Syrus Akbary
082186c169 Added dataloader docs 2017-04-20 00:53:17 -07:00
Syrus Akbary
b71a2cb69e Fixed middleware docs to use whitespaces instead of tabs 2017-04-20 00:34:05 -07:00
Syrus Akbary
bd754c1989 Updated dependencies: use promise 2.0 and graphql-core 1.1 2017-04-18 22:55:29 -07:00
Syrus Akbary
a7511d3a2c Added possible_types option to ObjectType.Meta 2017-04-14 22:32:12 -07:00
Syrus Akbary
e3663d41ce Merge pull request #452 from khankuan/patch-1
Update basic schema with arguments
2017-04-13 11:33:53 -07:00
Kuan
06757f10c6 Update basic schema with arguments 2017-04-13 10:32:49 -07:00
Syrus Akbary
b8323ed8e7 Merge pull request #446 from graphql-python/features/improved-enums
Improved enums comparison and getters
2017-04-12 23:26:52 -07:00
Syrus Akbary
e92b03bed5 Allow Node inner types to be lazy. Fixed #437 2017-04-12 23:23:44 -07:00
Syrus Akbary
5f71ac7d41 Merge pull request #449 from graphql-python/features/test-client-and-snapshot-testing
First version of the Graphene test client and snapshots 💪
2017-04-11 21:54:41 -07:00
Syrus Akbary
6c040e68a2 Fixed six import 2017-04-10 16:18:52 -07:00
Syrus Akbary
038f81e8e1 Added extra parameters section in testing docs
@BossGrand 😉
2017-04-10 16:18:45 -07:00
Syrus Akbary
917dc16ea6 Fixed format_error 2017-04-10 16:10:35 -07:00
Syrus Akbary
b369ccfa08 Updated snapshot files 2017-04-10 04:26:54 -07:00
Syrus Akbary
60e29028a8 Added testing docs 2017-04-10 00:48:06 -07:00
Syrus Akbary
dfcd7f2563 First version of the Graphene test client and snapshots 💪 2017-04-09 21:08:35 -07:00
Syrus Akbary
afed25a180 Improved enums comparison and getters. Fixed #444 2017-04-07 22:02:16 -07:00
Syrus Akbary
aaf9e92d24 Updated version to 1.3.0 💪 2017-04-06 22:20:56 -07:00
Syrus Akbary
4b71465922 Improved lazy types support in Graphene
This commit also adds support for string types in Field, InputField, List and NonNull, where the string will be import. Usage like: Field("graphene.String")
2017-04-06 22:13:06 -07:00
Syrus Akbary
bd0d418986 Fixed promisify 2017-04-05 16:27:17 -07:00
Syrus Akbary
d594a0eca8 Merge pull request #442 from blakegong/features/add-dotted-arguments-for-lazy-import
Improve lazy_import() to accept dotted_attributes
2017-03-25 12:15:46 -07:00
Yue Gong
3822d6568e Update module_loading documents 2017-03-25 17:59:01 +08:00
Yue Gong
087f1c55cd Improve lazy_import() to accept dotted_attributes 2017-03-25 17:41:47 +08:00
Syrus Akbary
d4d8a76a09 Fixed circular union. Fixed #439 2017-03-24 22:40:16 -07:00
Syrus Akbary
a837fb6836 Merge pull request #434 from gbezyuk/patch-1
a fypo fixed so the hyperlink to the graphQL official introduction is…
2017-03-10 02:17:08 -08:00
Grigoriy Beziuk
d86bbd8a86 a fypo fixed so the hyperlink to the graphQL official introduction is shown now 2017-03-10 11:05:01 +03:00
Syrus Akbary
360d5cfac5 Fixed test instructions 2017-03-04 18:17:53 -08:00
Syrus Akbary
48efec307c Improved Options merge attrs. Fixed #432 2017-03-04 18:13:16 -08:00
Syrus Akbary
d5960a7630 Merge pull request #427 from nattyait/requirements
Add Sphinx to requirements for building graphene docs
2017-03-01 09:41:27 -08:00
Syrus Akbary
5e7002ce76 Merge pull request #429 from ryanwilsonperkin/patch-1
Spelling/Grammar fixes in docs
2017-03-01 09:40:54 -08:00
Syrus Akbary
c3ad42564a Merge pull request #428 from chappers/master
Fixed indent in mutation docs
2017-03-01 09:40:32 -08:00
Ryan Wilson-Perkin
313a004141 Spelling/Grammar fixes in docs
Hi, thanks for writing these docs! I'm reading through them and hoping to give back by fixing up some spelling and grammatical issues.
2017-03-01 09:30:39 -05:00
Chapman Siu
3a198d052a fixed indent in mutation docs 2017-03-01 22:54:06 +11:00
nattyait
e405a20e3d Add Sphinx to requirements for building graphene docs 2017-03-01 16:11:04 +07:00
Syrus Akbary
ad251e9a8d Fix ObjectType special types. Fix #425 2017-02-26 21:09:21 -08:00
Syrus Akbary
98825fa4bc Added optional default_resolver to ObjectType. 2017-02-24 00:02:36 -08:00
Syrus Akbary
62e58bd953 Merge pull request #419 from yen223/fix-docstring-whitespace
Fix docstring whitespace
2017-02-22 19:52:21 -08:00
Syrus Akbary
215d131d2f Merge pull request #421 from helfer/patch-2
Fix typo
2017-02-22 10:43:59 -08:00
Jonas Helfer
47bb5292fa Fix typo 2017-02-22 10:42:12 -08:00
Wei Yen
c592e94f73 Use trim_docstring to ensure description has no leading whitespace 2017-02-22 07:03:30 +11:00
Wei Yen
0dc8e57c50 Implement trim_docstring
Thin wrapper around `inspect.clean_doc`
2017-02-22 07:03:30 +11:00
Wei Yen
d1d87221d5 Regression test to ensure docstring is trimmed
Related to issue #418
2017-02-22 06:55:47 +11:00
Syrus Akbary
e2cdd80a5c Added docs for List and NonNull types. Fixed #326 2017-02-20 22:44:27 -08:00
Syrus Akbary
81a2ed0bfe Updated graphene version to 1.2.0 2017-02-20 22:28:42 -08:00
Syrus Akbary
11bed46a26 Renamed Generic to GenericScalar 2017-02-20 22:22:54 -08:00
Syrus Akbary
8b0cd488d4 Improved Mutation docs. Fixed #402 2017-02-20 22:12:55 -08:00
Syrus Akbary
1a52cf9a3d Fixed lint 2017-02-20 21:59:38 -08:00
Syrus Akbary
b5cc0a81da Improved scalar docs. Fixed #394 2017-02-20 21:57:39 -08:00
Syrus Akbary
74400642ed Added lazy_import to graphene. Fixed #316 2017-02-20 21:57:04 -08:00
Syrus Akbary
0e2d9be6a8 Fixed test schema with empty query. Fixed #409 2017-02-20 21:41:11 -08:00
Syrus Akbary
ba29de5670 Improved assertion messages. Fixed #400 2017-02-20 21:26:47 -08:00
Syrus Akbary
51b72d8dc8 Renamed from JSON to Generic
As it's implementation is abstract of the serializer/unserializer used.
2017-02-20 02:54:54 -08:00
Syrus Akbary
2044d29edb Merge pull request #387 from hung-phan/master
Implement JSON type
2017-02-20 02:51:10 -08:00
Syrus Akbary
2f87698a0b Improved TypeMap and Dynamic Field to optionally include the schema 2017-02-20 02:35:30 -08:00
Syrus Akbary
ecb1edd5c2 Improved Docs 2017-02-18 12:50:58 -08:00
Syrus Akbary
52e68cf23e Merge pull request #415 from helfer/patch-1
Update README.md
2017-02-18 12:45:15 -08:00
Jonas Helfer
81c1cf3d61 Update README.md
Mention that Graphene works great with both Relay and Apollo
2017-02-15 20:59:56 -08:00
Syrus Akbary
8dff91d4c6 Fix typos in Node docs. 2017-02-08 08:21:14 -08:00
Syrus Akbary
e8fc58afd6 Improved Node get_node_from_global_id
This introduces a breaking changes for custom Nodes implementations
2017-02-07 22:35:03 -08:00
Syrus Akbary
256c84a9a5 Added test extra requirements 2017-02-07 21:54:50 -08:00
Syrus Akbary
8f373ccec3 Update mutations.rst 2017-02-06 19:48:09 -08:00
Syrus Akbary
eb1ded2a65 Merge pull request #412 from BossGrand/master
Added documentation on how to accept files in a mutation
2017-02-06 19:43:55 -08:00
Charles Haro
0ed4050bb6 fixed typo 2017-02-06 17:19:02 -08:00
BossGrand
b9d3abee31 fixed a few documentation bugs
there was a warning of header underline not being long enough

and code type graphql was being used intead of json
2017-02-06 17:14:07 -08:00
BossGrand
1232ff3ee1 Added documentation on how to accept files in a mutation 2017-02-06 11:40:04 -08:00
Syrus Akbary
a3c3be26f4 Merge pull request #410 from docmatrix/feature/source-method
Allow class methods to be used as a field source
2017-01-28 11:37:51 -08:00
James Pollock
f728542ce7 Allow class methods to be used as a field source 2017-01-27 21:17:49 +00:00
Syrus Akbary
02eb6856ed Merge pull request #406 from kelvintaywl/fix-small-readme-typo
small grammar fix on readme
2017-01-22 09:37:24 -08:00
Kelvin Tay
888348bd94 small grammar fix on readme 2017-01-22 17:46:31 +09:00
Syrus Akbary
2ef0e23dcf Set unions as unmounted types 2017-01-14 21:27:01 -08:00
Syrus Akbary
a749d02663 Fixed mutations Input code. Fixed #398 2017-01-10 15:45:32 +01:00
Syrus Akbary
573101fc90 Renamed from MountedType.mount to MuntedType.mounted 2016-12-18 14:03:03 -08:00
Syrus Akbary
dda3237e0a Merge pull request #318 from ksonj/master
Fixed typos and improved language and markup
2016-12-18 13:17:32 -08:00
Syrus Akbary
dda294d911 Merge branch 'master' into master 2016-12-18 13:12:51 -08:00
Syrus Akbary
edd090efde Added Mounted type tests 2016-12-17 17:17:32 -08:00
Syrus Akbary
27cd00b9f9 Merge pull request #391 from graphql-python/features/mounted-refactor
Refactored mounted types logic
2016-12-17 16:29:44 -08:00
Syrus Akbary
93dacda923 Refactored mounted types logic 2016-12-17 16:25:49 -08:00
Syrus Akbary
7e5285d859 Merge pull request #381 from riddlesio/master
fix so partial functions can be passed to field, solves issue #316
2016-12-13 21:25:21 -08:00
hung-phan
17ea139ce4 Update test 2016-12-08 17:50:36 +00:00
hung-phan
c200a088c0 Add None case 2016-12-08 17:47:33 +00:00
hung-phan
a74c402f13 Implement JSON type
Remove duplicated test

Remove unicode for python 3

Add more tests

Add None case

Update json type

Remove unnecessary dependencies

Add more test

Add test
2016-12-08 17:45:15 +00:00
Jim van Eeden
774e9bf463 fix so partial functions can be passed to field, solves issue #316 2016-12-02 15:35:43 +01:00
Syrus Akbary
da3683028e Updated external dependencies 2016-12-01 21:18:37 -08:00
Syrus Akbary
4a31c5a927 Updated version to 1.1.3 2016-12-01 21:10:55 -08:00
Syrus Akbary
80a809216b Removed unused Promise import 2016-12-01 21:07:58 -08:00
Syrus Akbary
3df62d26a7 Fixed coroutines as relay connection resolvers
Related PR #379
2016-12-01 21:05:09 -08:00
Syrus Akbary
51c37fef98 Merge pull request #373 from pizzapanther/master
add time query variable test
2016-11-23 08:26:31 -08:00
Paul Bailey
20ca84966e add time query variable test 2016-11-23 11:23:56 -05:00
Paul Bailey
4653a0e5df add time query variable test 2016-11-23 11:19:24 -05:00
Syrus Akbary
692d7e76ad Merge pull request #372 from pizzapanther/master
Added Time Type
2016-11-23 08:18:53 -08:00
Paul Bailey
ad83a7e076 add time query test 2016-11-23 11:14:49 -05:00
Paul Bailey
48b422e289 add time query test 2016-11-23 11:12:28 -05:00
Syrus Akbary
a8bb6ae348 Updated version to 1.1.2 2016-11-22 23:41:59 -08:00
Syrus Akbary
5e0923b560 Added type getter in the schema when accessing its attrs 2016-11-22 23:34:52 -08:00
Syrus Akbary
df2900e215 Removed schema.register 2016-11-22 23:08:28 -08:00
Syrus Akbary
cf8792ef9e Improved Typemap importing 2016-11-22 23:07:11 -08:00
Syrus Akbary
7c57d71e84 Added a test case for covering InputObjectType as Argument 2016-11-22 22:35:24 -08:00
Paul Bailey
f089c78b99 added time type 2016-11-22 18:08:48 -05:00
Paul Bailey
dddb20a0f4 added time type 2016-11-22 18:04:22 -05:00
Syrus Akbary
5cfa895881 Merge pull request #370 from sangheestyle/patch-1
fixed: wrong example for interface
2016-11-21 09:21:25 -08:00
SangHee Kim
11996e9121 fixed: wrong example for interface 2016-11-21 11:41:35 -05:00
Syrus Akbary
67c0872c9f Updated version to 1.1.1 2016-11-15 22:41:10 -08:00
Syrus Akbary
6817761a08 Fixed Union and Interface resolve_type when the field is a List/NonNull 2016-11-15 22:31:46 -08:00
Syrus Akbary
3c99302ed6 Updated version to 1.1.0 2016-11-14 22:19:38 -08:00
Syrus Akbary
90e8e30a3a Added PyPI upload based on travis 2016-11-14 21:29:24 -08:00
Syrus Akbary
cc776e8def Added execution context example. Fixed #306 2016-11-14 20:49:33 -08:00
Syrus Akbary
bb7976a75f Improved ConnectionField exception message. Fixed #356 2016-11-14 20:28:06 -08:00
Syrus Akbary
0efee6be5d Fixed Union resolve_type. Fixed #313 2016-11-14 20:14:21 -08:00
Syrus Akbary
2e58f53f18 Improved List/NonNull of_type exceptions and tests. Fixed #337 2016-11-14 19:52:40 -08:00
Syrus Akbary
78a1b18e44 Improved docs for generating documentation. Fixed #353 2016-11-14 19:38:45 -08:00
Syrus Akbary
473f97c7b8 Improved messaging for Argument transformation. Fixed #364 2016-11-14 19:34:10 -08:00
Syrus Akbary
e26bbdd937 Merge pull request #362 from Globegitter/node-parent-type
Node parent type
2016-11-14 19:13:36 -08:00
Syrus Akbary
d8ab8fec34 Fixed lint errors 2016-11-14 19:10:32 -08:00
Syrus Akbary
815f7528c5 Merge pull request #365 from BossGrand/master
Added documentation for InputFields and InputObjectTypes usage
2016-11-14 17:54:58 -08:00
BossGrand
85cad0efc3 fixed typo in documentation 2016-11-14 17:50:41 -08:00
BossGrand
b179d012d7 Added documentation for InputFields and InputObjectTypes usage 2016-11-14 13:04:19 -08:00
Syrus Akbary
b1bffc4f8d Added context example 2016-11-11 19:40:23 -08:00
markus
09969355fa Added tests. 2016-11-10 11:10:49 +00:00
markus
c01a9b1843 Merge branch 'master' into node-parent-type 2016-11-10 10:55:15 +00:00
markus
8fa6d61271 Added optional parent type to allow usage of GlobalID in mutations. 2016-11-10 10:54:03 +00:00
Syrus Akbary
6c7cd4e4fa Merge pull request #360 from timothyjlaurent/#359-fix-index-error-on-enum-functions
Add test for _is_sunder and _is_dunder array.py functions.
2016-11-10 02:50:56 -08:00
Syrus Akbary
a22c9276e5 Merge pull request #361 from Globegitter/node-simplifications
Make node arg options and default required to True for GlobalID.
2016-11-10 02:49:35 -08:00
markus
0a79df3d13 Added tests for global id. 2016-11-10 10:46:34 +00:00
markus
5f7af3e43f Make node arg options and default required to True for GlobalID. 2016-11-10 10:00:59 +00:00
Timothy Laurent
a427a0fb18 Add test for _is_sunder and _is_dunder array.py functions. 2016-11-09 22:27:08 -08:00
Syrus Akbary
50eadde8b2 Merge pull request #357 from ekampf/patch-3
Fix typo in Union initialization exception
2016-11-08 14:22:42 -08:00
Eran Kampf
937e257d60 Fix typo in Union initialization exception 2016-11-08 13:42:59 -08:00
Syrus Akbary
4a4123e660 Merge pull request #355 from bcb/master
Add tox dependencies
2016-11-07 07:48:22 -08:00
Beau Barker
d1a9bdb5c3 Add tox dependencies
Tox fails without pytz, iso8601 and pytest-benchmark
2016-11-07 09:26:28 +11:00
Syrus Akbary
5bb028e3d7 Merge pull request #352 from ttz21/docs_update
Add link to official GraphQL docs in Getting Started
2016-11-05 08:48:33 -07:00
Tina Zhang
c1f567c4e4 add link to official graphql website in Getting Started 2016-11-05 15:31:56 +01:00
Syrus Akbary
3f0c01ed3c Merge pull request #350 from nvie/doc-fixes
Various little documentation fixes
2016-11-03 17:36:37 -07:00
Vincent Driessen
b2d7dfe546 Fix sentences to be more readable 2016-11-03 22:17:37 +01:00
Vincent Driessen
f5c5d33639 Fix import paths to match graphene>=1.0 paths 2016-11-03 22:08:41 +01:00
Syrus Akbary
adfbffb267 Added middleware docs 2016-10-31 05:32:59 +01:00
Syrus Akbary
9a3d84319d Merge pull request #342 from ekampf/feature/connection_edges_should_be_nonnull
Connection Edges should be NonNull
2016-10-28 12:44:27 +02:00
Eran Kampf
344d85c19e fix tests 2016-10-27 10:37:52 -07:00
Eran Kampf
495361ef53 Edges should be NonNull 2016-10-27 10:27:13 -07:00
Syrus Akbary
c7a48c3c2c Added connection promise tests 2016-10-27 02:48:36 +02:00
Syrus Akbary
0b9aa7cbeb Merge branch 'patch-11' 2016-10-27 02:42:05 +02:00
Syrus Akbary
760ccc8358 Improved Promise connection abstraction 2016-10-27 02:41:36 +02:00
Markus Padourek
16e9f221b5 added missing import 2016-10-26 10:52:46 +01:00
Markus Padourek
ea69be6117 Add support to return a promise for connections. 2016-10-26 10:50:27 +01:00
Syrus Akbary
ecdfed257c Improved Field coverage 2016-10-21 09:22:19 -07:00
Syrus Akbary
d7fded7d98 Improved Enum coverage 2016-10-21 09:19:13 -07:00
Syrus Akbary
e1e24327b0 Improved options testing and coverage 2016-10-21 09:12:28 -07:00
Syrus Akbary
24b85d318c Improved OrderedType coverage 2016-10-21 09:00:33 -07:00
Syrus Akbary
47d7adf7b0 Improved documentation in UnmountedTypes 2016-10-21 08:44:44 -07:00
Syrus Akbary
0a80119f5e Fixed Dynamic arguments 2016-10-16 13:14:08 -07:00
Syrus Akbary
f8e636db80 Merge pull request #324 from Globegitter/add-dynamic-tests
Added tests for dynamic field and make more consistent.
2016-10-16 12:54:21 -07:00
Syrus Akbary
5cce7deb34 Merge pull request #323 from Globegitter/patch-9
Improve `is_node` error message
2016-10-16 12:21:42 -07:00
Syrus Akbary
1f5c0fe7df Merge pull request #330 from wenley/wenley/nit-fix-documentation
Tweak the documentation to match behavior in the playground.
2016-10-16 12:17:51 -07:00
Wenley Tong
77e4ead0d7 Tweak the documentation to match behavior in the playground. 2016-10-16 11:34:10 -07:00
Markus Padourek
0408591141 Added additional tests. 2016-10-13 16:54:54 +01:00
Markus Padourek
822b030938 Added tests for dynamic field and make more consistent. 2016-10-13 14:47:43 +01:00
Markus Padourek
ef18eb5ce3 Improve is_node error message 2016-10-13 14:08:28 +01:00
Kalle Jepsen
71b4de9369 Fixed typos and improved language and markup 2016-10-07 12:23:12 +02:00
Syrus Akbary
88ccaec8fa Added jsonstring tests 2016-10-03 21:42:07 -07:00
Syrus Akbary
5dd92b7d6b Added datetime tests 2016-10-03 20:51:37 -07:00
Syrus Akbary
95280e4f7c Merge pull request #312 from mikhuang/patch-1
Update datetime.py
2016-10-03 20:31:00 -07:00
Syrus Akbary
fa231fb472 Updated version to 1.0.2 2016-10-03 20:12:11 -07:00
Syrus Akbary
999bca84c9 Fixed mutation with unbound mutate method. Fixed #311 2016-10-03 19:59:26 -07:00
Syrus Akbary
02a6c1c603 Isolated unbound function logic in utils 2016-10-03 19:59:01 -07:00
Michael Huang
9231e0d28d Update datetime.py
Restore ios8601 handling per https://github.com/graphql-python/graphene/pull/152/files
2016-10-03 19:07:16 -07:00
Syrus Akbary
c961f0b3c6 Fixed ConnectionField arguments overwritten. Fixed #252 2016-10-01 11:52:31 -07:00
Syrus Akbary
bd207b5f06 Improved arguments and structures comparison 2016-10-01 11:49:30 -07:00
Syrus Akbary
c792923429 Added ability to return a Connection instance in the connection resolver 2016-10-01 10:44:53 -07:00
Syrus Akbary
ad953f01a7 Updated version to 1.0.1 2016-09-29 01:58:14 -07:00
Syrus Akbary
71556031bf Removing is_type_of from docs 2016-09-29 01:42:32 -07:00
Syrus Akbary
8030fea443 Fixed flexible resolving in return type 2016-09-29 01:38:56 -07:00
Syrus Akbary
cdd4afb79a Update objecttypes.rst 2016-09-28 13:58:39 -07:00
Syrus Akbary
c9aa461c65 Fixed code 2016-09-28 13:58:05 -07:00
Syrus Akbary
c65d5a532a Updated docs reflecting static resolvers
(And a working example of is_type_of)
2016-09-28 13:57:41 -07:00
Syrus Akbary
69ad249619 Updated docs 2016-09-26 09:46:49 -07:00
Syrus Akbary
c920537380 Updated graphene to 1.0 🎉 2016-09-26 09:20:41 -07:00
Syrus Akbary
46cd025835 Updated docs theme 2016-09-26 00:45:23 -07:00
Syrus Akbary
c9a30f7139 Improved docs 2016-09-25 05:01:12 -07:00
Syrus Akbary
6bd03d59d7 Added clientMutationId field to relay.ClientIDMutation. Fixed #300 2016-09-21 19:06:47 -07:00
Syrus Akbary
8128292b02 Improved quickstart 2016-09-21 09:45:57 -07:00
Syrus Akbary
b72684192f Fixed tests. 2016-09-21 08:33:56 -07:00
Syrus Akbary
aa86c27ea2 Merge pull request #298 from Globegitter/default-resolver-default-value
Added default value for default resolver.
2016-09-21 01:58:33 -07:00
Markus Padourek
d9b8f5941d Added default value for default resolver. 2016-09-21 09:34:29 +01:00
Syrus Akbary
316569b019 Improved docs. Added schema page 2016-09-21 01:16:35 -07:00
Syrus Akbary
d8eeb65b5c Added inter docs 2016-09-21 00:51:57 -07:00
Syrus Akbary
fc43421e68 Removed docs layout 2016-09-21 00:20:40 -07:00
Syrus Akbary
0148401c06 Removed executor and middleware from the Schema. 2016-09-20 00:04:41 -07:00
Syrus Akbary
227d9422ff Fixed READMES. Fixed #296 2016-09-19 18:56:01 -07:00
Syrus Akbary
d112cc5988 Merge pull request #297 from sjhewitt/connection-node
relay Connection.node does not have to subclass Node/ObjectType
2016-09-19 14:36:43 -07:00
Simon Hewitt
a77b27987e re-add node class check 2016-09-19 14:21:00 -07:00
Simon Hewitt
87634240c9 relay Connection.node does not have to subclass Node/ObjectType 2016-09-19 14:13:01 -07:00
Syrus Akbary
f955280d1a Improved sorting/PEP8 syntax 2016-09-18 13:23:35 -07:00
Syrus Akbary
8fb4214809 Improved Field args 2016-09-18 13:21:02 -07:00
Syrus Akbary
2ed800bae3 Added string type upgrade to function 2016-09-18 13:14:52 -07:00
Syrus Akbary
51eb2e593f Merge pull request #294 from mwilliamson/patch-1
Clarify indentation in UPGRADE-v1.0.md
2016-09-18 09:22:13 -07:00
Michael Williamson
c9777fd16e Clarify indentation in UPGRADE-v1.0.md 2016-09-18 17:08:45 +01:00
Syrus Akbary
4610f85af8 Updated license 2016-09-17 22:04:03 -07:00
Syrus Akbary
5287758f0e Fixed Relay Connection name 2016-09-17 21:14:56 -07:00
Syrus Akbary
92b04225b2 Moved Graphene-Django and Graphene-SQLAlchemy to individual packages 2016-09-17 19:39:35 -07:00
Syrus Akbary
aa84d6d8db Improved objecttype typemap duplication 2016-09-17 12:05:05 -07:00
Syrus Akbary
061c33f8d6 Merge branch 'next-typemap-duplicate' 2016-09-17 12:02:41 -07:00
Syrus Akbary
9824ae48cf Updated layout 2016-09-17 11:46:01 -07:00
Syrus Akbary
84c8711f79 Improved documentation 2016-09-15 00:50:45 -07:00
Syrus Akbary
78ff67eb13 Improved Upgrade guide 2016-09-14 21:17:43 -07:00
Syrus Akbary
5c6971a608 Updated graphene readmes fixing graphene dev installation 2016-09-14 20:56:32 -07:00
Syrus Akbary
a2b6d3dd05 Merge branch 'master' of github.com:graphql-python/graphene 2016-09-13 20:47:50 -07:00
Syrus Akbary
b01137f53a Updated Upgrade guide 2016-09-13 20:40:16 -07:00
Syrus Akbary
8e320da051 Merge pull request #285 from Globegitter/edge-for-type
Added test for node connection edge.
2016-09-12 08:58:57 -07:00
Syrus Akbary
2fbf17a109 Merge pull request #286 from Globegitter/easier-private-state
Allow initialising ObjectType with private state.
2016-09-12 08:09:31 -07:00
Markus Padourek
2975e1fc42 Allow initialising ObjectType with private state. 2016-09-12 15:51:51 +01:00
Markus Padourek
aa94fe157e compare as dict for py3.5 compat. 2016-09-12 15:36:09 +01:00
Syrus Akbary
bb636b81c2 Merge pull request #284 from dialoguemd/fix-assert-message
Make assertion message use same var as test
2016-09-12 07:31:18 -07:00
Syrus Akbary
e504c7227e Merge pull request #281 from Globegitter/union-type-export
Export union type directly.
2016-09-12 07:28:39 -07:00
Markus Padourek
73945fb569 Added test for node connection edge. 2016-09-12 15:28:13 +01:00
Hugo Duncan
f232e433e6 Make assertion message use same var as test
Ensure that the assertion message correctly shows the value used by
the assertion test.
2016-09-12 10:06:35 -04:00
Markus Padourek
3888307f89 Added GlobalID as well. 2016-09-12 09:31:22 +01:00
Markus Padourek
c15ce93542 Export union type directly. 2016-09-12 09:25:38 +01:00
Syrus Akbary
94d46f7960 Fixed rtd docs generation 2016-09-11 22:13:57 -07:00
Syrus Akbary
a0d07343e1 First version of integrated Graphene sphinx docs 2016-09-11 21:47:34 -07:00
Syrus Akbary
a2140110c2 Added descriptions to Django choices enum conversion. Fixed #279 2016-09-11 16:08:35 -07:00
Syrus Akbary
2ae6cc3b7c Updated docs reflecting latest resolver arguments 2016-09-10 22:24:18 -07:00
Syrus Akbary
cc4031f866 Updated graphene SQLAlchemy package version 2016-09-10 22:19:23 -07:00
Syrus Akbary
26e564c5b8 Improved SQLAlchemy examples. Fixed #269 2016-09-10 22:18:03 -07:00
Syrus Akbary
c78ff81f3a Make Mutation class visible in graphene root package 2016-09-10 22:17:13 -07:00
Syrus Akbary
9f30aa2d45 Added auto_camelcase to TypeMap/Schema 2016-09-10 21:44:10 -07:00
Syrus Akbary
210a2aed49 Updated Graphene Django version 2016-09-10 21:25:00 -07:00
Syrus Akbary
0bb1dd607d Fixed django form GobalID testing with string ids. 2016-09-10 21:22:42 -07:00
Syrus Akbary
bcfb5182fd DjangoFilterConnectionField now uses a correct filter resolver. Fixed #276 2016-09-10 21:21:43 -07:00
Syrus Akbary
b9cfa32029 Updated version 2016-09-09 19:04:50 -07:00
Syrus Akbary
893d6f681e Added get_query into sqlalchemy objecttype 2016-09-09 19:04:21 -07:00
Syrus Akbary
a8feba6ab4 Fixed IntegerField forcing in GlobalIDFormField. Fixed #259 2016-09-08 22:54:38 -07:00
Syrus Akbary
05d71aac75 Added auto_camelcase checking in Schema/Typemap 2016-09-08 22:50:23 -07:00
Syrus Akbary
aaf7abe831 Fixed coverage 2016-09-08 22:26:31 -07:00
Syrus Akbary
9875526891 Updated documentation 2016-09-08 21:35:52 -07:00
Syrus Akbary
751c4245c5 Fixed import error 2016-09-08 21:35:18 -07:00
Syrus Akbary
036210e097 Updated docs referencing the upgrade 2016-09-08 21:30:30 -07:00
Syrus Akbary
0e2092530b Updated Django and SQLAlchemy packages 2016-09-08 21:30:07 -07:00
Syrus Akbary
630556004a Revert "Fixed starwars relay tests schema representation"
This reverts commit c54b495b16.
2016-09-08 21:03:18 -07:00
Syrus Akbary
9992952908 Fixed mutation input 2016-09-08 20:38:07 -07:00
Syrus Akbary
c54b495b16 Fixed starwars relay tests schema representation 2016-09-08 20:32:24 -07:00
Syrus Akbary
907b34676d Django Connection PageInfo type solved. Fixed #274 2016-09-08 20:25:22 -07:00
Syrus Akbary
92dbba91b7 Fixed mutation tests 2016-09-08 20:16:34 -07:00
Syrus Akbary
b4657a5796 Added PageInfo to graphene exports 2016-09-08 20:14:25 -07:00
Syrus Akbary
d3716ff5db Fixed Mutation with no input 2016-09-08 20:13:52 -07:00
Syrus Akbary
5da0fef083 Merge branch 'next' of github.com:graphql-python/graphene into next 2016-09-04 22:01:06 -07:00
Syrus Akbary
9fc431b581 Fixed Python3 issues 2016-09-04 22:00:33 -07:00
Syrus Akbary
3edb4baf9b Merge pull request #265 from sjhewitt/next-sql-composite
next: handle sqlalchemy composite columns
2016-08-31 14:48:19 -07:00
Syrus Akbary
e24fb01e3c Merge pull request #264 from sjhewitt/next-sqla-scalar-list
next: Convert sqlalchemy-utils ScalarListType
2016-08-31 14:47:17 -07:00
Simon Hewitt
7952f94f53 handle objects being constructed in the typemap multiple times 2016-08-31 14:45:05 -07:00
Simon Hewitt
77d68689ba sqla: convert sqla-utils ScalarListType 2016-08-31 14:41:47 -07:00
Simon Hewitt
b9c4e62e97 handle sqlalchemy composite columns 2016-08-31 14:39:16 -07:00
Syrus Akbary
ceffc4de69 Merge branch 'next' of github.com:graphql-python/graphene into next 2016-08-24 01:16:19 -07:00
Syrus Akbary
80fb69a9ae Stop requiring get_node in implemented Nodes 2016-08-24 01:15:59 -07:00
Syrus Akbary
241b59dda9 Added Relay connection tests 2016-08-24 01:11:26 -07:00
Syrus Akbary
2d09ab8537 Merge pull request #258 from sjhewitt/next-sqla-pageinfo
sqla: pass pageinfo_type into connection_from_list_slice
2016-08-23 13:52:30 -07:00
Syrus Akbary
bcd523082b Fixed starwars relay mutation 2016-08-22 23:11:02 -07:00
Syrus Akbary
4d0b9a0f15 Fixed package version 2016-08-22 22:53:01 -07:00
Syrus Akbary
012d0098e0 Fixed Python3 issues 2016-08-22 22:45:28 -07:00
Syrus Akbary
6543f9272a Updated input field names with out_name 2016-08-22 22:08:49 -07:00
Syrus Akbary
208651a4c0 Fixed connection resolver 2016-08-22 20:34:37 -07:00
Syrus Akbary
9109b9de90 Fixed Django integration 2016-08-22 01:03:20 -07:00
Syrus Akbary
d17bd0aa3e Fixed arg names 2016-08-21 23:33:32 -07:00
Simon Hewitt
2635a0c70d sqla: pass pageinfo_type into connection_from_list_slice 2016-08-19 18:51:12 -07:00
Syrus Akbary
dac4f2dc19 Fixed SQLAlchemy integration 2016-08-19 09:18:29 -07:00
Syrus Akbary
4a2f10b116 Remove pip cache 2016-08-19 00:37:41 -07:00
Syrus Akbary
1e3b30124f Improved benchmarks isolated instancing from type resolution 2016-08-18 09:22:28 -07:00
Syrus Akbary
0922f91c33 Fixed Python3 test assertions 2016-08-17 22:13:55 -07:00
Syrus Akbary
0f76e8f817 Added simple benchmarks 2016-08-17 21:26:05 -07:00
Syrus Akbary
bf5e0e2881 Fixed flake error 2016-08-17 00:52:02 -07:00
Syrus Akbary
a48b41eaf9 Added NonNull restriction 2016-08-17 00:32:53 -07:00
Syrus Akbary
e2904a4d6e Improved typemap testing 2016-08-17 00:28:56 -07:00
Syrus Akbary
135a171fe4 Fixed mutation input inheritance 2016-08-16 23:43:10 -07:00
Syrus Akbary
8e5555a044 Merge branch 'next' into next-allow-subclassing 2016-08-16 23:26:42 -07:00
Syrus Akbary
657810aef7 Fixed enum import 2016-08-16 22:59:44 -07:00
Syrus Akbary
100e03ec0c Add documentation to is_node 2016-08-16 22:58:40 -07:00
Syrus Akbary
3787269812 Moved enum to pyutils 2016-08-16 22:58:03 -07:00
Syrus Akbary
af9e51e58d Added documentation 2016-08-16 21:32:53 -07:00
Syrus Akbary
f53c26c7ab Simplified fields implementation 2016-08-16 21:12:09 -07:00
Markus Padourek
81013fbafb abstract type interface test. 2016-08-16 16:15:00 +01:00
Markus Padourek
a78c487173 Some testing around. 2016-08-16 16:10:05 +01:00
Markus Padourek
ef8d7e2bd2 Added additional test. 2016-08-16 11:43:04 +01:00
Markus Padourek
7913052d07 Added failing test for relay mutation 2016-08-16 11:34:44 +01:00
Markus Padourek
0ef065e5cc Added breaking test to demonstrate wanted subclassing feature. 2016-08-16 11:21:31 +01:00
Syrus Akbary
018811036b Remove unused merge 2016-08-16 00:34:55 -07:00
Syrus Akbary
a056acba62 Added more info to the connections 2016-08-16 00:33:43 -07:00
Syrus Akbary
a55741b03c Added node resolver 2016-08-16 00:15:00 -07:00
Syrus Akbary
1820a4eb60 Updated subpackages dependency 2016-08-16 00:02:16 -07:00
Syrus Akbary
8c321875cf Simplified Relay Connection implementation 2016-08-16 00:00:01 -07:00
Syrus Akbary
f3dff38541 Improved Django implementation 2016-08-15 23:51:51 -07:00
Syrus Akbary
13f9b658c1 Improved SQLAlchemy integration 2016-08-15 23:46:30 -07:00
Syrus Akbary
e5831057f0 Updated SQLAlchemy 2016-08-15 23:28:35 -07:00
Syrus Akbary
bd41abcb5a Updated Django converter 2016-08-15 23:27:41 -07:00
Syrus Akbary
5cb5d9d65a Improved Relay Connection 2016-08-15 23:24:03 -07:00
Syrus Akbary
fd0b9223cf Made fields logic more clear 2016-08-15 23:19:18 -07:00
Syrus Akbary
030fde2cff Improved system for getting graphene package version 2016-08-14 17:47:52 -07:00
Syrus Akbary
ed12231ee8 Added uselist from a relationship for One to One mapping to a Field. Fixed #246 2016-08-14 17:21:05 -07:00
Syrus Akbary
6f99372287 Added relay imports to Graphene. 2016-08-14 17:07:51 -07:00
Syrus Akbary
7940f02ba9 Fixed Argument, Dynamic flake8 bug 2016-08-14 17:05:51 -07:00
Syrus Akbary
6fa32a7287 Fixed PEP8 errors 2016-08-14 16:58:32 -07:00
Syrus Akbary
9f1c5fa682 Fixed Python3 errors 2016-08-14 16:50:03 -07:00
Syrus Akbary
35169480d0 Moved iso8601 dependency into graphene-django package 2016-08-14 16:25:59 -07:00
Syrus Akbary
5ca6f6cb7b Added is_base_type back 2016-08-14 15:51:07 -07:00
Syrus Akbary
8bf6b22765 Updated UPGRADE guide 2016-08-14 15:45:41 -07:00
Syrus Akbary
f296a2a73f Updated SQLAlchemy code to work with latest version of graphene. 2016-08-14 15:42:27 -07:00
Syrus Akbary
c414b3f688 Improved format for messaging in DjangoObjectType.is_type_of 2016-08-14 15:30:59 -07:00
Syrus Akbary
b75da9fb8a Deprecated DjangoNode in favor of relay.Node 2016-08-14 13:51:13 -07:00
Syrus Akbary
e5a8eff4ac Fixed starwars example 2016-08-14 13:44:56 -07:00
Syrus Akbary
f74c23f02e Improved DjangoDebug integration. 2016-08-14 13:43:17 -07:00
Syrus Akbary
3feae35f69 Added schema middlewares 2016-08-14 13:40:33 -07:00
Syrus Akbary
12c4485a43 Added default manager to connection resolver 2016-08-14 12:12:06 -07:00
Syrus Akbary
29e5502e0e Improved relay ClientIDMutation 2016-08-14 11:05:40 -07:00
Syrus Akbary
26f364de0b Improved Django integration. 2016-08-14 10:57:08 -07:00
Syrus Akbary
dbc981c6d2 Fixed runtime type resolution. 2016-08-14 10:20:09 -07:00
Syrus Akbary
a0228ae6b2 Moved relay is_node definition 2016-08-14 02:19:37 -07:00
Syrus Akbary
f4062c3fc3 Added Dynamic type (resolved in runtime) 2016-08-14 02:19:03 -07:00
Syrus Akbary
99eec49a06 Removed unused code. Small refactor 2016-08-13 23:15:20 -07:00
Syrus Akbary
3f3bb113ce Removed unnecessary files. 2016-08-13 23:06:18 -07:00
Syrus Akbary
7804f10732 Added ClientIDMutation. All examples working 💪 2016-08-13 23:00:25 -07:00
Syrus Akbary
e2036da75f Added relay.Connection and relay.ConnectionField 2016-08-13 21:05:45 -07:00
Syrus Akbary
b19bca7f3b Improved base implementation 2016-08-13 17:37:57 -07:00
Syrus Akbary
0ffdd8d9ab Improved Relay implementation 2016-08-13 17:36:11 -07:00
Syrus Akbary
fd16de8748 Fixed required get_type in Enum for UnmountedType 2016-08-13 17:32:32 -07:00
Syrus Akbary
4f52498a06 Added required option in Argument 2016-08-13 17:32:07 -07:00
Syrus Akbary
2696ae9b73 Make new_types the deafult types 2016-08-13 14:43:51 -07:00
Syrus Akbary
c339afc1ce Added TypeMap objecttype test. Fixed Field arguments 2016-08-13 13:38:05 -07:00
Syrus Akbary
ec4a49498d Added datetime scalar 2016-08-13 13:19:58 -07:00
Syrus Akbary
6e0789bfcd Improved implementation 2016-08-13 13:19:47 -07:00
Syrus Akbary
b68b1753bb Added enum support in typemap 2016-08-13 13:05:38 -07:00
Syrus Akbary
84c1da60dd Added Union. Improved testing and code 2016-08-13 11:10:41 -07:00
Syrus Akbary
0802aaced0 Added InputObjectType conversion 2016-08-13 09:39:46 -07:00
Syrus Akbary
0f66dba7e8 Improved testing 2016-08-13 09:15:24 -07:00
Syrus Akbary
a7b3d193eb Added Field arguments. 2016-08-13 01:50:32 -07:00
Syrus Akbary
70a9de63f9 Added InputObjectType and InputField 2016-08-12 19:23:33 -07:00
Syrus Akbary
8cf5b1d9ab Added Enum 2016-08-12 18:57:18 -07:00
Syrus Akbary
9c4706f7c5 Added Mutation 2016-08-12 18:37:29 -07:00
Syrus Akbary
e408541c7b Improved testing. Added strucutre serialization. Remove unused code 2016-08-12 18:13:47 -07:00
Syrus Akbary
1c24e1b954 Added Union type 2016-08-12 18:06:01 -07:00
Syrus Akbary
7923f45595 Added TypeMap 2016-08-11 19:44:37 -07:00
Syrus Akbary
3620e2ad4e Improved scalars 2016-08-11 01:25:32 -07:00
Syrus Akbary
3e77f258b4 Improved schema 2016-08-11 01:25:24 -07:00
Syrus Akbary
c4fba3b7ca Improved error messaging 2016-08-11 01:02:37 -07:00
Syrus Akbary
feb8fb9b13 Improved schema implementation 2016-08-11 01:00:46 -07:00
Syrus Akbary
ac0e699069 Added schema 2016-08-11 00:27:37 -07:00
Syrus Akbary
453d6d6ab7 Added scalars 2016-08-11 00:05:33 -07:00
Syrus Akbary
55a1450dd3 Improved abstracttypes implementation 2016-08-10 23:39:28 -07:00
Syrus Akbary
cd0be62993 Added abstract types simplification 2016-08-10 23:15:32 -07:00
Syrus Akbary
550ad386f0 Next types 2016-08-10 22:03:38 -07:00
Syrus Akbary
04492600e5 First stage separate interfaces 2016-08-08 09:37:06 -07:00
Syrus Akbary
ff3968faea Removed unused function 2016-08-07 17:08:50 -07:00
Syrus Akbary
2c446658e5 Improved tests 2016-08-07 17:01:09 -07:00
Syrus Akbary
27a0d4147f Removed implements check 2016-08-07 16:53:40 -07:00
Syrus Akbary
0f279abecf Improved unmounted type logic 2016-08-07 16:31:06 -07:00
Syrus Akbary
73d37a1bb2 Upgrade guides 2016-08-06 19:56:43 -07:00
Syrus Akbary
1e4393f74d Improved travis tests 2016-08-06 19:45:11 -07:00
Syrus Akbary
387b997b1d Fixed tests and flake errors 2016-08-06 19:42:06 -07:00
Syrus Akbary
05144487ce Fixed travis 2016-08-06 19:28:09 -07:00
Syrus Akbary
05a48c634d Removed docs 2016-08-06 19:28:02 -07:00
Syrus Akbary
e6e08f60bc Fixed json literal parsing 2016-08-06 19:21:44 -07:00
Syrus Akbary
8f8b38d757 Update registry.py 2016-07-29 19:29:45 -07:00
Syrus Akbary
ba4d1d6abf Fixed Python3 tests 2016-07-22 20:38:45 -07:00
Syrus Akbary
9deec688ed Fixed SQLAlchemy model in node interface 2016-07-22 20:34:13 -07:00
Syrus Akbary
8ea2fde16e Updated SQLAlchemy example 2016-07-22 20:32:18 -07:00
Syrus Akbary
af4c63512c First working version of graphene-sqlalchemy 2016-07-22 20:24:12 -07:00
Syrus Akbary
79d7636ab6 Added initial basic SQLAlchemy example 2016-07-18 11:28:12 -04:00
Syrus Akbary
4cadf33b4f Fixed resolver in Django 2016-06-23 22:41:22 -07:00
Syrus Akbary
12ffb027fa Improved connection abstraction 2016-06-23 15:13:54 -07:00
Syrus Akbary
12f264b290 Improved Django implementation 2016-06-22 23:46:59 -07:00
Syrus Akbary
4168439abe Removed type definitions 2016-06-22 23:38:01 -07:00
Syrus Akbary
b6522f393c Refactored InputObjectType 2016-06-22 23:35:50 -07:00
Syrus Akbary
cbf0d8fedd Moved Enum logic 2016-06-22 23:30:49 -07:00
Syrus Akbary
3529fcb29b Moved scalar definitions 2016-06-22 23:25:09 -07:00
Syrus Akbary
1737089c6d Refactored GraphQL type generator 2016-06-22 23:22:09 -07:00
Syrus Akbary
24cb8306c0 Refactored Django tests 2016-06-21 23:56:38 -07:00
Syrus Akbary
91be6ac51e Removed unused Django code 2016-06-21 23:42:38 -07:00
Syrus Akbary
86fe19d84c Improved django defaults 2016-06-21 23:35:47 -07:00
Syrus Akbary
7d59489183 Remove abstract from options 2016-06-21 23:31:29 -07:00
Syrus Akbary
f9303dab72 Improved Django integration 2016-06-21 23:04:12 -07:00
Syrus Akbary
37ed617fce Fixed Graphene Django integration 2016-06-21 22:52:39 -07:00
Syrus Akbary
043e548f49 Added JSONString 2016-06-21 22:07:16 -07:00
Syrus Akbary
f2ed1e58d9 Merge branch '1.0-django-interfaceobjecttype' of github.com:graphql-python/graphene into 1.0-django-interfaceobjecttype
# Conflicts:
#	graphene/types/objecttype.py
2016-06-21 22:06:45 -07:00
Syrus Akbary
1827099381 Added get_fields to options 2016-06-21 17:40:38 -07:00
Syrus Akbary
b5458493ce Improved objecttype 2016-06-21 14:09:54 -07:00
Syrus Akbary
c87d87d1ea Improved ObjectType fields 2016-06-21 13:09:14 -07:00
Syrus Akbary
568718d573 Added support for Enum descriptions 2016-06-21 12:01:03 -07:00
Syrus Akbary
9a9d7f8873 Moved Interface to ObjectType. Improved integration with latest GraphQL-core 2016-06-21 11:54:14 -07:00
Syrus Akbary
6611c861d8 Moved Interface to ObjectType 2016-06-20 17:47:26 -07:00
Syrus Akbary
7a29502790 Updated first passing Django tests! 🎉 2016-06-19 14:30:33 -07:00
Syrus Akbary
b772499b9b Improved Interface/ObjectType is_type_of abstraction 2016-06-19 14:29:41 -07:00
Syrus Akbary
907a093117 Allow dates in Datetime scalar 2016-06-19 14:28:57 -07:00
Syrus Akbary
d3f98d75f6 Improved relay integration and abstraction 2016-06-19 14:28:47 -07:00
Syrus Akbary
4de77c95e1 Improved django integration 2016-06-18 14:33:04 -07:00
Syrus Akbary
ccd8349ef6 Added as_field utility 2016-06-18 14:32:53 -07:00
Syrus Akbary
3c2f2c3c06 Added DateTime scalar 2016-06-18 14:32:17 -07:00
Syrus Akbary
c88e933e9e Update graphql_relay to last version 2016-06-18 14:31:33 -07:00
Syrus Akbary
e7e2ed518a Use OrderedDict in Enum by default 2016-06-18 14:31:19 -07:00
Syrus Akbary
feaa09616d First 1.0 with a separated Django version 2016-06-17 09:29:38 -07:00
Syrus Akbary
80f98c5fd3 Improved enum. Removed old @implements 2016-06-17 01:27:31 -07:00
Syrus Akbary
995150bfa5 Improved is_graphene_type 2016-06-17 01:27:05 -07:00
Syrus Akbary
35f42f4e0c Improved relay types 2016-06-15 22:45:28 -07:00
Syrus Akbary
dd377c7da3 Fixed Python3 issues 2016-06-15 22:34:12 -07:00
Syrus Akbary
6e38e48faf Improved code lint 2016-06-15 21:40:54 -07:00
Syrus Akbary
ccfed3df3f Improved Python3 compat 2016-06-15 21:40:12 -07:00
Syrus Akbary
145183d0ae Remove commented code 2016-06-15 21:24:01 -07:00
Syrus Akbary
8bd9669d3d Removed unused implements 2016-06-15 21:20:35 -07:00
Syrus Akbary
ee46d8c7be Improved Scalars tests 2016-06-15 21:16:31 -07:00
Syrus Akbary
2172edc033 Improved docs 2016-06-15 21:00:06 -07:00
Syrus Akbary
b91e10ef8a Improved tests 2016-06-15 00:18:20 -07:00
Syrus Akbary
7caf96c746 Improved relay requirement, removed Django/SQLAlchemy dependency in main package 2016-06-14 23:59:37 -07:00
Syrus Akbary
5ccd815fbd Added ConnectionField 2016-06-14 23:48:25 -07:00
Syrus Akbary
c74a75133e Autolint all the files 2016-06-14 22:29:02 -07:00
Syrus Akbary
76ecd895e1 Removed unused code 2016-06-14 22:26:18 -07:00
Syrus Akbary
46918d3ba0 Fixed test 2016-06-14 22:20:06 -07:00
Syrus Akbary
88a81e306b Remove unused logic 2016-06-14 22:17:13 -07:00
Syrus Akbary
afd521de29 Improved relay Connection 2016-06-14 22:13:01 -07:00
Syrus Akbary
ac416b6ab0 Improved ClientIdMutation 2016-06-14 22:04:57 -07:00
Syrus Akbary
8d4cf2d059 Updated Node 2016-06-14 21:45:44 -07:00
Syrus Akbary
6c7cf55b18 Added Mutation support 2016-06-13 20:26:26 -07:00
Syrus Akbary
cf80f87dca Improved ObjectType implementation 2016-06-13 19:58:11 -07:00
Syrus Akbary
d8201c44fa Added better enum 2016-06-13 19:18:00 -07:00
Syrus Akbary
7219babbd7 Improved ScalarType 2016-06-13 18:58:06 -07:00
Syrus Akbary
8078937359 Improved InputObjectType abstraction 2016-06-12 01:15:57 -07:00
Syrus Akbary
a6346664a3 Improved fields logic 2016-06-12 00:20:33 -07:00
Syrus Akbary
e6788993ba Simplified interface logic 2016-06-11 00:47:38 -07:00
Syrus Akbary
eec4c52c33 Renamed from TypeProxy to UnmountedType 2016-06-10 22:40:22 -07:00
Syrus Akbary
c0460060a0 Simplified options 2016-06-10 22:36:48 -07:00
Syrus Akbary
397df4ea1a Moved django and sqlalchemy to own projects 2016-06-10 10:18:22 -07:00
Syrus Akbary
888d5037da Update mutation example 2016-06-10 01:43:06 -07:00
Syrus Akbary
01ddc83c4b Added UpgradeGuide 2016-06-10 01:37:08 -07:00
Syrus Akbary
a9e09dcee8 Improved relay connections 2016-06-10 01:20:53 -07:00
Syrus Akbary
66c375bfe3 Added simple relay connection 2016-06-10 00:44:49 -07:00
Syrus Akbary
51e97510c0 Improved relay nodes and field copies 2016-06-10 00:23:31 -07:00
Syrus Akbary
522f769cad Improved Node/Mutation fields 2016-06-09 22:56:41 -07:00
Syrus Akbary
9025b1c8f0 Improve Field and InputField copy 2016-06-09 22:03:04 -07:00
Syrus Akbary
d8d884c9be Improved extend interfaces syntax 2016-06-09 21:47:06 -07:00
Syrus Akbary
d67b7bc6a1 Improved relay compatibility 2016-06-09 21:24:28 -07:00
Syrus Akbary
b24e9a1051 Refactored fields getter to be immutable 2016-06-08 22:23:28 -07:00
Syrus Akbary
25e967200b Improved fields mounting 2016-06-07 22:39:29 -07:00
Syrus Akbary
9f655d9416 Improved interface fields getter 2016-06-07 22:00:00 -07:00
Syrus Akbary
01190fb6ff Added mutation and props utility 2016-06-07 02:28:13 -07:00
Syrus Akbary
4c8f5367ba Simplified code 2016-06-06 20:38:55 -07:00
Syrus Akbary
ec67303594 Restrict the usage of TypeProxy instances 2016-06-06 02:39:47 -07:00
Syrus Akbary
3a566241f3 Use always the resolve methods as unbounds. __func__ to the rescue 2016-06-06 02:06:17 -07:00
Syrus Akbary
0db5b1cfbc Move resolver to interface too 2016-06-06 02:03:57 -07:00
Syrus Akbary
da3769b902 Fix test case 2016-06-06 01:30:29 -07:00
Syrus Akbary
01130b8af5 Set interface list to be immutable 2016-06-06 01:29:05 -07:00
Syrus Akbary
251d7106e2 Improved scalar implementation thinking immutable 2016-06-06 00:48:43 -07:00
Syrus Akbary
77ec170dd5 Let the interfaces be immutable 2016-06-06 00:39:55 -07:00
Syrus Akbary
b17f081906 Improved enum attrs 2016-06-06 00:05:00 -07:00
Syrus Akbary
19dff03784 Improved documentation 2016-06-05 19:29:24 -07:00
Syrus Akbary
ad607eb122 Changed name from GrapheneType to GrapheneGraphQLType 2016-06-04 19:19:08 -07:00
Syrus Akbary
31ea09ff30 Improved options 2016-06-04 19:10:18 -07:00
Syrus Akbary
2b676743ae Removed slots 2016-06-04 19:06:33 -07:00
Syrus Akbary
ff7bf20f6d Added some mutable comments 2016-06-04 18:49:26 -07:00
Syrus Akbary
0f10ae884f Allow InputObjectType instances to be Type proxies 2016-06-04 16:04:21 -07:00
Syrus Akbary
50c1ab62ba Fixed Enum value getter 2016-06-04 15:45:54 -07:00
Syrus Akbary
449b8c67d1 Added reset_counter to ordered types. Improved node implementation 2016-06-04 15:36:32 -07:00
Syrus Akbary
ab72393e66 Added InputField, InputObjectType. Improved Field implementation 2016-06-04 15:22:10 -07:00
Syrus Akbary
9cf4da5fcb Improved simple example 2016-06-04 14:14:56 -07:00
Syrus Akbary
89790e7508 Added Enum type 2016-06-04 14:06:16 -07:00
Syrus Akbary
58291a3b25 Moved GraphQL definitions to each corresponding file 2016-06-04 13:05:51 -07:00
Syrus Akbary
a1454fdd74 Fixed resolve context 2016-06-04 12:48:08 -07:00
Syrus Akbary
6c42877758 Improved starwars tests 2016-06-04 11:21:33 -07:00
Syrus Akbary
3acf5fd588 Improved tests 2016-06-04 11:20:45 -07:00
Syrus Akbary
40ce604d2c Improved field resolving 2016-06-04 03:12:09 -07:00
Syrus Akbary
d58d1f8d89 Added List, NonNull types 2016-06-03 23:50:12 -07:00
Syrus Akbary
58dbfefc15 Improved interfaces in objecttypes 2016-06-03 21:28:29 -07:00
Syrus Akbary
33d4f44f04 Refactored all graphene code moving to 1.0 2016-06-03 21:06:54 -07:00
Syrus Akbary
1711e6a529 Updated version to 0.10.2 2016-05-31 22:15:01 -07:00
Syrus Akbary
7df1f8a88d Fixed unwrap cursor for make it work with DDT. Fixed #181 2016-05-31 21:15:10 -07:00
Syrus Akbary
b9695c877a Fixed ClientIDMutation GraphQL type name. Fixed #148 2016-05-31 20:55:01 -07:00
Syrus Akbary
de424f7d21 Merge pull request #191 from graphql-python/django-choices-grouping
Django choices grouping
2016-05-31 20:39:25 -07:00
Syrus Akbary
9e715cd902 Fixed Django converter of field with grouped choices 2016-05-31 20:29:20 -07:00
Syrus Akbary
4636f9290a Merge branch 'master' into django-choices-grouping
# Conflicts:
#	graphene/contrib/django/tests/test_converter.py
2016-05-31 20:26:21 -07:00
Syrus Akbary
6eb00083d9 Merge pull request #190 from graphql-python/fix_lazy_translated_choice
Fix lazy translated choice
2016-05-31 20:15:15 -07:00
Syrus Akbary
edfbbf52ef Fix field model 2016-05-31 20:05:49 -07:00
Syrus Akbary
4936e40258 Merge branch 'django-choices-translation' of https://github.com/Ian-Foote/graphene into fix_lazy_translated_choice 2016-05-31 19:49:25 -07:00
Syrus Akbary
7f6598518e Use Django forcetext for choices 2016-05-31 19:47:50 -07:00
Jacob Klapwijk
be449ab1c0 Fix ugettext_lazy objects in Choice tuples not being evaluated. Running .format() on it will return the string we want, and wont cause any problems when its run on a string without arguments 2016-05-31 16:11:54 +02:00
Syrus Akbary
0f94f2b2ef Improved homepage 2016-05-28 23:08:00 -07:00
Syrus Akbary
e5357ccc84 Merge pull request #187 from graphql-python/register-interface-failure-fix
Register interface failure fix
2016-05-28 16:52:56 -07:00
Syrus Akbary
da09bc3210 Fixed unregistered types in schema 2016-05-27 23:18:18 -07:00
Ian Foote
7d5d7eac3c Add test for django grouped choices 2016-05-26 16:07:18 +01:00
Ian Foote
8744f6a90e Add test for django choices with translation 2016-05-26 15:44:49 +01:00
Marc Tamlyn
aa2f4c5bac Failing test of interface implementation registration. 2016-05-26 12:16:45 +01:00
Syrus Akbary
8bc14953d7 Moved options testing to tests directory 2016-05-23 21:58:25 -07:00
Syrus Akbary
da0927aa84 Updated version to 0.10.1 2016-05-22 19:32:52 -07:00
Syrus Akbary
ed070b6a9a Merge pull request #178 from AlecAivazis/master
Fixed bug when no middlewares are present
2016-05-22 18:49:58 -07:00
Alec Aivazis
427a08106b fixed linting error 2016-05-22 17:17:07 -07:00
Alec Aivazis
161f198451 added test for auto_camelcase flag 2016-05-22 17:11:55 -07:00
Alec Aivazis
feb0825a63 fixed bug when no middlewares are present 2016-05-22 16:52:30 -07:00
403 changed files with 16897 additions and 18266 deletions

View File

@ -1,2 +1,2 @@
[run]
omit = graphene/utils/enum.py,graphene/contrib/django/debug/sql/tracking.py,*/tests/*
omit = graphene/pyutils/*,*/tests/*

View File

@ -11,4 +11,3 @@ trim_trailing_whitespace = true
[*.{py,rst,ini}]
indent_style = space
indent_size = 4

34
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,34 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: "\U0001F41B bug"
assignees: ''
---
**Note: for support questions, please use stackoverflow**. This repository's issues are reserved for feature requests and bug reports.
* **What is the current behavior?**
* **If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem** via
a github repo, https://repl.it or similar.
* **What is the expected behavior?**
* **What is the motivation / use case for changing the behavior?**
* **Please tell us about your environment:**
- Version:
- Platform:
* **Other information** (e.g. detailed explanation, stacktraces, related issues, suggestions how to fix, links for us to have context, eg. stackoverflow)

1
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1 @@
blank_issues_enabled: false

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: "✨ enhancement"
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

24
.github/stale.yml vendored Normal file
View File

@ -0,0 +1,24 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: false
# Number of days of inactivity before a stale issue is closed
daysUntilClose: false
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- 🐛 bug
- 📖 documentation
- 🙋 help wanted
- ✨ enhancement
- good first issue
- work in progress
# Label to use when marking an issue as stale
staleLabel: wontfix
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: false
# markComment: >
# This issue has been automatically marked as stale because it has not had
# recent activity. It will be closed if no further activity occurs. Thank you
# for your contributions.
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false

21
.github/workflows/build.yaml vendored Normal file
View File

@ -0,0 +1,21 @@
name: 📦 Build
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Building package
run: python3 -m build
- name: Check package with Twine
run: twine check dist/*

26
.github/workflows/deploy.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: 🚀 Deploy to PyPI
on:
push:
tags:
- 'v*'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Build wheel and source tarball
run: |
pip install wheel
python setup.py sdist bdist_wheel
- name: Publish a Python distribution to PyPI
uses: pypa/gh-action-pypi-publish@v1.1.0
with:
user: __token__
password: ${{ secrets.pypi_password }}

26
.github/workflows/lint.yml vendored Normal file
View File

@ -0,0 +1,26 @@
name: 💅 Lint
on: [push, pull_request]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install tox
- name: Run lint
run: tox
env:
TOXENV: pre-commit
- name: Run mypy
run: tox
env:
TOXENV: mypy

64
.github/workflows/tests.yml vendored Normal file
View File

@ -0,0 +1,64 @@
name: 📄 Tests
on:
push:
branches:
- master
- '*.x'
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'
pull_request:
branches:
- master
- '*.x'
paths-ignore:
- 'docs/**'
- '*.md'
- '*.rst'
jobs:
tests:
# runs the test suite
name: ${{ matrix.name }}
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- {name: '3.13', python: '3.13', os: ubuntu-latest, tox: py313}
- {name: '3.12', python: '3.12', os: ubuntu-latest, tox: py312}
- {name: '3.11', python: '3.11', os: ubuntu-latest, tox: py311}
- {name: '3.10', python: '3.10', os: ubuntu-latest, tox: py310}
- {name: '3.9', python: '3.9', os: ubuntu-latest, tox: py39}
- {name: '3.8', python: '3.8', os: ubuntu-latest, tox: py38}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python }}
- name: update pip
run: |
python -m pip install --upgrade pip
pip install --upgrade setuptools wheel
- name: get pip cache dir
id: pip-cache
run: echo "dir=$(pip cache dir)" >> $GITHUB_OUTPUT
- name: cache pip dependencies
uses: actions/cache@v3
with:
path: ${{ steps.pip-cache.outputs.dir }}
key: pip|${{ runner.os }}|${{ matrix.python }}|${{ hashFiles('setup.py') }}
- run: pip install tox
- run: tox -e ${{ matrix.tox }}
- name: Upload coverage.xml
if: ${{ matrix.python == '3.10' }}
uses: actions/upload-artifact@v4
with:
name: graphene-coverage
path: coverage.xml
if-no-files-found: error
- name: Upload coverage.xml to codecov
if: ${{ matrix.python == '3.10' }}
uses: codecov/codecov-action@v4

17
.gitignore vendored
View File

@ -10,7 +10,6 @@ __pycache__/
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
@ -42,9 +41,11 @@ htmlcov/
.coverage
.coverage.*
.cache
.pytest_cache
nosetests.xml
coverage.xml
*,cover
*.cover
.pytest_cache/
# Translations
*.mo
@ -59,6 +60,14 @@ docs/_build/
# PyBuilder
target/
# VirtualEnv
.env
.venv
env/
venv/
# Typing
.mypy_cache/
/tests/django.sqlite
@ -75,6 +84,10 @@ target/
# PyCharm
.idea
*.iml
# Databases
*.sqlite3
.vscode
.mypy_cache
.ruff_cache

29
.pre-commit-config.yaml Normal file
View File

@ -0,0 +1,29 @@
default_language_version:
python: python3.10
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.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.37.3
hooks:
- id: pyupgrade
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.5.0
hooks:
- id: ruff
- id: ruff-format
args: [ --check ]

View File

@ -1,96 +0,0 @@
language: python
sudo: false
python:
- 2.7
- 3.4
- 3.5
- pypy
cache:
directories:
- .cache/pip/
- $HOME/.cache/pip
- docs/node_modules/
- $HOME/docs/node_modules
before_install:
- |
git_diff=$(git diff --name-only $TRAVIS_COMMIT_RANGE)
if [ "$?" == 0 ] && [ "$TEST_TYPE" != build_website ] && \
! echo "$git_diff" | grep -qvE '(\.md$)|(^(docs))/'
then
echo "Only docs were updated, stopping build process."
exit
fi
install:
- |
if [ "$TEST_TYPE" = build ]; then
pip install --download-cache $HOME/.cache/pip/ pytest pytest-cov coveralls six pytest-django django-filter sqlalchemy_utils
pip install --download-cache $HOME/.cache/pip psycopg2 > /dev/null 2>&1
pip install --download-cache $HOME/.cache/pip/ -e .
pip install --download-cache $HOME/.cache/pip/ -e .[django]
pip install --download-cache $HOME/.cache/pip/ -e .[sqlalchemy]
pip install django==$DJANGO_VERSION
python setup.py develop
elif [ "$TEST_TYPE" = build_website ]; then
pip install --download-cache $HOME/.cache/pip/ -e .
python setup.py develop
elif [ "$TEST_TYPE" = lint ]; then
pip install --download-cache $HOME/.cache/pip/ flake8
fi
script:
- |
if [ "$TEST_TYPE" = build_website ]; then
if [ "$TRAVIS_BRANCH" = "master" ] && [ "$TRAVIS_PULL_REQUEST" = false ]; then
echo "Building the web."
nvm install 4.0
GH_PAGES_DIR="$TRAVIS_BUILD_DIR"/docs/public
git config --global user.name "Travis CI"
git config --global user.email "travis@graphene-python.org"
git clone --branch gh-pages --depth=50 \
https://graphql-python-bot@github.com/graphql-python/graphene.git \
$GH_PAGES_DIR
cd docs
./playground/graphene-js/build.sh
npm run deploy
cd $GH_PAGES_DIR
git status
git add --intent-to-add .
if ! git diff-index --quiet HEAD --; then
git add -A .
git commit -m "Rebuild website"
git push "https://${GITHUB_TOKEN}@github.com/graphql-python/graphene.git" gh-pages
fi
exit
fi
elif [ "$TEST_TYPE" = lint ]; then
echo "Checking Python code lint."
flake8
exit
elif [ "$TEST_TYPE" = build ]; then
py.test --cov=graphene
fi
after_success:
- |
if [ "$TEST_TYPE" = build ]; then
coveralls
fi
env:
matrix:
- TEST_TYPE=build
global:
secure: SQC0eCWCWw8bZxbLE8vQn+UjJOp3Z1m779s9SMK3lCLwJxro/VCLBZ7hj4xsrq1MtcFO2U2Kqf068symw4Hr/0amYI3HFTCFiwXAC3PAKXeURca03eNO2heku+FtnQcOjBanExTsIBQRLDXMOaUkf3MIztpLJ4LHqMfUupKmw9YSB0v40jDbSN8khBnndFykmOnVVHznFp8USoN5F0CiPpnfEvHnJkaX76lNf7Kc9XNShBTTtJsnsHMhuYQeInt0vg9HSjoIYC38Tv2hmMj1myNdzyrHF+LgRjI6ceGi50ApAnGepXC/DNRhXROfECKez+LON/ZSqBGdJhUILqC8A4WmWmIjNcwitVFp3JGBqO7LULS0BI96EtSLe8rD1rkkdTbjivajkbykM1Q0Tnmg1adzGwLxRUbTq9tJQlTTkHBCuXIkpKb1mAtb/TY7A6BqfnPi2xTc/++qEawUG7ePhscdTj0IBrUfZsUNUYZqD8E8XbSWKIuS3SHE+cZ+s/kdAsm4q+FFAlpZKOYGxIkwvgyfu4/Plfol4b7X6iAP9J3r1Kv0DgBVFst5CXEwzZs19/g0CgokQbCXf1N+xeNnUELl6/fImaR3RKP22EaABoil4z8vzl4EqxqVoH1nfhE+WlpryXsuSaF/1R+WklR7aQ1FwoCk8V8HxM2zrj4tI8k=
matrix:
fast_finish: true
include:
- python: '2.7'
env: TEST_TYPE=build DJANGO_VERSION=1.6
- python: '2.7'
env: TEST_TYPE=build DJANGO_VERSION=1.7
- python: '2.7'
env: TEST_TYPE=build DJANGO_VERSION=1.8
- python: '2.7'
env: TEST_TYPE=build DJANGO_VERSION=1.9
- python: '2.7'
env: TEST_TYPE=build_website
- python: '2.7'
env: TEST_TYPE=lint

View File

@ -1,6 +1,6 @@
The MIT License (MIT)
Copyright (c) 2015 Syrus Akbary
Copyright (c) 2015-Present Syrus Akbary
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -2,3 +2,4 @@ global-exclude tests/*
recursive-exclude tests *
recursive-exclude tests_py35 *
recursive-exclude examples *
include LICENSE

28
Makefile Normal file
View File

@ -0,0 +1,28 @@
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@grep -E '^\.PHONY: [a-zA-Z_-]+ .*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = "(: |##)"}; {printf "\033[36m%-30s\033[0m %s\n", $$2, $$3}'
.PHONY: install-dev ## Install development dependencies
install-dev:
pip install -e ".[dev]"
.PHONY: test ## Run tests
test:
py.test graphene examples
.PHONY: docs ## Generate docs
docs: install-dev
cd docs && make install && make html
.PHONY: docs-live ## Generate docs with live reloading
docs-live: install-dev
cd docs && make install && make livehtml
.PHONY: format
format:
black graphene examples setup.py
.PHONY: lint
lint:
flake8 graphene examples setup.py

110
README.md
View File

@ -1,47 +1,53 @@
# ![Graphene Logo](http://graphene-python.org/favicon.png) [Graphene](http://graphene-python.org) [![Build Status](https://travis-ci.org/graphql-python/graphene.svg?branch=master)](https://travis-ci.org/graphql-python/graphene) [![PyPI version](https://badge.fury.io/py/graphene.svg)](https://badge.fury.io/py/graphene) [![Coverage Status](https://coveralls.io/repos/graphql-python/graphene/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-python/graphene?branch=master)
# ![Graphene Logo](http://graphene-python.org/favicon.png) [Graphene](http://graphene-python.org) [![PyPI version](https://badge.fury.io/py/graphene.svg)](https://badge.fury.io/py/graphene) [![Coverage Status](https://coveralls.io/repos/graphql-python/graphene/badge.svg?branch=master&service=github)](https://coveralls.io/github/graphql-python/graphene?branch=master) [![](https://dcbadge.vercel.app/api/server/T6Gp6NFYHe?style=flat)](https://discord.gg/T6Gp6NFYHe)
[💬 Join the community on Discord](https://discord.gg/T6Gp6NFYHe)
[Graphene](http://graphene-python.org) is a Python library for building GraphQL schemas/types fast and easily.
**We are looking for contributors**! Please check the current issues to see how you can help ❤️
## Introduction
[Graphene](http://graphene-python.org) is an opinionated 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
- **Django:** Automatic *Django model* mapping to Graphene Types. Check a fully working [Django](http://github.com/graphql-python/swapi-graphene) implementation
- **Relay:** Graphene has builtin support for Relay.
- **Data agnostic:** Graphene supports any kind of data source: SQL (Django, SQLAlchemy), Mongo, 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.
Graphene also supports *SQLAlchemy*!
## Integrations
*What is supported in this Python version?* **Everything**: Interfaces, ObjectTypes, Scalars, Unions and Relay (Nodes, Connections), in addition to queries, mutations and subscriptions.
Graphene has multiple integrations with different frameworks:
**NEW**!: [Try graphene online](http://graphene-python.org/playground/)
| integration | Package |
| ----------------- | --------------------------------------------------------------------------------------- |
| SQLAlchemy | [graphene-sqlalchemy](https://github.com/graphql-python/graphene-sqlalchemy/) |
| Mongo | [graphene-mongo](https://github.com/graphql-python/graphene-mongo/) |
| Apollo Federation | [graphene-federation](https://github.com/graphql-python/graphene-federation/) |
| Django | [graphene-django](https://github.com/graphql-python/graphene-django/) |
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).
## Installation
For instaling graphene, just run this command in your shell
To install `graphene`, just run this command in your shell
```bash
pip install graphene
# In case of need Django model support
pip install graphene[django]
# Or in case of need SQLAlchemy support
pip install graphene[sqlalchemy]
pip install "graphene>=3.1"
```
## Examples
Here is one example for get you started:
Here is one example for you to get started:
```python
import graphene
class Query(graphene.ObjectType):
hello = graphene.String(description='A typical hello world')
ping = graphene.String(description='Ping someone',
to=graphene.String())
def resolve_hello(self, args, info):
def resolve_hello(self, info):
return 'World'
def resolve_ping(self, args, info):
return 'Pinging {}'.format(args.get('to'))
schema = graphene.Schema(query=Query)
```
@ -51,7 +57,6 @@ Then Querying `graphene.Schema` is as simple as:
query = '''
query SayHello {
hello
ping(to:"peter")
}
'''
result = schema.execute(query)
@ -59,22 +64,67 @@ result = schema.execute(query)
If you want to learn even more, you can also check the following [examples](examples/):
* **Basic Schema**: [Starwars example](examples/starwars)
* **Relay Schema**: [Starwars Relay example](examples/starwars_relay)
* **Django model mapping**: [Starwars Django example](examples/starwars_django)
* **SQLAlchemy model mapping**: [Flask SQLAlchemy example](examples/flask_sqlalchemy)
- **Basic Schema**: [Starwars example](examples/starwars)
- **Relay Schema**: [Starwars Relay example](examples/starwars_relay)
## Documentation
Documentation and links to additional resources are available at
https://docs.graphene-python.org/en/latest/
## Contributing
After cloning this repo, ensure dependencies are installed by running:
After cloning this repo, create a [virtualenv](https://virtualenv.pypa.io/en/stable/) and ensure dependencies are installed by running:
```sh
python setup.py install
virtualenv venv
source venv/bin/activate
pip install -e ".[test]"
```
After developing, the full test suite can be evaluated by running:
Well-written tests and maintaining good test coverage is important to this project. While developing, run new and existing tests with:
```sh
python setup.py test # Use --pytest-args="-v -s" for verbose mode
pytest graphene/relay/tests/test_node.py # Single file
pytest 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](https://docs.pytest.org/en/latest/) for more options and test running controls.
Regularly ensure your `pre-commit` hooks are up to date and enabled:
```sh
pre-commit install
```
You can also run the benchmarks with:
```sh
pytest 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:
```sh
tox
```
If you wish to run against a specific version defined in the `tox.ini` file:
```sh
tox -e py39
```
Tox can only use whatever versions of Python are installed on your system. When you create a pull request, GitHub Actions pipelines 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](http://www.sphinx-doc.org/) and a custom theme.
An HTML version of the documentation is produced by running:
```sh
make docs
```

View File

@ -1,101 +0,0 @@
|Graphene Logo| `Graphene <http://graphene-python.org>`__ |Build Status| |PyPI version| |Coverage Status|
=========================================================================================================
`Graphene <http://graphene-python.org>`__ 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
- **Django:** Automatic *Django model* mapping to Graphene Types. Check
a fully working
`Django <http://github.com/graphql-python/swapi-graphene>`__
implementation
Graphene also supports *SQLAlchemy*!
*What is supported in this Python version?* **Everything**: Interfaces,
ObjectTypes, Scalars, Unions and Relay (Nodes, Connections), in addition
to queries, mutations and subscriptions.
**NEW**!: `Try graphene
online <http://graphene-python.org/playground/>`__
Installation
------------
For instaling graphene, just run this command in your shell
.. code:: bash
pip install graphene
# In case of need Django model support
pip install graphene[django]
# Or in case of need SQLAlchemy support
pip install graphene[sqlalchemy]
Examples
--------
Here is one example for get you started:
.. code:: python
class Query(graphene.ObjectType):
hello = graphene.String(description='A typical hello world')
ping = graphene.String(description='Ping someone',
to=graphene.String())
def resolve_hello(self, args, info):
return 'World'
def resolve_ping(self, args, info):
return 'Pinging {}'.format(args.get('to'))
schema = graphene.Schema(query=Query)
Then Querying ``graphene.Schema`` is as simple as:
.. code:: python
query = '''
query SayHello {
hello
ping(to:"peter")
}
'''
result = schema.execute(query)
If you want to learn even more, you can also check the following
`examples <examples/>`__:
- **Basic Schema**: `Starwars example <examples/starwars>`__
- **Relay Schema**: `Starwars Relay
example <examples/starwars_relay>`__
- **Django model mapping**: `Starwars Django
example <examples/starwars_django>`__
- **SQLAlchemy model mapping**: `Flask SQLAlchemy
example <examples/flask_sqlalchemy>`__
Contributing
------------
After cloning this repo, ensure dependencies are installed by running:
.. code:: sh
python setup.py install
After developing, the full test suite can be evaluated by running:
.. code:: sh
python setup.py test # Use --pytest-args="-v -s" for verbose mode
.. |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

15
SECURITY.md Normal file
View File

@ -0,0 +1,15 @@
# Security Policy
## Supported Versions
Support for security issues is currently provided for Graphene 3.0 and above. Support on earlier versions cannot be guaranteed by the maintainers of this library, but community PRs may be accepted in critical cases.
The preferred mitigation strategy is via an upgrade to Graphene 3.
| Version | Supported |
| ------- | ------------------ |
| 3.x | :white_check_mark: |
| <3.x | :x: |
## Reporting a Vulnerability
Please use responsible disclosure by contacting a core maintainer via Discord or E-Mail.

190
UPGRADE-v1.0.md Normal file
View File

@ -0,0 +1,190 @@
# v1.0 Upgrade Guide
Big changes from v0.10.x to 1.0. While on the surface a lot of this just looks like shuffling around API, the entire codebase has been rewritten to handle some really great use cases and improved performance.
## Backwards Compatibility and Deprecation Warnings
This has been a community project from the start, we need your help making the upgrade as smooth as possible for everybody!
We have done our best to provide backwards compatibility with deprecated APIs.
## Deprecations
- `with_context` is no longer needed. Resolvers now always take the context argument.
Before:
```python
def resolve_xxx(root, args, info):
# ...
```
With 1.0:
```python
def resolve_xxx(root, args, context, info):
# ...
```
- `ObjectType` and `Interface` no longer accept the `abstract` option in the `Meta`.
Inheriting fields should be now achieved using `AbstractType` inheritance.
Before:
```python
class MyBaseQuery(graphene.ObjectType):
my_field = String()
class Meta:
abstract = True
class Query(MyBaseQuery):
pass
```
With 1.0:
```python
class MyBaseQuery(graphene.AbstractType):
my_field = String()
class Query(MyBaseQuery, graphene.ObjectType):
pass
```
- The `type_name` option in the Meta in types is now `name`
- Type references no longer work with strings, but with functions.
Before:
```python
class Query(graphene.ObjectType):
user = graphene.Field('User')
users = graphene.List('User')
```
With 1.0:
```python
class Query(graphene.ObjectType):
user = graphene.Field(lambda: User)
users = graphene.List(lambda: User)
```
## Schema
Schemas in graphene `1.0` are `Immutable`, that means that once you create a `graphene.Schema` any
change in their attributes will not have any effect.
The `name` argument is removed from the Schema.
The arguments `executor` and `middlewares` are also removed from the `Schema` definition.
You can still use them, but by calling explicitly in the `execute` method in `graphql`.
```python
# Old way
schema = graphene.Schema(name='My Schema')
schema.query = Query
schema.mutation = Mutation
# New way
schema = graphene.Schema(
query=Query,
mutation=Mutation
)
```
## Interfaces
For implementing an Interface in an ObjectType, you have to add it onto `Meta.interfaces`.
Like:
```python
from graphene import Interface, ObjectType, String
class Character(Interface):
name = String()
class Human(Character): # Old way, Human will still be an Interface
pass
class Droid(ObjectType): # New way, you have to specify the ObjectType
class Meta:
interfaces = (Character, )
```
## Mutations
Mutation fields have changed the way of usage, before if you have the mutation `MyMutation` you
only have to reference with `graphene.Field(MyMutation)` now it's simply `MyMutation.Field()`
Example:
```python
from graphene import ObjectType, Mutation, String
class ReverseString(Mutation):
class Input:
input = String(required=True)
reversed = String()
def mutate(root, args, context, info):
reversed = args.get('input')[::-1]
return ReverseString(reversed=reversed)
class Query(ObjectType):
reverse_string = graphene.Field(ReverseString) # Old way, will not include the mutation arguments by default
reverse_string = ReverseString.Field()
```
## Nodes
Apart from implementing as shown in the previous section, to use the node field you have to
specify the node Type.
Example:
```python
from graphene import ObjectType, relay
class Query(ObjectType):
node = relay.NodeField() # Old way, NodeField no longer exists. Use Node.Field
node = relay.Node.Field() # New way
```
Also, if you wanted to create an `ObjectType` that implements `Node`, you have to do it
explicitly.
## Django
The Django integration with Graphene now has an independent package: `graphene-django`.
For installing, you have to replace the old `graphene[django]` with `graphene-django`.
- As the package is now independent, you now have to import from `graphene_django`.
- **DjangoNode no longer exists**, please use `relay.Node` instead:
```python
from graphene.relay import Node
from graphene_django import DjangoObjectType
class Droid(DjangoObjectType):
class Meta:
interfaces = (Node, )
```
## SQLAlchemy
The SQLAlchemy integration with Graphene now has an independent package: `graphene-sqlalchemy`.
For installing, you have to replace the old `graphene[sqlalchemy]` with `graphene-sqlalchemy`.
- As the package is now independent, you have to import now from `graphene_sqlalchemy`.
- **SQLAlchemyNode no longer exists**, please use `relay.Node` instead:
```python
from graphene.relay import Node
from graphene_sqlalchemy import SQLAlchemyObjectType
class Droid(SQLAlchemyObjectType):
class Meta:
interfaces = (Node, )
```

385
UPGRADE-v2.0.md Normal file
View File

@ -0,0 +1,385 @@
# v2.0 Upgrade Guide
`ObjectType`, `Interface`, `InputObjectType`, `Scalar` and `Enum` implementations
have been quite simplified, without the need to define a explicit Metaclass for each subtype.
It also improves the field resolvers, [simplifying the code](#simpler-resolvers) the
developer has to write to use them.
**Deprecations:**
- [`AbstractType`](#abstracttype-deprecated)
- [`resolve_only_args`](#resolve_only_args)
- [`Mutation.Input`](#mutationinput)
**Breaking changes:**
- [`Simpler Resolvers`](#simpler-resolvers)
- [`Node Connections`](#node-connections)
**New Features!**
- [`InputObjectType`](#inputobjecttype)
- [`Meta as Class arguments`](#meta-as-class-arguments) (_only available for Python 3_)
> The type metaclasses are now deleted as they are no longer necessary. If your code was depending
> on this strategy for creating custom attrs, see an [example on how to do it in 2.0](https://github.com/graphql-python/graphene/blob/v2.0.0/graphene/tests/issues/test_425.py).
## Deprecations
### AbstractType deprecated
AbstractType is deprecated in graphene 2.0, you can now use normal inheritance instead.
Before:
```python
class CommonFields(AbstractType):
name = String()
class Pet(CommonFields, Interface):
pass
```
With 2.0:
```python
class CommonFields(object):
name = String()
class Pet(CommonFields, Interface):
pass
```
### resolve_only_args
`resolve_only_args` is now deprecated as the resolver API has been simplified.
Before:
```python
class User(ObjectType):
name = String()
@resolve_only_args
def resolve_name(root):
return root.name
```
With 2.0:
```python
class User(ObjectType):
name = String()
def resolve_name(root, info):
return root.name
```
### Mutation.Input
`Mutation.Input` is now deprecated in favor of using `Mutation.Arguments` (`ClientIDMutation` still uses `Input`).
Before:
```python
class User(Mutation):
class Input:
name = String()
```
With 2.0:
```python
class User(Mutation):
class Arguments:
name = String()
```
## Breaking Changes
### Simpler resolvers
All the resolvers in graphene have been simplified.
Prior to Graphene `2.0`, all resolvers required four arguments: `(root, args, context, info)`.
Now, resolver `args` are passed as keyword arguments to the function, and `context` argument dissapeared in favor of `info.context`.
Before:
```python
my_field = graphene.String(my_arg=graphene.String())
def resolve_my_field(root, args, context, info):
my_arg = args.get('my_arg')
return ...
```
With 2.0:
```python
my_field = graphene.String(my_arg=graphene.String())
def resolve_my_field(root, info, my_arg):
return ...
```
**PS.: Take care with receiving args like `my_arg` as above. This doesn't work for optional (non-required) arguments as standard `Connection`'s arguments (first, last, after, before).**
You may need something like this:
```python
def resolve_my_field(root, info, known_field1, known_field2, **args): ## get other args with: args.get('arg_key')
```
And, if you need the context in the resolver, you can use `info.context`:
```python
my_field = graphene.String(my_arg=graphene.String())
def resolve_my_field(root, info, my_arg):
context = info.context
return ...
```
### Node Connections
Node types no longer have a `Connection` by default.
In 2.0 and onwards `Connection`s should be defined explicitly.
Before:
```python
class User(ObjectType):
class Meta:
interfaces = [relay.Node]
name = String()
class Query(ObjectType):
user_connection = relay.ConnectionField(User)
```
With 2.0:
```python
class User(ObjectType):
class Meta:
interfaces = [relay.Node]
name = String()
class UserConnection(relay.Connection):
class Meta:
node = User
class Query(ObjectType):
user_connection = relay.ConnectionField(UserConnection)
```
## Node.get_node
The method `get_node` in `ObjectTypes` that have `Node` as interface, changes its API.
From `def get_node(cls, id, context, info)` to `def get_node(cls, info, id)`.
```python
class MyObject(ObjectType):
class Meta:
interfaces = (Node, )
@classmethod
def get_node(cls, id, context, info):
return ...
```
To:
```python
class MyObject(ObjectType):
class Meta:
interfaces = (Node, )
@classmethod
def get_node(cls, info, id):
return ...
```
## Node.get_node_from_global_id
The parameters' order of `get_node_from_global_id` method has changed. You may need to adjust your [Node Root Field](http://docs.graphene-python.org/en/latest/relay/nodes/#node-root-field) and maybe other places that uses this method to obtain an object.
Before:
```python
class RootQuery(object):
...
node = Field(relay.Node, id=ID(required=True))
def resolve_node(root, args, context, info):
node = relay.Node.get_node_from_global_id(args['id'], context, info)
return node
```
Now:
```python
class RootQuery(object):
...
node = Field(relay.Node, id=ID(required=True))
def resolve_node(root, info, id):
node = relay.Node.get_node_from_global_id(info, id)
return node
```
## Mutation.mutate
Now only receives (`root`, `info`, `**kwargs`) and is not a @classmethod
Before:
```python
class SomeMutation(Mutation):
...
@classmethod
def mutate(cls, instance, args, context, info):
...
```
With 2.0:
```python
class SomeMutation(Mutation):
...
def mutate(root, info, **args):
...
```
With 2.0 you can also get your declared (as above) `args` this way:
```python
class SomeMutation(Mutation):
class Arguments:
first_name = String(required=True)
last_name = String(required=True)
...
def mutate(root, info, first_name, last_name):
...
```
## ClientIDMutation.mutate_and_get_payload
Now only receives (`root`, `info`, `**input`)
### Middlewares
If you are using Middelwares, you need to some adjustments:
Before:
```python
class MyGrapheneMiddleware(object):
def resolve(self, next_mw, root, args, context, info):
## Middleware code
return next_mw(root, args, context, info)
```
With 2.0:
```python
class MyGrapheneMiddleware(object):
def resolve(self, next_mw, root, info, **args):
context = info.context
## Middleware code
info.context = context
       return next_mw(root, info, **args)
```
## New Features
### InputObjectType
If you are using `InputObjectType`, you now can access
its fields via `getattr` (`my_input.myattr`) when resolving, instead of
the classic way `my_input['myattr']`.
And also use custom defined properties on your input class.
Example. Before:
```python
class UserInput(InputObjectType):
id = ID(required=True)
def is_valid_input(input):
return input.get('id').startswith('userid_')
class Query(ObjectType):
user = graphene.Field(User, input=UserInput())
@resolve_only_args
def resolve_user(root, input):
user_id = input.get('id')
if is_valid_input(user_id):
return get_user(user_id)
```
With 2.0:
```python
class UserInput(InputObjectType):
id = ID(required=True)
@property
def is_valid(root):
return root.id.startswith('userid_')
class Query(ObjectType):
user = graphene.Field(User, input=UserInput())
def resolve_user(root, info, input):
if input.is_valid:
return get_user(input.id)
```
### Meta as Class arguments
Now you can use the meta options as class arguments (**ONLY PYTHON 3**).
Before:
```python
class Dog(ObjectType):
class Meta:
interfaces = [Pet]
name = String()
```
With 2.0:
```python
class Dog(ObjectType, interfaces=[Pet]):
name = String()
```
### Abstract types
Now you can create abstact types super easily, without the need of subclassing the meta.
```python
class Base(ObjectType):
class Meta:
abstract = True
id = ID()
def resolve_id(root, info):
return f"{root.__class__.__name__}_{root.id}"
```
### UUID Scalar
In Graphene 2.0 there is a new dedicated scalar for UUIDs, `UUID`.

View File

@ -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/

View File

@ -1,3 +0,0 @@
{
"stage": 0
}

29
docs/.gitignore vendored
View File

@ -1,29 +0,0 @@
# Logs
logs
*.log
# Runtime data
pids
*.pid
*.seed
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# node-waf configuration
.lock-wscript
# Compiled binary addons (http://nodejs.org/api/addons.html)
build/Release
# Dependency directory
# https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
node_modules
public/

208
docs/Makefile Normal file
View File

@ -0,0 +1,208 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of"
@grep -E '^\.PHONY: [a-zA-Z_-]+ .*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = "(: |##)"}; {printf "\033[36m%-30s\033[0m %s\n", $$2, $$3}'
.PHONY: install ## to install all documentation related requirements
install:
pip install -r requirements.txt
.PHONY: clean ## to remove all built documentation
clean:
rm -rf $(BUILDDIR)/*
.PHONY: html ## to make standalone HTML files
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: dirhtml ## to make HTML files named index.html in directories
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml ## to make a single large HTML file
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: pickle ## to make pickle files
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
.PHONY: json ## to make JSON files
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
.PHONY: htmlhelp ## to make HTML files and a HTML help project
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
.PHONY: qthelp ## to make HTML files and a qthelp project
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Graphene.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Graphene.qhc"
.PHONY: applehelp ## to make an Apple Help Book
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
.PHONY: devhelp ## to make HTML files and a Devhelp project
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/Graphene"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Graphene"
@echo "# devhelp"
.PHONY: epub ## to make an epub
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
.PHONY: epub3 ## to make an epub3
epub3:
$(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3
@echo
@echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3."
.PHONY: latex ## to make LaTeX files, you can set PAPER=a4 or PAPER=letter
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
.PHONY: latexpdf ## to make LaTeX files and run them through pdflatex
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: latexpdfja ## to make LaTeX files and run them through platex/dvipdfmx
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
.PHONY: text ## to make text files
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: man ## to make manual pages
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
.PHONY: texinfo ## to make Texinfo files
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
.PHONY: info ## to make Texinfo files and run them through makeinfo
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
.PHONY: gettext ## to make PO message catalogs
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
.PHONY: changes ## to make an overview of all changed/added/deprecated items
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
.PHONY: linkcheck ## to check all external links for integrity
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
.PHONY: doctest ## to run all doctests embedded in the documentation (if enabled)
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
.PHONY: coverage ## to run coverage check of the documentation (if enabled)
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
.PHONY: xml ## to make Docutils-native XML files
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
.PHONY: pseudoxml ## to make pseudoxml-XML files for display purposes
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
.PHONY: dummy ## to check syntax errors of document sources
dummy:
$(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy
@echo
@echo "Build finished. Dummy builder generates no files."
.PHONY: livehtml ## to build and serve live-reloading documentation
livehtml:
sphinx-autobuild -b html --watch ../graphene $(ALLSPHINXOPTS) $(BUILDDIR)/html

View File

@ -1,43 +0,0 @@
# Graphene Docs
Graphene docs are powered by [gatsby](https://github.com/gatsbyjs/gatsby).
## Installation
For running locally this docs. You have to execute
```bash
npm install -g gatsby && npm install
```
And then
```bash
gatsby develop
```
## Playground
If you want to have the playground running too, just execute
```
./playground/graphene-js/build.sh
```
This command will clone the [pypyjs-release-nojit](https://github.com/pypyjs/pypyjs-release-nojit) repo, update it with the latest graphene, graphql-core and graphql-relay code, and make it available for the `/playground` view in the docs.
## Build
For building the docs into the `public` dir, just run:
```bash
npm run build
```
## Automation
Thanks to [Travis](https://github.com/graphql-python/graphene/blob/master/.travis.yml#L39-L58), we automated the way documentation is updated in the `gh-pages` branch.
Each time we modify the docs in the `master` branch the travis job runs and updates the `gh-pages` branch with the latest code, so [Graphene's website](http://graphene-python.org) have always the latest docs.

110
docs/api/index.rst Normal file
View File

@ -0,0 +1,110 @@
API Reference
=============
Schema
------
.. autoclass:: graphene.types.schema.Schema
:members:
.. Uncomment sections / types as API documentation is fleshed out
.. in each class
Object types
------------
.. autoclass:: graphene.ObjectType
.. autoclass:: graphene.InputObjectType
.. autoclass:: graphene.Mutation
:members:
.. _fields-mounted-types:
Fields (Mounted Types)
----------------------
.. autoclass:: graphene.Field
.. autoclass:: graphene.Argument
.. autoclass:: graphene.InputField
Fields (Unmounted Types)
------------------------
.. autoclass:: graphene.types.unmountedtype.UnmountedType
GraphQL Scalars
---------------
.. autoclass:: graphene.Int()
.. autoclass:: graphene.Float()
.. autoclass:: graphene.String()
.. autoclass:: graphene.Boolean()
.. autoclass:: graphene.ID()
Graphene Scalars
----------------
.. autoclass:: graphene.Date()
.. autoclass:: graphene.DateTime()
.. autoclass:: graphene.Time()
.. autoclass:: graphene.Decimal()
.. autoclass:: graphene.UUID()
.. autoclass:: graphene.JSONString()
.. autoclass:: graphene.Base64()
Enum
----
.. autoclass:: graphene.Enum()
Structures
----------
.. autoclass:: graphene.List
.. autoclass:: graphene.NonNull
Type Extension
--------------
.. autoclass:: graphene.Interface()
.. autoclass:: graphene.Union()
Execution Metadata
------------------
.. autoclass:: graphene.ResolveInfo
.. autoclass:: graphene.Context
.. autoclass:: graphql.ExecutionResult
.. Relay
.. -----
.. .. autoclass:: graphene.Node
.. .. autoclass:: graphene.GlobalID
.. .. autoclass:: graphene.ClientIDMutation
.. .. autoclass:: graphene.Connection
.. .. autoclass:: graphene.ConnectionField
.. .. autoclass:: graphene.PageInfo

View File

@ -1,19 +0,0 @@
exports.loadContext = function(callback) {
var context;
context = require.context('./pages', true);
if (module.hot) {
module.hot.accept(context.id, function() {
context = require.context('./pages', true);
return callback(context);
});
}
return callback(context);
};
exports.onRouteChange = function(state) {
if (typeof window !== "undefined" && window.ga) {
window.ga('send', 'pageview', {
page: state.pathname
});
}
}

View File

@ -1,7 +0,0 @@
import React from 'react';
export default class Icon extends React.Component {
render() {
return <span {...this.props} src={null} dangerouslySetInnerHTML={{__html:this.props.src}} />
}
}

View File

@ -1,10 +0,0 @@
<svg width="100%" height="100%" viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg" class="logo"><g fill="none" fill-rule="evenodd"><path class="logo-path" d="M49.17 10.915L15.415 30.29l.058 39.252 34.633 20.082 33.345-18.95-.023-39.79-34.185 19.238" stroke="white" stroke-width="4.987"/>
<g transform="translate(41.5 3)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(8 22.482)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(8 62.33)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(42.382 81.813)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(75.882 62.33)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(75.882 22.482)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
<g transform="translate(42.382 41.964)"><ellipse cx="7.934" cy="7.97" rx="7.934" ry="7.97" fill="white"/></g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

458
docs/conf.py Normal file
View File

@ -0,0 +1,458 @@
import os
import sys
import sphinx_graphene_theme
on_rtd = os.environ.get("READTHEDOCS", None) == "True"
# -*- coding: utf-8 -*-
#
# Graphene documentation build configuration file, created by
# sphinx-quickstart on Sun Sep 11 18:30:51 2016.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
sys.path.insert(0, os.path.abspath(".."))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
"sphinx.ext.autodoc",
"sphinx.ext.intersphinx",
"sphinx.ext.todo",
"sphinx.ext.coverage",
"sphinx.ext.viewcode",
"sphinx.ext.napoleon",
]
if not on_rtd:
extensions += ["sphinx.ext.githubpages"]
# Add any paths that contain templates here, relative to this directory.
templates_path = ["_templates"]
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
# source_suffix = ['.rst', '.md']
source_suffix = ".rst"
# The encoding of source files.
#
# source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = "index"
# General information about the project.
project = "Graphene"
copyright = "Graphene 2016"
author = "Syrus Akbary"
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = "1.0"
# The full version, including alpha/beta/rc tags.
release = "1.0"
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
# language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#
# today = ''
#
# Else, today_fmt is used as the format for a strftime call.
#
# today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"]
# The reST default role (used for this markup: `text`) to use for all
# documents.
#
# default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#
# add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#
# add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#
# show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = "sphinx"
# A list of ignored prefixes for module index sorting.
# modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
# keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = True
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
# html_theme = 'alabaster'
# if on_rtd:
# html_theme = 'sphinx_rtd_theme'
html_theme = "sphinx_graphene_theme"
html_theme_path = [sphinx_graphene_theme.get_html_theme_path()]
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#
# html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
# html_theme_path = []
# The name for this set of Sphinx documents.
# "<project> v<release> documentation" by default.
#
# html_title = u'Graphene v1.0'
# A shorter title for the navigation bar. Default is the same as html_title.
#
# html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#
# html_logo = None
# The name of an image file (relative to this directory) to use as a favicon of
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#
# html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ["_static"]
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#
# html_extra_path = []
# If not None, a 'Last updated on:' timestamp is inserted at every page
# bottom, using the given strftime format.
# The empty string is equivalent to '%b %d, %Y'.
#
# html_last_updated_fmt = None
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#
# html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#
# html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#
# html_additional_pages = {}
# If false, no module index is generated.
#
# html_domain_indices = True
# If false, no index is generated.
#
# html_use_index = True
# If true, the index is split into individual pages for each letter.
#
# html_split_index = False
# If true, links to the reST sources are added to the pages.
#
# html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#
# html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#
# html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#
# html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
# html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr', 'zh'
#
# html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# 'ja' uses this config value.
# 'zh' user can custom change `jieba` dictionary path.
#
# html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#
# html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = "Graphenedoc"
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, "Graphene.tex", "Graphene Documentation", "Syrus Akbary", "manual")
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#
# latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#
# latex_use_parts = False
# If true, show page references after internal links.
#
# latex_show_pagerefs = False
# If true, show URL addresses after external links.
#
# latex_show_urls = False
# Documents to append as an appendix to all manuals.
#
# latex_appendices = []
# It false, will not define \strong, \code, itleref, \crossref ... but only
# \sphinxstrong, ..., \sphinxtitleref, ... To help avoid clash with user added
# packages.
#
# latex_keep_old_macro_names = True
# If false, no module index is generated.
#
# latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [(master_doc, "graphene", "Graphene Documentation", [author], 1)]
# If true, show URL addresses after external links.
#
# man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(
master_doc,
"Graphene",
"Graphene Documentation",
author,
"Graphene",
"One line description of project.",
"Miscellaneous",
)
]
# Documents to append as an appendix to all manuals.
#
# texinfo_appendices = []
# If false, no module index is generated.
#
# texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#
# texinfo_no_detailmenu = False
# -- Options for Epub output ----------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
epub_author = author
epub_publisher = author
epub_copyright = copyright
# The basename for the epub file. It defaults to the project name.
# epub_basename = project
# The HTML theme for the epub output. Since the default themes are not
# optimized for small screen space, using the same theme for HTML and epub
# output is usually not wise. This defaults to 'epub', a theme designed to save
# visual space.
#
# epub_theme = 'epub'
# The language of the text. It defaults to the language option
# or 'en' if the language is not set.
#
# epub_language = ''
# The scheme of the identifier. Typical schemes are ISBN or URL.
# epub_scheme = ''
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A tuple containing the cover image and cover page html template filenames.
#
# epub_cover = ()
# A sequence of (type, uri, title) tuples for the guide element of content.opf.
#
# epub_guide = ()
# HTML files that should be inserted before the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#
# epub_pre_files = []
# HTML files that should be inserted after the pages created by sphinx.
# The format is a list of tuples containing the path and title.
#
# epub_post_files = []
# A list of files that should not be packed into the epub file.
epub_exclude_files = ["search.html"]
# The depth of the table of contents in toc.ncx.
#
# epub_tocdepth = 3
# Allow duplicate toc entries.
#
# epub_tocdup = True
# Choose between 'default' and 'includehidden'.
#
# epub_tocscope = 'default'
# Fix unsupported image types using the Pillow.
#
# epub_fix_images = False
# Scale large images.
#
# epub_max_image_width = 0
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#
# epub_show_urls = 'inline'
# If false, no index is generated.
#
# epub_use_index = True
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {
"https://docs.python.org/": None,
"python": ("https://docs.python.org/", None),
"graphene_django": (
"http://docs.graphene-python.org/projects/django/en/latest/",
None,
),
"graphene_sqlalchemy": (
"http://docs.graphene-python.org/projects/sqlalchemy/en/latest/",
None,
),
}

View File

@ -1,38 +0,0 @@
siteTitle = "Graphene"
ga = "UA-12613282-7"
[docs.quickstart]
name = "Quickstart"
pages = [
"/docs/quickstart/",
]
[docs.walkthrough]
name = "Walkthrough"
pages = [
"/docs/interfaces/",
"/docs/objecttypes/",
"/docs/resolvers/",
"/docs/mutations/",
"/docs/basic-types/",
"/docs/enums/",
"/docs/relay/",
"/docs/middleware/",
]
[docs.django]
name = "Django"
pages = [
"/docs/django/tutorial/",
"/docs/django/filtering/",
"/docs/django/authorization/",
"/docs/django/introspection-schema/",
"/docs/django/debug/",
]
[docs.sqlalchemy]
name = "SQLAlchemy"
pages = [
"/docs/sqlalchemy/tutorial/",
"/docs/sqlalchemy/tips/",
]

View File

@ -1,41 +0,0 @@
/* Position and sizing of burger button */
.bm-burger-button {
position: absolute;
width: 24px;
height: 20px;
right: 36px;
top: 42px;
}
/* Color/shape of burger icon bars */
.bm-burger-bars {
background: white;
}
/* Color of close button cross */
.bm-cross {
background: #bdc3c7;
margin-top: -1px;
width: 1px!important;
height: 18px!important;
}
/* Background color of sidebar */
.bm-menu {
background: #3c3c3c;
box-shadow: -1px 0 5px rgba(0,0,0,.15);
}
/* Morph shape necessary with bubble or elastic */
.bm-morph-shape {
fill: white;
}
.bm-menu-wrap {
z-index: 10000!important;
}
/* General menu styles */
.bm-menu {
padding: 2.5em 1.5em 0;
font-size: 1.15em;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,70 +0,0 @@
/**
* GitHub Gist Theme
* Author : Louis Barranqueiro - https://github.com/LouisBarranqueiro
*/
.hljs {
display: block;
background: white;
padding: 0.5em;
color: #333333;
overflow-x: auto;
}
.hljs-comment,
.hljs-meta {
color: #969896;
}
.hljs-string,
.hljs-variable,
.hljs-template-variable,
.hljs-strong,
.hljs-emphasis,
.hljs-quote {
color: #df5000;
}
.hljs-keyword,
.hljs-selector-tag,
.hljs-type {
color: #a71d5d;
}
.hljs-literal,
.hljs-symbol,
.hljs-bullet,
.hljs-attribute {
color: #0086b3;
}
.hljs-section,
.hljs-name {
color: #63a35c;
}
.hljs-tag {
color: #333333;
}
.hljs-title,
.hljs-attr,
.hljs-selector-id,
.hljs-selector-class,
.hljs-selector-attr {
color: #795da3;
}
.hljs-addition {
color: #55a532;
background-color: #eaffea;
}
.hljs-deletion {
color: #bd2c00;
background-color: #ffecec;
}
.hljs-link {
text-decoration: underline;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 372 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 688 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,426 +0,0 @@
@import 'nib'
@import 'jeet'
@import 'https://fonts.googleapis.com/css?family=Raleway:400,500,600,200,100&.css'
normalize-css()
@import 'hljs.css'
@import 'bm.css'
$wrapper
center(960px, pad:20px)
.wrapper
@extend $wrapper
position relative
a, a:hover
text-decoration none
a
color rgb(42,93,173)
p
margin-bottom 1em
html, body
font-family "Helvetica Neue", Helvetica, Arial, sans-serif
font-weight 300
font-size 16px
color #606060
line-height 1.5
height 100%
margin 0
width 100%
.header
clearfix()
position relative
text-align center
background: #DB594C;
background-image: radial-gradient(95% 101%, #E46643 5%, rgba(226,91,72,0.00) 100%)
.logo
width 42px
height @width
vertical-align middle
h1
max-width 380px
font-family 'Raleway', sans-serif
font-weight 200
font-size 42px
color #FFFFFF
line-height 49px
margin 80px auto 40px
z-index 110
.get-started
font-family 'Raleway'
display inline-block
margin 0 auto
font-size 13px
color #FFFFFF
padding 0 18px
text-transform uppercase
font-weight 600
line-height 15px
border 1px solid #FFFFFF
border-radius 2px
padding 12px 18px
z-index 111
position relative
&:hover
background white
color #E05B49
text-decoration none
.header-wrapper
@extend $wrapper
text-align left
padding-top 32px
padding-bottom 32px
position relative
z-index 100
.header-extended
padding-bottom 100px
.header-nav
margin-top 8px
a
font-family 'Raleway'
font-size 13px
color #FFFFFF
margin 0 16px
padding 0 2px
text-transform uppercase
font-weight 600
line-height 15px
position relative
&.active:before
content: ''
width 5px
height 5px
border-radius 3px
display block
position absolute
background white
left 50%
margin-left -3px
bottom -24px
+below(600px)
display none
.bm-burger-button, .bm-menu-wrap, .bm-overlay
display none
+below(600px)
display block
.bm-burger-button
z-index 300!important
.bm-overlay
z-index 1000!important
.bm-item-list
a
font-family 'Raleway'
display block
font-size 15px
color #CCC
margin 6px 0
padding 10px 6px
text-transform uppercase
font-weight 500
line-height 20px
position relative
&:hover
color white
.header-logo
font-family 'Raleway'
font-size 22px
color #FFFFFF
float left
font-weight 500
text-transform uppercase
text-decoration none
.header-nav
float right
.logo
path
stroke-dasharray 250
stroke-dashoffset 250
animation logo-dash .9s ease-in-out forwards
animation-delay .12s
g
ellipse
animation logo-dot .3s ease forwards
animation-fill-mode both
transform-origin 50% 50%
&:nth-child(2)
ellipse
animation-delay .1s
&:nth-child(3)
ellipse
animation-delay .2s
&:nth-child(4)
ellipse
animation-delay .3s
&:nth-child(5)
ellipse
animation-delay .4s
&:nth-child(6)
ellipse
animation-delay .5s
&:nth-child(7)
ellipse
animation-delay .6s
&:nth-child(8)
ellipse
animation-delay .7s
@keyframes logo-dash
to
stroke-dashoffset 0
@keyframes logo-dot
from
opacity 0.5
transform scale(0)
to
opacity 1
transform scale(1)
#header-background
z-index 0
display block
position absolute
width 100%
top 0
bottom 0
right 0
left 0
.particles-js-canvas-el
display block
opacity 0
position absolute
.starwars-example-wrapper
+below(600px)
margin-bottom 30px
.starwars-example
background: #3C3C3C
display inline-block
position absolute
right 20px
top -100px
box-shadow: 0px 2px 5px 0px rgba(0,0,0,0.25);
border-radius: 100px
font-size 13px
padding 17px 17px 17px 71px
width 236px
box-sizing border-box
color white
font-family 'Raleway'
font-weight 500
transition all .2s ease-in-out
&:before
content: ''
display block
position absolute
left 20px
top 20px
height 32px
width 32px
image './images/starwars-icon.png' 32px 32px
&:hover
transform translateY(-3px)
box-shadow 0px 4px 8px 0px rgba(0,0,0,0.32)
+below(600px)
top -70px
.improve-document-link
position fixed
right 0
bottom 70px
transform-origin 100% 100%
background: #999;
border: 1px solid #919191;
border-radius: 3px 3px 0 0;
border-bottom 0
padding 9px 12px 12px 34px
transform: rotate(270deg) translateX(100%) translateY(3px);
font-size: 11px;
font-weight: 500;
text-transform uppercase
color: #FFFFFF;
letter-spacing: 0.3px;
line-height: 11px;
transition all .2s ease-in-out
&:before
content: ''
display block
position absolute
left 10px
top 8px
height 16px
width 16px
image './images/edit.png' 16px 16px
&:hover
transform: rotate(270deg) translateX(100%)
background #666
border-color #555
+below(600px)
display none
$title
display block
font-family: 'Raleway';
font-weight 500
line-height 1.2em
padding-top .3em
margin-bottom .5em
padding-bottom .5em
color #4A4A4A
.markdown
.wrapper
margin-top 60px
+below(600px)
margin-top 30px
h1, h2, h3, h4, h5, h6
@extend $title
h1
font-size 32px
h2
font-size 26px
h3
font-size 24px
h4
font-size 21px
h5
font-size 18px
h6
font-size 16px
strong
font-weight 500
pre
line-height 20px
background #FAFAFA
padding 20px
white-space: pre
display: block;
color: #333333;
overflow-x: auto;
p code, ul code
background #FAFAFA
padding 2px 4px
border-radius 2px
border 1px solid #CCC
color #000
p + p, p + ul
margin-top -.4em
p + ul
margin-top -.6em
code
font-size 14px
line-height 20px
overflow-x: auto;
margin-bottom 40px
.markdown h1:first-child
margin-top 0
padding-top 0
.page-title
background: #F9F9F9;
padding 48px 0
h1
margin 0 auto
@extend $wrapper
font-family: 'Raleway';
font-size: 40px;
font-weight 200
color: #585858;
line-height: 50px;
+below(600px)
padding 30px 0
.docs
@extend $wrapper
.docs-aside
col(1/4)
margin-top 60px
+below(600px)
padding 20px
width 100%
box-sizing content-box
margin 0 -20px
margin-bottom 30px
background #F9F9F9
.docs-aside-group
display block
margin-bottom 40px
h3
font-family: 'Raleway';
font-weight 500
font-size 12px
text-transform uppercase
line-height 1.2em
margin-bottom 1em
color #AAA
a
display block
font-size 15px
font-weight 400
line-height 22px
height 28px
padding 3px 0
color #4A4A4A
&.active
font-weight 500
line-height 21px
color #E05B49
+below(600px)
display none
.docs-aside-navselect
margin-top -18px
display none
width 100%
+below(600px)
display block
.docs-content
col(3/4)
margin-top 60px
margin-bottom 20px
+below(600px)
margin-top 10px
col(1)
>h1
margin 0
@extend $title
font-size 32px
.docs-next
float right
color #e05b49
font-weight 400

View File

@ -1,148 +0,0 @@
@import 'nib'
@import 'graphiql.css'
.playground
position absolute
top 106px
left 0
right 0
bottom 0
display flex
flex-direction row
min-width 960px
.loading
position absolute
display block
left 0
right 0
bottom 0
top 0
z-index 10000
background rgba(255,255,255,.6)
.playground-schema
min-width 400px
width 36%
border-right 1px solid #E0E0E0
// box-shadow 0 0 8px rgba(0, 0, 0, 0.15)
position relative
z-index 100
display flex
flex-direction: column
.cm-def
.cm-variable + .cm-keyword // lambda
&:not(.CodeMirror-lint-mark-error)
transition all .3s ease-in-out
background transparent
.activeline
.cm-def
.cm-variable + .cm-keyword // lambda
$color = #D7D3F1
// $color = rgba(219, 89, 76, .2)
background $color
border-radius 1px
box-shadow 0 0 0 2px $color
.playground-schema-editor
flex 1
position relative
.CodeMirror
font-size: 13px;
position absolute
height 100%
width 100%
top 0
left 0
right 0
bottom 0
font-family: 'Consolas', 'Inconsolata', 'Droid Sans Mono', 'Monaco', monospace;
color: #141823;
.CodeMirror-lines
padding 20px 0
.playground-schema-header
// height 48px
// font-family 'Raleway', sans-serif
// font-weight 300
// line-height 48px
// padding 0 10px
// border-bottom solid 1px #d0d0d0
height: 48px;
box-sizing border-box
font-family: 'Raleway', sans-serif;
color: #999;
font-weight: 600;
font-size: 12px;
text-transform: uppercase;
line-height: 52px;
padding: 0 12px;
border-bottom: solid 1px #d0d0d0;
background: #F9F9F9;
.playground-graphiql
flex 1
height 100%
.cm-s-graphene
/* Comment */
.cm-s-graphene .cm-comment
color: #999;
/* Punctuation */
.cm-s-graphene .cm-punctuation
color: #555;
/* Keyword */
.cm-s-graphene .cm-keyword
// color: #B11A04;
// color #D2054E
color #a71d5d
/* OperationName, FragmentName */
.cm-s-graphene .cm-def
// color: #D2054E;
color: #1F61A0;
/* FieldName */
.cm-s-graphene .cm-property
color: #333;
/* FieldAlias */
.cm-s-graphene .cm-qualifier
color: #1C92A9;
/* ArgumentName and ObjectFieldName */
.cm-s-graphene .cm-attribute
color: #8B2BB9;
/* Number */
.cm-s-graphene .cm-number
color: #2882F9;
/* String */
.cm-s-graphene .cm-string
color: #D64292;
/* Boolean */
.cm-s-graphene .cm-builtin
color: #D47509;
/* EnumValue */
.cm-s-graphene .cm-string-2
color: #0B7FC7;
/* Variable */
.cm-s-graphene .cm-variable
color: #333;
/* Directive */
.cm-s-graphene .cm-meta
color: #B33086;
/* Type */
.cm-s-graphene .cm-atom
color: #CA9800;

View File

@ -0,0 +1,117 @@
Dataloader
==========
DataLoader is a generic utility to be used as part of your application's
data fetching layer to provide a simplified and consistent API over
various remote data sources such as databases or web services via batching
and caching. It is provided by a separate package `aiodataloader <https://pypi.org/project/aiodataloader/>`.
Batching
--------
Batching is not an advanced feature, it's DataLoader's primary feature.
Create loaders by providing a batch loading function.
.. code:: python
from aiodataloader import DataLoader
class UserLoader(DataLoader):
async def batch_load_fn(self, keys):
# Here we call a function to return a user for each key in keys
return [get_user(id=key) for key in keys]
A batch loading async function accepts a list of keys, and returns a list of ``values``.
``DataLoader`` will coalesce all individual loads which occur within a
single frame of execution (executed once the wrapping event loop is resolved)
and then call your batch function with all requested keys.
.. code:: python
user_loader = UserLoader()
user1 = await user_loader.load(1)
user1_best_friend = await user_loader.load(user1.best_friend_id)
user2 = await user_loader.load(2)
user2_best_friend = await user_loader.load(user2.best_friend_id)
A naive application may have issued *four* round-trips to a backend for the
required information, but with ``DataLoader`` this application will make at most *two*.
Note that loaded values are one-to-one with the keys and must have the same
order. This means that if you load all values from a single query, you must
make sure that you then order the query result for the results to match the keys:
.. code:: python
class UserLoader(DataLoader):
async def batch_load_fn(self, keys):
users = {user.id: user for user in User.objects.filter(id__in=keys)}
return [users.get(user_id) for user_id in keys]
``DataLoader`` allows you to decouple unrelated parts of your application without
sacrificing the performance of batch data-loading. While the loader presents
an API that loads individual values, all concurrent requests will be coalesced
and presented to your batch loading function. This allows your application to
safely distribute data fetching requirements throughout your application and
maintain minimal outgoing data requests.
Using with Graphene
-------------------
DataLoader pairs nicely well with Graphene/GraphQL. GraphQL fields are designed
to be stand-alone functions. Without a caching or batching mechanism, it's easy
for a naive GraphQL server to issue new database requests each time a field is resolved.
Consider the following GraphQL request:
.. code::
{
me {
name
bestFriend {
name
}
friends(first: 5) {
name
bestFriend {
name
}
}
}
}
If ``me``, ``bestFriend`` and ``friends`` each need to send a request to the backend,
there could be at most 13 database requests!
When using DataLoader, we could define the User type using our previous example with
leaner code and at most 4 database requests, and possibly fewer if there are cache hits.
.. code:: python
class User(graphene.ObjectType):
name = graphene.String()
best_friend = graphene.Field(lambda: User)
friends = graphene.List(lambda: User)
async def resolve_best_friend(root, info):
return await user_loader.load(root.best_friend_id)
async def resolve_friends(root, info):
return await user_loader.load_many(root.friend_ids)

138
docs/execution/execute.rst Normal file
View File

@ -0,0 +1,138 @@
.. _SchemaExecute:
Executing a query
=================
For executing a query against a schema, you can directly call the ``execute`` method on it.
.. code:: python
from graphene import Schema
schema = Schema(...)
result = schema.execute('{ name }')
``result`` represents the result of execution. ``result.data`` is the result of executing the query, ``result.errors`` is ``None`` if no errors occurred, and is a non-empty list if an error occurred.
.. _SchemaExecuteContext:
Context
_______
You can pass context to a query via ``context``.
.. code:: python
from graphene import ObjectType, String, Schema
class Query(ObjectType):
name = String()
def resolve_name(root, info):
return info.context.get('name')
schema = Schema(Query)
result = schema.execute('{ name }', context={'name': 'Syrus'})
assert result.data['name'] == 'Syrus'
Variables
_________
You can pass variables to a query via ``variables``.
.. code:: python
from graphene import ObjectType, Field, ID, Schema
class Query(ObjectType):
user = Field(User, id=ID(required=True))
def resolve_user(root, info, id):
return get_user_by_id(id)
schema = Schema(Query)
result = schema.execute(
'''
query getUser($id: ID) {
user(id: $id) {
id
firstName
lastName
}
}
''',
variables={'id': 12},
)
Root Value
__________
Value used for :ref:`ResolverParamParent` in root queries and mutations can be overridden using ``root`` parameter.
.. code:: python
from graphene import ObjectType, Field, Schema
class Query(ObjectType):
me = Field(User)
def resolve_user(root, info):
return {'id': root.id, 'firstName': root.name}
schema = Schema(Query)
user_root = User(id=12, name='bob')
result = schema.execute(
'''
query getUser {
user {
id
firstName
lastName
}
}
''',
root=user_root
)
assert result.data['user']['id'] == user_root.id
Operation Name
______________
If there are multiple operations defined in a query string, ``operation_name`` should be used to indicate which should be executed.
.. code:: python
from graphene import ObjectType, Field, Schema
class Query(ObjectType):
user = Field(User)
def resolve_user(root, info):
return get_user_by_id(12)
schema = Schema(Query)
query_string = '''
query getUserWithFirstName {
user {
id
firstName
lastName
}
}
query getUserWithFullName {
user {
id
fullName
}
}
'''
result = schema.execute(
query_string,
operation_name='getUserWithFullName'
)
assert result.data['user']['fullName']

View File

@ -0,0 +1,8 @@
File uploading
==============
File uploading is not part of the official GraphQL spec yet and is not natively
implemented in Graphene.
If your server needs to support file uploading then you can use the library: `graphene-file-upload <https://github.com/lmcgartland/graphene-file-upload>`_ which enhances Graphene to add file
uploads and conforms to the unoffical GraphQL `multipart request spec <https://github.com/jaydenseric/graphql-multipart-request-spec>`_.

13
docs/execution/index.rst Normal file
View File

@ -0,0 +1,13 @@
=========
Execution
=========
.. toctree::
:maxdepth: 2
execute
middleware
dataloader
fileuploading
subscriptions
queryvalidation

View File

@ -0,0 +1,70 @@
Middleware
==========
You can use ``middleware`` to affect the evaluation of fields in your schema.
A middleware is any object or function that responds to ``resolve(next_middleware, *args)``.
Inside that method, it should either:
- Send ``resolve`` to the next middleware to continue the evaluation; or
- Return a value to end the evaluation early.
Resolve arguments
-----------------
Middlewares ``resolve`` is invoked with several arguments:
- ``next`` represents the execution chain. Call ``next`` to continue evaluation.
- ``root`` is the root value object passed throughout the query.
- ``info`` is the resolver info.
- ``args`` is the dict of arguments passed to the field.
Example
-------
This middleware only continues evaluation if the ``field_name`` is not ``'user'``
.. code:: python
class AuthorizationMiddleware(object):
def resolve(self, next, root, info, **args):
if info.field_name == 'user':
return None
return next(root, info, **args)
And then execute it with:
.. code:: python
result = schema.execute('THE QUERY', middleware=[AuthorizationMiddleware()])
If the ``middleware`` argument includes multiple middlewares,
these middlewares will be executed bottom-up, i.e. from last to first.
Functional example
------------------
Middleware can also be defined as a function. Here we define a middleware that
logs the time it takes to resolve each field:
.. code:: python
from time import time as timer
def timing_middleware(next, root, info, **args):
start = timer()
return_value = next(root, info, **args)
duration = round((timer() - start) * 1000, 2)
parent_type_name = root._meta.name if root and hasattr(root, '_meta') else ''
logger.debug(f"{parent_type_name}.{info.field_name}: {duration} ms")
return return_value
And then execute it with:
.. code:: python
result = schema.execute('THE QUERY', middleware=[timing_middleware])

View File

@ -0,0 +1,123 @@
Query Validation
================
GraphQL uses query validators to check if Query AST is valid and can be executed. Every GraphQL server implements
standard query validators. For example, there is an validator that tests if queried field exists on queried type, that
makes query fail with "Cannot query field on type" error if it doesn't.
To help with common use cases, graphene provides a few validation rules out of the box.
Depth limit Validator
---------------------
The depth limit validator helps to prevent execution of malicious
queries. It takes in the following arguments.
- ``max_depth`` is the maximum allowed depth for any operation in a GraphQL document.
- ``ignore`` Stops recursive depth checking based on a field name. Either a string or regexp to match the name, or a function that returns a boolean
- ``callback`` Called each time validation runs. Receives an Object which is a map of the depths for each operation.
Usage
-----
Here is how you would implement depth-limiting on your schema.
.. code:: python
from graphql import validate, parse
from graphene import ObjectType, Schema, String
from graphene.validation import depth_limit_validator
class MyQuery(ObjectType):
name = String(required=True)
schema = Schema(query=MyQuery)
# queries which have a depth more than 20
# will not be executed.
validation_errors = validate(
schema=schema.graphql_schema,
document_ast=parse('THE QUERY'),
rules=(
depth_limit_validator(
max_depth=20
),
)
)
Disable Introspection
---------------------
the disable introspection validation rule ensures that your schema cannot be introspected.
This is a useful security measure in production environments.
Usage
-----
Here is how you would disable introspection for your schema.
.. code:: python
from graphql import validate, parse
from graphene import ObjectType, Schema, String
from graphene.validation import DisableIntrospection
class MyQuery(ObjectType):
name = String(required=True)
schema = Schema(query=MyQuery)
# introspection queries will not be executed.
validation_errors = validate(
schema=schema.graphql_schema,
document_ast=parse('THE QUERY'),
rules=(
DisableIntrospection,
)
)
Implementing custom validators
------------------------------
All custom query validators should extend the `ValidationRule <https://github.com/graphql-python/graphql-core/blob/v3.0.5/src/graphql/validation/rules/__init__.py#L37>`_
base class importable from the graphql.validation.rules module. Query validators are visitor classes. They are
instantiated at the time of query validation with one required argument (context: ASTValidationContext). In order to
perform validation, your validator class should define one or more of enter_* and leave_* methods. For possible
enter/leave items as well as details on function documentation, please see contents of the visitor module. To make
validation fail, you should call validator's report_error method with the instance of GraphQLError describing failure
reason. Here is an example query validator that visits field definitions in GraphQL query and fails query validation
if any of those fields are blacklisted:
.. code:: python
from graphql import GraphQLError
from graphql.language import FieldNode
from graphql.validation import ValidationRule
my_blacklist = (
"disallowed_field",
)
def is_blacklisted_field(field_name: str):
return field_name.lower() in my_blacklist
class BlackListRule(ValidationRule):
def enter_field(self, node: FieldNode, *_args):
field_name = node.name.value
if not is_blacklisted_field(field_name):
return
self.report_error(
GraphQLError(
f"Cannot query '{field_name}': field is blacklisted.", node,
)
)

View File

@ -0,0 +1,40 @@
.. _SchemaSubscription:
Subscriptions
=============
To create a subscription, you can directly call the ``subscribe`` method on the
schema. This method is async and must be awaited.
.. code:: python
import asyncio
from datetime import datetime
from graphene import ObjectType, String, Schema, Field
# Every schema requires a query.
class Query(ObjectType):
hello = String()
def resolve_hello(root, info):
return "Hello, world!"
class Subscription(ObjectType):
time_of_day = String()
async def subscribe_time_of_day(root, info):
while True:
yield datetime.now().isoformat()
await asyncio.sleep(1)
schema = Schema(query=Query, subscription=Subscription)
async def main(schema):
subscription = 'subscription { timeOfDay }'
result = await schema.subscribe(subscription)
async for item in result:
print(item.data['timeOfDay'])
asyncio.run(main(schema))
The ``result`` is an async iterator which yields items in the same manner as a query.

View File

@ -1,72 +0,0 @@
var nib = require("nib");
var jeet = require("jeet");
var rupture = require("rupture");
var path = require("path");
var ExtractTextPlugin = require("extract-text-webpack-plugin");
var webpack = require("webpack");
var CopyWebpackPlugin = require('copy-webpack-plugin');
module.exports = function(config, env) {
var IS_STATIC = env === 'static';
var entry = config._config.entry.slice();
var publicPath = config._config.output.publicPath;
// var output = config._config.output;
// output.filename = "[name].js";
config._config.entry = {
bundle: entry,
};
config.merge({
stylus: {
use: [nib(), jeet(), rupture()]
},
output: {
filename: "[name].js",
publicPath: "/",
},
resolveLoader: {
root: path.join(__dirname, "node_modules"),
modulesDirectories: ['./'],
},
resolve: {
root: path.join(__dirname, "node_modules"),
alias: {
'original-react': path.join(__dirname, "node_modules", "react"),
'react/lib': path.join(__dirname, "node_modules", "react", "lib"),
'react': path.join(__dirname, 'patched-react.js'),
'pypyjs': '../playground/graphene-js/pypyjs',
'playground-page': (env != "static")?'../playground/page':'../pages/_empty',
'playground-wrapper': (env == "develop")?'../playground/page':'../playground/wrapper',
},
modulesDirectories: ['./']
}
});
if (IS_STATIC) {
config.plugin('extract-css', ExtractTextPlugin, ["app.css"]);
}
config.plugin('static', CopyWebpackPlugin, [[{ from: '../static'}]]);
config.plugin('define-env', webpack.DefinePlugin, [{
"ENV": JSON.stringify(env),
"PUBLIC_PATH": JSON.stringify(publicPath),
}]);
// if (env != "static") {
// config.plugin('commons', webpack.optimize.CommonsChunkPlugin, ["commons.js"]);
// }
config.loader('stylus', function(cfg) {
cfg.test = /\.styl$/;
if (IS_STATIC) {
cfg.loader = ExtractTextPlugin.extract('style-loader', 'css-loader!stylus-loader', { allChunks: true });
}
else {
cfg.loader = 'style-loader!css-loader!stylus-loader';
}
return cfg
});
config.removeLoader('png');
config.loader('png', function(cfg) {
cfg.test = /\.png$/;
cfg.loader = 'url-loader'
return cfg
})
return config;
};

View File

@ -1,35 +0,0 @@
import React from 'react';
import DocumentTitle from 'react-document-title';
export default class Html extends React.Component {
render() {
var title = this.props.title || DocumentTitle.rewind();
return (
<html lang={this.props.lang}>
<head>
<meta charSet="utf-8"/>
<meta httpEquiv="X-UA-Compatible" content="IE=edge"/>
<meta name='viewport' content='width=device-width, initial-scale=1.0 maximum-scale=1.0'/>
<title>{title}</title>
<link rel="shortcut icon" href="/favicon.png"/>
<link href='https://fonts.googleapis.com/css?family=Raleway:400,600,200,100' rel='stylesheet' type='text/css' />
<link href='/app.css' rel='stylesheet' type='text/css' />
</head>
<body>
<div id="react-mount" dangerouslySetInnerHTML={{__html: this.props.body}} />
<script src="/bundle.js"/>
{this.props.config.ga?<script dangerouslySetInnerHTML={{__html: `
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', '${this.props.config.ga}', 'auto');
ga('send', 'pageview');
`}}
/>:null}
</body>
</html>
);
}
}

26
docs/index.rst Normal file
View File

@ -0,0 +1,26 @@
Graphene
========
Contents:
.. toctree::
:maxdepth: 2
quickstart
types/index
execution/index
relay/index
testing/index
api/index
.. _Integrations:
Integrations
------------
* `Graphene-Django <http://docs.graphene-python.org/projects/django/en/latest/>`_ (`source <https://github.com/graphql-python/graphene-django/>`_)
* Flask-Graphql (`source <https://github.com/graphql-python/flask-graphql>`_)
* `Graphene-SQLAlchemy <http://docs.graphene-python.org/projects/sqlalchemy/en/latest/>`_ (`source <https://github.com/graphql-python/graphene-sqlalchemy/>`_)
* `Graphene-Mongo <http://graphene-mongo.readthedocs.io/en/latest/>`_ (`source <https://github.com/graphql-python/graphene-mongo>`_)
* `Starlette <https://www.starlette.io/graphql/>`_ (`source <https://github.com/encode/starlette>`_)
* `FastAPI <https://fastapi.tiangolo.com/advanced/graphql/>`_ (`source <https://github.com/tiangolo/fastapi>`_)

View File

@ -1,37 +0,0 @@
{
"name": "graphene-docs",
"version": "1.0.0",
"description": "Graphene docs",
"main": "n/a",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "npm install && ./node_modules/.bin/gatsby build",
"deploy": "npm run build"
},
"keywords": [
"graphene"
],
"license": "MIT",
"dependencies": {
"codemirror": "5.9.0",
"copy-webpack-plugin": "^0.2.0",
"es6-promise": "^3.0.2",
"extract-text-webpack-plugin": "^0.9.1",
"gatsby": "^0.7.7",
"graphiql": "^0.4.5",
"graphql": "^0.4.13",
"jeet": "^6.1.2",
"lodash": "^3.10.1",
"nib": "^1.1.0",
"react": "^0.14.6",
"radium": "0.14.2",
"react-burger-menu": "1.4.12",
"react-document-title": "^2.0.1",
"react-dom": "^0.14.6",
"react-router": "^0.13.5",
"rupture": "^0.6.1",
"stylus-loader": "^1.4.2",
"url-loader": "^0.5.7",
"webpack": "^1.12.9"
}
}

View File

@ -1,9 +0,0 @@
import React from 'react';
class Empty extends React.Component {
render() {
return <div />;
}
}
module.exports = Empty;

View File

@ -1,156 +0,0 @@
var IN_BROWSER = typeof window != 'undefined';
import React from 'react';
var browser_supported;
if (IN_BROWSER) {
var isSafari = navigator.vendor && navigator.vendor.indexOf('Apple') > -1 &&
navigator.userAgent && !navigator.userAgent.match('CriOS');
var browser_supported = !isSafari;
}
if (IN_BROWSER && browser_supported) {
var glfx = require('../vendor/glfx.optim')
var particlesJS = require('../vendor/particles.js')
}
class Header extends React.Component {
update() {
if (!this.mounted) return;
var w = this.video.width;
var h = this.video.height;
if (window.devicePixelRatio > 1) {
w = w/2;
h = h/2;
}
this.texture._.initFromCanvas(w, h, this.video);
this.canvas.draw(this.texture).tiltShift(0, h*2/3, 10, h*2/3, 15, 200).update();
requestAnimationFrame(this.update.bind(this));
}
componentWillUnmount() {
this.mounted = false;
}
componentDidMount() {
if (!(IN_BROWSER && browser_supported)) return;
this.mounted = true;
new particlesJS('header-background', {
"particles": {
"number": {
"value": 40,
"density": {
"enable": true,
"value_area": 800
}
},
"color": {
"value": "#ffffff"
},
"shape": {
"type": "circle",
"stroke": {
"width": 0,
"color": "#000000"
},
"polygon": {
"nb_sides": 8
}
},
"opacity": {
"value": 1,
"random": true,
"anim": {
"enable": true,
"speed": .1,
"opacity_min": .1,
"sync": true
}
},
"size": {
"value": 2.2,
"random": false,
"anim": {
"enable": false,
"speed": .2,
"size_min": 2.44,
"sync": true
}
},
"line_linked": {
"enable": true,
"distance": 240,
"color": "#ffffff",
"opacity": .2,
"width": 3
},
"move": {
"enable": true,
"speed": 1.1,
"direction": "none",
"random": true,
"straight": false,
"out_mode": "bounce",
"bounce": false,
"attract": {
"enable": false,
"rotateX": 600,
"rotateY": 600
}
}
},
"interactivity": {
"detect_on": "canvas",
"events": {
"onhover": {
"enable": true,
"mode": "repulse"
},
"onclick": {
"enable": true,
"mode": "repulse"
},
"resize": true
},
"modes": {
"grab": {
"distance": 400,
"line_linked": {
"opacity": 1
}
},
"bubble": {
"distance": 250,
"size": 0,
"duration": 2,
"opacity": 0,
"speed": 3
},
"repulse": {
"distance": 73.08694910712113,
"duration": 0.4
},
"push": {
"particles_nb": 4
},
"remove": {
"particles_nb": 2
}
}
},
"retina_detect": true
});
var header_background = document.getElementById('header-background');
this.canvas = glfx.canvas();
this.video = header_background.children[0];
this.context = window.pJSDom[0].pJS.canvas.ctx;
this.texture = this.canvas.texture(this.video);
header_background.appendChild(this.canvas);
requestAnimationFrame(this.update.bind(this));
}
render() {
return (
<div id="header-background">
</div>
);
}
}
module.exports = Header;

View File

@ -1,51 +0,0 @@
import React from 'react';
import { RouteHandler, Link, State } from 'react-router';
import Icon from 'assets/icon'
import {stack as Menu} from 'react-burger-menu';
import Header from './_header'
import logo from '!raw!assets/logo.svg'
import styles from '../css/main.styl'
class Template extends React.Component {
render() {
var path = this.props.page.path;
var isIndex = path == '/';
return (
<div>
<Menu width={200} right>
<span><Link to="/playground/" className={path.indexOf('/playground')==0?"active":null}>Try it out</Link></span>
<span><Link to="/docs/quickstart/" className={path.indexOf('/docs')==0?"active":null}>Docs</Link></span>
<span><Link to="/community/">Community</Link></span>
<a href="https://github.com/graphql-python/graphene/">Github</a>
</Menu>
<header className="header">
<div className="header-wrapper">
<Link className="header-logo" to="/">
<Icon src={logo} />
Graphene
</Link>
<nav className="header-nav">
<Link to="/playground/" className={path.indexOf('/playground')==0?"active":null}>Try it out</Link>
<Link to="/docs/quickstart/" className={path.indexOf('/docs')==0?"active":null}>Docs</Link>
<Link to="/community/">Community</Link>
<a href="https://github.com/graphql-python/graphene/">Github</a>
</nav>
</div>
{isIndex?
<div className="header-extended">
<h1>
GraphQL in Python<br />
made <strong>simple</strong>
</h1>
<Link to="/docs/quickstart/" className="get-started">Get Started</Link>
<Header />
</div>:null}
</header>
<RouteHandler {...this.props}/>
</div>
);
}
}
module.exports = Template;

View File

@ -1,45 +0,0 @@
---
layout: page
title: Community
active_tab: community
description: The biggest GraphQL Community in Python
---
Graphene is constantly developing thanks to an active volunteer community. There are many different places where you discuss Graphene, share your experiences or ask for help. **Your feedback and participation are very welcome**!
If you think working with Graphene is fun, there are many ways you can contribute to it. Please join us in the Slack community and help us shape the next generation APIs.
[![Public Slack Discussion](https://graphql-slack.herokuapp.com/badge.svg)](https://graphql-slack.herokuapp.com/)
## Our Repositories
- **GraphQL Core**: [Source Code] - [PyPI package]
- **GraphQL Relay**: [Source Code][1] - [PyPI package][2]
- **Graphene**: [Source Code][3] - [PyPI package][4]
Django integration:
- **graphql-django-view**: [Source Code][5] - [PyPI package][6]
- **django-graphiql**: [Source Code][7] - [PyPI package][8]
Flask integration:
- **Flask-GraphQL**: [Source Code][9] - [PyPI package][10]
## Other related projects
- [Graphene Todo MVC Example](https://github.com/mickeyinfoshan/graphene_todo) by [@mickeyinfoshan](https://github.com/mickeyinfoshan)
- [Flask GraphQL Demo](https://github.com/amitsaha/flask-graphql-demo) by [@echorand](https://twitter.com/echorand)
- [Example GraphQL application](https://github.com/msoedov/flask-graphql-example) by [@msoedov](https://twitter.com/msoedov) with Flask, pypy/python3 and MongoDB (using Docker containers)
[Source Code]: https://github.com/graphql-python/graphql-core
[PyPI package]: https://pypi.python.org/pypi/graphql-core
[1]: https://github.com/graphql-python/graphql-relay
[2]: https://pypi.python.org/pypi/graphql-relay
[3]: https://github.com/graphql-python/graphene
[4]: https://pypi.python.org/pypi/graphene
[5]: https://github.com/graphql-python/graphql-django-view
[6]: https://pypi.python.org/pypi/graphql-django-view
[7]: https://github.com/graphql-python/django-graphiql
[8]: https://pypi.python.org/pypi/django-graphiql
[9]: https://github.com/graphql-python/flask-graphql
[10]: https://pypi.python.org/pypi/Flask-GraphQL

View File

@ -1,59 +0,0 @@
import React from 'react';
import { RouteHandler, Link, State } from 'react-router';
import _ from 'lodash';
class Template extends React.Component {
goToPage(event) {
event.target.blur();
var page = event.target.value;
this.context.router.transitionTo(page);
}
render() {
var docs = this.props.config.docs;
var docs_index = _.indexBy(this.props.pages, 'path');
var pages = [];
var aside_links = Object.keys(docs).map((key) => {
let group = docs[key];
return <div className="docs-aside-group" key={key}>
<h3>{group.name}</h3>
{group.pages.map((page) => {
pages.push(page)
return <Link key={page} to={page}>{docs_index[page].data.title}</Link>
})}
</div>;
});
var aside_options = Object.keys(docs).map((key) => {
let group = docs[key];
return <optgroup key={key} label={group.name}>
{group.pages.map((page) => {
return <option key={page} value={page}>{docs_index[page].data.title}</option>
})}
</optgroup>;
});
var next_page_index = pages.indexOf(this.props.page.path)+1;
var next_page = pages[next_page_index];
return (
<div>
<div className="page-title"><h1>Documentation</h1></div>
<div className="docs">
<aside className="docs-aside">
{aside_links}
<select className="docs-aside-navselect" value={this.props.page.path} onChange={this.goToPage.bind(this)}>
{aside_options}
</select>
</aside>
<div className="docs-content">
<RouteHandler {...this.props} docs={true}/>
{next_page?<Link className="docs-next" to={next_page}>Next - {docs_index[next_page].data.title} </Link>:null}
</div>
</div>
</div>
);
}
}
Template.contextTypes = {
router: React.PropTypes.func
};
module.exports = Template;

View File

@ -1,107 +0,0 @@
---
title: Basic Types
description: Walkthrough Basic Types
---
# Basic Types
Graphene define the following base Scalar Types:
- `graphene.String`
- `graphene.Int`
- `graphene.Float`
- `graphene.Boolean`
- `graphene.ID`
Also the following Types are available:
- `graphene.List`
- `graphene.NonNull`
Graphene also provides custom scalars for Dates and JSON:
- `graphene.core.types.custom_scalars.DateTime`
- `graphene.core.types.custom_scalars.JSONString`
## Shortcuts
There are some shortcuts for building schemas more easily.
The following are equivalent
```python
# A list of strings
string_list = graphene.List(graphene.String())
string_list = graphene.String().List
# A non-null string
string_non_null = graphene.String().NonNull
string_non_null = graphene.NonNull(graphene.String())
```
## Custom scalars
You can also create a custom scalar for your schema.
If you want to create a DateTime Scalar Type just type:
```python
import datetime
from graphene.core.classtypes import Scalar
from graphql.core.language import ast
class DateTime(Scalar):
'''DateTime'''
@staticmethod
def serialize(dt):
return dt.isoformat()
@staticmethod
def parse_literal(node):
if isinstance(node, ast.StringValue):
return datetime.datetime.strptime(
node.value, "%Y-%m-%dT%H:%M:%S.%f")
@staticmethod
def parse_value(value):
return datetime.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f")
```
## Mounting in ClassTypes
This types if are mounted in a `ObjectType`, `Interface` or `Mutation`,
would act as `Field`s.
```python
class Person(graphene.ObjectType):
name = graphene.String()
# Is equivalent to:
class Person(graphene.ObjectType):
name = graphene.Field(graphene.String())
```
## Mounting in Fields
If the types are mounted in a `Field`, would act as `Argument`s.
```python
graphene.Field(graphene.String(), to=graphene.String())
# Is equivalent to:
graphene.Field(graphene.String(), to=graphene.Argument(graphene.String()))
```
## Using custom object types as argument
To use a custom object type as an argument, you need to inherit `graphene.InputObjectType`, not `graphene.ObjectType`.
```python
class CustomArgumentObjectType(graphene.InputObjectType):
field1 = graphene.String()
field2 = graphene.String()
```
Then, when defining this in an argument, you need to wrap it in an `Argument` object.
```python
graphene.Field(graphene.String(), to=graphene.Argument(CustomArgumentObjectType))
```

View File

@ -1,116 +0,0 @@
---
title: Authorization
description: Details on how to restrict data access
---
# Authorization in Django
There are two main ways you may want to limit access to data when working
with Graphene and Django: limiting which fields are accessible via GraphQL
and limiting which objects a user can access.
Let's use a simple example model.
```python
from django.db import models
class Post(models.Model):
name = models.CharField(max_length=100)
content = models.TextField()
published = models.BooleanField(default=False)
owner = models.ForeignKey('auth.User')
```
## Limiting Field Access
This is easy, simply use the `only_fields` meta attribute.
```python
from graphene.contrib.django.types import DjangoNode
from .models import Post
class PostNode(DjangoNode):
class Meta:
model = Post
only_fields = ('title', 'content')
```
## Queryset Filtering On Lists
In order to filter which objects are available in a queryset-based list,
define a resolve method for that field and return the desired queryset.
```python
from graphene import ObjectType
from graphene.contrib.django.filter import DjangoFilterConnectionField
from .models import Post
class Query(ObjectType):
all_posts = DjangoFilterConnectionField(CategoryNode)
class Meta:
abstract = True
def resolve_all_posts(self, args, info):
return Post.objects.filter(published=True)
```
## User-based Queryset Filtering
If you are using `graphql-django-view` you can access Django's request object
via `with_context` decorator.
```python
from graphene import ObjectType
from graphene.contrib.django.filter import DjangoFilterConnectionField
from .models import Post
class Query(ObjectType):
my_posts = DjangoFilterConnectionField(CategoryNode)
class Meta:
abstract = True
@with_context
def resolve_my_posts(self, args, context, info):
# context will reference to the Django request
if not context.user.is_authenticated():
return []
else:
return Post.objects.filter(owner=context.user)
```
If you're using your own view, passing the request context into the schema is
simple.
```python
result = schema.execute(query, context_value=request)
```
## Filtering ID-based node access
In order to add authorization to id-based node access, we need to add a method
to your `DjangoNode`.
```python
from graphene.contrib.django.types import DjangoNode
from .models import Post
class PostNode(DjangoNode):
class Meta:
model = Post
only_fields = ('title', 'content')
@classmethod
@with_context
def get_node(Cls, id, context, info):
try:
post = Cls._meta.model.objects.get(id=id)
except Cls._meta.model.DoesNotExist:
return None
if post.published or context.user is post.owner:
return Cls(instance)
else:
return None
```

View File

@ -1,55 +0,0 @@
---
title: Django Debug Middleware
description: How to debug Django queries and requests using Graphene
---
# Django Debug Middleware
You can debug your GraphQL queries in a similar way to [django-debug-toolbar](https://django-debug-toolbar.readthedocs.org/),
but outputing in the results in GraphQL response as fields, instead of the graphical HTML interface.
For that, you will need to add the plugin in your graphene schema.
## Installation
For use the Django Debug plugin in Graphene:
* Import `DjangoDebugMiddleware` and add it to the `middlewares` argument when you initiate the `Schema`.
* Add the `debug` field into the schema root `Query` with the value `graphene.Field(DjangoDebug, name='__debug')`.
```python
from graphene.contrib.django.debug import DjangoDebugMiddleware, DjangoDebug
class Query(graphene.ObjectType):
# ...
debug = graphene.Field(DjangoDebug, name='__debug')
schema = graphene.Schema(query=Query, middlewares=[DjangoDebugMiddleware()])
```
## Querying
You can query it for outputing all the sql transactions that happened in the GraphQL request, like:
```graphql
{
# A example that will use the ORM for interact with the DB
allIngredients {
edges {
node {
id,
name
}
}
}
# Here is the debug field that will output the SQL queries
__debug {
sql {
rawSql
}
}
}
```
Note that the `__debug` field must be the last field in your query.

View File

@ -1,159 +0,0 @@
---
title: Filtering
description: Details of how to perform filtering in Graphene Django
---
# Filtering
Graphene integrates with [django-filter](https://django-filter.readthedocs.org)
to provide filtering of results. See the
[usage documentation](https://django-filter.readthedocs.org/en/latest/usage.html#the-filter)
for details on the format for `filter_fields`.
This filtering is only available when using the Django integrations
(i.e. nodes which extend `DjangoNode`). Additionally `django-filter`
is an optional dependency of Graphene. You will need to
install it manually, which can be done as follows:
```bash
# You'll need to django-filter
pip install django-filter
```
**Note: The techniques below are demoed in the
[cookbook example app](https://github.com/graphql-python/graphene/tree/master/examples/cookbook_django).**
## Filterable fields
The `filter_fields` parameter is used to specify the fields which can be filtered upon.
The value specified here is passed directly to `django-filter`, so see the
[filtering documentation](https://django-filter.readthedocs.org/en/latest/usage.html#the-filter)
for full details on the range of options available.
For example:
```python
class AnimalNode(DjangoNode):
class Meta:
# Assume you have an Animal model defined with the following fields
model = Animal
filter_fields = ['name', 'genus', 'is_domesticated']
class Query(ObjectType):
animal = relay.NodeField(AnimalNode)
all_animals = DjangoFilterConnectionField(AnimalNode)
```
You could then perform a query such as:
```graphql
query {
# Note that fields names become camelcased
allAnimals(genus: "cat", isDomesticated: true) {
edges {
node {
id,
name
}
}
}
}
```
You can also make more complex lookup types available:
```python
class AnimalNode(DjangoNode):
class Meta:
model = Animal
# Provide more complex lookup types
filter_fields = {
'name': ['exact', 'icontains', 'istartswith'],
'genus': ['exact'],
'is_domesticated': ['exact'],
}
```
Which you could query as follows:
```graphql
query {
# Note that fields names become camelcased
allAnimals(name_Icontains: "lion") {
edges {
node {
id,
name
}
}
}
}
```
## Orderable fields
Ordering can also be specified using `filter_order_by`. Like `filter_fields`,
this value is also passed directly to `django-filter` as the `order_by` field.
For full details see the
[order_by documentation](https://django-filter.readthedocs.org/en/latest/usage.html#ordering-using-order-by).
For example:
```python
class AnimalNode(DjangoNode):
class Meta:
model = Animal
filter_fields = ['name', 'genus', 'is_domesticated']
# Either a tuple/list of fields upon which ordering is allowed, or
# True to allow filtering on all fields specified in filter_fields
order_by_fields = True
```
You can then control the ordering via the `orderBy` argument:
```graphql
query {
allAnimals(orderBy: "name") {
edges {
node {
id,
name
}
}
}
}
```
## Custom Filtersets
By default Graphene provides easy access to the most commonly used
features of `django-filter`. This is done by transparently creating a
`django_filters.FilterSet` class for you and passing in the values for
`filter_fields` and `order_by_fields`.
However, you may find this to be insufficient. In these cases you can
create your own `Filterset` as follows:
```python
class AnimalNode(DjangoNode):
class Meta:
# Assume you have an Animal model defined with the following fields
model = Animal
filter_fields = ['name', 'genus', 'is_domesticated']
class AnimalFilter(django_filters.FilterSet):
# Do case-insensitive lookups on 'name'
name = django_filters.CharFilter(lookup_type='iexact')
class Meta:
model = Animal
fields = ['name', 'genus', 'is_domesticated']
class Query(ObjectType):
animal = relay.NodeField(AnimalNode)
# We specify our custom AnimalFilter using the filterset_class param
all_animals = DjangoFilterConnectionField(AnimalNode,
filterset_class=AnimalFilter)
```

View File

@ -1,50 +0,0 @@
---
title: Introspection Schema
description: A guide to instrospection schema in Django
---
# Introspection Schema
Relay uses [Babel Relay Plugin](https://facebook.github.io/relay/docs/guides-babel-plugin.html)
that requires you to provide your GraphQL schema data.
Graphene comes with a management command for Django to dump your schema data to
`schema.json` that is compatible with babel-relay-plugin.
## Usage
Include `graphene.contrib.django` to `INSTALLED_APPS` in you project settings:
```python
INSTALLED_APPS += ('graphene.contrib.django')
```
Assuming your Graphene schema is at `tutorial.quickstart.schema`, run the command:
```bash
./manage.py graphql_schema --schema tutorial.quickstart.schema --out schema.json
```
It dumps your full introspection schema to `schema.json` inside your project root
directory. Point `babel-relay-plugin` to this file and you're ready to use Relay
with Graphene GraphQL implementation.
## Advanced Usage
To simplify the command to `./manage.py graphql_schema`, you can specify the
parameters in your settings.py:
```python
GRAPHENE_SCHEMA = 'tutorial.quickstart.schema'
GRAPHENE_SCHEMA_OUTPUT = 'data/schema.json' # defaults to schema.json
```
Running `./manage.py graphql_schema` dumps your schema to
`<project root>/data/schema.json`.
## Help
Run `./manage.py graphql_schema -h` for command usage.

View File

@ -1,312 +0,0 @@
---
title: Quickstart
description: A Quick guide to Graphene in Django
---
# Django Tutorial
Graphene has a number of additional features that are designed to make
working with Django *really simple*.
**Note: The code in this quickstart is pulled from the
[cookbook example app](https://github.com/graphql-python/graphene/tree/master/examples/cookbook_django)**.
## Setup the Django project
We will setup the project, create the following:
* A Django project called `cookbook`
* An app within `cookbook` called `ingredients`
```bash
# Create the project directory
mkdir cookbook
cd cookbook
# Create a virtualenv to isolate our package dependencies locally
virtualenv env
source env/bin/activate # On Windows use `env\Scripts\activate`
# Install Django and Graphene with Django support
pip install django
pip install graphene[django]
pip install django-graphiql
# Set up a new project with a single application
django-admin.py startproject cookbook . # Note the trailing '.' character
django-admin.py startapp ingredients
```
Now sync your database for the first time:
```bash
python manage.py migrate
```
Let's create a few simple models...
## Defining our models
Let's get started with these models:
```python
# cookbook/ingredients/models.py
from django.db import models
class Category(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Ingredient(models.Model):
name = models.CharField(max_length=100)
notes = models.TextField()
category = models.ForeignKey(Category, related_name='ingredients')
def __str__(self):
return self.name
```
## Schema
GraphQL presents your objects to the world as a graph structure rather than a more
hierarchical structure to which you may be accustomed. In order to create this
representation, Graphene needs to know about each *type* of object which will appear in
the graph.
This graph also has a *root type* through which all access begins. This is the `Query` class below.
In this example, we provide the ability to list all ingredients via `all_ingredients`, and the
ability to obtain a specific ingredient via `ingredient`.
Create `cookbook/ingredients/schema.py` and type the following:
```python
# cookbook/ingredients/schema.py
from graphene import relay, ObjectType
from graphene.contrib.django.filter import DjangoFilterConnectionField
from graphene.contrib.django.types import DjangoNode
from cookbook.ingredients.models import Category, Ingredient
# Graphene will automatically map the Category model's fields onto the CategoryNode.
# This is configured in the CategoryNode's Meta class (as you can see below)
class CategoryNode(DjangoNode):
class Meta:
model = Category
filter_fields = ['name', 'ingredients']
filter_order_by = ['name']
class IngredientNode(DjangoNode):
class Meta:
model = Ingredient
# Allow for some more advanced filtering here
filter_fields = {
'name': ['exact', 'icontains', 'istartswith'],
'notes': ['exact', 'icontains'],
'category': ['exact'],
'category__name': ['exact'],
}
filter_order_by = ['name', 'category__name']
class Query(ObjectType):
category = relay.NodeField(CategoryNode)
all_categories = DjangoFilterConnectionField(CategoryNode)
ingredient = relay.NodeField(IngredientNode)
all_ingredients = DjangoFilterConnectionField(IngredientNode)
class Meta:
abstract = True
```
The filtering functionality is provided by
[django-filter](https://django-filter.readthedocs.org). See the
[usage documentation](https://django-filter.readthedocs.org/en/latest/usage.html#the-filter)
for details on the format for `filter_fields`. While optional, this tutorial makes use of this functionality so you will need to install `django-filter` for this tutorial to work:
```bash
pip install django-filter
```
Note that the above `Query` class is marked as 'abstract'. This is because we
will now create a project-level query which will combine all our app-level
queries.
Create the parent project-level `cookbook/schema.py`:
```python
import graphene
import cookbook.ingredients.schema
class Query(cookbook.ingredients.schema.Query):
# This class will inherit from multiple Queries
# as we begin to add more apps to our project
pass
schema = graphene.Schema(name='Cookbook Schema')
schema.query = Query
```
You can think of this as being something like your top-level `urls.py`
file (although it currently lacks any namespacing).
## Update `INSTALLED_APPS`
Next, install your app and GraphiQL in your Django project. GraphiQL is
a web-based integrated development environment to assist in the writing and
executing of GraphQL queries. It will provide us with a simple and easy way
of testing our cookbook project.
Add `ingredients`, `graphene.contrib.django` and `django_graphiql` to
`INSTALLED_APPS` in `cookbook/settings.py`:
```python
INSTALLED_APPS = [
...
'django_graphiql',
# This will also make the `graphql_schema` management command available
'graphene.contrib.django',
# Install the ingredients app
'ingredients',
]
```
## Creating GraphQL and GraphiQL views
Unlike a RESTful API, there is only a single URL from which GraphQL is accessed.
Requests to this URL are handled by Graphene's `GraphQLView` view.
Additionally, we'll add a URL for aforementioned GraphiQL, and for the Django admin
interface (the latter can be useful for creating test data).
```python
from django.conf.urls import url, include
from django.contrib import admin
from django.views.decorators.csrf import csrf_exempt
from graphene.contrib.django.views import GraphQLView
from cookbook.schema import schema
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^graphql', csrf_exempt(GraphQLView.as_view(schema=schema))),
url(r'^graphiql', include('django_graphiql.urls')),
]
```
## Apply model changes to database
Tell Django that we've added models and update the database schema to reflect these additions.
```bash
python manage.py makemigrations
python manage.py migrate
```
## Load some test data
Now is a good time to load up some test data. The easiest option will be to
[download the ingredients.json](https://raw.githubusercontent.com/graphql-python/graphene/master/examples/cookbook_django/cookbook/ingredients/fixtures/ingredients.json)
fixture and place it in
`cookbook/ingredients/fixtures/ingredients.json`. You can then run the following:
```
$ python ./manage.py loaddata ingredients
Installed 6 object(s) from 1 fixture(s)
```
Alternatively you can use the Django admin interface to create some data yourself.
You'll need to run the development server (see below), and create a login
for yourself too (`./manage.py createsuperuser`).
## Testing our GraphQL schema
We're now ready to test the API we've built. Let's fire up the server from the command line.
```bash
$ python ./manage.py runserver
Performing system checks...
Django version 1.9, using settings 'cookbook.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```
Go to [localhost:8000/graphiql](http://localhost:8000/graphiql) and type your first query!
```graphql
query {
allIngredients {
edges {
node {
id,
name
}
}
}
}
```
The above will return the names & IDs for all ingredients. But perhaps you want
a specific ingredient:
```graphql
query {
# Graphene creates globally unique IDs for all objects.
# You may need to copy this value from the results of the first query
ingredient(id: "SW5ncmVkaWVudE5vZGU6MQ==") {
name
}
}
```
You can also get each ingredient for each category:
```graphql
query {
allCategories {
edges {
node {
name,
ingredients {
edges {
node {
name
}
}
}
}
}
}
}
```
Or you can get only 'meat' ingredients containing the letter 'e':
```graphql
query {
# You can also use `category: "CATEGORY GLOBAL ID"`
allIngredients(name_Icontains: "e", category_Name: "Meat") {
edges {
node {
name
}
}
}
}
```

View File

@ -1,33 +0,0 @@
---
title: Enums
description: Walkthrough Enums
---
# Enums
A `Enum` is a special `GraphQL` type that represents a set of symbolic names (members) bound to unique, constant values.
## Enum definition
You can create an `Enum` using classes:
```python
import graphene
class Episode(graphene.Enum):
NEWHOPE = 4
EMPIRE = 5
JEDI = 6
```
But also using instances of Enum:
```python
Episode = graphene.Enum('Episode', [('NEWHOPE', 4), ('EMPIRE', 5), ('JEDI', 6)])
```
## Notes
Internally, `graphene.Enum` uses [`enum.Enum`](https://docs.python.org/3/library/enum.html) Python implementation if available, or a backport if not.
So you can use it in the same way as you would do with Python `enum.Enum`.

View File

@ -1,53 +0,0 @@
---
title: Interfaces
description: Walkthrough Interfaces
---
# Interfaces
An Interface contains the essential fields that will be shared among multiple ObjectTypes.
The basics:
- Each Interface is a Python class that inherits from `graphene.Interface`.
- Each attribute of the Interface represents a GraphQL field.
## Quick example
This example model defines a Character, which has a name. `Human` and `Droid` inherit from it.
```python
import graphene
# Character is an Interface
class Character(graphene.Interface):
name = graphene.String()
# Human is an ObjectType, as inherits an interface
class Human(Character):
born_in = graphene.String()
# Droid is an ObjectType, as inherits an interface
class Droid(Character):
function = graphene.String()
```
**name** is a field in the `Character` interface that will be in both `Human` and `Droid` ObjectTypes (as those inherit from `Character`). Each ObjectType also define extra fields at the same time.
The above types would have the following representation in a schema:
```graphql
interface Character {
name: String
}
type Droid implements Character {
name: String
function: String
}
type Human implements Character {
name: String
bornIn: String
}
```

View File

@ -1,43 +0,0 @@
---
title: Middleware
description: Walkthrough Middleware
---
# Middleware
You can use _middleware_ to affect the evaluation of fields in your schema.
A middleware is any object that responds to `resolve(*args, next_middleware)`. Inside that method, it should either:
* Send `resolve` to the next middleware to continue the evaluation; or
* Return a value to end the evaluation early.
Middlewares' `resolve` is invoked with several arguments:
* `next` represents the execution chain. Call `next` to continue evalution.
* `root` is the root value object passed throughout the query
* `args` is the hash of arguments passed to the field
* `context` is the context object passed throughout the query
* `info` is the resolver info
Add a middleware to a schema by adding to the `middlewares` list.
### Example: Authorization
This middleware only continues evaluation if the `field_name` is not `'user'`:
```python
class AuthorizationMiddleware(object):
def resolve(self, next, root, args, context, info):
if info.field_name == 'user':
return None
return next(root, args, context, info)
```
Then, add the middleware to your schema:
```python
schema = Schema(middlewares=[AuthorizationMiddleware])
```

View File

@ -1,75 +0,0 @@
---
title: Mutations
description: Walkthrough Mutations
---
# Mutations
A Mutation is a special ObjectType that also defines an Input.
## Quick example
This example defines a Mutation:
```python
import graphene
class CreatePerson(graphene.Mutation):
class Input:
name = graphene.String()
ok = graphene.Boolean()
person = graphene.Field('Person')
@classmethod
def mutate(cls, instance, args, info):
person = Person(name=args.get('name'))
ok = True
return CreatePerson(person=person, ok=ok)
```
**person** and **ok** are the output fields of the Mutation when is resolved.
**Input** attributes are the arguments that the Mutation `CreatePerson` needs for resolving, in this case **name** will be the only argument for the mutation.
**mutate** is the function that will be applied once the mutation is called.
So, we can finish our schema like this:
```python
# ... the Mutation Class
class Person(graphene.ObjectType):
name = graphene.String()
class MyMutations(graphene.ObjectType):
create_person = graphene.Field(CreatePerson)
schema = graphene.Schema(mutation=MyMutations)
```
## Executing the Mutation
Then, if we query (`schema.execute(query_str)`) the following:
```graphql
mutation myFirstMutation {
createPerson(name:"Peter") {
person {
name
}
ok
}
}
```
We should receive:
```json
{
"createPerson": {
"person" : {
name: "Peter"
},
"ok": true
}
}

View File

@ -1,49 +0,0 @@
---
title: ObjectTypes
description: Walkthrough ObjectTypes
---
# ObjectTypes
An ObjectType is the single, definitive source of information about your data. It contains the essential fields and behaviors of the data youre querying.
The basics:
- Each ObjectType is a Python class that inherits `graphene.ObjectType` or inherits an implemented [Interface](/docs/interfaces/).
- Each attribute of the ObjectType represents a GraphQL field.
## Quick example
This example model defines a Person, which has a first_name and last_name:
```python
import graphene
class Person(graphene.ObjectType):
first_name = graphene.String()
last_name = graphene.String()
full_name = graphene.String()
def resolve_full_name(self, args, info):
return '{} {}'.format(self.first_name, self.last_name)
```
**first_name** and **last_name** are fields of the ObjectType. Each field is specified as a class attribute, and each attribute maps to a GraphQL field.
The above `Person` ObjectType would have the following representation in a schema:
```graphql
type Person {
firstName: String
lastName: String
fullName: String
}
```
## Instances as containers
Graphene `ObjectType`s could act as containers too.
So with the previous example you could do.
```python
peter = Person(first_name='Peter', last_name='Griffin')
```

View File

@ -1,52 +0,0 @@
---
title: Getting started
description: A Quick guide to Graphene
---
# Getting started
Let's build a basic GraphQL schema from scratch.
## Requirements
- Python (2.6.5+, 2.7, 3.2, 3.3, 3.4, 3.5, pypy)
- Graphene (0.4+)
## Project setup
```bash
pip install graphene
```
## Creating a basic Schema
A GraphQL schema describes your data model, and provides a GraphQL server with an associated set of resolve methods that know how to fetch data.
We are going to create a very simple schema, with a `Query` with only one field: `hello`. And when we query it should return `"World"`.
```python
import graphene
class Query(graphene.ObjectType):
hello = graphene.String()
def resolve_hello(self, args, info):
return 'World'
schema = graphene.Schema(query=Query)
```
## Querying
Then, we can start querying our schema:
```python
result = schema.execute('{ hello }')
print result.data['hello'] # "World"
```
Congrats! You got your first graphene schema working!

View File

@ -1,85 +0,0 @@
---
title: Relay
description: A Relay implementation in Graphene
---
# Relay
Graphene has complete support for [Relay](https://facebook.github.io/relay/docs/graphql-relay-specification.html) and offers some utils to make integration from Python easy.
## Nodes
A `Node` is an Interface provided by `graphene.relay` that contains a single field `id` (which is a `ID!`). Any object that inherits from it have to implement a `get_node` method for retrieving a `Node` by an *id*.
Example usage (taken from the [Starwars Relay example](https://github.com/graphql-python/graphene/blob/master/examples/starwars_relay/schema.py)):
```python
class Ship(relay.Node):
'''A ship in the Star Wars saga'''
name = graphene.String(description='The name of the ship.')
@classmethod
def get_node(cls, id, info):
return get_ship(id)
```
The `id` returned by the `Ship` type when you query it will be a scalar which contains the enough info for the server for knowing it's type and it's id.
For example, the instance `Ship(id=1)` will return `U2hpcDox` as the id when you query it (which is the base64 encoding of `Ship:1`), and which could be useful later if we want to query a node by its id.
## Connection
A connection is a vitaminized version of a List that provides ways of slicing and paginating through it. The way you create Connection fields in `graphene` is using `relay.ConnectionField`.
You can create connection fields in any ObjectType, but the connection **must** be linked to an object which inherits from `Node` (in this case, a `Ship`).
```python
class Faction(graphene.ObjectType):
name = graphene.String()
ships = relay.ConnectionField(Ship)
def resolve_ships(self, args, info):
return []
```
## Node Root field
As is required in the [Relay specification](https://facebook.github.io/relay/graphql/objectidentification.htm#sec-Node-root-field), the server must implement a root field called `node` that returns a `Node` Interface.
For this reason, `graphene` provides the field `relay.NodeField`, which links to any type in the Schema which inherits from `Node`. Example usage:
```python
class Query(graphene.ObjectType):
node = relay.NodeField()
```
## Mutations
Most APIs don't just allow you to read data, they also allow you to write. In GraphQL, this is done using mutations. Just like queries, Relay puts some additional requirements on mutations, but Graphene nicely manages that for you. All you need to do is make your mutation a subclass of `relay.ClientIDMutation`.
```python
class IntroduceShip(relay.ClientIDMutation):
class Input:
ship_name = graphene.String(required=True)
faction_id = graphene.String(required=True)
ship = graphene.Field(Ship)
faction = graphene.Field(Faction)
@classmethod
def mutate_and_get_payload(cls, input, info):
ship_name = input.get('ship_name')
faction_id = input.get('faction_id')
ship = create_ship(ship_name, faction_id)
faction = get_faction(faction_id)
return IntroduceShip(ship=ship, faction=faction)
```
## Useful links
* [Getting started with Relay](https://facebook.github.io/relay/docs/graphql-relay-specification.html)
* [Relay Global Identification Specification](https://facebook.github.io/relay/graphql/objectidentification.htm)
* [Relay Cursor Connection Specification](https://facebook.github.io/relay/graphql/connections.htm)
* [Relay input Object Mutation](https://facebook.github.io/relay/graphql/mutations.htm)

View File

@ -1,62 +0,0 @@
---
title: Resolvers
description: Walkthrough Resolvers
---
# Resolvers
A resolver is a method that resolves certain field within a `ObjectType`.
The resolver of a field will be, if not specified otherwise, the `resolve_{field_name}` within the `ObjectType`.
By default a resolver will take the `args`, and `info` arguments.
*This is likely to be simplified in the future*.
## Quick example
This example model defines a `Query` type, which has a reverse field that reverses the given `word`
argument using the `resolve_reverse` method in the class.
```python
import graphene
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String())
def resolve_reverse(self, args, info):
word = args.get('word')
return word[::-1]
```
## Resolvers outside the class
A field could also specify a custom resolver outside the class:
```python
import graphene
def reverse(root, args, info):
word = args.get('word')
return word[::-1]
class Query(graphene.ObjectType):
reverse = graphene.String(word=graphene.String(), resolver=reverse)
```
## Context
A query in a GraphQL schema could have some context that we can use in any resolver.
In this case we need to decorate the resolver function with `with_context`.
```python
class Query(graphene.ObjectType):
name = graphene.String()
@with_context
def resolve_name(self, args, context, info):
return context['name']
result = schema.execute(query, context_value={'name': 'Peter'})
```

View File

@ -1,30 +0,0 @@
---
title: Tips
description: Tips when SQLAlchemy in Graphene
---
# Tips
## Querying
For make querying to the database work, there are two alternatives:
* Expose the db session when you create the `graphene.Schema`:
```python
schema = graphene.Schema(session=session)
```
* Create a query for the models.
```python
Base = declarative_base()
Base.query = db_session.query_property()
class MyModel(Base):
# ...
```
If you don't specify any, the following error will be displayed:
`A query in the model Base or a session in the schema is required for querying.`

View File

@ -1,199 +0,0 @@
---
title: Tutorial
description: Using SQLAlchemy with Graphene
---
# SQLAlchemy + Flask Tutorial
Graphene comes with builtin support to SQLAlchemy, which makes quite easy to operate with your current models.
**Note: The code in this tutorial is pulled from the
[Flask SQLAlchemy example app](https://github.com/graphql-python/graphene/tree/master/examples/flask_sqlalchemy)**.
## Setup the Project
We will setup the project, execute the following:
```bash
# Create the project directory
mkdir flask_sqlalchemy
cd flask_sqlalchemy
# Create a virtualenv to isolate our package dependencies locally
virtualenv env
source env/bin/activate # On Windows use `env\Scripts\activate`
# SQLAlchemy and Graphene with SQLAlchemy support
pip install SQLAlchemy
pip install graphene[sqlalchemy]
# Install Flask and GraphQL Flask for exposing the schema through HTTP
pip install Flask
pip install Flask-GraphQL
```
## Defining our models
Let's get started with these models:
```python
# flask_sqlalchemy/models.py
from sqlalchemy import *
from sqlalchemy.orm import (scoped_session, sessionmaker, relationship,
backref)
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:///database.sqlite3', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
# We will need this for querying
Base.query = db_session.query_property()
class Department(Base):
__tablename__ = 'department'
id = Column(Integer, primary_key=True)
name = Column(String)
class Employee(Base):
__tablename__ = 'employee'
id = Column(Integer, primary_key=True)
name = Column(String)
hired_on = Column(DateTime, default=func.now())
department_id = Column(Integer, ForeignKey('department.id'))
department = relationship(
Department,
backref=backref('employees',
uselist=True,
cascade='delete,all'))
```
## Schema
GraphQL presents your objects to the world as a graph structure rather than a more
hierarchical structure to which you may be accustomed. In order to create this
representation, Graphene needs to know about each *type* of object which will appear in
the graph.
This graph also has a *root type* through which all access begins. This is the `Query` class below.
In this example, we provide the ability to list all employees via `all_employees`, and the
ability to obtain a specific node via `node`.
Create `flask_sqlalchemy/schema.py` and type the following:
```python
# flask_sqlalchemy/schema.py
import graphene
from graphene import relay
from graphene.contrib.sqlalchemy import SQLAlchemyNode, SQLAlchemyConnectionField
from models import db_session, Department as DepartmentModel, Employee as EmployeeModel
schema = graphene.Schema()
@schema.register
class Department(SQLAlchemyNode):
class Meta:
model = DepartmentModel
@schema.register
class Employee(SQLAlchemyNode):
class Meta:
model = EmployeeModel
class Query(graphene.ObjectType):
node = relay.NodeField()
all_employees = SQLAlchemyConnectionField(Employee)
schema.query = Query
```
## Creating GraphQL and GraphiQL views in Flask
Unlike a RESTful API, there is only a single URL from which GraphQL is accessed.
We are going to use Flask to create a server that expose the GraphQL schema under `/graphql` and a interface for querying it easily: GraphiQL under `/graphiql`.
Fortunately for us, the library `Flask-GraphQL` that we previously installed makes this task quite easy.
```python
# flask_sqlalchemy/app.py
from flask import Flask
from flask_graphql import GraphQL
from models import db_session
from schema import schema, Department
app = Flask(__name__)
app.debug = True
# This is creating the `/graphql` and `/graphiql` endpoints
GraphQL(app, schema=schema)
@app.teardown_appcontext
def shutdown_session(exception=None):
db_session.remove()
if __name__ == '__main__':
app.run()
```
## Creating some data
```bash
$ python
>>> from models import engine, db_session, Base, Department, Employee
>>> Base.metadata.create_all(bind=engine)
>>> # Fill the tables with some data
>>> engineering = Department(name='Engineering')
>>> db_session.add(engineering)
>>> hr = Department(name='Human Resources')
>>> db_session.add(hr)
>>> peter = Employee(name='Peter', department=engineering)
>>> db_session.add(peter)
>>> roy = Employee(name='Roy', department=engineering)
>>> db_session.add(roy)
>>> tracy = Employee(name='Tracy', department=hr)
>>> db_session.add(tracy)
>>> db_session.commit()
```
## Testing our GraphQL schema
We're now ready to test the API we've built. Let's fire up the server from the command line.
```bash
$ python ./app.py
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
```
Go to [localhost:5000/graphiql](http://localhost:5000/graphiql) and type your first query!
```graphql
{
allEmployees {
edges {
node {
id
name
department {
name
}
}
}
}
}
```

View File

@ -1,10 +0,0 @@
---
path: /
---
<div class="starwars-example-wrapper"><a class="starwars-example" href="http://swapi.graphene-python.org/">Check our Django Starwars API example!</a></div>
## Meet Graphene
Graphene is a Python library for building GraphQL schemas/types fast and easily.
**But, what is GraphQL?** A GraphQL query is a string interpreted by a server that returns data in a specified format. We believe *GraphQL* is the next big thing after peanut butter and *REST*.

View File

@ -1,13 +0,0 @@
import React from 'react';
import DocumentTitle from 'react-document-title';
import PlaygroundWrapper from 'playground-wrapper';
class Playground extends React.Component {
render() {
return <DocumentTitle title="Playground - Graphene">
<PlaygroundWrapper />
</DocumentTitle>;
}
}
module.exports = Playground;

View File

@ -1,9 +0,0 @@
// React patched version for render in server side always with same ids
if (typeof window === "undefined") {
var ServerReactRootIndex = require('react/lib/ServerReactRootIndex');
ServerReactRootIndex.createReactRootIndex = function(){
return "graphene";
};
}
module.exports = require('original-react');

View File

@ -1,234 +0,0 @@
import React from 'react';
import ReactDOM from 'react-dom';
import { RouteHandler, Link, State } from 'react-router';
import CodeMirror from 'codemirror';
import { graphql } from 'graphql';
import GraphiQL from 'graphiql';
import schema from './schema';
import pypyjs_vm from 'pypyjs';
import 'codemirror/mode/python/python';
import 'codemirror/addon/lint/lint';
import '../css/playground.styl';
if (typeof PUBLIC_PATH === "undefined") {
var PUBLIC_PATH = '';
}
pypyjs_vm.rootURL = `${PUBLIC_PATH}/playground/lib/`;
pypyjs_vm.cacheKey = 'graphene';
CodeMirror.registerHelper('lint', 'python', function (text, options, editor) {
return (options.errors || []).map((error) => {
var tokens = editor.getLineTokens(error.line - 1);
tokens = tokens.filter((token, pos) => {
return !!token.type || token.string.trim().length > 0;
});
if (!tokens) return [];
return {
message: `${error.name}: ${error.message}`,
severity: 'error',
type: 'syntax',
from: CodeMirror.Pos(error.line - 1, tokens[0].start),
to: CodeMirror.Pos(error.line - 1, tokens[tokens.length-1].end),
};
});
});
function graphQLFetcher(graphQLParams) {
return graphql(schema, graphQLParams.query);
}
var default_interpreter;
class Playground extends React.Component {
constructor() {
super();
this.state = {pypyjs: false, stdout: '', response:''};
}
stdout() {
console.log('stdout', arguments);
}
componentDidMount() {
if (default_interpreter) {
this.pypy_interpreter = default_interpreter;
this.pypy_interpreter.stdout = this.stdout.bind(this);
}
else {
this.pypy_interpreter = new pypyjs_vm({
stdin: function(){},
stdout: this.stdout.bind(this),
stderr: function(){},
rootURL: `${PUBLIC_PATH}/playground/lib/`
});
default_interpreter = this.pypy_interpreter;
}
this.pypyjs = this.pypy_interpreter.ready().then(() => {
return this.pypy_interpreter.exec(`
import graphene
import js
from collections import OrderedDict
from graphql.core.execution.executor import Executor
from graphql.core.execution.middlewares.sync import SynchronousExecutionMiddleware
from graphql.core.error import GraphQLError, format_error
def get_wrapped(f):
if hasattr(f, 'func_closure') and f.func_closure:
return get_wrapped(f.func_closure[0].cell_contents)
return f
class TrackResolver(SynchronousExecutionMiddleware):
@staticmethod
def run_resolve_fn(resolver, original_resolver):
if resolver.func.__module__ == '__main__':
line = get_wrapped(resolver.func).resolver.func_code.co_firstlineno
js.globals.markLine(line-3)
return SynchronousExecutionMiddleware.run_resolve_fn(resolver, original_resolver)
__graphene_executor = Executor([TrackResolver()], map_type=OrderedDict)
`);
}).then(() => {
this.createSchema(this.props.initialSchema);
}).then(() => {
this.setState({pypyjs: true, response:'"Execute the query for see the results"'});
});
window.markLine = (lineNo) => {
this.markLine(lineNo);
}
this.editor = CodeMirror(ReactDOM.findDOMNode(this.refs.schemaCode), {
value: this.props.initialSchema,
mode: "python",
theme: "graphene",
lineNumbers: true,
tabSize: 4,
indentUnit: 4,
gutters: ["CodeMirror-linenumbers", "breakpoints"],
lint: {
errors: [],
},
});
this.editor.on("change", this.onEditorChange.bind(this));
}
onEditorChange() {
if (this.changeTimeout) {
clearTimeout(this.changeTimeout);
}
if (this.props.onEditSchema) {
var value = this.editor.getValue();
if (value != this.props.initialSchema) {
this.props.onEditSchema(value)
}
}
this.changeTimeout = setTimeout(() =>
this.updateSchema()
, 300);
}
updateSchema() {
this.createSchema(this.editor.getValue());
}
createSchema(code) {
if (this.previousCode == code) return;
console.log('createSchema');
this.validSchema = null;
this.pypyjs.then(() => {
return this.pypy_interpreter.exec(`
schema = None
${code}
assert schema, 'You have to define a schema'
`)
}).then(() => {
console.log('NO ERRORS');
this.removeErrors();
this.validSchema = true;
}, (err) => {
this.editor.options.lint.errors = [];
console.log('ERRORS', err);
this.logError(err);
this.validSchema = false;
}).then(this.updateGraphiQL.bind(this));
this.previousCode = code;
}
updateGraphiQL() {
if (this.validSchema) {
this.refs.graphiql.state.schema = null;
this.refs.graphiql.componentDidMount();
this.refs.graphiql.forceUpdate();
this.refs.graphiql.refs.docExplorer.forceUpdate();
}
}
logError(error) {
var lines = error.trace.split('\n');
var file_errors = lines.map((errorLine) => {
return errorLine.match(/File "<string>", line (\d+)/);
}).filter((x) => !! x);
if (!file_errors.length) return;
var line = parseInt(file_errors[file_errors.length-1][1]);
error.line = line-2;
if (error.name == "ImportError" && error.message == "No module named django") {
error.message = "Django is not supported yet in Playground editor";
}
this.editor.options.lint.errors.push(error);
CodeMirror.signal(this.editor, 'change', this.editor);
}
removeErrors() {
this.editor.options.lint.errors = [];
CodeMirror.signal(this.editor, 'change', this.editor);
}
fetcher (graphQLParams) {
if (!this.validSchema) {
return graphQLFetcher(arguments);
}
return this.execute(graphQLParams.query);
}
execute(query) {
// console.log('execute', query);
return this.pypyjs.then(() => {
var x = `
import json
result = __graphene_executor.execute(schema.schema, '''${query}''')
result_dict = {};
if result.errors:
result_dict['errors'] = [format_error(e) for e in result.errors]
if result.data:
result_dict['data'] = result.data
result_json = json.dumps(result_dict)
`;
return this.pypy_interpreter.exec(x)
}
).then(() =>
this.pypy_interpreter.get(`result_json`)
).then((data) => {
var json_data = JSON.parse(data);
return json_data;
});
}
markLine(lineNo) {
console.log(lineNo);
var hlLine = this.editor.addLineClass(lineNo, "text", "activeline");
// var mark = this.editor.markText({line: lineNo, ch: 0}, {line: lineNo, ch: 10}, {className: "called-function"});
setTimeout(() => {
this.editor.removeLineClass(lineNo, "text", "activeline");
}, 1200);
}
render() {
return (
<div className="playground">
{!this.state.pypyjs?<div className="loading" />:null}
<div className="playground-schema">
<header className="playground-schema-header">
Schema
</header>
<div className="playground-schema-editor" ref="schemaCode" />
</div>
<div className="playground-graphiql">
<GraphiQL ref="graphiql" fetcher={this.fetcher.bind(this)} response={this.state.response} onEditQuery={this.props.onEditQuery} query={this.props.initialQuery}/>
</div>
</div>
);
}
}
module.exports = Playground;

View File

@ -1,4 +0,0 @@
query {
hello
ping(to:"Peter")
}

View File

@ -1,13 +0,0 @@
import graphene
class Query(graphene.ObjectType):
hello = graphene.String()
ping = graphene.String(to=graphene.String())
def resolve_hello(self, args, info):
return 'World'
def resolve_ping(self, args, info):
return 'Pinging {}'.format(args.get('to'))
schema = graphene.Schema(query=Query)

View File

@ -1,20 +0,0 @@
query {
empire {
id
name
ships(first:2) {
edges {
node {
id
name
}
}
}
}
node(id:"U2hpcDo4") {
id
... on Ship {
name
}
}
}

View File

@ -1,148 +0,0 @@
import graphene
from graphene import relay, resolve_only_args
class Ship(relay.Node):
'''A ship in the Star Wars saga'''
name = graphene.String(description='The name of the ship.')
@classmethod
def get_node(cls, id, info):
return get_ship(id)
class Faction(relay.Node):
'''A faction in the Star Wars saga'''
name = graphene.String(description='The name of the faction.')
ships = relay.ConnectionField(
Ship, description='The ships used by the faction.')
@resolve_only_args
def resolve_ships(self, **args):
# Transform the instance ship_ids into real instances
return [get_ship(ship_id) for ship_id in self.ships]
@classmethod
def get_node(cls, id, info):
return get_faction(id)
class IntroduceShip(relay.ClientIDMutation):
class Input:
ship_name = graphene.String(required=True)
faction_id = graphene.String(required=True)
ship = graphene.Field(Ship)
faction = graphene.Field(Faction)
@classmethod
def mutate_and_get_payload(cls, input, info):
ship_name = input.get('ship_name')
faction_id = input.get('faction_id')
ship = create_ship(ship_name, faction_id)
faction = get_faction(faction_id)
return IntroduceShip(ship=ship, faction=faction)
class Query(graphene.ObjectType):
rebels = graphene.Field(Faction)
empire = graphene.Field(Faction)
node = relay.NodeField()
@resolve_only_args
def resolve_rebels(self):
return get_rebels()
@resolve_only_args
def resolve_empire(self):
return get_empire()
class Mutation(graphene.ObjectType):
introduce_ship = graphene.Field(IntroduceShip)
schema = graphene.Schema(name='Starwars Relay Schema')
schema.query = Query
schema.mutation = Mutation
xwing = Ship(
id='1',
name='X-Wing',
)
ywing = Ship(
id='2',
name='Y-Wing',
)
awing = Ship(
id='3',
name='A-Wing',
)
# Yeah, technically it's Corellian. But it flew in the service of the rebels,
# so for the purposes of this demo it's a rebel ship.
falcon = Ship(
id='4',
name='Millenium Falcon',
)
homeOne = Ship(
id='5',
name='Home One',
)
tieFighter = Ship(
id='6',
name='TIE Fighter',
)
tieInterceptor = Ship(
id='7',
name='TIE Interceptor',
)
executor = Ship(
id='8',
name='Executor',
)
rebels = Faction(
id='1',
name='Alliance to Restore the Republic',
ships=['1', '2', '3', '4', '5']
)
empire = Faction(
id='2',
name='Galactic Empire',
ships=['6', '7', '8']
)
data = {
'Faction': {
'1': rebels,
'2': empire
},
'Ship': {
'1': xwing,
'2': ywing,
'3': awing,
'4': falcon,
'5': homeOne,
'6': tieFighter,
'7': tieInterceptor,
'8': executor
}
}
def create_ship(ship_name, faction_id):
from .schema import Ship
next_ship = len(data['Ship'].keys()) + 1
new_ship = Ship(
id=str(next_ship),
name=ship_name
)
data['Ship'][new_ship.id] = new_ship
data['Faction'][faction_id].ships.append(new_ship.id)
return new_ship
def get_ship(_id):
return data['Ship'][_id]
def get_faction(_id):
return data['Faction'][_id]
def get_rebels():
return get_faction('1')
def get_empire():
return get_faction('2')

View File

@ -1,8 +0,0 @@
query {
store {
teas(orderBy:"name") {
name
steepingTime
}
}
}

View File

@ -1,38 +0,0 @@
import graphene
class Tea(graphene.ObjectType):
name = graphene.String()
steeping_time = graphene.Int()
TEAS = [
Tea(name='Earl Grey Blue Star', steeping_time=5),
Tea(name='Milk Oolong', steeping_time=3),
Tea(name='Gunpowder Golden Temple', steeping_time=3),
Tea(name='Assam Hatimara', steeping_time=5),
Tea(name='Bancha', steeping_time=2),
Tea(name='Ceylon New Vithanakande', steeping_time=5),
Tea(name='Golden Tip Yunnan', steeping_time=5),
Tea(name='Jasmine Phoenix Pearls', steeping_time=3),
Tea(name='Kenya Milima', steeping_time=5),
Tea(name='Pu Erh First Grade', steeping_time=4),
Tea(name='Sencha Makoto', steeping_time=3),
]
class Store(graphene.ObjectType):
teas = graphene.List(Tea, order_by=graphene.String())
def resolve_teas(self, args, info):
order_by = args.get("order_by")
if order_by == "steepingTime":
return sorted(self.teas, key=lambda tea: tea.steeping_time)
elif order_by == "name":
return sorted(self.teas, key=lambda tea: tea.name)
return self.teas
class Query(graphene.ObjectType):
store = graphene.Field(Store)
def resolve_store(self, args, info):
return Store(teas=TEAS)
schema = graphene.Schema(query=Query)

View File

@ -1 +0,0 @@
pypy-release-nojit

View File

@ -1,107 +0,0 @@
//
// FunctionPromise: possibly-asynchronous function constructor.
//
// This is a prototype polyfill for a FunctionPromise object as described in:
//
// https://bugzilla.mozilla.org/show_bug.cgi?id=854627
//
// Where possible it will arrange for the function body to be parsed/compiled
// off of the main thread, with the function object returned asynchronously
// via a promise. The fallback implementation processes just falls back to
// the standard synchronous Function() constructor.
//
// It doesn't (yet) have the following features from the linked proposal:
//
// * ability to copy to different workers
// * ability to store in IndexedDB
//
function FunctionPromise(/* [args1[, args2[, ...argN]],], functionBody) */) {
var useFallback =
typeof window === "undefined" ||
window.FunctionPromise !== FunctionPromise ||
typeof document === "undefined" ||
typeof document.createElement === "undefined" ||
typeof document.head === "undefined" ||
typeof document.head.appendChild === "undefined" ||
typeof Blob === "undefined" ||
typeof URL === "undefined" ||
typeof URL.createObjectURL === "undefined";
var args = Array.prototype.slice.call(arguments);
// For the fallback case, we just use the normal Function constructor.
if (useFallback) {
try {
var fn = Function.apply(null, args);
return Promise.resolve(fn);
} catch (err) {
return Promise.reject(err);
}
}
// If we have all the necessary pieces, we can do this asynchronously
// by writing a <script> tag into the DOM.
var funcid = FunctionPromise._nextid++;
return new Promise(function(resolve, reject) {
try {
var funcSrc = [];
funcSrc.push("window.FunctionPromise._results[" + funcid + "]=");
funcSrc.push("function(");
if (args.length > 1) {
funcSrc.push(args[0]);
for (var i = 1; i < args.length - 1; i++) {
funcSrc.push(",");
funcSrc.push(args[i]);
}
}
funcSrc.push("){");
funcSrc.push(args[args.length - 1]);
funcSrc.push("}");
var dataUrl = URL.createObjectURL(new Blob(funcSrc));
var scriptTag = document.createElement("script");
var cleanup = function() {
URL.revokeObjectURL(dataUrl);
scriptTag.remove();
delete window.FunctionPromise._results[funcid];
}
scriptTag.onerror = function() {
reject(new Error("unknown error loading FunctionPromise"))
cleanup();
}
scriptTag.onload = function() {
if (window.FunctionPromise._results[funcid]) {
resolve(window.FunctionPromise._results[funcid]);
} else {
// No function, something must have gone wrong.
// Likely a syntax error in the function body string.
// Fall back to Function() constructor to surface it.
try {
Function.apply(null, args);
reject(new Error("unknown error fulfilling FunctionPromise"));
} catch (err) {
reject(err);
}
}
cleanup();
}
scriptTag.src = dataUrl;
document.head.appendChild(scriptTag);
} catch (err) {
reject(err);
}
});
}
FunctionPromise._nextid = 0;
FunctionPromise._results = {};
if (typeof module !== "undefined" && typeof module.exports !== "undefined") {
if (typeof Promise === "undefined") {
Promise = require('es6-promise').Promise;
}
module.exports = FunctionPromise;
}

View File

@ -1,37 +0,0 @@
#!/bin/bash
cd "$(dirname "$0")"
if [ ! -d pypyjs-release-nojit ] ; then
git clone https://github.com/pypyjs/pypyjs-release-nojit.git
fi
GRAPHENE_DIR="$(python -c "import os; import graphene; print os.path.dirname(graphene.__file__)")"
GRAPHQL_DIR="$(python -c "import os; import graphql; print os.path.dirname(graphql.__file__)")"
GRAPHQL_RELAY_DIR="$(python -c "import os; import graphql_relay; print os.path.dirname(graphql_relay.__file__)")"
SIX_DIR="$(python -c "import os; import six; print six.__file__.rstrip('c')")"
cd pypyjs-release-nojit
eval python tools/module_bundler.py add ./lib/modules "$GRAPHENE_DIR"
eval python tools/module_bundler.py add ./lib/modules "$GRAPHQL_DIR"
eval python tools/module_bundler.py add ./lib/modules "$GRAPHQL_RELAY_DIR"
eval python tools/module_bundler.py add ./lib/modules "$SIX_DIR"
python ./tools/module_bundler.py preload ./lib/modules graphene
python ./tools/module_bundler.py preload ./lib/modules graphene.relay
python ./tools/module_bundler.py preload ./lib/modules graphql
python ./tools/module_bundler.py preload ./lib/modules graphql_relay
python ./tools/module_bundler.py preload ./lib/modules six
python ./tools/module_bundler.py remove ./lib/modules unittest
lib_dirname=`perl -e 'use Cwd "abs_path";print abs_path(shift)' lib/`
if [ -d ../../../static/playground/lib ] ; then
rm ../../../static/playground/lib
fi
mkdir -p ../../../static/playground
exec ln -s "$lib_dirname/" ../../../static/playground/lib

View File

@ -1,976 +0,0 @@
//
// pypyjs: an experimental in-browser python environment.
//
(function() {
// Expose the main pypyjs function at global scope for this file,
// as well as in any module exports or 'window' object we can find.
if (this) {
this.pypyjs = pypyjs;
}
if (typeof window !== "undefined") {
window.pypyjs = pypyjs;
}
if (typeof module !== "undefined") {
if (typeof module.exports !== "undefined") {
module.exports = pypyjs;
}
}
// Generic debugging printf.
var debug = function(){};
if (typeof console !== "undefined") {
debug = console.log.bind(console);
} else if (typeof print !== "undefined" && typeof window === "undefined") {
debug = print;
}
// Find the directory containing this very file.
// It can be quite difficult depending on execution environment...
if (typeof __dirname === "undefined" || true) {
var __dirname = "./";
// A little hackery to find the URL of this very file.
// Throw an error, then parse the stack trace looking for filenames.
var errlines = (new Error()).stack.split("\n");
for (var i = 0; i < errlines.length; i++) {
var match = /(at Anonymous function \(|at |@)(.+\/)pypyjs.js/.exec(errlines[i]);
if (match) {
__dirname = match[2];
break;
}
}
}
if (__dirname.charAt(__dirname.length - 1) !== "/") {
__dirname += "/";
}
if (typeof Promise === "undefined") {
var Promise = require('es6-promise').Promise;
}
// Ensure we have reference to a 'FunctionPromise' constructor.
var FunctionPromise = require("./FunctionPromise.js");
if (typeof FunctionPromise === "undefined") {
throw "FunctionPromise object not found";
}
// Create functions for handling default stdio streams.
// These will be shared by all VM instances by default.
//
// We default stdout and stderr to process outputs if available,
// printing/logging functions otherwise, and /dev/null if nothing
// else is available. Unfortunately there's no good way to read
// synchronously from stdin in javascript, so that's always /dev/null.
var devNull = {
stdin: function() { return null; },
stdout: function() { },
stderr: function() { }
}
var stdio = {
stdin: null,
stdout: null,
stderr: null
}
stdio.stdin = devNull.stdin;
if (typeof process !== "undefined") {
if (typeof process.stdout !== "undefined") {
stdio.stdout = function(x) { process.stdout.write(x); }
}
if (typeof process.stderr !== "undefined") {
stdio.stderr = function(x) { process.stderr.write(x); }
}
}
var _print, _printErr;
if (typeof window === "undefined") {
// print, printErr from v8, spidermonkey
if (typeof print !== "undefined") {
_print = print;
}
if (typeof printErr !== "undefined") {
_printErr = printErr;
}
}
if (typeof console !== "undefined") {
if (typeof _print === "undefined") {
_print = console.log.bind(console);
}
if (typeof _printErr === "undefined") {
_printErr = console.error.bind(console);
}
}
if (stdio.stdout == null && typeof _print !== "undefined") {
// print()/console.log() will add a newline, so we buffer until we
// receive one and then let it add it for us.
stdio.stdout = (function() {
var buffer = [];
return function(data) {
for (var i = 0; i < data.length; i++) {
var x = data.charAt(i);
if (x !== "\n") {
buffer.push(x);
} else {
_print(buffer.join(""));
buffer.splice(undefined, buffer.length);
}
}
}
})();
}
if (stdio.stderr == null && typeof _printErr !== "undefined") {
// printErr()/console.error() will add a newline, so we buffer until we
// receive one and then let it add it for us.
stdio.stderr = (function() {
var buffer = [];
return function(data) {
for (var i = 0; i < data.length; i++) {
var x = data.charAt(i);
if (x !== "\n") {
buffer.push(x);
} else {
_printErr(buffer.join(""));
buffer.splice(undefined, buffer.length);
}
}
}
})();
}
if (stdio.stdout === null) {
stdio.stdout = devNull.stdout;
}
if (stdio.stderr === null) {
stdio.stderr = devNull.stderr;
}
function pypyjs(opts) {
opts = opts || {};
this.rootURL = opts.rootURL;
this.totalMemory = opts.totalMemory || 128 * 1024 * 1024;
this.autoLoadModules = opts.autoLoadModules || true;
this._pendingModules = {};
this._loadedModules = {};
this._allModules = {};
// Allow opts to override default IO streams.
this.stdin = opts.stdin || stdio.stdin;
this.stdout = opts.stdout || stdio.stdout;
this.stderr = opts.stderr || stdio.stderr;
// Default to finding files relative to this very file.
if (!this.rootURL && !pypyjs.rootURL) {
pypyjs.rootURL = __dirname;
}
if (this.rootURL && this.rootURL.charAt(this.rootURL.length - 1) !== "/") {
this.rootURL += "/";
}
// If we haven't already done so, fetch and load the code for the VM.
// We do this once and cache the result for re-use, so that we don't
// have to pay asmjs compilation overhead each time we create the VM.
if (! pypyjs._vmBuilderPromise) {
pypyjs._vmBuilderPromise = this.fetch("pypyjs.vm.js").then((function(xhr) {
// Parse the compiled code, hopefully asynchronously.
// Unfortunately our use of Function constructor here doesn't
// play very well with nodejs, where things like 'module' and
// 'require' are not in the global scope. We have to pass them
// in explicitly as arguments.
var funcBody = [
// This is the compiled code for the VM.
xhr.responseText,
'\n',
// Ensure that some functions are available on the Module,
// for linking with jitted code.
'if (!Module._jitInvoke && typeof _jitInvoke !== "undefined") {',
' Module._jitInvoke = _jitInvoke;',
'}',
// Keep some functions that are not exported by default, but
// which appear in this scope when evaluating the above.
"Module._emjs_make_handle = _emjs_make_handle;",
"Module._emjs_free = _emjs_free;",
// Call dependenciesFulfilled if it won't be done automatically.
"dependenciesFulfilled=function() { inDependenciesFulfilled(FS); };",
"if(!memoryInitializer||(!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_WORKER))dependenciesFulfilled();",
].join("");
return FunctionPromise("Module", "inDependenciesFulfilled", "require",
"module", "__filename", "__dirname", funcBody)
}).bind(this));
}
// Create a new instance of the compiled VM, bound to local state
// and a local Module object.
this._ready = new Promise((function(resolve, reject) {
// Initialize the Module object.
// We make it available on this object so that we can use
// its methods to execute code in the VM.
var Module = {};
this._module = Module;
Module.TOTAL_MEMORY = this.totalMemory;
// We will set up the filesystem manually when we're ready.
Module.noFSInit = true;
Module.thisProgram = "/lib/pypyjs/pypyjs.js";
Module.filePackagePrefixURL = this.rootURL || pypyjs.rootURL;
Module.memoryInitializerPrefixURL = this.rootURL || pypyjs.rootURL;
Module.locateFile = function(name) {
return (this.rootURL || pypyjs.rootURL) + name;
}
// Don't start or stop the program, just set it up.
// We'll call the API functions ourself.
Module.noInitialRun = true;
Module.noExitRuntime = true;
// Route stdin to an overridable method on the object.
var stdin = (function stdin() {
return this.stdin();
}).bind(this);
// Route stdout to an overridable method on the object.
// We buffer the output for efficiency.
var stdout_buffer = []
var stdout = (function stdout(x) {
var c = String.fromCharCode(x);
stdout_buffer.push(c);
if (c === "\n" || stdout_buffer.length >= 128) {
this.stdout(stdout_buffer.join(""));
stdout_buffer = [];
}
}).bind(this);
// Route stderr to an overridable method on the object.
// We do not buffer stderr.
var stderr = (function stderr(x) {
var c = String.fromCharCode(x);
this.stderr(c);
}).bind(this);
// This is where execution will continue after loading
// the memory initialization data, if any.
var initializedResolve, initializedReject;
var initializedP = new Promise(function(resolve, reject) {
initializedResolve = resolve;
initializedReject = reject;
});
var FS;
var dependenciesFulfilled = function(fs) {
FS = fs;
// Initialize the filesystem state.
try {
FS.init(stdin, stdout, stderr);
Module.FS_createPath("/", "lib/pypyjs/lib_pypy", true, false);
Module.FS_createPath("/", "lib/pypyjs/lib-python/2.7", true, false);
initializedResolve();
} catch (err) {
initializedReject(err);
}
}
// Begin fetching the metadata for available python modules.
// With luck these can download while we jank around compiling
// all of that javascript.
// XXX TODO: also load memory initializer this way.
var moduleDataP = this.fetch("modules/index.json");
pypyjs._vmBuilderPromise.then((function(vmBuilder) {
var args = [
Module,
dependenciesFulfilled,
typeof undefined,
typeof undefined,
typeof undefined,
typeof __dirname
];
// This links the async-compiled module into our Module object.
vmBuilder.apply(null, args);
return initializedP;
}).bind(this)).then((function() {
// Continue with processing the downloaded module metadata.
return moduleDataP.then((function(xhr) {
// Store the module index, and load any preload modules.
var modIndex = JSON.parse(xhr.responseText);
this._allModules = modIndex.modules;
if (modIndex.preload) {
for (var name in modIndex.preload) {
this._writeModuleFile(name, modIndex.preload[name]);
}
}
// It's finally safe to launch the VM.
Module.run();
Module._rpython_startup_code();
var pypy_home = Module.intArrayFromString("/lib/pypyjs/pypyjs.js");
pypy_home = Module.allocate(pypy_home, 'i8', Module.ALLOC_NORMAL);
Module._pypy_setup_home(pypy_home, 0);
Module._free(pypy_home);
var initCode = [
"import js",
"import sys; sys.platform = 'js'",
"import traceback",
"top_level_scope = {'__name__': '__main__'}"
];
initCode.forEach(function(codeStr) {
var code = Module.intArrayFromString(codeStr);
var code = Module.allocate(code, 'i8', Module.ALLOC_NORMAL);
if (!code) {
throw new pypyjs.Error('Failed to allocate memory');
}
var res = Module._pypy_execute_source(code);
if (res < 0) {
throw new pypyjs.Error('Failed to execute python code');
}
Module._free(code);
});
}).bind(this))
}).bind(this))
.then(resolve, reject);
}).bind(this));
};
// A simple file-fetching wrapper around XMLHttpRequest,
// that treats paths as relative to the pypyjs.js root url.
//
pypyjs.prototype.fetch = function (relpath, responseType) {
if (typeof window === "undefined") {
var localStorage = false;
}
else {
var localStorage = window.localStorage;
}
var use_cache = pypyjs.cacheKey && localStorage && relpath != "pypyjs.vm.js";
if (use_cache) {
var item = localStorage.getItem(pypyjs.cacheKey+':'+relpath);
if (item) {
return new Promise((function(resolve, reject) {
resolve({ responseText: item });
}))
}
}
// For the web, use XMLHttpRequest.
if (typeof XMLHttpRequest !== "undefined") {
return new Promise((function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
if (xhr.status >= 400) {
reject(xhr)
} else {
if (use_cache && xhr.responseText) {
localStorage.setItem(pypyjs.cacheKey+':'+relpath, xhr.responseText);
}
resolve(xhr);
}
};
var rootURL = this.rootURL || pypyjs.rootURL;
xhr.open('GET', rootURL + relpath, true);
xhr.responseType = responseType || "text";
xhr.send(null);
}).bind(this));
}
// For nodejs, use fs.readFile.
if (typeof fs !== "undefined" && typeof fs.readFile !== "undefined") {
return new Promise((function(resolve, reject) {
var rootURL = this.rootURL || pypyjs.rootURL;
fs.readFile(path.join(rootURL, relpath), function(err, data) {
if (err) return reject(err);
resolve({ responseText: data.toString() });
});
}).bind(this));
}
// For spidermonkey, use snarf (which has a binary read mode).
if (typeof snarf !== "undefined") {
return new Promise((function(resolve, reject) {
var rootURL = this.rootURL || pypyjs.rootURL;
var data = snarf(rootURL + relpath);
resolve({ responseText: data });
}).bind(this));
}
// For d8, use read() and readbuffer().
if (typeof read !== "undefined" && typeof readbuffer !== "undefined") {
return new Promise((function(resolve, reject) {
var rootURL = this.rootURL || pypyjs.rootURL;
var data = read(rootURL + relpath);
resolve({ responseText: data });
}).bind(this));
}
return new Promise(function(resolve, reject) {
reject("unable to fetch files");
});
};
if (typeof localStorage !== "undefined") {
var localStorage = false;
}
// pypyjs.prototype.fetch = function fetch(relpath, responseType) {
// // For the web, use XMLHttpRequest.
// var use_cache = pypyjs.cacheKey && localStorage;
// if (use_cache) {
// if (var item = localStorage.getItem(pypyjs.cacheKey+'-'+relpath)) {
// resolve({ responseText: item });
// }
// }
// if (typeof XMLHttpRequest !== "undefined") {
// return new Promise((function(resolve, reject) {
// var xhr = new XMLHttpRequest();
// xhr.onload = function() {
// if (xhr.status >= 400) {
// reject(xhr)
// } else {
// console.log(xhr.responseText);
// if (use_cache && xhr.responseText) {
// localStorage.setItem(pypyjs.cacheKey+'-'+relpath, xhr.responseText);
// }
// resolve(xhr);
// }
// };
// var rootURL = this.rootURL || pypyjs.rootURL;
// xhr.open('GET', rootURL + relpath, true);
// xhr.responseType = responseType || "text";
// xhr.send(null);
// }).bind(this));
// }
// // For nodejs, use fs.readFile.
// if (typeof fs !== "undefined" && typeof fs.readFile !== "undefined") {
// return new Promise((function(resolve, reject) {
// var rootURL = this.rootURL || pypyjs.rootURL;
// fs.readFile(path.join(rootURL, relpath), function(err, data) {
// if (err) return reject(err);
// resolve({ responseText: data.toString() });
// });
// }).bind(this));
// }
// // For spidermonkey, use snarf (which has a binary read mode).
// if (typeof snarf !== "undefined") {
// return new Promise((function(resolve, reject) {
// var rootURL = this.rootURL || pypyjs.rootURL;
// var data = snarf(rootURL + relpath);
// resolve({ responseText: data });
// }).bind(this));
// }
// // For d8, use read() and readbuffer().
// if (typeof read !== "undefined" && typeof readbuffer !== "undefined") {
// return new Promise((function(resolve, reject) {
// var rootURL = this.rootURL || pypyjs.rootURL;
// var data = read(rootURL + relpath);
// resolve({ responseText: data });
// }).bind(this));
// }
// return new Promise(function(resolve, reject) {
// reject("unable to fetch files");
// });
// };
// Method to execute python source directly in the VM.
//
// This is the basic way to push code into the pypyjs VM.
// Calling code should not use it directly; rather we use it
// as a primitive to build up a nicer execution API.
//
pypyjs.prototype._execute_source = function _execute_source(code) {
var Module = this._module;
code = "try:\n" +
" " + code + "\n" +
"except Exception:\n" +
" typ, val, tb = sys.exc_info()\n" +
" err_name = getattr(typ, '__name__', str(typ))\n" +
" err_msg = str(val)\n" +
" err_trace = traceback.format_exception(typ, val, tb)\n" +
" err_trace = ''.join(err_trace)\n" +
" js.globals['pypyjs']._lastErrorName = err_name\n" +
" js.globals['pypyjs']._lastErrorMessage = err_msg\n" +
" js.globals['pypyjs']._lastErrorTrace = err_trace\n";
var code_chars = Module.intArrayFromString(code);
var code_ptr = Module.allocate(code_chars, 'i8', Module.ALLOC_NORMAL);
if (!code_ptr) {
return Promise.reject(new pypyjs.Error("Failed to allocate memory"));
}
var res = Module._pypy_execute_source(code_ptr);
Module._free(code_ptr);
// XXX TODO: races/re-entrancy on _lastError?
if (pypyjs._lastErrorName) {
var err = new pypyjs.Error(
pypyjs._lastErrorName,
pypyjs._lastErrorMessage,
pypyjs._lastErrorTrace
);
pypyjs._lastErrorName = null;
pypyjs._lastErrorMessage = null;
pypyjs._lastErrorTrace = null;
return Promise.reject(err);
}
if (res < 0) {
return Promise.reject(new pypyjs.Error("Error executing python code"));
}
return Promise.resolve(null);
}
function _escape(value) {
return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
}
// Method to determine when the interpreter is ready.
//
// This method returns a promise that will resolve once the interpreter
// is ready for use.
//
pypyjs.prototype.ready = function ready() {
return this._ready;
}
// Method to execute some python code.
//
// This passes the given python code to the VM for execution.
// It's fairly directly analogous to the "exec" statement in python.
// It is not possible to directly access the result of the code, if any.
// Rather you should store it into a variable and then use the get() method.
//
pypyjs.prototype.exec = function exec(code) {
return this._ready.then((function() {
var p = Promise.resolve();
// Find any "import" statements in the code,
// and ensure the modules are ready for loading.
if (this.autoLoadModules) {
p = p.then((function() {
return this.findImportedNames(code);
}).bind(this))
.then((function(imports) {
return this.loadModuleData.apply(this, imports);
}).bind(this))
}
// Now we can execute the code in custom top-level scope.
code = 'exec \'\'\'' + _escape(code) + '\'\'\' in top_level_scope';
p = p.then((function() {
return this._execute_source(code);
}).bind(this));
return p;
}).bind(this));
}
// Method to evaluate an expression.
//
// This method evaluates an expression and returns its value (assuming the
// value can be translated into javascript). It's fairly directly analogous
// to the "eval" function in python.
//
// For backwards-compatibility reasons, it will also evaluate statements.
// This behaviour is deprecated and will be removed in a future release.
//
pypyjs.prototype.eval = function (expr) {
return this._ready.then((function() {
// First try to execute it as an expression.
code = "r = eval('" + _escape(expr) + "', top_level_scope)";
return this._execute_source(code);
}).bind(this)).then(
(function() {
// If that succeeded, return the result.
return this.get("r", true)
}).bind(this),
(function(err) {
if (err && err.name && err.name !== "SyntaxError") {
throw err;
}
// If that failed, try again via exec().
if (typeof console !== "undefined") {
console.warn("Calling pypyjs.eval() with statements is deprecated.");
console.warn("Use eval() for expressions, exec() for statements.");
}
return this.exec(expr);
}).bind(this)
)
}
// Method to evaluate some python code from a file..
//
// This fetches the named file and passes it to the VM for execution.
//
pypyjs.prototype.execfile = function execfile(filename) {
return this.fetch(filename).then((function(xhr) {
var code = xhr.responseText;
return this.exec(code);
}).bind(this));
}
// Method to read a python variable.
//
// This tries to convert the value in the named python variable into an
// equivalent javascript value and returns it. It will fail if the variable
// does not exist or contains a value that cannot be converted.
//
pypyjs._resultsID = 0;
pypyjs._resultsMap = {};
pypyjs.prototype.get = function get(name, _fromGlobals) {
var resid = ""+(pypyjs._resultsID++);
// We can read from global scope for internal use; don't do this from calling code!
if (_fromGlobals) {
var namespace = "globals()";
} else {
var namespace = "top_level_scope";
}
return this._ready.then((function() {
var code = namespace + ".get('" + _escape(name) + "', js.undefined)";
code = "js.convert(" + code + ")"
code = "js.globals['pypyjs']._resultsMap['" + resid + "'] = " + code;
return this._execute_source(code);
}).bind(this)).then((function() {
var res = pypyjs._resultsMap[resid];
delete pypyjs._resultsMap[resid];
return res;
}).bind(this));
}
// Method to set a python variable to a javascript value.
//
// This generates a handle to the given object, and arranges for the named
// python variable to reference it via that handle.
//
pypyjs.prototype.set = function set(name, value) {
return this._ready.then((function() {
var Module = this._module;
var h = Module._emjs_make_handle(value);
name = _escape(name);
var code = "top_level_scope['" + name + "'] = js.Value(" + h + ")";
return this._execute_source(code);
}).bind(this));
}
// Method to run an interactive REPL.
//
// This method takes takes callback function implementing the user
// input prompt, and runs a REPL loop using it. The prompt function
// may either return the input as a string, or a promise resolving to
// the input as a string. If not specified, we read from stdin (which
// works fine in e.g. nodejs, but is almost certainly not what you want
// in the browser, because it's blocking).
//
pypyjs.prototype.repl = function repl(prmpt) {
if (!prmpt) {
// If there's a custom stdin, or we're not in nodejs, then we should
// default to prompting on stdin/stdout. For nodejs, we can build
// an async prompt atop process.stdin.
var buffer = "";
if (this.stdin !== devNull.stdin || typeof process === "undefined") {
prmpt = (function(ps1) {
var input;
this.stdout(ps1);
var c = this.stdin();
while (c) {
var idx = c.indexOf("\n");
if (idx >= 0) {
var input = buffer + c.substr(0, idx + 1);
buffer = c.substr(idx + 1);
return input;
}
buffer += c;
c = this.stdin();
}
input = buffer;
buffer = "";
return input;
}).bind(this);
} else {
prmpt = (function(ps1) {
return new Promise((function(resolve, reject) {
this.stdout(ps1);
var slurp = function() {
process.stdin.once("readable", function() {
var chunk = process.stdin.read();
if (chunk === null) {
slurp();
} else {
chunk = chunk.toString();
var idx = chunk.indexOf("\n");
if (idx < 0) {
buffer += chunk;
slurp();
} else {
resolve(buffer + chunk.substr(0, idx + 1));
buffer = chunk.substr(idx + 1);
}
}
});
}
slurp();
}).bind(this));
}).bind(this);
}
}
// Set up an InteractiveConsole instance,
// then loop forever via recursive promises.
return this._ready.then((function() {
return this.loadModuleData("code");
}).bind(this)).then((function() {
return this._execute_source("import code");
}).bind(this)).then((function() {
return this._execute_source("c = code.InteractiveConsole(top_level_scope)");
}).bind(this)).then((function() {
return this._repl_loop(prmpt, ">>> ");
}).bind(this));
}
pypyjs.prototype._repl_loop = function _repl_loop(prmpt, ps1) {
return Promise.resolve().then((function() {
// Prompt for input, which may happen via async promise.
return prmpt.call(this, ps1);
}).bind(this)).then((function(input) {
// Push it into the InteractiveConsole, a line at a time.
var p = Promise.resolve();
input.split("\n").forEach((function(line) {
// Find any "import" statements in the code,
// and ensure the modules are ready for loading.
if (this.autoLoadModules) {
p = p.then((function() {
return this.findImportedNames(line);
}).bind(this))
.then((function(imports) {
return this.loadModuleData.apply(this, imports);
}).bind(this))
}
var code = 'r = c.push(\'' + _escape(line) + '\')';
p = p.then((function() {
return this._execute_source(code);
}).bind(this));
}).bind(this));
return p;
}).bind(this)).then((function() {
// Check the result from the final push.
return this.get("r", true)
}).bind(this)).then((function(r) {
// If r == 1, we're in a multi-line definition.
// Adjust the prompt accordingly.
if (r) {
return this._repl_loop(prmpt, "... ");
} else {
return this._repl_loop(prmpt, ">>> ");
}
}).bind(this));
}
// Method to look for "import" statements in a code string.
// Returns a promise that will resolve to a list of imported module names.
//
// XXX TODO: this is far from complete and should not be done with a regex.
// Perhaps we can call into python's "ast" module for this parsing?
//
var importStatementRE = /(from\s+([a-zA-Z0-9_\.]+)\s+)?import\s+\(?\s*([a-zA-Z0-9_\.\*]+(\s+as\s+[a-zA-Z0-9_]+)?[ \t]*,?[ \t]*)+[ \t]*\)?/g
pypyjs.prototype.findImportedNames = function findImportedNames(code) {
var match = null;
var imports = [];
importStatementRE.lastIndex = 0;
while ((match = importStatementRE.exec(code)) !== null) {
var relmod = match[2];
if (relmod) {
relmod = relmod + ".";
} else {
relmod = "";
}
var submods = match[0].split("import")[1];
while (submods && /[\s(]/.test(submods.charAt(0))) {
submods = submods.substr(1);
}
while (submods && /[\s)]/.test(submods.charAt(submods.length - 1))) {
submods = submods.substr(0, submods.length - 1);
}
submods = submods.split(/\s*,\s*/);
for (var i = 0; i < submods.length; i++) {
var submod = submods[i];
submod = submod.split(/\s*as\s*/)[0];
imports.push(relmod + submod);
}
}
return Promise.resolve(imports);
}
// Method to load the contents of a python module, along with
// any dependencies. This populates the relevant paths within
// the VMs simulated filesystem so that is can find and import
// the specified module.
//
pypyjs.prototype.loadModuleData = function loadModuleData(/* names */) {
// Each argument is a name that we want to import.
// We must find the longest prefix that is an available module
// and load it along with all its dependencies.
var modules = Array.prototype.slice.call(arguments);
return this._ready.then((function() {
var toLoad = {};
NEXTNAME: for (var i = 0; i < modules.length; i++) {
var name = modules[i];
// Find the nearest containing module for the given name.
// Note that it may not match a module at all, in which case we ignore it.
while (true) {
if (this._allModules[name]) {
break;
}
name = name.substr(0, name.lastIndexOf("."));
if (!name) continue NEXTNAME;
}
this._findModuleDeps(name, toLoad);
}
// Now ensure that each module gets loaded.
// XXX TODO: we could load these concurrently.
var p = Promise.resolve();
for (var name in toLoad) {
p = p.then(this._makeLoadModuleData(name));
}
return p;
}).bind(this));
}
pypyjs.prototype._findModuleDeps = function _findModuleDeps(name, seen) {
if (!seen) seen = {};
var deps = [];
// If we don't know about this module, ignore it.
if (!this._allModules[name]) {
return seen;
}
// Depend on any explicitly-named imports.
var imports = this._allModules[name].imports;
if (imports) {
for (var i = 0; i < imports.length; i++) {
deps.push(imports[i]);
}
}
// Depend on the __init__.py for packages.
if (this._allModules[name].dir) {
deps.push(name + ".__init__");
}
// Include the parent package, if any.
var idx = name.lastIndexOf(".");
if (idx !== -1) {
deps.push(name.substr(0, idx));
}
// Recurse for any previously-unseen dependencies.
seen[name] = true;
for (var i = 0; i < deps.length; i++) {
if (!seen[deps[i]]) {
this._findModuleDeps(deps[i], seen);
}
}
return seen;
}
pypyjs.prototype._makeLoadModuleData = function _makeLoadModuleData(name) {
return (function() {
// If we've already loaded this module, we're done.
if (this._loadedModules[name]) {
return Promise.resolve();
}
// If we're already in the process of loading it, use the existing promise.
if (this._pendingModules[name]) {
return this._pendingModules[name];
}
// If it's a package directory, there's not actually anything to do.
if (this._allModules[name].dir) {
return Promise.resolve();
}
// We need to fetch the module file and write it out.
var modfile = this._allModules[name].file;
var p = this.fetch("modules/" + modfile)
.then((function(xhr) {
var contents = xhr.responseText;
this._writeModuleFile(name, contents)
delete this._pendingModules[name];
}).bind(this))
this._pendingModules[name] = p;
return p;
}).bind(this);
}
pypyjs.prototype._writeModuleFile = function _writeModuleFile(name, data) {
var Module = this._module;
var file = this._allModules[name].file;
// Create the containing directory first.
var dir = file.split("/").slice(0, -1).join("/")
try {
Module.FS_createPath("/lib/pypyjs/lib_pypy", dir, true, false);
} catch (e) { }
// Now we can safely create the file.
var fullpath = "/lib/pypyjs/lib_pypy/" + file;
Module.FS_createDataFile(fullpath, "", data, true, false, true);
this._loadedModules[name] = true;
}
// An error class for reporting python exceptions back to calling code.
// XXX TODO: this could be a lot more user-friendly than a opaque error...
pypyjs.Error = function pypyjsError(name, message, trace) {
if (name && typeof message === "undefined") {
message = name;
name = "";
}
this.name = name || "pypyjs.Error";
this.message = message || "pypyjs Unknown Error";
this.trace = trace || "";
}
pypyjs.Error.prototype = new Error();
pypyjs.Error.prototype.constructor = pypyjs.Error;
// XXX TODO: expose the filesystem for manipulation by calling code.
// Add convenience methods directly on the 'pypyjs' function, that
// will invoke corresponding methods on a default VM instance.
// This makes it look like 'pypyjs' is a singleton VM instance.
pypyjs._defaultVM = null;
pypyjs.stdin = stdio.stdin
pypyjs.stdout = stdio.stdout
pypyjs.stderr = stdio.stderr
var PUBLIC_NAMES = ['ready', 'exec', 'eval', 'execfile', 'get', 'set',
'repl', 'loadModuleData'];
PUBLIC_NAMES.forEach(function(name) {
pypyjs[name] = function() {
if (!pypyjs._defaultVM) {
pypyjs._defaultVM = new pypyjs({
stdin: function(){ return pypyjs.stdin.apply(this, arguments); },
stdout: function(){ return pypyjs.stdout.apply(this, arguments); },
stderr: function(){ return pypyjs.stderr.apply(this, arguments); },
});
}
return pypyjs._defaultVM[name].apply(pypyjs._defaultVM, arguments)
}
})
// For nodejs, run a repl when invoked directly from the command-line.
return pypyjs;
})();

View File

@ -1,150 +0,0 @@
import React from 'react';
import GraphenePlayground from './GraphenePlayground';
import _ from 'lodash';
const DEFAULT_CACHE_KEY = 'default';
function filterObject(object, callback, context) {
if (!object) {
return null;
}
var result = {};
for (var name in object) {
if (hasOwnProperty.call(object, name) &&
callback.call(context, object[name], name, object)) {
result[name] = object[name];
}
}
return result;
}
class Playground extends React.Component {
componentWillMount() {
var sourceWasInjected = false;
var queryParams = this.context.router.getCurrentQuery();
var {
cacheKey,
noCache,
} = queryParams;
noCache = (noCache !== undefined) && (noCache !== 'false');
if (noCache) {
cacheKey = undefined;
} else if (!cacheKey) {
cacheKey = DEFAULT_CACHE_KEY;
}
this.schemaCacheKey = `rp-${cacheKey}-schema`;
this.queryCacheKey = `rp-${cacheKey}-query`;
this.cacheKey = cacheKey;
var initialSchema;
var initialQuery;
var storedSchema = localStorage.getItem(this.schemaCacheKey);
var storedQuery = localStorage.getItem(this.queryCacheKey);
if (noCache) {
// Use case #1
// We use the noCache param to force a playground to have certain contents.
// eg. static example apps
initialSchema = queryParams.schema || '';
initialQuery = queryParams.query || '';
sourceWasInjected = true;
queryParams = {};
} else if (cacheKey === DEFAULT_CACHE_KEY) {
// Use case #2
// The user loaded the playground without a custom cache key.
// Allow code injection via the URL
// OR load code from localStorage
// OR prime the playground with some default 'hello world' code
if (queryParams.schema != null) {
initialSchema = queryParams.schema;
sourceWasInjected = queryParams.schema !== storedSchema;
} else if (storedSchema != null) {
initialSchema = storedSchema;
} else {
initialSchema = require('!raw!./examples/hello.schema.py');
}
if (queryParams.query != null) {
initialQuery = queryParams.query;
sourceWasInjected = queryParams.query !== storedQuery;
} else if (storedQuery != null) {
initialQuery = storedQuery;
} else {
initialQuery = require('!raw!./examples/hello.graphql');
}
queryParams = filterObject({
schema: queryParams.schema,
query: queryParams.query,
}, v => v !== undefined);
} else if (cacheKey) {
// Use case #3
// Custom cache keys are useful in cases where you want to embed a playground
// that features both custom boilerplate code AND saves the developer's
// progress, without overwriting the default code cache. eg. a tutorial.
if (storedSchema != null) {
initialSchema = storedSchema;
} else {
initialSchema = queryParams[`schema_${cacheKey}`];
if (initialSchema != null) {
sourceWasInjected = true;
}
}
if (storedQuery != null) {
initialQuery = storedQuery;
} else {
initialQuery = queryParams[`query_${cacheKey}`];
if (initialQuery != null) {
sourceWasInjected = true;
}
}
queryParams = {};
}
this.changeParams(queryParams);
this.state = {initialSchema, initialQuery, sourceWasInjected};
this.queryParams = queryParams;
}
shouldComponentUpdate() {
return false;
}
changeParams(queryParams) {
var router = this.context.router;
var routeName = router.getCurrentPathname();
var params = router.getCurrentParams();
queryParams = _.mapValues(queryParams, encodeURIComponent);
router.replaceWith(routeName, params, queryParams);
}
render() {
return (<GraphenePlayground
initialSchema={this.state.initialSchema}
initialQuery={this.state.initialQuery}
onEditSchema={(source) => {
localStorage.setItem(this.schemaCacheKey, source);
if (this.cacheKey === DEFAULT_CACHE_KEY) {
this.queryParams.schema = source;
if (!this.queryParams.query) {
this.queryParams.query = this.state.initialQuery;
}
this.changeParams(this.queryParams);
}
}}
onEditQuery={(source) => {
localStorage.setItem(this.queryCacheKey, source);
if (this.cacheKey === DEFAULT_CACHE_KEY) {
this.queryParams.query = source;
if (!this.queryParams.schema) {
this.queryParams.schema = this.state.initialSchema;
}
this.changeParams(this.queryParams);
}
}}
/>);
}
};
Playground.contextTypes = {
router: React.PropTypes.func
};
module.exports = Playground;

View File

@ -1,15 +0,0 @@
import {
GraphQLObjectType,
GraphQLString,
GraphQLSchema,
} from 'graphql';
export default new GraphQLSchema({
query: new GraphQLObjectType({
name: 'Query',
fields: () => ({
__emptyField: {type: GraphQLString},
}),
}),
});

View File

@ -1,21 +0,0 @@
import React from 'react';
class PlaygroundWrapper extends React.Component {
constructor() {
super();
this.state = { currentComponent: null };
}
componentDidMount() {
require(["playground-page"], (Playground) =>{
this.setState({
currentComponent: Playground
});
});
}
render() {
var Current = this.state.currentComponent;
return Current?<Current />:null;
}
}
module.exports = PlaygroundWrapper;

144
docs/quickstart.rst Normal file
View File

@ -0,0 +1,144 @@
Getting started
===============
Introduction
------------
What is GraphQL?
~~~~~~~~~~~~~~~~
GraphQL is a query language for your API.
It provides a standard way to:
* *describe data provided by a server* in a statically typed **Schema**
* *request data* in a **Query** which exactly describes your data requirements and
* *receive data* in a **Response** containing only the data you requested.
For an introduction to GraphQL and an overview of its concepts, please refer to `the official GraphQL documentation`_.
.. _the official GraphQL documentation: http://graphql.org/learn/
What is Graphene?
~~~~~~~~~~~~~~~~~
Graphene is a library that provides tools to implement a GraphQL API in Python using a *code-first* approach.
Compare Graphene's *code-first* approach to building a GraphQL API with *schema-first* approaches like `Apollo Server`_ (JavaScript) or Ariadne_ (Python). Instead of writing GraphQL **Schema Definition Language (SDL)**, we write Python code to describe the data provided by your server.
.. _Apollo Server: https://www.apollographql.com/docs/apollo-server/
.. _Ariadne: https://ariadnegraphql.org/
Graphene is fully featured with integrations for the most popular web frameworks and ORMs. Graphene produces schemas that are fully compliant with the GraphQL spec and provides tools and patterns for building a Relay-Compliant API as well.
An example in Graphene
----------------------
Lets build a basic GraphQL schema to say "hello" and "goodbye" in Graphene.
When we send a **Query** requesting only one **Field**, ``hello``, and specify a value for the ``firstName`` **Argument**...
.. code::
{
hello(firstName: "friend")
}
...we would expect the following Response containing only the data requested (the ``goodbye`` field is not resolved).
.. code::
{
"data": {
"hello": "Hello friend!"
}
}
Requirements
~~~~~~~~~~~~
- Python (3.8, 3.9, 3.10, 3.11, 3.12, pypy)
- Graphene (3.0)
Project setup
~~~~~~~~~~~~~
.. code:: bash
pip install "graphene>=3.0"
Creating a basic Schema
~~~~~~~~~~~~~~~~~~~~~~~
In Graphene, we can define a simple schema using the following code:
.. code:: python
from graphene import ObjectType, String, Schema
class Query(ObjectType):
# this defines a Field `hello` in our Schema with a single Argument `first_name`
# By default, the argument name will automatically be camel-based into firstName in the generated schema
hello = String(first_name=String(default_value="stranger"))
goodbye = String()
# our Resolver method takes the GraphQL context (root, info) as well as
# Argument (first_name) for the Field and returns data for the query Response
def resolve_hello(root, info, first_name):
return f'Hello {first_name}!'
def resolve_goodbye(root, info):
return 'See ya!'
schema = Schema(query=Query)
A GraphQL **Schema** describes each **Field** in the data model provided by the server using scalar types like *String*, *Int* and *Enum* and compound types like *List* and *Object*. For more details refer to the Graphene :ref:`TypesReference`.
Our schema can also define any number of **Arguments** for our **Fields**. This is a powerful way for a **Query** to describe the exact data requirements for each **Field**.
For each **Field** in our **Schema**, we write a **Resolver** method to fetch data requested by a client's **Query** using the current context and **Arguments**. For more details, refer to this section on :ref:`Resolvers`.
Schema Definition Language (SDL)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In the `GraphQL Schema Definition Language`_, we could describe the fields defined by our example code as shown below.
.. _GraphQL Schema Definition Language: https://graphql.org/learn/schema/
.. code::
type Query {
hello(firstName: String = "stranger"): String
goodbye: String
}
Further examples in this documentation will use SDL to describe schema created by ObjectTypes and other fields.
Querying
~~~~~~~~
Then we can start querying our **Schema** by passing a GraphQL query string to ``execute``:
.. code:: python
# we can query for our field (with the default argument)
query_string = '{ hello }'
result = schema.execute(query_string)
print(result.data['hello'])
# "Hello stranger!"
# or passing the argument in the query
query_with_argument = '{ hello(firstName: "GraphQL") }'
result = schema.execute(query_with_argument)
print(result.data['hello'])
# "Hello GraphQL!"
Next steps
~~~~~~~~~~
Congrats! You got your first Graphene schema working!
Normally, we don't need to directly execute a query string against our schema as Graphene provides many useful Integrations with popular web frameworks like Flask and Django. Check out :ref:`Integrations` for more information on how to get started serving your GraphQL API.

45
docs/relay/connection.rst Normal file
View File

@ -0,0 +1,45 @@
Connection
==========
A connection is a vitaminized version of a List that provides ways of
slicing and paginating through it. The way you create Connection types
in ``graphene`` is using ``relay.Connection`` and ``relay.ConnectionField``.
Quick example
-------------
If we want to create a custom Connection on a given node, we have to subclass the
``Connection`` class.
In the following example, ``extra`` will be an extra field in the connection,
and ``other`` an extra field in the Connection Edge.
.. code:: python
class ShipConnection(Connection):
extra = String()
class Meta:
node = Ship
class Edge:
other = String()
The ``ShipConnection`` connection class, will have automatically a ``pageInfo`` field,
and a ``edges`` field (which is a list of ``ShipConnection.Edge``).
This ``Edge`` will have a ``node`` field linking to the specified node
(in ``ShipConnection.Meta``) and the field ``other`` that we defined in the class.
Connection Field
----------------
You can create connection fields in any Connection, in case any ObjectType
that implements ``Node`` will have a default Connection.
.. code:: python
class Faction(graphene.ObjectType):
name = graphene.String()
ships = relay.ConnectionField(ShipConnection)
def resolve_ships(root, info):
return []

26
docs/relay/index.rst Normal file
View File

@ -0,0 +1,26 @@
Relay
=====
Graphene has complete support for `Relay`_ and offers some utils to make
integration from Python easy.
.. toctree::
:maxdepth: 2
nodes
connection
mutations
Useful links
------------
- `Getting started with Relay`_
- `Relay Global Identification Specification`_
- `Relay Cursor Connection Specification`_
.. _Relay: https://relay.dev/docs/guides/graphql-server-specification/
.. _Getting started with Relay: https://relay.dev/docs/getting-started/step-by-step-guide/
.. _Relay Global Identification Specification: https://relay.dev/graphql/objectidentification.htm
.. _Relay Cursor Connection Specification: https://relay.dev/graphql/connections.htm

57
docs/relay/mutations.rst Normal file
View File

@ -0,0 +1,57 @@
Mutations
=========
Most APIs dont just allow you to read data, they also allow you to
write.
In GraphQL, this is done using mutations. Just like queries,
Relay puts some additional requirements on mutations, but Graphene
nicely manages that for you. All you need to do is make your mutation a
subclass of ``relay.ClientIDMutation``.
.. code:: python
class IntroduceShip(relay.ClientIDMutation):
class Input:
ship_name = graphene.String(required=True)
faction_id = graphene.String(required=True)
ship = graphene.Field(Ship)
faction = graphene.Field(Faction)
@classmethod
def mutate_and_get_payload(cls, root, info, **input):
ship_name = input.ship_name
faction_id = input.faction_id
ship = create_ship(ship_name, faction_id)
faction = get_faction(faction_id)
return IntroduceShip(ship=ship, faction=faction)
Accepting Files
---------------
Mutations can also accept files, that's how it will work with different integrations:
.. code:: python
class UploadFile(graphene.ClientIDMutation):
class Input:
pass
# nothing needed for uploading file
# your return fields
success = graphene.String()
@classmethod
def mutate_and_get_payload(cls, root, info, **input):
# When using it in Django, context will be the request
files = info.context.FILES
# Or, if used in Flask, context will be the flask global request
# files = context.files
# do something with files
return UploadFile(success=True)

102
docs/relay/nodes.rst Normal file
View File

@ -0,0 +1,102 @@
Nodes
=====
A ``Node`` is an Interface provided by ``graphene.relay`` that contains
a single field ``id`` (which is a ``ID!``). Any object that inherits
from it has to implement a ``get_node`` method for retrieving a
``Node`` by an *id*.
Quick example
-------------
Example usage (taken from the `Starwars Relay example`_):
.. code:: python
class Ship(graphene.ObjectType):
'''A ship in the Star Wars saga'''
class Meta:
interfaces = (relay.Node, )
name = graphene.String(description='The name of the ship.')
@classmethod
def get_node(cls, info, id):
return get_ship(id)
The ``id`` returned by the ``Ship`` type when you query it will be a
scalar which contains enough info for the server to know its type and
its id.
For example, the instance ``Ship(id=1)`` will return ``U2hpcDox`` as the
id when you query it (which is the base64 encoding of ``Ship:1``), and
which could be useful later if we want to query a node by its id.
Custom Nodes
------------
You can use the predefined ``relay.Node`` or you can subclass it, defining
custom ways of how a node id is encoded (using the ``to_global_id`` method in the class)
or how we can retrieve a Node given a encoded id (with the ``get_node_from_global_id`` method).
Example of a custom node:
.. code:: python
class CustomNode(Node):
class Meta:
name = 'Node'
@staticmethod
def to_global_id(type_, id):
return f"{type_}:{id}"
@staticmethod
def get_node_from_global_id(info, global_id, only_type=None):
type_, id = global_id.split(':')
if only_type:
# We assure that the node type that we want to retrieve
# is the same that was indicated in the field type
assert type_ == only_type._meta.name, 'Received not compatible node.'
if type_ == 'User':
return get_user(id)
elif type_ == 'Photo':
return get_photo(id)
The ``get_node_from_global_id`` method will be called when ``CustomNode.Field`` is resolved.
Accessing node types
--------------------
If we want to retrieve node instances from a ``global_id`` (scalar that identifies an instance by it's type name and id),
we can simply do ``Node.get_node_from_global_id(info, global_id)``.
In the case we want to restrict the instance retrieval to a specific type, we can do:
``Node.get_node_from_global_id(info, global_id, only_type=Ship)``. This will raise an error
if the ``global_id`` doesn't correspond to a Ship type.
Node Root field
---------------
As is required in the `Relay specification`_, the server must implement
a root field called ``node`` that returns a ``Node`` Interface.
For this reason, ``graphene`` provides the field ``relay.Node.Field``,
which links to any type in the Schema which implements ``Node``.
Example usage:
.. code:: python
class Query(graphene.ObjectType):
# Should be CustomNode.Field() if we want to use our custom Node
node = relay.Node.Field()
.. _Relay specification: https://facebook.github.io/relay/docs/graphql-relay-specification.html
.. _Starwars Relay example: https://github.com/graphql-python/graphene/blob/master/examples/starwars_relay/schema.py

5
docs/requirements.txt Normal file
View File

@ -0,0 +1,5 @@
# Required library
Sphinx==6.1.3
sphinx-autobuild==2021.3.14
# Docs template
http://graphene-python.org/sphinx_graphene_theme.zip

1
docs/static/CNAME vendored
View File

@ -1 +0,0 @@
graphene-python.org

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

71
docs/testing/index.rst Normal file
View File

@ -0,0 +1,71 @@
===================
Testing in Graphene
===================
Automated testing is an extremely useful bug-killing tool for the modern developer. You can use a collection of tests a test suite to solve, or avoid, a number of problems:
- When youre writing new code, you can use tests to validate your code works as expected.
- When youre refactoring or modifying old code, you can use tests to ensure your changes havent affected your applications behavior unexpectedly.
Testing a GraphQL application is a complex task, because a GraphQL application is made of several layers of logic schema definition, schema validation, permissions and field resolution.
With Graphene test-execution framework and assorted utilities, you can simulate GraphQL requests, execute mutations, inspect your applications output and generally verify your code is doing what it should be doing.
Testing tools
-------------
Graphene provides a small set of tools that come in handy when writing tests.
Test Client
~~~~~~~~~~~
The test client is a Python class that acts as a dummy GraphQL client, allowing you to test your views and interact with your Graphene-powered application programmatically.
Some of the things you can do with the test client are:
- Simulate Queries and Mutations and observe the response.
- Test that a given query request is rendered by a given Django template, with a template context that contains certain values.
Overview and a quick example
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To use the test client, instantiate ``graphene.test.Client`` and retrieve GraphQL responses:
.. code:: python
from graphene.test import Client
def test_hey():
client = Client(my_schema)
executed = client.execute('''{ hey }''')
assert executed == {
'data': {
'hey': 'hello!'
}
}
Execute parameters
~~~~~~~~~~~~~~~~~~
You can also add extra keyword arguments to the ``execute`` method, such as
``context``, ``root``, ``variables``, ...:
.. code:: python
from graphene.test import Client
def test_hey():
client = Client(my_schema)
executed = client.execute('''{ hey }''', context={'user': 'Peter'})
assert executed == {
'data': {
'hey': 'hello Peter!'
}
}

Some files were not shown because too many files have changed in this diff Show More