Repository: graphql-python/graphene

Issue:
Bad hyperlink on documentation
NonNull reference under required field from this page https://docs.graphene-python.org/en/latest/types/scalars/ redirects to an inexistent page, namely: 
`https://docs.graphene-python.org/en/latest/types/scalars/list-and-nonnull/#nonnull`
The correct link is
`https://docs.graphene-python.org/en/latest/types/list-and-nonnull/#nonnull`


Discussion:

Patch:
diff --git a/CODEOWNERS b/CODEOWNERS
index 26bb1af..e4457b1 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,1 +1,3 @@
 / @syrusakbary @ekampf @dan98765 @projectcheshire
+/docs/ @dvndrsn @phalt @changeling
+/examples/ @dvndrsn @phalt @changeling
diff --git a/README.rst b/README.rst
index d6f4592..bb8fecb 100644
--- a/README.rst
+++ b/README.rst
@@ -7,180 +7,6 @@ to see how you can help ❤️
 |Graphene Logo| `Graphene <http://graphene-python.org>`__ |Build Status| |PyPI version| |Coverage Status|
 =========================================================================================================
 
-.. raw:: html
-
-   <h1 align="center">
-
-Supporting Graphene Python
-
-.. raw:: html
-
-   </h1>
-
-Graphene is an MIT-licensed open source project. It's an independent
-project with its ongoing development made possible entirely thanks to
-the support by these awesome
-`backers <https://github.com/graphql-python/graphene/blob/master/BACKERS.md>`__.
-If you'd like to join them, please consider:
-
--  `Become a backer or sponsor on
-   Patreon <https://www.patreon.com/syrusakbary>`__.
--  `One-time donation via
-   PayPal. <https://graphene-python.org/support-graphene/>`__
-
-<!--
-
-.. raw:: html
-
-   <h2 align="center">
-
-Special Sponsors
-
-.. raw:: html
-
-   </h2>
-
-.. raw:: html
-
-   <p align="center">
-
-.. raw:: html
-
-   </p>
-
-.. raw:: html
-
-   <!--special end-->
-
-.. raw:: html
-
-   <h2 align="center">
-
-Platinum via Patreon
-
-.. raw:: html
-
-   </h2>
-
-.. raw:: html
-
-   <!--platinum start-->
-
-.. raw:: html
-
-   <table>
-
-.. raw:: html
-
-   <tbody>
-
-::
-
-    <tr>
-      <td align="center" valign="middle">
-        <a href="https://www.patreon.com/join/syrusakbary" target="_blank">
-          <img width="222px" src="https://raw.githubusercontent.com/graphql-python/graphene-python.org/master/src/pages/sponsors/generic-logo.png">
-        </a>
-      </td>
-    </tr>
-
-.. raw:: html
-
-   </tbody>
-
-.. raw:: html
-
-   </table>
-
-.. raw:: html
-
-   <h2 align="center">
-
-Gold via Patreon
-
-.. raw:: html
-
-   </h2>
-
-.. raw:: html
-
-   <!--gold start-->
-
-.. raw:: html
-
-   <table>
-
-.. raw:: html
-
-   <tbody>
-
-::
-
-    <tr>
-      <td align="center" valign="middle">
-        <a href="https://www.patreon.com/join/syrusakbary" target="_blank">
-          <img width="148px" src="https://raw.githubusercontent.com/graphql-python/graphene-python.org/master/src/pages/sponsors/generic-logo.png">
-        </a>
-      </td>
-    </tr>
-
-.. raw:: html
-
-   </tbody>
-
-.. raw:: html
-
-   </table>
-
-.. raw:: html
-
-   <!--gold end-->
-
-.. raw:: html
-
-   <h2 align="center">
-
-Silver via Patreon
-
-.. raw:: html
-
-   </h2>
-
-.. raw:: html
-
-   <!--silver start-->
-
-.. raw:: html
-
-   <table>
-
-.. raw:: html
-
-   <tbody>
-
-::
-
-    <tr>
-      <td align="center" valign="middle">
-        <a href="https://www.patreon.com/join/syrusakbary" target="_blank">
-          <img width="148px" src="https://raw.githubusercontent.com/graphql-python/graphene-python.org/master/src/pages/sponsors/generic-logo.png">
-        </a>
-      </td>
-    </tr>
-
-.. raw:: html
-
-   </tbody>
-
-.. raw:: html
-
-   </table>
-
-.. raw:: html
-
-   <!--silver end-->
-
---------------
 
 Introduction
 ------------
@@ -331,7 +157,7 @@ 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.
diff --git a/docs/types/scalars.rst b/docs/types/scalars.rst
index b4552cf..acbd534 100644
--- a/docs/types/scalars.rst
+++ b/docs/types/scalars.rst
@@ -13,7 +13,7 @@ All Scalar types accept the following arguments. All are optional:
 
 ``required``: *boolean*
 
-    If ``True``, the server will enforce a value for this field. See `NonNull <./list-and-nonnull.html#nonnull>`_. Default is ``False``.
+    If ``True``, the server will enforce a value for this field. See `NonNull <../list-and-nonnull.html#nonnull>`_. Default is ``False``.
 
 ``deprecation_reason``: *string*
 
diff --git a/graphene/__init__.py b/graphene/__init__.py
index c922aea..0984d87 100644
--- a/graphene/__init__.py
+++ b/graphene/__init__.py
@@ -43,7 +43,7 @@ from .utils.resolve_only_args import resolve_only_args
 from .utils.module_loading import lazy_import
 
 
-VERSION = (2, 1, 3, "final", 0)
+VERSION = (2, 1, 5, "final", 0)
 
 __version__ = get_version(VERSION)
 
diff --git a/graphene/types/base.py b/graphene/types/base.py
index 75685d9..f43feb4 100644
--- a/graphene/types/base.py
+++ b/graphene/types/base.py
@@ -34,7 +34,9 @@ class BaseType(SubclassWithMeta):
         return type(class_name, (cls,), {"Meta": options})
 
     @classmethod
-    def __init_subclass_with_meta__(cls, name=None, description=None, _meta=None):
+    def __init_subclass_with_meta__(
+        cls, name=None, description=None, _meta=None, **_kwargs
+    ):
         assert "_meta" not in cls.__dict__, "Can't assign directly meta"
         if not _meta:
             return
diff --git a/tox.ini b/tox.ini
index c1dbd01..57d1f78 100644
--- a/tox.ini
+++ b/tox.ini
@@ -10,7 +10,8 @@ setenv =
      PYTHONPATH = .:{envdir}
 commands =
     py{27,py}: py.test --cov=graphene graphene examples {posargs}
-    py{35,36,37}: py.test --cov=graphene graphene examples tests_asyncio {posargs}
+    py{35}: py.test --cov=graphene graphene examples tests_asyncio {posargs}
+    py{36,37}: py.test --cov=graphene graphene examples tests_asyncio tests_py36 {posargs}
 
 [testenv:pre-commit]
 basepython=python3.6


Test patch:
diff --git a/graphene/types/tests/test_datetime.py b/graphene/types/tests/test_datetime.py
index 0d9ee11..bb6f212 100644
--- a/graphene/types/tests/test_datetime.py
+++ b/graphene/types/tests/test_datetime.py
@@ -27,28 +27,48 @@ class Query(ObjectType):
 schema = Schema(query=Query)
 
 
-def test_datetime_query():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc)
-    isoformat = now.isoformat()
+@pytest.fixture
+def sample_datetime():
+    utc_datetime = datetime.datetime(2019, 5, 25, 5, 30, 15, 10, pytz.utc)
+    return utc_datetime
+
+
+@pytest.fixture
+def sample_time(sample_datetime):
+    time = datetime.time(
+        sample_datetime.hour,
+        sample_datetime.minute,
+        sample_datetime.second,
+        sample_datetime.microsecond,
+        sample_datetime.tzinfo,
+    )
+    return time
+
+
+@pytest.fixture
+def sample_date(sample_datetime):
+    date = sample_datetime.date()
+    return date
+
+
+def test_datetime_query(sample_datetime):
+    isoformat = sample_datetime.isoformat()
 
     result = schema.execute("""{ datetime(in: "%s") }""" % isoformat)
     assert not result.errors
     assert result.data == {"datetime": isoformat}
 
 
-def test_date_query():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
-    isoformat = now.isoformat()
+def test_date_query(sample_date):
+    isoformat = sample_date.isoformat()
 
     result = schema.execute("""{ date(in: "%s") }""" % isoformat)
     assert not result.errors
     assert result.data == {"date": isoformat}
 
 
-def test_time_query():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc)
-    time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
-    isoformat = time.isoformat()
+def test_time_query(sample_time):
+    isoformat = sample_time.isoformat()
 
     result = schema.execute("""{ time(at: "%s") }""" % isoformat)
     assert not result.errors
@@ -85,14 +105,13 @@ def test_bad_time_query():
     assert result.data is None
 
 
-def test_datetime_query_variable():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc)
-    isoformat = now.isoformat()
+def test_datetime_query_variable(sample_datetime):
+    isoformat = sample_datetime.isoformat()
 
     # test datetime variable provided as Python datetime
     result = schema.execute(
         """query Test($date: DateTime){ datetime(in: $date) }""",
-        variables={"date": now},
+        variables={"date": sample_datetime},
     )
     assert not result.errors
     assert result.data == {"datetime": isoformat}
@@ -106,13 +125,13 @@ def test_datetime_query_variable():
     assert result.data == {"datetime": isoformat}
 
 
-def test_date_query_variable():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc).date()
-    isoformat = now.isoformat()
+def test_date_query_variable(sample_date):
+    isoformat = sample_date.isoformat()
 
     # test date variable provided as Python date
     result = schema.execute(
-        """query Test($date: Date){ date(in: $date) }""", variables={"date": now}
+        """query Test($date: Date){ date(in: $date) }""",
+        variables={"date": sample_date},
     )
     assert not result.errors
     assert result.data == {"date": isoformat}
@@ -125,14 +144,13 @@ def test_date_query_variable():
     assert result.data == {"date": isoformat}
 
 
-def test_time_query_variable():
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc)
-    time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
-    isoformat = time.isoformat()
+def test_time_query_variable(sample_time):
+    isoformat = sample_time.isoformat()
 
     # test time variable provided as Python time
     result = schema.execute(
-        """query Test($time: Time){ time(at: $time) }""", variables={"time": time}
+        """query Test($time: Time){ time(at: $time) }""",
+        variables={"time": sample_time},
     )
     assert not result.errors
     assert result.data == {"time": isoformat}
@@ -148,11 +166,13 @@ def test_time_query_variable():
 @pytest.mark.xfail(
     reason="creating the error message fails when un-parsable object is not JSON serializable."
 )
-def test_bad_variables():
-    def _test_bad_variables(type, input):
+def test_bad_variables(sample_date, sample_datetime, sample_time):
+    def _test_bad_variables(type_, input_):
         result = schema.execute(
-            """query Test($input: {}){{ {}(in: $input) }}""".format(type, type.lower()),
-            variables={"input": input},
+            """query Test($input: {}){{ {}(in: $input) }}""".format(
+                type_, type_.lower()
+            ),
+            variables={"input": input_},
         )
         assert len(result.errors) == 1
         # when `input` is not JSON serializable formatting the error message in
@@ -163,9 +183,9 @@ def test_bad_variables():
 
     not_a_date = dict()
     not_a_date_str = "Some string that's not a date"
-    today = datetime.date.today()
-    now = datetime.datetime.now().replace(tzinfo=pytz.utc)
-    time = datetime.time(now.hour, now.minute, now.second, now.microsecond, now.tzinfo)
+    today = sample_date
+    now = sample_datetime
+    time = sample_time
 
     bad_pairs = [
         ("DateTime", not_a_date),
@@ -182,5 +202,5 @@ def test_bad_variables():
         ("Time", today),
     ]
 
-    for type, input in bad_pairs:
-        _test_bad_variables(type, input)
+    for type_, input_ in bad_pairs:
+        _test_bad_variables(type_, input_)
diff --git a/tests_py36/test_objecttype.py b/tests_py36/test_objecttype.py
new file mode 100644
index 0000000..bce38d9
--- /dev/null
+++ b/tests_py36/test_objecttype.py
@@ -0,0 +1,15 @@
+from graphene import Schema, ObjectType, String
+
+
+def test_objecttype_meta_with_annotations():
+    class Query(ObjectType):
+        class Meta:
+            name: str = "oops"
+
+        hello = String()
+
+        def resolve_hello(self, info):
+            return "Hello"
+
+    schema = Schema(query=Query)
+    assert schema is not None