strawberry-graphql 0.278.1__tar.gz → 0.279.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of strawberry-graphql might be problematic. Click here for more details.

Files changed (245) hide show
  1. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/PKG-INFO +1 -1
  2. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/pyproject.toml +1 -1
  3. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/upgrade/__init__.py +2 -0
  4. strawberry_graphql-0.279.0/strawberry/codemods/__init__.py +9 -0
  5. strawberry_graphql-0.279.0/strawberry/codemods/maybe_optional.py +118 -0
  6. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/schema.py +2 -0
  7. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/schema_converter.py +7 -0
  8. strawberry_graphql-0.279.0/strawberry/schema/validation_rules/maybe_null.py +136 -0
  9. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/arguments.py +16 -2
  10. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/maybe.py +1 -1
  11. strawberry_graphql-0.278.1/strawberry/types/fields/__init__.py +0 -0
  12. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/LICENSE +0 -0
  13. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/README.md +0 -0
  14. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/__init__.py +0 -0
  15. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/__main__.py +0 -0
  16. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/aiohttp/__init__.py +0 -0
  17. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/aiohttp/test/__init__.py +0 -0
  18. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/aiohttp/test/client.py +0 -0
  19. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/aiohttp/views.py +0 -0
  20. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/annotation.py +0 -0
  21. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/asgi/__init__.py +0 -0
  22. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/asgi/test/__init__.py +0 -0
  23. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/asgi/test/client.py +0 -0
  24. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/chalice/__init__.py +0 -0
  25. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/chalice/views.py +0 -0
  26. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/__init__.py +0 -0
  27. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/handlers/__init__.py +0 -0
  28. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/handlers/base.py +0 -0
  29. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/handlers/http_handler.py +0 -0
  30. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/handlers/ws_handler.py +0 -0
  31. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/router.py +0 -0
  32. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/channels/testing.py +0 -0
  33. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/__init__.py +0 -0
  34. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/app.py +0 -0
  35. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/__init__.py +0 -0
  36. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/codegen.py +0 -0
  37. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/export_schema.py +0 -0
  38. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/locate_definition.py +0 -0
  39. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/schema_codegen.py +0 -0
  40. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/server.py +0 -0
  41. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/upgrade/_fake_progress.py +0 -0
  42. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/commands/upgrade/_run_codemod.py +0 -0
  43. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/constants.py +0 -0
  44. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/debug_server.py +0 -0
  45. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/utils/__init__.py +0 -0
  46. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/cli/utils/load_schema.py +0 -0
  47. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/__init__.py +0 -0
  48. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/exceptions.py +0 -0
  49. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/plugins/__init__.py +0 -0
  50. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/plugins/print_operation.py +0 -0
  51. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/plugins/python.py +0 -0
  52. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/plugins/typescript.py +0 -0
  53. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/query_codegen.py +0 -0
  54. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codegen/types.py +0 -0
  55. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codemods/annotated_unions.py +0 -0
  56. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/codemods/update_imports.py +0 -0
  57. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/dataloader.py +0 -0
  58. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/directive.py +0 -0
  59. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/__init__.py +0 -0
  60. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/apps.py +0 -0
  61. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/context.py +0 -0
  62. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/test/__init__.py +0 -0
  63. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/test/client.py +0 -0
  64. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/django/views.py +0 -0
  65. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/__init__.py +0 -0
  66. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/conflicting_arguments.py +0 -0
  67. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/duplicated_type_name.py +0 -0
  68. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/exception.py +0 -0
  69. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/exception_source.py +0 -0
  70. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/handler.py +0 -0
  71. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/invalid_argument_type.py +0 -0
  72. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/invalid_superclass_interface.py +0 -0
  73. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/invalid_union_type.py +0 -0
  74. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/missing_arguments_annotations.py +0 -0
  75. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/missing_dependencies.py +0 -0
  76. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/missing_field_annotation.py +0 -0
  77. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/missing_return_annotation.py +0 -0
  78. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/object_is_not_a_class.py +0 -0
  79. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/object_is_not_an_enum.py +0 -0
  80. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/permission_fail_silently_requires_optional.py +0 -0
  81. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/private_strawberry_field.py +0 -0
  82. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/scalar_already_registered.py +0 -0
  83. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/syntax.py +0 -0
  84. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/unresolved_field_type.py +0 -0
  85. {strawberry_graphql-0.278.1/strawberry/codemods → strawberry_graphql-0.279.0/strawberry/exceptions/utils}/__init__.py +0 -0
  86. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/exceptions/utils/source_finder.py +0 -0
  87. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/__init__.py +0 -0
  88. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/__init__.py +0 -0
  89. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/_compat.py +0 -0
  90. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/conversion.py +0 -0
  91. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/conversion_types.py +0 -0
  92. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/error_type.py +0 -0
  93. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/exceptions.py +0 -0
  94. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/fields.py +0 -0
  95. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/object_type.py +0 -0
  96. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/experimental/pydantic/utils.py +0 -0
  97. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/ext/LICENSE +0 -0
  98. {strawberry_graphql-0.278.1/strawberry/exceptions/utils → strawberry_graphql-0.279.0/strawberry/ext}/__init__.py +0 -0
  99. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/ext/dataclasses/LICENSE +0 -0
  100. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/ext/dataclasses/README.md +0 -0
  101. {strawberry_graphql-0.278.1/strawberry/ext → strawberry_graphql-0.279.0/strawberry/ext/dataclasses}/__init__.py +0 -0
  102. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/ext/dataclasses/dataclasses.py +0 -0
  103. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/ext/mypy_plugin.py +0 -0
  104. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/__init__.py +0 -0
  105. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/add_validation_rules.py +0 -0
  106. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/base_extension.py +0 -0
  107. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/context.py +0 -0
  108. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/directives.py +0 -0
  109. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/disable_introspection.py +0 -0
  110. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/disable_validation.py +0 -0
  111. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/field_extension.py +0 -0
  112. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/mask_errors.py +0 -0
  113. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/max_aliases.py +0 -0
  114. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/max_tokens.py +0 -0
  115. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/parser_cache.py +0 -0
  116. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/pyinstrument.py +0 -0
  117. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/query_depth_limiter.py +0 -0
  118. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/runner.py +0 -0
  119. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/tracing/__init__.py +0 -0
  120. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/tracing/apollo.py +0 -0
  121. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/tracing/datadog.py +0 -0
  122. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/tracing/opentelemetry.py +0 -0
  123. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/tracing/utils.py +0 -0
  124. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/utils.py +0 -0
  125. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/extensions/validation_cache.py +0 -0
  126. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/fastapi/__init__.py +0 -0
  127. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/fastapi/context.py +0 -0
  128. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/fastapi/router.py +0 -0
  129. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/__init__.py +0 -0
  130. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/argument.py +0 -0
  131. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/enum.py +0 -0
  132. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/field.py +0 -0
  133. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/mutation.py +0 -0
  134. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/object_type.py +0 -0
  135. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/scalar.py +0 -0
  136. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/schema.py +0 -0
  137. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/schema_directive.py +0 -0
  138. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/schema_directives.py +0 -0
  139. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/types.py +0 -0
  140. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/federation/union.py +0 -0
  141. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/field_extensions/__init__.py +0 -0
  142. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/field_extensions/input_mutation.py +0 -0
  143. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/file_uploads/__init__.py +0 -0
  144. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/file_uploads/scalars.py +0 -0
  145. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/file_uploads/utils.py +0 -0
  146. {strawberry_graphql-0.278.1/strawberry/ext/dataclasses → strawberry_graphql-0.279.0/strawberry/flask}/__init__.py +0 -0
  147. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/flask/views.py +0 -0
  148. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/__init__.py +0 -0
  149. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/async_base_view.py +0 -0
  150. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/base.py +0 -0
  151. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/exceptions.py +0 -0
  152. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/ides.py +0 -0
  153. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/parse_content_type.py +0 -0
  154. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/sync_base_view.py +0 -0
  155. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/temporal_response.py +0 -0
  156. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/types.py +0 -0
  157. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/http/typevars.py +0 -0
  158. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/litestar/__init__.py +0 -0
  159. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/litestar/controller.py +0 -0
  160. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/parent.py +0 -0
  161. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/permission.py +0 -0
  162. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/printer/__init__.py +0 -0
  163. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/printer/ast_from_value.py +0 -0
  164. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/printer/printer.py +0 -0
  165. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/py.typed +0 -0
  166. {strawberry_graphql-0.278.1/strawberry/flask → strawberry_graphql-0.279.0/strawberry/quart}/__init__.py +0 -0
  167. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/quart/views.py +0 -0
  168. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/relay/__init__.py +0 -0
  169. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/relay/exceptions.py +0 -0
  170. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/relay/fields.py +0 -0
  171. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/relay/types.py +0 -0
  172. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/relay/utils.py +0 -0
  173. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/resolvers.py +0 -0
  174. {strawberry_graphql-0.278.1/strawberry/quart → strawberry_graphql-0.279.0/strawberry/sanic}/__init__.py +0 -0
  175. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/sanic/context.py +0 -0
  176. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/sanic/utils.py +0 -0
  177. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/sanic/views.py +0 -0
  178. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/scalars.py +0 -0
  179. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/__init__.py +0 -0
  180. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/_graphql_core.py +0 -0
  181. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/base.py +0 -0
  182. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/compat.py +0 -0
  183. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/config.py +0 -0
  184. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/exceptions.py +0 -0
  185. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/name_converter.py +0 -0
  186. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/types/__init__.py +0 -0
  187. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/types/base_scalars.py +0 -0
  188. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/types/concrete_type.py +0 -0
  189. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/types/scalar.py +0 -0
  190. {strawberry_graphql-0.278.1/strawberry/sanic → strawberry_graphql-0.279.0/strawberry/schema/validation_rules}/__init__.py +0 -0
  191. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema/validation_rules/one_of.py +0 -0
  192. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema_codegen/__init__.py +0 -0
  193. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema_directive.py +0 -0
  194. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/schema_directives.py +0 -0
  195. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/static/apollo-sandbox.html +0 -0
  196. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/static/graphiql.html +0 -0
  197. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/static/pathfinder.html +0 -0
  198. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/streamable.py +0 -0
  199. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/__init__.py +0 -0
  200. {strawberry_graphql-0.278.1/strawberry/schema/validation_rules → strawberry_graphql-0.279.0/strawberry/subscriptions/protocols}/__init__.py +0 -0
  201. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py +0 -0
  202. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +0 -0
  203. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/protocols/graphql_transport_ws/types.py +0 -0
  204. {strawberry_graphql-0.278.1/strawberry/subscriptions/protocols → strawberry_graphql-0.279.0/strawberry/subscriptions/protocols/graphql_ws}/__init__.py +0 -0
  205. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/protocols/graphql_ws/handlers.py +0 -0
  206. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/subscriptions/protocols/graphql_ws/types.py +0 -0
  207. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/test/__init__.py +0 -0
  208. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/test/client.py +0 -0
  209. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/tools/__init__.py +0 -0
  210. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/tools/create_type.py +0 -0
  211. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/tools/merge_types.py +0 -0
  212. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/__init__.py +0 -0
  213. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/auto.py +0 -0
  214. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/base.py +0 -0
  215. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/cast.py +0 -0
  216. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/enum.py +0 -0
  217. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/execution.py +0 -0
  218. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/field.py +0 -0
  219. {strawberry_graphql-0.278.1/strawberry/subscriptions/protocols/graphql_ws → strawberry_graphql-0.279.0/strawberry/types/fields}/__init__.py +0 -0
  220. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/fields/resolver.py +0 -0
  221. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/graphql.py +0 -0
  222. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/info.py +0 -0
  223. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/lazy_type.py +0 -0
  224. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/mutation.py +0 -0
  225. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/nodes.py +0 -0
  226. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/object_type.py +0 -0
  227. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/private.py +0 -0
  228. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/scalar.py +0 -0
  229. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/type_resolver.py +0 -0
  230. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/union.py +0 -0
  231. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/types/unset.py +0 -0
  232. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/__init__.py +0 -0
  233. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/aio.py +0 -0
  234. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/await_maybe.py +0 -0
  235. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/dataclasses.py +0 -0
  236. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/debug.py +0 -0
  237. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/deprecations.py +0 -0
  238. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/graphql_lexer.py +0 -0
  239. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/importer.py +0 -0
  240. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/inspect.py +0 -0
  241. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/locate_definition.py +0 -0
  242. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/logging.py +0 -0
  243. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/operation.py +0 -0
  244. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/str_converters.py +0 -0
  245. {strawberry_graphql-0.278.1 → strawberry_graphql-0.279.0}/strawberry/utils/typing.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: strawberry-graphql
3
- Version: 0.278.1
3
+ Version: 0.279.0
4
4
  Summary: A library for creating GraphQL APIs
5
5
  License: MIT
6
6
  Keywords: graphql,api,rest,starlette,async
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "strawberry-graphql"
3
- version = "0.278.1"
3
+ version = "0.279.0"
4
4
  description = "A library for creating GraphQL APIs"
5
5
  authors = [{ name = "Patrick Arminio", email = "patrick.arminio@gmail.com" }]
6
6
  license = { text = "MIT" }
@@ -10,6 +10,7 @@ from libcst.codemod import CodemodContext
10
10
 
11
11
  from strawberry.cli.app import app
12
12
  from strawberry.codemods.annotated_unions import ConvertUnionToAnnotatedUnion
13
+ from strawberry.codemods.maybe_optional import ConvertMaybeToOptional
13
14
  from strawberry.codemods.update_imports import UpdateImportsCodemod
14
15
 
15
16
  from ._run_codemod import run_codemod
@@ -17,6 +18,7 @@ from ._run_codemod import run_codemod
17
18
  codemods = {
18
19
  "annotated-union": ConvertUnionToAnnotatedUnion,
19
20
  "update-imports": UpdateImportsCodemod,
21
+ "maybe-optional": ConvertMaybeToOptional,
20
22
  }
21
23
 
22
24
 
@@ -0,0 +1,9 @@
1
+ from .annotated_unions import ConvertUnionToAnnotatedUnion
2
+ from .maybe_optional import ConvertMaybeToOptional
3
+ from .update_imports import UpdateImportsCodemod
4
+
5
+ __all__ = [
6
+ "ConvertMaybeToOptional",
7
+ "ConvertUnionToAnnotatedUnion",
8
+ "UpdateImportsCodemod",
9
+ ]
@@ -0,0 +1,118 @@
1
+ from __future__ import annotations
2
+
3
+ import libcst as cst
4
+ import libcst.matchers as m
5
+ from libcst._nodes.expression import BaseExpression # noqa: TC002
6
+ from libcst.codemod import CodemodContext, VisitorBasedCodemodCommand
7
+ from libcst.codemod.visitors import AddImportsVisitor
8
+
9
+
10
+ class ConvertMaybeToOptional(VisitorBasedCodemodCommand):
11
+ DESCRIPTION: str = (
12
+ "Converts strawberry.Maybe[T] to strawberry.Maybe[T | None] "
13
+ "to match the new Maybe type definition"
14
+ )
15
+
16
+ def __init__(
17
+ self,
18
+ context: CodemodContext,
19
+ use_pipe_syntax: bool = True, # Default to pipe syntax for modern Python
20
+ ) -> None:
21
+ self.use_pipe_syntax = use_pipe_syntax
22
+ super().__init__(context)
23
+
24
+ @m.leave(
25
+ m.Subscript(
26
+ value=m.Attribute(value=m.Name("strawberry"), attr=m.Name("Maybe"))
27
+ | m.Name("Maybe")
28
+ )
29
+ )
30
+ def leave_maybe_subscript(
31
+ self, original_node: cst.Subscript, updated_node: cst.Subscript
32
+ ) -> BaseExpression:
33
+ # Skip if it's not a strawberry.Maybe or imported Maybe
34
+ if isinstance(original_node.value, cst.Name):
35
+ # Check if this is an imported Maybe from strawberry
36
+ # For now, we'll assume any standalone "Maybe" is from strawberry
37
+ # In a more robust implementation, we'd track imports
38
+ pass
39
+
40
+ # Get the inner type
41
+ if isinstance(original_node.slice, (list, tuple)):
42
+ if len(original_node.slice) != 1:
43
+ return original_node
44
+ slice_element = original_node.slice[0]
45
+ else:
46
+ slice_element = original_node.slice
47
+
48
+ if not isinstance(slice_element, cst.SubscriptElement):
49
+ return original_node
50
+
51
+ if not isinstance(slice_element.slice, cst.Index):
52
+ return original_node
53
+
54
+ inner_type = slice_element.slice.value
55
+
56
+ # Check if the inner type already includes None
57
+ if self._already_includes_none(inner_type):
58
+ return original_node
59
+
60
+ # Create the new union type with None
61
+ new_type: BaseExpression
62
+ if self.use_pipe_syntax:
63
+ new_type = cst.BinaryOperation(
64
+ left=inner_type,
65
+ operator=cst.BitOr(
66
+ whitespace_before=cst.SimpleWhitespace(" "),
67
+ whitespace_after=cst.SimpleWhitespace(" "),
68
+ ),
69
+ right=cst.Name("None"),
70
+ )
71
+ else:
72
+ # Use Union[T, None] syntax
73
+ AddImportsVisitor.add_needed_import(self.context, "typing", "Union")
74
+ new_type = cst.Subscript(
75
+ value=cst.Name("Union"),
76
+ slice=[
77
+ cst.SubscriptElement(slice=cst.Index(value=inner_type)),
78
+ cst.SubscriptElement(slice=cst.Index(value=cst.Name("None"))),
79
+ ],
80
+ )
81
+
82
+ # Return the updated Maybe[T | None]
83
+ return updated_node.with_changes(
84
+ slice=[cst.SubscriptElement(slice=cst.Index(value=new_type))]
85
+ )
86
+
87
+ def _already_includes_none(self, node: BaseExpression) -> bool:
88
+ """Check if the type already includes None (e.g., T | None or Union[T, None])."""
89
+ # Check for T | None pattern
90
+ if isinstance(node, cst.BinaryOperation) and isinstance(
91
+ node.operator, cst.BitOr
92
+ ):
93
+ if isinstance(node.right, cst.Name) and node.right.value == "None":
94
+ return True
95
+ # Recursively check left side for chained unions
96
+ if self._already_includes_none(node.left):
97
+ return True
98
+
99
+ # Check for Union[..., None] pattern
100
+ if (
101
+ isinstance(node, cst.Subscript)
102
+ and isinstance(node.value, cst.Name)
103
+ and node.value.value == "Union"
104
+ ):
105
+ # Handle both list and tuple slice formats
106
+ slice_elements = (
107
+ node.slice if isinstance(node.slice, (list, tuple)) else [node.slice]
108
+ )
109
+ for element in slice_elements:
110
+ if (
111
+ isinstance(element, cst.SubscriptElement)
112
+ and isinstance(element.slice, cst.Index)
113
+ and isinstance(element.slice.value, cst.Name)
114
+ and element.slice.value.value == "None"
115
+ ):
116
+ return True
117
+
118
+ return False
@@ -50,6 +50,7 @@ from strawberry.extensions.directives import (
50
50
  from strawberry.extensions.runner import SchemaExtensionsRunner
51
51
  from strawberry.printer import print_schema
52
52
  from strawberry.schema.schema_converter import GraphQLCoreConverter
53
+ from strawberry.schema.validation_rules.maybe_null import MaybeNullValidationRule
53
54
  from strawberry.schema.validation_rules.one_of import OneOfInputValidationRule
54
55
  from strawberry.types.base import (
55
56
  StrawberryObjectDefinition,
@@ -124,6 +125,7 @@ def validate_document(
124
125
  ) -> list[GraphQLError]:
125
126
  validation_rules = (
126
127
  *validation_rules,
128
+ MaybeNullValidationRule,
127
129
  OneOfInputValidationRule,
128
130
  )
129
131
  return validate(
@@ -854,6 +854,13 @@ class GraphQLCoreConverter:
854
854
  NoneType = type(None)
855
855
  if type_ is None or type_ is NoneType:
856
856
  return self.from_type(type_)
857
+ if isinstance(type_, StrawberryMaybe):
858
+ # StrawberryMaybe should always generate optional types
859
+ # because Maybe[T] = Union[Some[T], None] (field can be absent)
860
+ # But we need to handle the case where of_type is itself optional
861
+ if isinstance(type_.of_type, StrawberryOptional):
862
+ return self.from_type(type_.of_type.of_type)
863
+ return self.from_type(type_.of_type)
857
864
  if isinstance(type_, StrawberryOptional):
858
865
  return self.from_type(type_.of_type)
859
866
  return GraphQLNonNull(self.from_type(type_))
@@ -0,0 +1,136 @@
1
+ from typing import Any
2
+
3
+ from graphql import (
4
+ ArgumentNode,
5
+ GraphQLError,
6
+ GraphQLNamedType,
7
+ ObjectValueNode,
8
+ ValidationContext,
9
+ ValidationRule,
10
+ get_named_type,
11
+ )
12
+
13
+ from strawberry.types.base import StrawberryMaybe, StrawberryOptional
14
+ from strawberry.utils.str_converters import to_camel_case
15
+
16
+
17
+ class MaybeNullValidationRule(ValidationRule):
18
+ """Validates that Maybe[T] fields do not receive explicit null values.
19
+
20
+ This rule ensures that:
21
+ - Maybe[T] fields can only be omitted or have non-null values
22
+ - Maybe[T | None] fields can be omitted, null, or have non-null values
23
+
24
+ This provides clear semantics where Maybe[T] means "either present with value or absent"
25
+ and Maybe[T | None] means "present with value, present but null, or absent".
26
+ """
27
+
28
+ def __init__(self, validation_context: ValidationContext) -> None:
29
+ super().__init__(validation_context)
30
+
31
+ def enter_argument(self, node: ArgumentNode, *_args: Any) -> None:
32
+ # Check if this is a null value
33
+ if node.value.kind != "null_value":
34
+ return
35
+
36
+ # Get the argument definition from the schema
37
+ argument_def = self.context.get_argument()
38
+ if not argument_def:
39
+ return
40
+
41
+ # Check if this argument corresponds to a Maybe[T] (not Maybe[T | None])
42
+ # The argument type extensions should contain the Strawberry type info
43
+ strawberry_arg_info = argument_def.extensions.get("strawberry-definition")
44
+ if not strawberry_arg_info:
45
+ return
46
+
47
+ # Get the Strawberry type from the argument info
48
+ field_type = getattr(strawberry_arg_info, "type", None)
49
+ if not field_type:
50
+ return
51
+
52
+ if isinstance(field_type, StrawberryMaybe) and not isinstance(
53
+ field_type.of_type, StrawberryOptional
54
+ ):
55
+ # This is Maybe[T] - should not accept null values
56
+ type_name = self._get_type_name(field_type.of_type)
57
+
58
+ self.report_error(
59
+ GraphQLError(
60
+ f"Expected value of type '{type_name}', found null. "
61
+ f"Argument '{node.name.value}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
62
+ f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
63
+ nodes=[node],
64
+ )
65
+ )
66
+
67
+ def enter_object_value(self, node: ObjectValueNode, *_args: Any) -> None:
68
+ # Get the input type for this object
69
+ input_type = get_named_type(self.context.get_input_type())
70
+ if not input_type:
71
+ return
72
+
73
+ # Get the Strawberry type definition from extensions
74
+ strawberry_type = input_type.extensions.get("strawberry-definition")
75
+ if not strawberry_type:
76
+ return
77
+
78
+ # Check each field in the object for null Maybe[T] violations
79
+ self.validate_maybe_fields(node, input_type, strawberry_type)
80
+
81
+ def validate_maybe_fields(
82
+ self, node: ObjectValueNode, input_type: GraphQLNamedType, strawberry_type: Any
83
+ ) -> None:
84
+ # Create a map of field names to field nodes for easy lookup
85
+ field_node_map = {field.name.value: field for field in node.fields}
86
+
87
+ # Check each field in the Strawberry type definition
88
+ if not hasattr(strawberry_type, "fields"):
89
+ return
90
+
91
+ for field_def in strawberry_type.fields:
92
+ # Resolve the actual GraphQL field name using the same logic as NameConverter
93
+ if field_def.graphql_name is not None:
94
+ field_name = field_def.graphql_name
95
+ else:
96
+ # Apply auto_camel_case conversion if enabled (default behavior)
97
+ field_name = to_camel_case(field_def.python_name)
98
+
99
+ # Check if this field is present in the input and has a null value
100
+ if field_name in field_node_map:
101
+ field_node = field_node_map[field_name]
102
+
103
+ # Check if this field has a null value
104
+ if field_node.value.kind == "null_value":
105
+ # Check if this is a Maybe[T] (not Maybe[T | None])
106
+ field_type = field_def.type
107
+ if isinstance(field_type, StrawberryMaybe) and not isinstance(
108
+ field_type.of_type, StrawberryOptional
109
+ ):
110
+ # This is Maybe[T] - should not accept null values
111
+ type_name = self._get_type_name(field_type.of_type)
112
+ self.report_error(
113
+ GraphQLError(
114
+ f"Expected value of type '{type_name}', found null. "
115
+ f"Field '{field_name}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
116
+ f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
117
+ nodes=[field_node],
118
+ )
119
+ )
120
+
121
+ def _get_type_name(self, type_: Any) -> str:
122
+ """Get a readable type name for error messages."""
123
+ if hasattr(type_, "__name__"):
124
+ return type_.__name__
125
+ # Handle Strawberry types that don't have __name__
126
+ if hasattr(type_, "of_type") and hasattr(type_.of_type, "__name__"):
127
+ # For StrawberryList, StrawberryOptional, etc.
128
+ return (
129
+ f"list[{type_.of_type.__name__}]"
130
+ if "List" in str(type_.__class__)
131
+ else type_.of_type.__name__
132
+ )
133
+ return str(type_)
134
+
135
+
136
+ __all__ = ["MaybeNullValidationRule"]
@@ -191,10 +191,24 @@ def convert_argument(
191
191
  from strawberry.relay.types import GlobalID
192
192
 
193
193
  # TODO: move this somewhere else and make it first class
194
- if isinstance(type_, StrawberryOptional):
194
+ # Handle StrawberryMaybe first, since it extends StrawberryOptional
195
+ if isinstance(type_, StrawberryMaybe):
196
+ # Check if this is Maybe[T | None] (has StrawberryOptional as of_type)
197
+ if isinstance(type_.of_type, StrawberryOptional):
198
+ # This is Maybe[T | None] - allows null values
199
+ res = convert_argument(value, type_.of_type, scalar_registry, config)
200
+
201
+ return Some(res)
202
+
203
+ # This is Maybe[T] - validation for null values is handled by MaybeNullValidationRule
204
+ # Convert the value and wrap in Some()
195
205
  res = convert_argument(value, type_.of_type, scalar_registry, config)
196
206
 
197
- return Some(res) if isinstance(type_, StrawberryMaybe) else res
207
+ return Some(res)
208
+
209
+ # Handle regular StrawberryOptional (not Maybe)
210
+ if isinstance(type_, StrawberryOptional):
211
+ return convert_argument(value, type_.of_type, scalar_registry, config)
198
212
 
199
213
  if value is None:
200
214
  return None
@@ -31,7 +31,7 @@ class Some(Generic[T]):
31
31
 
32
32
 
33
33
  if TYPE_CHECKING:
34
- Maybe: TypeAlias = Union[Some[Union[T, None]], None]
34
+ Maybe: TypeAlias = Union[Some[T], None]
35
35
  else:
36
36
  # we do this trick so we can inspect that at runtime
37
37
  class Maybe(Generic[T]): ...