├── .editorconfig ├── .github ├── ISSUE_TEMPLATE │ └── bug_report.md └── workflows │ ├── install-edgedb.sh │ ├── release.yml │ └── tests.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── MANIFEST.in ├── Makefile ├── README.rst ├── docs ├── .gitignore ├── Makefile ├── README.md ├── _static │ └── theme_overrides.css ├── api │ ├── advanced.rst │ ├── asyncio_client.rst │ ├── blocking_client.rst │ ├── codegen.rst │ └── types.rst ├── conf.py ├── index.rst ├── installation.rst ├── requirements.txt └── usage.rst ├── edgedb ├── __init__.py ├── _version.py ├── abstract.py ├── ai │ ├── __init__.py │ ├── core.py │ └── types.py ├── asyncio_client.py ├── base_client.py ├── blocking_client.py ├── codegen.py ├── con_utils.py ├── credentials.py ├── datatypes │ ├── __init__.py │ ├── datatypes.py │ └── range.py ├── describe.py ├── enums.py ├── errors │ ├── __init__.py │ ├── _base.py │ └── tags.py ├── introspect.py ├── options.py ├── pgproto │ ├── __init__.py │ ├── pgproto.py │ └── types.py ├── protocol │ ├── __init__.py │ ├── asyncio_proto.py │ ├── blocking_proto.py │ └── protocol.py ├── py.typed ├── scram │ ├── __init__.py │ └── saslprep.py └── transaction.py ├── gel ├── __init__.py ├── __main__.py ├── _internal │ ├── __init__.py │ ├── _codegen │ │ ├── __init__.py │ │ ├── _generator.py │ │ ├── _models │ │ │ ├── __init__.py │ │ │ └── _pydantic.py │ │ └── _module.py │ ├── _color.py │ ├── _dataclass_extras.py │ ├── _dlist.py │ ├── _edgeql │ │ ├── __init__.py │ │ ├── _keywords.py │ │ ├── _quoting.py │ │ ├── _schema.py │ │ └── _tokens.py │ ├── _hybridmethod.py │ ├── _integration │ │ ├── __init__.py │ │ └── _fastapi │ │ │ ├── __init__.py │ │ │ └── _cli │ │ │ ├── __init__.py │ │ │ ├── _lifespan.py │ │ │ └── _patch.py │ ├── _lazyprop.py │ ├── _platform.py │ ├── _polyfills │ │ ├── __init__.py │ │ ├── _strenum.py │ │ ├── _strenum_impl.py │ │ ├── _taskgroup.py │ │ └── _taskgroup_impl.py │ ├── _qb │ │ ├── __init__.py │ │ ├── _abstract.py │ │ ├── _expressions.py │ │ ├── _generics.py │ │ └── _protocols.py │ ├── _qbmodel │ │ ├── __init__.py │ │ ├── _abstract │ │ │ ├── __init__.py │ │ │ ├── _base.py │ │ │ ├── _descriptors.py │ │ │ ├── _expressions.py │ │ │ ├── _functions.py │ │ │ ├── _objects.py │ │ │ └── _primitive.py │ │ └── _pydantic │ │ │ ├── __init__.py │ │ │ ├── _fields.py │ │ │ ├── _models.py │ │ │ └── _types.py │ ├── _reflection │ │ ├── __init__.py │ │ ├── _callables.py │ │ ├── _casts.py │ │ ├── _enums.py │ │ ├── _functions.py │ │ ├── _modules.py │ │ ├── _operators.py │ │ ├── _query.py │ │ ├── _struct.py │ │ ├── _support.py │ │ └── _types.py │ ├── _save.py │ ├── _typing_dispatch.py │ ├── _typing_eval.py │ ├── _typing_inspect.py │ ├── _typing_parametric.py │ ├── _typing_protos.py │ ├── _unsetid.py │ ├── _utils.py │ └── ruff.toml ├── _testbase.py ├── _version.py ├── abstract.py ├── ai │ ├── __init__.py │ ├── core.py │ └── types.py ├── asyncio_client.py ├── base_client.py ├── blocking_client.py ├── cli.py ├── codegen │ ├── __init__.py │ ├── __main__.py │ ├── cli.py │ └── generator.py ├── con_utils.py ├── connresource.py ├── credentials.py ├── datatypes │ ├── .gitignore │ ├── NOTES │ ├── __init__.pxd │ ├── __init__.py │ ├── abstract.pxd │ ├── abstract.pyx │ ├── args.c │ ├── comp.c │ ├── config_memory.pxd │ ├── config_memory.pyx │ ├── datatypes.h │ ├── datatypes.pxd │ ├── datatypes.pyi │ ├── datatypes.pyx │ ├── date_duration.pxd │ ├── date_duration.pyx │ ├── enum.pyx │ ├── freelist.h │ ├── hash.c │ ├── internal.h │ ├── namedtuple.c │ ├── object.c │ ├── pythoncapi_compat.h │ ├── range.py │ ├── record.c │ ├── record_desc.c │ ├── relative_duration.pxd │ ├── relative_duration.pyx │ └── repr.c ├── describe.py ├── enums.py ├── errors │ ├── __init__.py │ ├── _base.py │ └── tags.py ├── introspect.py ├── models │ ├── __init__.py │ ├── pydantic.py │ └── ruff.toml ├── options.py ├── orm │ ├── __init__.py │ ├── cli.py │ ├── django │ │ ├── __init__.py │ │ ├── gelmodels │ │ │ ├── __init__.py │ │ │ ├── apps.py │ │ │ └── compiler.py │ │ └── generator.py │ ├── introspection.py │ ├── sqla.py │ └── sqlmodel.py ├── protocol │ ├── .gitignore │ ├── __init__.py │ ├── asyncio_proto.pxd │ ├── asyncio_proto.pyx │ ├── blocking_proto.pxd │ ├── blocking_proto.pyx │ ├── codecs │ │ ├── array.pxd │ │ ├── array.pyx │ │ ├── base.pxd │ │ ├── base.pyx │ │ ├── codecs.pxd │ │ ├── codecs.pyx │ │ ├── edb_types.pxi │ │ ├── enum.pxd │ │ ├── enum.pyx │ │ ├── namedtuple.pxd │ │ ├── namedtuple.pyx │ │ ├── object.pxd │ │ ├── object.pyx │ │ ├── range.pxd │ │ ├── range.pyx │ │ ├── record.pxd │ │ ├── record.pyx │ │ ├── scalar.pxd │ │ ├── scalar.pyx │ │ ├── set.pxd │ │ ├── set.pyx │ │ ├── tuple.pxd │ │ └── tuple.pyx │ ├── consts.pxi │ ├── cpythonx.pxd │ ├── lru.pxd │ ├── lru.pyx │ ├── protocol.pxd │ ├── protocol.pyx │ ├── protocol_v0.pxd │ └── protocol_v0.pyx ├── py.typed ├── scram │ ├── __init__.py │ └── saslprep.py └── transaction.py ├── pyproject.toml ├── setup.py ├── tests ├── __init__.py ├── bench_uuid.py ├── codegen │ ├── linked │ │ ├── test_linked.edgeql │ │ ├── test_linked_async_edgeql.py.assert │ │ └── test_linked_edgeql.py.assert │ ├── test-project1 │ │ ├── edgedb.toml │ │ ├── generated_async_edgeql.py.assert │ │ ├── generated_async_edgeql.py.assert3 │ │ ├── generated_async_edgeql.py.assert5 │ │ ├── linked │ │ ├── select_optional_json.edgeql │ │ ├── select_optional_json_async_edgeql.py.assert │ │ ├── select_optional_json_edgeql.py.assert │ │ ├── select_scalar.edgeql │ │ ├── select_scalar_async_edgeql.py.assert │ │ └── select_scalar_edgeql.py.assert │ └── test-project2 │ │ ├── argnames │ │ ├── query_one.edgeql │ │ ├── query_one_async_edgeql.py.assert │ │ └── query_one_edgeql.py.assert │ │ ├── dbschema │ │ └── migrations │ │ │ └── 00001.edgeqll │ │ ├── edgedb.toml │ │ ├── generated_async_edgeql.py.assert │ │ ├── generated_async_edgeql.py.assert3 │ │ ├── generated_async_edgeql.py.assert5 │ │ ├── object │ │ ├── link_prop.edgeql │ │ ├── link_prop_async_edgeql.py.assert │ │ ├── link_prop_edgeql.py.assert │ │ ├── select_object.edgeql │ │ ├── select_object_async_edgeql.py.assert │ │ ├── select_object_edgeql.py.assert │ │ ├── select_objects.edgeql │ │ ├── select_objects_async_edgeql.py.assert │ │ └── select_objects_edgeql.py.assert │ │ ├── parpkg │ │ ├── select_args.edgeql │ │ ├── select_args_async_edgeql.py.assert │ │ ├── select_args_async_edgeql.py.assert3 │ │ ├── select_args_async_edgeql.py.assert5 │ │ ├── select_args_edgeql.py.assert │ │ ├── select_args_edgeql.py.assert3 │ │ ├── select_args_edgeql.py.assert5 │ │ └── subpkg │ │ │ ├── my_query.edgeql │ │ │ ├── my_query_async_edgeql.py.assert │ │ │ ├── my_query_async_edgeql.py.assert3 │ │ │ ├── my_query_async_edgeql.py.assert5 │ │ │ ├── my_query_edgeql.py.assert │ │ │ ├── my_query_edgeql.py.assert3 │ │ │ └── my_query_edgeql.py.assert5 │ │ └── scalar │ │ ├── custom_vector_input.edgeql │ │ ├── custom_vector_input_async_edgeql.py.assert │ │ ├── custom_vector_input_async_edgeql.py.assert3 │ │ ├── custom_vector_input_edgeql.py.assert │ │ ├── custom_vector_input_edgeql.py.assert3 │ │ ├── select_scalar.edgeql │ │ ├── select_scalar_async_edgeql.py.assert │ │ ├── select_scalar_edgeql.py.assert │ │ ├── select_scalars.edgeql │ │ ├── select_scalars_async_edgeql.py.assert │ │ └── select_scalars_edgeql.py.assert ├── credentials1.json ├── datatypes │ ├── __init__.py │ ├── test_datatypes.py │ └── test_uuid.py ├── dbsetup │ ├── base.edgeql │ ├── base.esdl │ ├── features.edgeql │ ├── features_default.esdl │ ├── features_other.esdl │ ├── features_other_nested.esdl │ ├── orm.edgeql │ └── orm.gel ├── test_array.py ├── test_async_query.py ├── test_async_retry.py ├── test_async_tx.py ├── test_asyncio_client.py ├── test_blocking_client.py ├── test_codegen.py ├── test_con_utils.py ├── test_connect.py ├── test_credentials.py ├── test_datetime.py ├── test_distinct_list.py ├── test_django_basic.py ├── test_enum.py ├── test_errors.py ├── test_globals.py ├── test_memory.py ├── test_model_generator.py ├── test_namedtuples.py ├── test_postgis.py ├── test_proto.py ├── test_scram.py ├── test_sourcecode.py ├── test_sqla_basic.py ├── test_sqla_features.py ├── test_sqlmodel_basic.py ├── test_sqlmodel_features.py ├── test_state.py ├── test_sync_query.py ├── test_sync_retry.py ├── test_sync_tx.py └── test_vector.py └── tools ├── gen_init.py └── make_import_shims.py /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | trim_trailing_whitespace = true 5 | insert_final_newline = true 6 | 7 | [Makefile] 8 | indent_style = tab 9 | 10 | [*.{py,pyx,pxd,pxi,yml,h,c}] 11 | indent_size = 4 12 | indent_style = space 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug in the client library API 4 | title: "" 5 | labels: "" 6 | assignees: "" 7 | --- 8 | 9 | **Describe the bug** 10 | A clear and concise description of what the bug is. 11 | 12 | **Reproduction** 13 | Include the code that is causing the error: 14 | 15 | ```python 16 | # code here 17 | ``` 18 | 19 | **Expected behavior** 20 | A clear and concise description of what you expected to happen. If applicable, add screenshots to help explain your problem. 21 | 22 | **Versions (please complete the following information):** 23 | 24 | 30 | 31 | - OS: 32 | - EdgeDB version: 33 | - EdgeDB CLI version: 34 | - `edgedb-python` version: 35 | - Python version: 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /.github/workflows/install-edgedb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -Eexuo pipefail 4 | shopt -s nullglob 5 | 6 | srv="https://packages.edgedb.com" 7 | 8 | curl -fL "${srv}/dist/$(uname -m)-unknown-linux-musl/edgedb-cli" \ 9 | > "/usr/bin/edgedb" 10 | 11 | chmod +x "/usr/bin/edgedb" 12 | 13 | if command -v useradd >/dev/null 2>&1; then 14 | useradd --shell /bin/bash edgedb 15 | else 16 | # musllinux/alpine doesn't have useradd 17 | adduser -s /bin/bash -D edgedb 18 | fi 19 | 20 | su -l edgedb -c "edgedb server install --version ${EDGEDB_SERVER_VERSION}" 21 | ln -s $(su -l edgedb -c "edgedb server info --latest --bin-path") \ 22 | "/usr/bin/edgedb-server" 23 | 24 | edgedb-server --version 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *._* 2 | *.pyc 3 | *.pyo 4 | *.so 5 | *~ 6 | .#* 7 | .DS_Store 8 | \#*# 9 | /test*.py 10 | /.local 11 | /perf.data* 12 | /build 13 | __pycache__/ 14 | .d8_history 15 | /.eggs 16 | /*.egg 17 | /*.egg-info 18 | /dist 19 | /.cache 20 | docs/_build 21 | /AUTHORS 22 | /ChangeLog 23 | /.coverage* 24 | !/.coveragerc 25 | /.vscode 26 | .pytest_cache 27 | .mypy_cache 28 | .ruff_cache 29 | .dmypy.json 30 | /reflog.txt 31 | /edgedb/**/*.html 32 | /tmp 33 | /wheelhouse 34 | /env* 35 | /.venv 36 | /uv.lock 37 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "edgedb/pgproto"] 2 | path = gel/pgproto 3 | url = https://github.com/MagicStack/py-pgproto.git 4 | [submodule "tests/shared-client-testcases"] 5 | path = tests/shared-client-testcases 6 | url = https://github.com/edgedb/shared-client-testcases.git 7 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include docs *.py *.rst 2 | recursive-include examples *.py 3 | recursive-include tests *.py *.pem *.json 4 | recursive-include edgedb *.pyx *.pxd *.pxi *.py *.c *.h py.typed 5 | recursive-include gel *.pyx *.pxd *.pxi *.py *.c *.h py.typed 6 | include LICENSE README.rst Makefile 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: compile debug test quicktest clean all gen-errors gen-types _touch 2 | 3 | 4 | PYTHON ?= python 5 | ROOT = $(dir $(realpath $(firstword $(MAKEFILE_LIST)))) 6 | 7 | 8 | all: compile 9 | 10 | 11 | clean: 12 | rm -fr $(ROOT)/dist/ 13 | rm -fr $(ROOT)/doc/_build/ 14 | rm -fr $(ROOT)/gel/pgproto/*.c 15 | rm -fr $(ROOT)/gel/pgproto/*.html 16 | rm -fr $(ROOT)/gel/pgproto/codecs/*.html 17 | rm -fr $(ROOT)/gel/protocol/*.c 18 | rm -fr $(ROOT)/gel/protocol/*.html 19 | rm -fr $(ROOT)/gel/protocol/*.so 20 | rm -fr $(ROOT)/gel/datatypes/*.so 21 | rm -fr $(ROOT)/gel/datatypes/datatypes.c 22 | rm -fr $(ROOT)/build 23 | rm -fr $(ROOT)/gel/protocol/codecs/*.html 24 | find . -name '__pycache__' | xargs rm -rf 25 | 26 | 27 | _touch: 28 | rm -fr $(ROOT)/gel/datatypes/datatypes.c 29 | rm -fr $(ROOT)/gel/protocol/protocol.c 30 | find $(ROOT)/gel/protocol -name '*.pyx' | xargs touch 31 | find $(ROOT)/gel/datatypes -name '*.pyx' | xargs touch 32 | find $(ROOT)/gel/datatypes -name '*.c' | xargs touch 33 | 34 | 35 | compile: _touch 36 | $(PYTHON) setup.py build_ext --inplace 37 | 38 | 39 | compile-fast: 40 | rm -fr $(ROOT)/gel/datatypes/datatypes.c 41 | rm -fr $(ROOT)/gel/protocol/protocol.c 42 | $(PYTHON) setup.py build_ext --inplace 43 | 44 | 45 | gen-errors: 46 | edb gen-errors --import "$$(printf 'from gel.errors._base import *\nfrom gel.errors.tags import *')" \ 47 | --extra-all "_base.__all__" --stdout --client > $(ROOT)/.errors 48 | mv $(ROOT)/.errors $(ROOT)/gel/errors/__init__.py 49 | $(PYTHON) tools/gen_init.py 50 | 51 | 52 | gen-types: 53 | edb gen-types --stdout > $(ROOT)/gel/protocol/codecs/edb_types.pxi 54 | 55 | 56 | debug: _touch 57 | EDGEDB_DEBUG=1 $(PYTHON) setup.py build_ext --inplace 58 | 59 | 60 | test: 61 | PYTHONASYNCIODEBUG=1 $(PYTHON) -m unittest tests.suite 62 | $(PYTHON) -m unittest tests.suite 63 | USE_UVLOOP=1 $(PYTHON) -m unittest tests.suite 64 | 65 | 66 | testinstalled: 67 | cd /tmp && $(PYTHON) $(ROOT)/tests/__init__.py 68 | 69 | 70 | quicktest: 71 | $(PYTHON) -m unittest tests.suite 72 | 73 | 74 | htmldocs: 75 | $(PYTHON) setup.py build_ext --inplace 76 | $(MAKE) -C docs html SPHINXOPTS="-W -n" 77 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | The Python driver for Gel 2 | ========================= 3 | 4 | .. image:: https://github.com/geldata/gel-python/workflows/Tests/badge.svg?event=push&branch=master 5 | :target: https://github.com/geldata/gel-python/actions 6 | 7 | .. image:: https://img.shields.io/pypi/v/gel.svg 8 | :target: https://pypi.python.org/pypi/gel 9 | 10 | .. image:: https://img.shields.io/badge/join-github%20discussions-green 11 | :target: https://github.com/geldata/gel/discussions 12 | 13 | 14 | **gel-python** is the official Gel driver for Python. 15 | It provides both blocking IO and asyncio implementations. 16 | 17 | The library requires Python 3.9 or later. 18 | 19 | 20 | Documentation 21 | ------------- 22 | 23 | The project documentation can be found 24 | `here `_. 25 | 26 | 27 | Installation 28 | ------------ 29 | 30 | The library is available on PyPI. Use ``pip`` to install it:: 31 | 32 | $ pip install gel 33 | 34 | 35 | Basic Usage 36 | ----------- 37 | 38 | .. code-block:: python 39 | 40 | import datetime 41 | import gel 42 | 43 | def main(): 44 | client = gel.create_client() 45 | # Create a User object type 46 | client.execute(''' 47 | CREATE TYPE User { 48 | CREATE REQUIRED PROPERTY name -> str; 49 | CREATE PROPERTY dob -> cal::local_date; 50 | } 51 | ''') 52 | 53 | # Insert a new User object 54 | client.query(''' 55 | INSERT User { 56 | name := $name, 57 | dob := $dob 58 | } 59 | ''', name='Bob', dob=datetime.date(1984, 3, 1)) 60 | 61 | # Select User objects. 62 | user_set = client.query( 63 | 'SELECT User {name, dob} FILTER .name = $name', name='Bob') 64 | # *user_set* now contains 65 | # Set{Object{name := 'Bob', dob := datetime.date(1984, 3, 1)}} 66 | 67 | # Close the client. 68 | client.close() 69 | 70 | if __name__ == '__main__': 71 | main() 72 | 73 | Development 74 | ----------- 75 | 76 | Instructions for installing Gel and gel-python locally can be found at 77 | `docs.geldata.com/resources/guides/contributing/code `_. 78 | 79 | To run the test suite, run ``$ python setup.py test``. 80 | 81 | License 82 | ------- 83 | 84 | gel-python is developed and distributed under the Apache 2.0 license. 85 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | _templates 3 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | Documentation 2 | ============= 3 | 4 | About 5 | ----- 6 | 7 | This directory contains the source code for gel-python documentation 8 | and build scripts. The documentation uses Sphinx and reStructuredText. 9 | 10 | Building the documentation 11 | -------------------------- 12 | 13 | Install Sphinx and other dependencies (i.e. theme) needed for the documentation. 14 | From the `docs` directory, use `pip`: 15 | 16 | ``` 17 | $ pip install -r requirements.txt 18 | ``` 19 | 20 | Build the documentation like this: 21 | 22 | ``` 23 | $ make html 24 | ``` 25 | 26 | The built documentation will be placed in the `docs/_build` directory. Open 27 | `docs/_build/index.html` to view the documentation. 28 | 29 | Helpful documentation build commands 30 | ------------------------------------ 31 | 32 | Clean the documentation build: 33 | 34 | ``` 35 | $ make clean 36 | ``` 37 | 38 | Test and check the links found in the documentation: 39 | 40 | ``` 41 | $ make linkcheck 42 | ``` -------------------------------------------------------------------------------- /docs/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | @media screen and (min-width: 767px) { 3 | 4 | .wy-table-responsive table td { 5 | white-space: normal !important; 6 | vertical-align: top !important; 7 | } 8 | 9 | .wy-table-responsive { 10 | overflow: visible !important; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /docs/api/codegen.rst: -------------------------------------------------------------------------------- 1 | .. _edgedb-python-codegen: 2 | 3 | =============== 4 | Code Generation 5 | =============== 6 | 7 | .. py:currentmodule:: edgedb 8 | 9 | The ``edgedb-python`` package exposes a command-line tool to generate 10 | typesafe functions from ``*.edgeql`` files, using :py:mod:`dataclasses` for 11 | objects primarily. 12 | 13 | .. code-block:: bash 14 | 15 | $ edgedb-py 16 | 17 | Or alternatively: 18 | 19 | .. code-block:: bash 20 | 21 | $ python -m edgedb.codegen 22 | 23 | Consider a simple query that lives in a file called ``get_number.edgeql``: 24 | 25 | .. code-block:: edgeql 26 | 27 | select $arg; 28 | 29 | Running the code generator will generate a new file called 30 | ``get_number_async_edgeql.py`` containing the following code (roughly): 31 | 32 | .. code-block:: python 33 | 34 | from __future__ import annotations 35 | import gel 36 | 37 | 38 | async def get_number( 39 | client: edgedb.AsyncIOClient, 40 | *, 41 | arg: int, 42 | ) -> int: 43 | return await client.query_single( 44 | """\ 45 | select $arg\ 46 | """, 47 | arg=arg, 48 | ) 49 | 50 | Target 51 | ~~~~~~ 52 | 53 | By default, the generated code uses an ``async`` API. The generator supports 54 | additional targets via the ``--target`` flag. 55 | 56 | .. code-block:: bash 57 | 58 | $ edgedb-py --target async # generate async function (default) 59 | $ edgedb-py --target blocking # generate blocking code 60 | 61 | The names of the generated files will differ accordingly: 62 | ``{query_filename}_{target}_edgeql.py``. 63 | 64 | Single-file mode 65 | ~~~~~~~~~~~~~~~~ 66 | 67 | It may be preferable to generate a single file containing all the generated 68 | functions. This can be done by passing the ``--file`` flag. 69 | 70 | .. code-block:: bash 71 | 72 | $ edgedb-py --file 73 | 74 | This generates a single file called ``generated_{target}_edgeql.py`` in the 75 | root of your project. 76 | 77 | Connection 78 | ~~~~~~~~~~ 79 | 80 | The ``edgedb-py`` command supports the same set of :ref:`connection options 81 | ` as the ``edgedb`` CLI. 82 | 83 | .. code-block:: 84 | 85 | -I, --instance 86 | --dsn 87 | --credentials-file 88 | -H, --host 89 | -P, --port 90 | -d, --database 91 | -u, --user 92 | --password 93 | --password-from-stdin 94 | --tls-ca-file 95 | --tls-security 96 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. _edgedb-python-intro: 2 | 3 | ==================== 4 | EdgeDB Python Driver 5 | ==================== 6 | 7 | **edgedb-python** is the official EdgeDB driver for Python. 8 | It provides both :ref:`blocking IO ` 9 | and :ref:`asyncio ` implementations. 10 | 11 | .. rubric:: Contents 12 | 13 | * :ref:`edgedb-python-installation` 14 | 15 | edgedb-python is installable via ``$ pip install edgedb``. Read 16 | the section for more information on how to install the library. 17 | 18 | * :ref:`edgedb-python-examples` 19 | 20 | High-level examples on how to use blocking and asyncio connections, 21 | as well as on how to work with transactions. 22 | 23 | * :ref:`edgedb-python-asyncio-api-reference` 24 | 25 | Asynchronous API reference. 26 | 27 | * :ref:`edgedb-python-blocking-api-reference` 28 | 29 | Synchronous API reference. 30 | 31 | * :ref:`edgedb-python-datatypes` 32 | 33 | EdgeDB Python types documentation. 34 | 35 | * :ref:`edgedb-python-codegen` 36 | 37 | Python code generation command-line tool documentation. 38 | 39 | * :ref:`edgedb-python-advanced` 40 | 41 | Advanced usages of the state and optional customization. 42 | 43 | 44 | .. toctree:: 45 | :maxdepth: 3 46 | :hidden: 47 | 48 | installation 49 | usage 50 | api/asyncio_client 51 | api/blocking_client 52 | api/types 53 | api/codegen 54 | api/advanced 55 | -------------------------------------------------------------------------------- /docs/installation.rst: -------------------------------------------------------------------------------- 1 | .. _edgedb-python-installation: 2 | 3 | 4 | Installation 5 | ============ 6 | 7 | The recommended way to install the EdgeDB driver is to use **pip**: 8 | 9 | .. code-block:: bash 10 | 11 | $ pip install edgedb 12 | 13 | 14 | .. note:: 15 | 16 | It is recommended to use **pip** version **8.1** or later to take 17 | advantage of the precompiled wheel packages. Older versions of pip 18 | will ignore the wheel packages and install from the source 19 | package. In that case a working C compiler is required. 20 | 21 | 22 | Building from source 23 | -------------------- 24 | 25 | If you want to build the EdgeDB driver from a Git checkout you will need: 26 | 27 | * A working C compiler. 28 | * CPython header files. These can usually be obtained by installing 29 | the relevant Python development package: **python3-dev** on Debian/Ubuntu, 30 | **python3-devel** on RHEL/Fedora. 31 | 32 | Once the above requirements are satisfied, run the following command 33 | in the root of the source checkout: 34 | 35 | .. code-block:: bash 36 | 37 | $ pip install -e . 38 | 39 | A debug build containing more runtime checks at the expense of performance 40 | can be created by setting the ``EDGEDB_DEBUG`` environment variable when 41 | building: 42 | 43 | .. code-block:: bash 44 | 45 | $ env EDGEDB_DEBUG=1 pip install -e . 46 | 47 | 48 | Running tests 49 | ------------- 50 | 51 | The testsuite requires a working local installation of the EdgeDB server. 52 | To execute the testsuite run: 53 | 54 | .. code-block:: bash 55 | 56 | $ python setup.py test 57 | -------------------------------------------------------------------------------- /docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinxcontrib-asyncio 2 | sphinx_rtd_theme 3 | -------------------------------------------------------------------------------- /edgedb/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel import * # noqa 5 | import gel as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/_version.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel._version import * # noqa 5 | import gel._version as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb._version'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/abstract.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.abstract import * # noqa 5 | import gel.abstract as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.abstract'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/ai/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.ai import * # noqa 5 | create_ai = create_rag_client # noqa 6 | EdgeDBAI = RAGClient # noqa 7 | create_async_ai = create_async_rag_client # noqa 8 | AsyncEdgeDBAI = AsyncRAGClient # noqa 9 | AIOptions = RAGOptions # noqa 10 | import gel.ai as _mod 11 | import sys as _sys 12 | _cur = _sys.modules['edgedb.ai'] 13 | for _k in vars(_mod): 14 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 15 | setattr(_cur, _k, getattr(_mod, _k)) 16 | _cur.create_ai = _mod.create_rag_client 17 | _cur.EdgeDBAI = _mod.RAGClient 18 | _cur.create_async_ai = _mod.create_async_rag_client 19 | _cur.AsyncEdgeDBAI = _mod.AsyncRAGClient 20 | _cur.AIOptions = _mod.RAGOptions 21 | if hasattr(_cur, '__all__'): 22 | _cur.__all__ = _cur.__all__ + [ 23 | 'create_ai', 24 | 'EdgeDBAI', 25 | 'create_async_ai', 26 | 'AsyncEdgeDBAI', 27 | 'AIOptions', 28 | ] 29 | del _cur 30 | del _sys 31 | del _mod 32 | del _k 33 | -------------------------------------------------------------------------------- /edgedb/ai/core.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.ai.core import * # noqa 5 | import gel.ai.core as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.ai.core'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/ai/types.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.ai.types import * # noqa 5 | import gel.ai.types as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.ai.types'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/asyncio_client.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.asyncio_client import * # noqa 5 | import gel.asyncio_client as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.asyncio_client'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/base_client.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.base_client import * # noqa 5 | import gel.base_client as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.base_client'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/blocking_client.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.blocking_client import * # noqa 5 | import gel.blocking_client as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.blocking_client'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/codegen.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.codegen import * # noqa 5 | import gel.codegen as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.codegen'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/con_utils.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.con_utils import * # noqa 5 | import gel.con_utils as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.con_utils'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/credentials.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.credentials import * # noqa 5 | import gel.credentials as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.credentials'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/datatypes/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.datatypes import * # noqa 5 | import gel.datatypes as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.datatypes'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/datatypes/datatypes.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.datatypes.datatypes import * # noqa 5 | import gel.datatypes.datatypes as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.datatypes.datatypes'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/datatypes/range.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.datatypes.range import * # noqa 5 | import gel.datatypes.range as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.datatypes.range'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/describe.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.describe import * # noqa 5 | import gel.describe as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.describe'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/enums.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.enums import * # noqa 5 | import gel.enums as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.enums'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/errors/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.errors import * # noqa 5 | import gel.errors as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.errors'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/errors/_base.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.errors._base import * # noqa 5 | import gel.errors._base as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.errors._base'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/errors/tags.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.errors.tags import * # noqa 5 | import gel.errors.tags as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.errors.tags'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/introspect.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.introspect import * # noqa 5 | import gel.introspect as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.introspect'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/options.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.options import * # noqa 5 | import gel.options as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.options'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/pgproto/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.pgproto import * # noqa 5 | import gel.pgproto as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.pgproto'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/pgproto/pgproto.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.pgproto.pgproto import * # noqa 5 | import gel.pgproto.pgproto as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.pgproto.pgproto'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/pgproto/types.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.pgproto.types import * # noqa 5 | import gel.pgproto.types as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.pgproto.types'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/protocol/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.protocol import * # noqa 5 | import gel.protocol as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.protocol'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/protocol/asyncio_proto.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.protocol.asyncio_proto import * # noqa 5 | import gel.protocol.asyncio_proto as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.protocol.asyncio_proto'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/protocol/blocking_proto.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.protocol.blocking_proto import * # noqa 5 | import gel.protocol.blocking_proto as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.protocol.blocking_proto'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/protocol/protocol.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.protocol.protocol import * # noqa 5 | import gel.protocol.protocol as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.protocol.protocol'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/edgedb/py.typed -------------------------------------------------------------------------------- /edgedb/scram/__init__.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.scram import * # noqa 5 | import gel.scram as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.scram'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/scram/saslprep.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.scram.saslprep import * # noqa 5 | import gel.scram.saslprep as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.scram.saslprep'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /edgedb/transaction.py: -------------------------------------------------------------------------------- 1 | # Auto-generated shim 2 | TYPE_CHECKING = False 3 | if TYPE_CHECKING: 4 | from gel.transaction import * # noqa 5 | import gel.transaction as _mod 6 | import sys as _sys 7 | _cur = _sys.modules['edgedb.transaction'] 8 | for _k in vars(_mod): 9 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 10 | setattr(_cur, _k, getattr(_mod, _k)) 11 | del _cur 12 | del _sys 13 | del _mod 14 | del _k 15 | -------------------------------------------------------------------------------- /gel/__main__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2022-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from .cli import main 21 | 22 | if __name__ == "__main__": 23 | main() 24 | -------------------------------------------------------------------------------- /gel/_internal/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/gel/_internal/__init__.py -------------------------------------------------------------------------------- /gel/_internal/_codegen/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | -------------------------------------------------------------------------------- /gel/_internal/_codegen/_models/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from ._pydantic import PydanticModelsGenerator 7 | 8 | 9 | __all__ = ("PydanticModelsGenerator",) 10 | -------------------------------------------------------------------------------- /gel/_internal/_color.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | import typing 7 | from collections.abc import Callable 8 | 9 | import functools 10 | import os 11 | import sys 12 | import warnings 13 | 14 | 15 | class Color(typing.NamedTuple): 16 | HEADER: str = "" 17 | BLUE: str = "" 18 | CYAN: str = "" 19 | GREEN: str = "" 20 | WARNING: str = "" 21 | FAIL: str = "" 22 | ENDC: str = "" 23 | BOLD: str = "" 24 | UNDERLINE: str = "" 25 | 26 | 27 | @functools.cache 28 | def get_color() -> Color: 29 | if type(USE_COLOR) is bool: 30 | use_color = USE_COLOR 31 | else: 32 | try: 33 | use_color = USE_COLOR() 34 | except Exception: 35 | use_color = False 36 | if use_color: 37 | color = Color( 38 | HEADER="\033[95m", 39 | BLUE="\033[94m", 40 | CYAN="\033[96m", 41 | GREEN="\033[92m", 42 | WARNING="\033[93m", 43 | FAIL="\033[91m", 44 | ENDC="\033[0m", 45 | BOLD="\033[1m", 46 | UNDERLINE="\033[4m", 47 | ) 48 | else: 49 | color = Color() 50 | 51 | return color 52 | 53 | 54 | try: 55 | USE_COLOR: bool | Callable[[], bool] = { 56 | "default": sys.stderr.isatty, 57 | "auto": sys.stderr.isatty, 58 | "enabled": True, 59 | "disabled": False, 60 | }[os.getenv("EDGEDB_COLOR_OUTPUT", "default")] 61 | except KeyError: 62 | warnings.warn( 63 | "EDGEDB_COLOR_OUTPUT can only be one of: " 64 | "default, auto, enabled or disabled", 65 | stacklevel=1, 66 | ) 67 | USE_COLOR = False 68 | -------------------------------------------------------------------------------- /gel/_internal/_dataclass_extras.py: -------------------------------------------------------------------------------- 1 | from typing import ( 2 | Any, 3 | TypeVar, 4 | ) 5 | 6 | import dataclasses 7 | import typing 8 | 9 | from . import _typing_eval 10 | from . import _typing_inspect 11 | from . import _utils 12 | 13 | T = TypeVar("T") 14 | 15 | 16 | def coerce_to_dataclass(cls: type[T], obj: Any) -> T: 17 | """Reconstruct a dataclass from a dataclass-like object including 18 | all nested dataclass-like instances.""" 19 | if not dataclasses.is_dataclass(cls): 20 | raise TypeError(f"{cls!r} is not a dataclass") 21 | if not dataclasses.is_dataclass(obj) or isinstance(obj, type): 22 | raise TypeError(f"{obj!r} is not a dataclass instance") 23 | 24 | new_kwargs = {} 25 | for field in dataclasses.fields(cls): 26 | field_type = _typing_eval.resolve_type( 27 | field.type, owner=_utils.module_of(cls) 28 | ) 29 | if _typing_inspect.is_optional_type(field_type): 30 | value = getattr(obj, field.name, None) 31 | else: 32 | value = getattr(obj, field.name) 33 | 34 | if value is not None: 35 | if dataclasses.is_dataclass(field_type): 36 | assert isinstance(field_type, type) 37 | value = coerce_to_dataclass(field_type, value) 38 | elif _typing_inspect.is_generic_alias(field_type): 39 | origin = typing.get_origin(field_type) 40 | 41 | if origin is not None and origin in {list, tuple, set}: 42 | element_type = typing.get_args(field_type)[0] 43 | new_values = [] 44 | for item in value: 45 | if dataclasses.is_dataclass(item): 46 | new_item = coerce_to_dataclass(element_type, item) 47 | else: 48 | new_item = item 49 | new_values.append(new_item) 50 | 51 | value = origin(new_values) 52 | elif origin is dict: 53 | args = typing.get_args(field_type) 54 | element_type = args[1] 55 | value = {} 56 | for k, v in value.items(): 57 | if dataclasses.is_dataclass(v): 58 | new_item = coerce_to_dataclass(element_type, v) 59 | else: 60 | new_item = v 61 | 62 | value[k] = new_item 63 | 64 | new_kwargs[field.name] = value 65 | 66 | return cls(**new_kwargs) # type: ignore [return-value] 67 | -------------------------------------------------------------------------------- /gel/_internal/_edgeql/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from ._quoting import ( 7 | quote_ident, 8 | quote_literal, 9 | needs_quoting, 10 | ) 11 | 12 | from ._schema import ( 13 | Cardinality, 14 | PointerKind, 15 | ) 16 | 17 | from ._tokens import ( 18 | PRECEDENCE, 19 | Assoc, 20 | Operation, 21 | Precedence, 22 | Token, 23 | need_left_parens, 24 | need_right_parens, 25 | ) 26 | 27 | 28 | __all__ = ( 29 | "PRECEDENCE", 30 | "Assoc", 31 | "Cardinality", 32 | "Operation", 33 | "PointerKind", 34 | "Precedence", 35 | "Token", 36 | "need_left_parens", 37 | "need_right_parens", 38 | "needs_quoting", 39 | "quote_ident", 40 | "quote_literal", 41 | ) 42 | -------------------------------------------------------------------------------- /gel/_internal/_edgeql/_quoting.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from __future__ import annotations 7 | 8 | import re 9 | 10 | from . import _keywords 11 | 12 | 13 | _re_ident = re.compile(r"""(?x) 14 | [^\W\d]\w* # alphanumeric identifier 15 | """) 16 | 17 | _re_ident_or_num = re.compile(r"""(?x) 18 | [^\W\d]\w* # alphanumeric identifier 19 | | 20 | ([1-9]\d* | 0) # purely integer identifier 21 | """) 22 | 23 | 24 | def escape_string(s: str) -> str: 25 | # characters escaped according to 26 | # https://docs.geldata.com/reference/edgeql/literals#strings 27 | result = s 28 | 29 | # escape backslash first 30 | result = result.replace("\\", "\\\\") 31 | 32 | result = result.replace("'", "\\'") 33 | result = result.replace("\b", "\\b") 34 | result = result.replace("\f", "\\f") 35 | result = result.replace("\n", "\\n") 36 | result = result.replace("\r", "\\r") 37 | result = result.replace("\t", "\\t") 38 | 39 | return result 40 | 41 | 42 | def quote_literal(string: str) -> str: 43 | return "'" + escape_string(string) + "'" 44 | 45 | 46 | def dollar_quote_literal(text: str) -> str: 47 | quote = "$$" 48 | qq = 0 49 | 50 | while quote in text: 51 | if qq % 16 < 10: # noqa: PLR2004 52 | qq += 10 - qq % 16 53 | 54 | quote = f"${qq:x}$"[::-1] 55 | qq += 1 56 | 57 | return quote + text + quote 58 | 59 | 60 | def needs_quoting( 61 | string: str, 62 | *, 63 | allow_reserved: bool, 64 | allow_num: bool, 65 | ) -> bool: 66 | if not string or string.startswith("@") or "::" in string: 67 | # some strings are illegal as identifiers and as such don't 68 | # require quoting 69 | return False 70 | 71 | r = _re_ident_or_num if allow_num else _re_ident 72 | isalnum = r.fullmatch(string) 73 | 74 | string = string.lower() 75 | 76 | is_reserved = ( 77 | string not in {"__type__", "__std__"} 78 | and string in _keywords.RESERVED_KEYWRORDS 79 | ) 80 | 81 | return not isalnum or (not allow_reserved and is_reserved) 82 | 83 | 84 | def _quote_ident(string: str) -> str: 85 | return "`" + string.replace("`", "``") + "`" 86 | 87 | 88 | def quote_ident( 89 | string: str, 90 | *, 91 | force: bool = False, 92 | allow_reserved: bool = False, 93 | allow_num: bool = False, 94 | ) -> str: 95 | if force or needs_quoting( 96 | string, 97 | allow_reserved=allow_reserved, 98 | allow_num=allow_num, 99 | ): 100 | return _quote_ident(string) 101 | else: 102 | return string 103 | -------------------------------------------------------------------------------- /gel/_internal/_edgeql/_schema.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from __future__ import annotations 7 | 8 | from typing import final 9 | 10 | from gel._internal._polyfills._strenum import StrEnum 11 | 12 | 13 | @final 14 | class Cardinality(StrEnum): 15 | AtMostOne = "AtMostOne" 16 | One = "One" 17 | Many = "Many" 18 | AtLeastOne = "AtLeastOne" 19 | Empty = "Empty" 20 | 21 | def is_multi(self) -> bool: 22 | return self in { 23 | Cardinality.AtLeastOne, 24 | Cardinality.Many, 25 | } 26 | 27 | def is_optional(self) -> bool: 28 | return self in { 29 | Cardinality.AtMostOne, 30 | Cardinality.Many, 31 | Cardinality.Empty, 32 | } 33 | 34 | 35 | @final 36 | class PointerKind(StrEnum): 37 | Link = "Link" 38 | Property = "Property" 39 | 40 | 41 | __all__ = ( 42 | "Cardinality", 43 | "PointerKind", 44 | ) 45 | -------------------------------------------------------------------------------- /gel/_internal/_hybridmethod.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from typing import ( 6 | Any, 7 | Generic, 8 | TypeVar, 9 | ParamSpec, 10 | overload, 11 | ) 12 | from collections.abc import Callable 13 | 14 | import functools 15 | import types 16 | 17 | P = ParamSpec("P") 18 | R = TypeVar("R") 19 | 20 | 21 | class hybridmethod(Generic[P, R]): # noqa: N801 22 | """Transform a method in a hybrid class/instance method. 23 | 24 | A hybrid method would receive either the class or the instance 25 | as the first implicit argument depending on whether the method 26 | was called on a class or an instance of a class. 27 | """ 28 | 29 | def __init__(self, func: Callable[P, R]) -> None: 30 | self.func = func 31 | # Copy __doc__, __name__, __qualname__, __annotations__, 32 | # and set __wrapped__ so inspect.signature works 33 | functools.update_wrapper(self, func) 34 | 35 | def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: 36 | # Make the descriptor itself a Callable[P, R], 37 | # satisfying update_wrapper's signature 38 | return self.func(*args, **kwargs) 39 | 40 | @overload 41 | def __get__(self, obj: None, cls: type[Any]) -> Callable[P, R]: ... 42 | 43 | @overload 44 | def __get__(self, obj: Any, cls: type[Any]) -> Callable[P, R]: ... 45 | 46 | def __get__(self, obj: Any, cls: type[Any]) -> Callable[P, R]: 47 | target = obj if obj is not None else cls 48 | # bind to either instance or class 49 | return types.MethodType(self.func, target) 50 | -------------------------------------------------------------------------------- /gel/_internal/_integration/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Support for integration into frameworks.""" 6 | -------------------------------------------------------------------------------- /gel/_internal/_integration/_fastapi/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Support for integration with FastAPI.""" 6 | -------------------------------------------------------------------------------- /gel/_internal/_integration/_fastapi/_cli/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """FastAPI CLI extensions""" 6 | 7 | from ._patch import maybe_patch_fastapi_cli 8 | 9 | 10 | __all__ = ("maybe_patch_fastapi_cli",) 11 | -------------------------------------------------------------------------------- /gel/_internal/_integration/_fastapi/_cli/_patch.py: -------------------------------------------------------------------------------- 1 | from typing import ( 2 | Any, 3 | ) 4 | 5 | import inspect 6 | import importlib.util 7 | import types 8 | 9 | 10 | def _get_fastapi_cli_import_site() -> types.FrameType | None: 11 | stack = inspect.stack() 12 | for frame_info in stack: 13 | frame = frame_info.frame 14 | caller_module = frame.f_globals.get("__name__") 15 | if ( 16 | caller_module == "fastapi_cli.cli" 17 | and frame.f_code.co_name == "_run" 18 | ): 19 | return frame 20 | return None 21 | 22 | 23 | def maybe_patch_fastapi_cli() -> None: 24 | if importlib.util.find_spec("fastapi") is None: 25 | # No FastAPI here, move along. 26 | return 27 | 28 | try: 29 | import uvicorn # noqa: PLC0415 # pyright: ignore [reportMissingImports] 30 | except ImportError: 31 | return 32 | 33 | fastapi_cli_import_site = _get_fastapi_cli_import_site() 34 | if fastapi_cli_import_site is None: 35 | # Not being imported by fastapi.cli 36 | return 37 | 38 | def _patched_uvicorn_run(*args: Any, **kwargs: Any) -> None: 39 | from . import _lifespan # noqa: PLC0415 40 | 41 | import_data = fastapi_cli_import_site.f_locals.get("import_data") 42 | cli = fastapi_cli_import_site.f_locals.get("toolkit") 43 | if import_data is not None and cli is not None: 44 | app_path = import_data.module_data.module_paths[-1].parent 45 | with _lifespan.fastapi_cli_lifespan(cli, app_path): 46 | uvicorn.run(*args, **kwargs) 47 | else: 48 | uvicorn.run(*args, **kwargs) 49 | 50 | class PatchedUvicornModule(types.ModuleType): 51 | def __getattribute__(self, name: str) -> Any: 52 | if name == "run": 53 | return _patched_uvicorn_run 54 | else: 55 | return getattr(uvicorn, name) 56 | 57 | fastapi_cli_import_site.f_globals["uvicorn"] = PatchedUvicornModule( 58 | uvicorn.__name__, 59 | doc=uvicorn.__doc__, 60 | ) 61 | -------------------------------------------------------------------------------- /gel/_internal/_platform.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | import os 7 | import pathlib 8 | import sys 9 | 10 | if sys.platform == "darwin": 11 | 12 | def config_dir() -> pathlib.Path: 13 | return ( 14 | pathlib.Path.home() / "Library" / "Application Support" / "edgedb" 15 | ) 16 | 17 | IS_WINDOWS = False 18 | 19 | elif sys.platform == "win32": 20 | import ctypes 21 | from ctypes import windll 22 | 23 | def config_dir() -> pathlib.Path: 24 | path_buf = ctypes.create_unicode_buffer(255) 25 | csidl = 28 # CSIDL_LOCAL_APPDATA 26 | windll.shell32.SHGetFolderPathW(0, csidl, 0, 0, path_buf) 27 | return pathlib.Path(path_buf.value) / "EdgeDB" / "config" 28 | 29 | IS_WINDOWS = True 30 | 31 | else: 32 | 33 | def config_dir() -> pathlib.Path: 34 | xdg_conf_dir = pathlib.Path(os.environ.get("XDG_CONFIG_HOME", ".")) 35 | if not xdg_conf_dir.is_absolute(): 36 | xdg_conf_dir = pathlib.Path.home() / ".config" 37 | return xdg_conf_dir / "edgedb" 38 | 39 | IS_WINDOWS = False 40 | 41 | 42 | def old_config_dir() -> pathlib.Path: 43 | return pathlib.Path.home() / ".edgedb" 44 | 45 | 46 | def search_config_dir(*suffix: str) -> pathlib.Path: 47 | rv = config_dir().joinpath(*suffix) 48 | if rv.exists(): 49 | return rv 50 | 51 | fallback = old_config_dir().joinpath(*suffix) 52 | if fallback.exists(): 53 | return fallback 54 | 55 | # None of the searched files exists, return the new path. 56 | return rv 57 | -------------------------------------------------------------------------------- /gel/_internal/_polyfills/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """ 6 | Polyfills for modern Python features used in the driver or generated code. 7 | """ 8 | -------------------------------------------------------------------------------- /gel/_internal/_polyfills/_strenum.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """enum.StrEnum polyfill""" 6 | 7 | import sys 8 | 9 | if sys.version_info >= (3, 11): 10 | from enum import StrEnum 11 | else: 12 | from ._strenum_impl import StrEnum 13 | 14 | 15 | __all__ = ("StrEnum",) 16 | -------------------------------------------------------------------------------- /gel/_internal/_polyfills/_strenum_impl.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from typing import Any 7 | 8 | import sys 9 | 10 | if sys.version_info >= (3, 11): 11 | from enum import StrEnum 12 | else: 13 | import enum as _enum 14 | 15 | class StrEnum(str, _enum.Enum): 16 | __str__ = str.__str__ 17 | __format__ = str.__format__ # type: ignore [assignment] 18 | 19 | @staticmethod 20 | def _generate_next_value_( 21 | name: str, start: int, count: int, last_values: list[Any] 22 | ) -> str: 23 | return name.lower() 24 | 25 | 26 | __all__ = ("StrEnum",) 27 | -------------------------------------------------------------------------------- /gel/_internal/_polyfills/_taskgroup.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """asyncio.TaskGroup polyfill""" 6 | 7 | import sys 8 | 9 | 10 | if sys.version_info >= (3, 11): 11 | from asyncio import TaskGroup 12 | else: 13 | from ._taskgroup_impl import TaskGroup 14 | 15 | 16 | __all__ = ("TaskGroup",) 17 | -------------------------------------------------------------------------------- /gel/_internal/_qbmodel/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Query builder model implementation""" 6 | -------------------------------------------------------------------------------- /gel/_internal/_qbmodel/_abstract/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Base types used to implement class-based query builders.""" 6 | 7 | from __future__ import annotations 8 | 9 | from ._base import ( 10 | GelType, 11 | GelType_T, 12 | GelTypeMeta, 13 | GelTypeMetadata, 14 | ) 15 | 16 | from ._descriptors import ( 17 | AnyPropertyDescriptor, 18 | LinkDescriptor, 19 | ModelFieldDescriptor, 20 | OptionalLinkDescriptor, 21 | OptionalPointerDescriptor, 22 | OptionalPropertyDescriptor, 23 | PointerDescriptor, 24 | PointerInfo, 25 | PropertyDescriptor, 26 | field_descriptor, 27 | ) 28 | 29 | from ._objects import ( 30 | GelModel, 31 | GelModelMeta, 32 | ) 33 | 34 | from ._primitive import ( 35 | AnyEnum, 36 | AnyTuple, 37 | Array, 38 | BaseScalar, 39 | DateTimeLike, 40 | GelPrimitiveType, 41 | MultiRange, 42 | PyConstType, 43 | PyTypeScalar, 44 | Range, 45 | Tuple, 46 | get_py_type_for_scalar, 47 | get_py_type_for_scalar_hierarchy, 48 | get_py_type_scalar_match_rank, 49 | maybe_get_protocol_for_py_type, 50 | ) 51 | 52 | 53 | __all__ = ( 54 | "AnyEnum", 55 | "AnyPropertyDescriptor", 56 | "AnyTuple", 57 | "Array", 58 | "BaseScalar", 59 | "DateTimeLike", 60 | "GelModel", 61 | "GelModelMeta", 62 | "GelPrimitiveType", 63 | "GelType", 64 | "GelTypeMeta", 65 | "GelTypeMetadata", 66 | "GelType_T", 67 | "LinkDescriptor", 68 | "ModelFieldDescriptor", 69 | "MultiRange", 70 | "OptionalLinkDescriptor", 71 | "OptionalPointerDescriptor", 72 | "OptionalPropertyDescriptor", 73 | "PointerDescriptor", 74 | "PointerInfo", 75 | "PropertyDescriptor", 76 | "PyConstType", 77 | "PyTypeScalar", 78 | "Range", 79 | "Tuple", 80 | "field_descriptor", 81 | "get_py_type_for_scalar", 82 | "get_py_type_for_scalar_hierarchy", 83 | "get_py_type_scalar_match_rank", 84 | "maybe_get_protocol_for_py_type", 85 | ) 86 | -------------------------------------------------------------------------------- /gel/_internal/_qbmodel/_abstract/_base.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from __future__ import annotations 6 | from typing import TYPE_CHECKING, ClassVar, TypeVar 7 | 8 | 9 | from gel._internal import _qb 10 | from gel._internal._hybridmethod import hybridmethod 11 | 12 | if TYPE_CHECKING: 13 | import uuid 14 | from gel._internal import _reflection 15 | 16 | 17 | T = TypeVar("T") 18 | T_co = TypeVar("T_co", covariant=True) 19 | GelType_T = TypeVar("GelType_T", bound="GelType") 20 | 21 | 22 | class GelTypeMetadata: 23 | class __gel_reflection__: # noqa: N801 24 | id: ClassVar[uuid.UUID] 25 | name: ClassVar[_reflection.SchemaPath] 26 | 27 | 28 | if TYPE_CHECKING: 29 | 30 | class GelTypeMeta(type): 31 | def __edgeql_qb_expr__(cls) -> _qb.Expr: ... 32 | 33 | class GelType( 34 | _qb.AbstractDescriptor, 35 | GelTypeMetadata, 36 | metaclass=GelTypeMeta, 37 | ): 38 | __gel_type_class__: ClassVar[type] 39 | 40 | def __edgeql_qb_expr__(self) -> _qb.Expr: ... 41 | 42 | @staticmethod 43 | def __edgeql__() -> tuple[type, str]: ... 44 | 45 | @staticmethod 46 | def __edgeql_expr__() -> str: ... 47 | 48 | else: 49 | GelTypeMeta = type 50 | 51 | class GelType(_qb.AbstractDescriptor, GelTypeMetadata): 52 | @hybridmethod 53 | def __edgeql_qb_expr__(self) -> _qb.Expr: 54 | if isinstance(self, type): 55 | return _qb.ExprPlaceholder() 56 | else: 57 | return self.__edgeql_literal__() 58 | 59 | def __edgeql_literal__(self) -> _qb.Literal: 60 | raise NotImplementedError( 61 | f"{type(self).__name__}.__edgeql_literal__" 62 | ) 63 | 64 | @hybridmethod 65 | def __edgeql__(self) -> tuple[type, str]: 66 | if isinstance(self, type): 67 | raise NotImplementedError(f"{type(self).__name__}.__edgeql__") 68 | else: 69 | return type(self), _qb.toplevel_edgeql(self) 70 | 71 | 72 | class GelObjectType(GelType): 73 | pass 74 | -------------------------------------------------------------------------------- /gel/_internal/_qbmodel/_abstract/_functions.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Base object types used to implement class-based query builders""" 6 | 7 | from __future__ import annotations 8 | from typing import TYPE_CHECKING 9 | 10 | 11 | from gel._internal import _qb 12 | 13 | 14 | if TYPE_CHECKING: 15 | from ._base import GelType 16 | 17 | 18 | def assert_single( 19 | cls: type[GelType], 20 | *, 21 | message: _qb.ExprCompatible | str | None = None, 22 | __operand__: _qb.ExprAlias | None = None, 23 | ) -> _qb.Expr: 24 | kwargs: dict[str, _qb.ExprCompatible] = {} 25 | if message is None: 26 | pass 27 | elif isinstance(message, str): 28 | kwargs["message"] = _qb.StringLiteral(val=message) 29 | else: 30 | kwargs["message"] = _qb.edgeql_qb_expr(message) 31 | 32 | subj = _qb.edgeql_qb_expr(cls if __operand__ is None else __operand__) 33 | return _qb.FuncCall( 34 | fname="std::assert_single", 35 | args=[subj], 36 | kwargs=kwargs, 37 | type_=subj.type, 38 | ) 39 | -------------------------------------------------------------------------------- /gel/_internal/_qbmodel/_pydantic/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Pydantic implementation of the query builder model""" 6 | 7 | from ._fields import ( 8 | ComputedMultiLink, 9 | ComputedMultiLinkWithProps, 10 | ComputedProperty, 11 | IdProperty, 12 | MultiLink, 13 | MultiLinkWithProps, 14 | OptionalComputedLink, 15 | OptionalComputedLinkWithProps, 16 | OptionalComputedProperty, 17 | OptionalLink, 18 | OptionalLinkWithProps, 19 | OptionalProperty, 20 | Property, 21 | ) 22 | 23 | from ._models import ( 24 | GelLinkModel, 25 | GelModel, 26 | GelModelMeta, 27 | LinkClassNamespace, 28 | LinkPropsDescriptor, 29 | ProxyModel, 30 | ) 31 | 32 | from ._types import ( 33 | Array, 34 | MultiRange, 35 | Range, 36 | Tuple, 37 | PyTypeScalar, 38 | ) 39 | 40 | 41 | __all__ = ( 42 | "Array", 43 | "ComputedMultiLink", 44 | "ComputedMultiLinkWithProps", 45 | "ComputedProperty", 46 | "GelLinkModel", 47 | "GelModel", 48 | "GelModelMeta", 49 | "IdProperty", 50 | "LinkClassNamespace", 51 | "LinkPropsDescriptor", 52 | "MultiLink", 53 | "MultiLinkWithProps", 54 | "MultiRange", 55 | "OptionalComputedLink", 56 | "OptionalComputedLinkWithProps", 57 | "OptionalComputedProperty", 58 | "OptionalLink", 59 | "OptionalLinkWithProps", 60 | "OptionalProperty", 61 | "Property", 62 | "ProxyModel", 63 | "PyTypeScalar", 64 | "Range", 65 | "Tuple", 66 | ) 67 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from ._enums import ( 6 | CallableParamKind, 7 | Cardinality, 8 | OperatorKind, 9 | PointerKind, 10 | SchemaPart, 11 | TypeKind, 12 | TypeModifier, 13 | ) 14 | 15 | from ._support import ( 16 | SchemaPath, 17 | parse_name, 18 | ) 19 | 20 | from ._casts import ( 21 | CastMatrix, 22 | fetch_casts, 23 | ) 24 | 25 | from ._functions import ( 26 | Function, 27 | fetch_functions, 28 | ) 29 | 30 | from ._operators import ( 31 | Operator, 32 | OperatorMatrix, 33 | fetch_operators, 34 | ) 35 | 36 | from ._types import ( 37 | AnyType, 38 | ArrayType, 39 | InheritingType, 40 | NamedTupleType, 41 | ObjectType, 42 | Pointer, 43 | PrimitiveType, 44 | ScalarType, 45 | TupleType, 46 | Type, 47 | fetch_types, 48 | is_array_type, 49 | is_link, 50 | is_multi_range_type, 51 | is_named_tuple_type, 52 | is_non_enum_scalar_type, 53 | is_object_type, 54 | is_primitive_type, 55 | is_property, 56 | is_pseudo_type, 57 | is_range_type, 58 | is_scalar_type, 59 | is_tuple_type, 60 | ) 61 | 62 | from ._modules import ( 63 | fetch_modules, 64 | ) 65 | 66 | __all__ = ( 67 | "AnyType", 68 | "ArrayType", 69 | "CallableParamKind", 70 | "Cardinality", 71 | "CastMatrix", 72 | "Function", 73 | "InheritingType", 74 | "NamedTupleType", 75 | "ObjectType", 76 | "Operator", 77 | "OperatorKind", 78 | "OperatorMatrix", 79 | "Pointer", 80 | "PointerKind", 81 | "PrimitiveType", 82 | "ScalarType", 83 | "SchemaPart", 84 | "SchemaPath", 85 | "TupleType", 86 | "Type", 87 | "TypeKind", 88 | "TypeModifier", 89 | "fetch_casts", 90 | "fetch_functions", 91 | "fetch_modules", 92 | "fetch_operators", 93 | "fetch_types", 94 | "is_array_type", 95 | "is_link", 96 | "is_multi_range_type", 97 | "is_named_tuple_type", 98 | "is_non_enum_scalar_type", 99 | "is_object_type", 100 | "is_primitive_type", 101 | "is_property", 102 | "is_pseudo_type", 103 | "is_range_type", 104 | "is_scalar_type", 105 | "is_tuple_type", 106 | "parse_name", 107 | ) 108 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_callables.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | # Type annotations must be visible in coerce_to_dataclass() 6 | # 7 | # ruff: noqa: TC001, TC003 8 | 9 | from __future__ import annotations 10 | 11 | import uuid 12 | import dataclasses 13 | 14 | from . import _types 15 | from . import _enums 16 | 17 | 18 | @dataclasses.dataclass(frozen=True, kw_only=True) 19 | class CallableParam: 20 | name: str 21 | type: _types.TypeRef 22 | kind: _enums.CallableParamKind 23 | typemod: _enums.TypeModifier 24 | default: str | None 25 | 26 | 27 | @dataclasses.dataclass(frozen=True, kw_only=True) 28 | class Callable: 29 | id: uuid.UUID 30 | name: str 31 | description: str 32 | return_type: _types.TypeRef 33 | return_typemod: _enums.TypeModifier 34 | params: list[CallableParam] 35 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_enums.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | import enum 7 | 8 | 9 | class StrEnum(str, enum.Enum): 10 | pass 11 | 12 | 13 | class SchemaPart(enum.Enum): 14 | STD = enum.auto() 15 | USER = enum.auto() 16 | 17 | 18 | class Cardinality(StrEnum): 19 | AtMostOne = "AtMostOne" 20 | One = "One" 21 | Many = "Many" 22 | AtLeastOne = "AtLeastOne" 23 | Empty = "Empty" 24 | 25 | def is_multi(self) -> bool: 26 | return self in { 27 | Cardinality.AtLeastOne, 28 | Cardinality.Many, 29 | } 30 | 31 | def is_optional(self) -> bool: 32 | return self in { 33 | Cardinality.AtMostOne, 34 | Cardinality.Many, 35 | Cardinality.Empty, 36 | } 37 | 38 | 39 | class TypeKind(StrEnum): 40 | Array = "Array" 41 | Enum = "Enum" 42 | MultiRange = "MultiRange" 43 | NamedTuple = "NamedTuple" 44 | Object = "Object" 45 | Range = "Range" 46 | Scalar = "Scalar" 47 | Tuple = "Tuple" 48 | Pseudo = "Pseudo" 49 | 50 | 51 | class TypeModifier(StrEnum): 52 | SetOf = "SetOfType" 53 | Optional = "OptionalType" 54 | Singleton = "SingletonType" 55 | 56 | 57 | class PointerKind(StrEnum): 58 | Link = "Link" 59 | Property = "Property" 60 | 61 | 62 | class OperatorKind(StrEnum): 63 | Infix = "Infix" 64 | Postfix = "Postfix" 65 | Prefix = "Prefix" 66 | Ternary = "Ternary" 67 | 68 | 69 | class CallableParamKind(StrEnum): 70 | Variadic = "VariadicParam" 71 | NamedOnly = "NamedOnlyParam" 72 | Positional = "PositionalParam" 73 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_functions.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from __future__ import annotations 7 | from typing import TYPE_CHECKING 8 | 9 | import dataclasses 10 | 11 | 12 | from . import _enums 13 | from . import _query 14 | from ._callables import Callable 15 | 16 | if TYPE_CHECKING: 17 | from gel import abstract 18 | 19 | 20 | @dataclasses.dataclass(frozen=True, kw_only=True) 21 | class Function(Callable): 22 | pass 23 | 24 | 25 | def fetch_functions( 26 | db: abstract.ReadOnlyExecutor, 27 | schema_part: _enums.SchemaPart, 28 | ) -> list[Function]: 29 | builtin = schema_part is _enums.SchemaPart.STD 30 | fns: list[Function] = db.query(_query.FUNCTIONS, builtin=builtin) 31 | return fns 32 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_modules.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from __future__ import annotations 7 | from typing import TYPE_CHECKING 8 | 9 | 10 | from . import _enums as enums 11 | from . import _query 12 | 13 | if TYPE_CHECKING: 14 | from gel import abstract 15 | 16 | 17 | def fetch_modules( 18 | db: abstract.ReadOnlyExecutor, 19 | schema_part: enums.SchemaPart, 20 | ) -> list[str]: 21 | builtin = schema_part is enums.SchemaPart.STD 22 | modules: list[str] = db.query(_query.MODULES, builtin=builtin) 23 | return modules 24 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_struct.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from __future__ import annotations 7 | from typing import TypeVar 8 | from typing_extensions import dataclass_transform 9 | 10 | import dataclasses 11 | 12 | 13 | _dataclass = dataclasses.dataclass(eq=False, frozen=True, kw_only=True) 14 | 15 | _T = TypeVar("_T") 16 | 17 | 18 | @dataclass_transform( 19 | eq_default=False, 20 | frozen_default=True, 21 | kw_only_default=True, 22 | ) 23 | def struct(t: type[_T]) -> type[_T]: 24 | return _dataclass(t) 25 | -------------------------------------------------------------------------------- /gel/_internal/_reflection/_support.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from __future__ import annotations 6 | from typing import NamedTuple 7 | 8 | import pathlib 9 | 10 | 11 | class QualName(NamedTuple): 12 | module: str 13 | name: str 14 | 15 | 16 | class SchemaPath(pathlib.PurePosixPath): 17 | @classmethod 18 | def from_schema_name(cls, name: str) -> SchemaPath: 19 | return SchemaPath(*name.split("::")) 20 | 21 | def common_parts(self, other: SchemaPath) -> list[str]: 22 | prefix = [] 23 | for a, b in zip(self.parts, other.parts, strict=False): 24 | if a == b: 25 | prefix.append(a) 26 | else: 27 | break 28 | 29 | return prefix 30 | 31 | def has_prefix(self, other: SchemaPath) -> bool: 32 | return self.parts[: len(other.parts)] == other.parts 33 | 34 | def as_schema_name(self) -> str: 35 | return "::".join(self.parts) 36 | 37 | 38 | def parse_name(name: str) -> SchemaPath: 39 | return SchemaPath.from_schema_name(name) 40 | -------------------------------------------------------------------------------- /gel/_internal/_typing_dispatch.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from typing import ( 7 | Any, 8 | ) 9 | from collections.abc import ( 10 | Callable, 11 | ) 12 | from typing_extensions import ( 13 | get_overloads, 14 | ) 15 | 16 | import inspect 17 | 18 | 19 | def dispatch_overload( 20 | func: Callable[..., object], 21 | *args: Any, 22 | **kwargs: Any, 23 | ) -> Any: 24 | for func_overload in get_overloads(func): 25 | sig = inspect.signature(func_overload) 26 | try: 27 | sig.bind(*args, **kwargs) 28 | except TypeError: 29 | pass 30 | else: 31 | result = func_overload(*args, **kwargs) 32 | break 33 | else: 34 | raise TypeError( 35 | f"cannot dispatch to {func}: no overload found for " 36 | f"args={args} and kwargs={kwargs}" 37 | ) 38 | 39 | return result 40 | -------------------------------------------------------------------------------- /gel/_internal/_typing_inspect.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | 6 | from typing import ( 7 | Annotated, 8 | Any, 9 | ClassVar, 10 | ForwardRef, 11 | TypeGuard, 12 | Union, 13 | get_args, 14 | get_origin, 15 | ) 16 | from typing import _GenericAlias, _SpecialGenericAlias # type: ignore [attr-defined] # noqa: PLC2701 17 | from typing_extensions import TypeAliasType 18 | from types import GenericAlias, UnionType 19 | 20 | from typing_inspection.introspection import ( 21 | AnnotationSource, 22 | InspectedAnnotation, 23 | inspect_annotation, 24 | ) 25 | 26 | 27 | def is_classvar(t: Any) -> bool: 28 | return t is ClassVar or (is_generic_alias(t) and get_origin(t) is ClassVar) # type: ignore [comparison-overlap] 29 | 30 | 31 | def is_generic_alias(t: Any) -> TypeGuard[GenericAlias]: 32 | return isinstance(t, (GenericAlias, _GenericAlias, _SpecialGenericAlias)) 33 | 34 | 35 | def is_type_alias(t: Any) -> TypeGuard[TypeAliasType]: 36 | return isinstance(t, TypeAliasType) and not is_generic_alias(t) 37 | 38 | 39 | def is_generic_type_alias(t: Any) -> TypeGuard[GenericAlias]: 40 | return is_generic_alias(t) and isinstance(get_origin(t), TypeAliasType) 41 | 42 | 43 | def is_annotated(t: Any) -> TypeGuard[Annotated[Any, ...]]: 44 | return is_generic_alias(t) and get_origin(t) is Annotated # type: ignore [comparison-overlap] 45 | 46 | 47 | def is_forward_ref(t: Any) -> TypeGuard[ForwardRef]: 48 | return isinstance(t, ForwardRef) 49 | 50 | 51 | def is_union_type(t: Any) -> bool: 52 | return ( 53 | (is_generic_alias(t) and get_origin(t) is Union) # type: ignore [comparison-overlap] 54 | or isinstance(t, UnionType) 55 | ) 56 | 57 | 58 | def is_optional_type(t: Any) -> bool: 59 | return is_union_type(t) and type(None) in get_args(t) 60 | 61 | 62 | __all__ = ( 63 | "AnnotationSource", 64 | "InspectedAnnotation", 65 | "inspect_annotation", 66 | "is_annotated", 67 | "is_classvar", 68 | "is_forward_ref", 69 | "is_generic_alias", 70 | "is_generic_type_alias", 71 | "is_optional_type", 72 | "is_type_alias", 73 | "is_union_type", 74 | ) 75 | -------------------------------------------------------------------------------- /gel/_internal/_typing_protos.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from typing import Protocol, TypeVar 6 | from typing_extensions import TypeAliasType 7 | from collections.abc import Iterable, Set as AbstractSet 8 | 9 | 10 | _KT = TypeVar("_KT") 11 | _VT = TypeVar("_VT") 12 | _KT_co = TypeVar("_KT_co", covariant=True) 13 | _VT_co = TypeVar("_VT_co", covariant=True) 14 | _T_contra = TypeVar("_T_contra", contravariant=True) 15 | 16 | 17 | class SupportsDunderLT(Protocol[_T_contra]): 18 | def __lt__(self, other: _T_contra, /) -> bool: ... 19 | 20 | 21 | class SupportsDunderGT(Protocol[_T_contra]): 22 | def __gt__(self, other: _T_contra, /) -> bool: ... 23 | 24 | 25 | SupportsRichComparison = TypeAliasType( 26 | "SupportsRichComparison", 27 | SupportsDunderLT[_T_contra] | SupportsDunderGT[_T_contra], 28 | type_params=(_T_contra,), 29 | ) 30 | 31 | 32 | class SupportsKeysAndGetItem(Protocol[_KT, _VT_co]): 33 | def keys(self) -> Iterable[_KT]: ... 34 | def __getitem__(self, key: _KT, /) -> _VT_co: ... 35 | 36 | 37 | class SupportsItems(Protocol[_KT_co, _VT_co]): 38 | def items(self) -> AbstractSet[tuple[_KT_co, _VT_co]]: ... 39 | 40 | 41 | MappingInput = TypeAliasType( 42 | "MappingInput", 43 | SupportsKeysAndGetItem[_KT, _VT] | Iterable[tuple[_KT, _VT]], 44 | type_params=(_KT, _VT), 45 | ) 46 | 47 | 48 | class SupportsToOrdinal(Protocol): 49 | def toordinal(self) -> int: ... 50 | -------------------------------------------------------------------------------- /gel/_internal/_unsetid.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | from __future__ import annotations 6 | from typing import ( 7 | Any, 8 | ) 9 | 10 | import uuid 11 | 12 | 13 | class _UnsetUUID(uuid.UUID): 14 | """A UUID subclass that only lets you str()/repr() it; everything 15 | else errors out.""" 16 | 17 | def __init__(self) -> None: 18 | # Create a “zero” UUID under the hood. It doesn't really matter what it 19 | # is, since we won't let anyone do anything with it except print it. 20 | super().__init__(int=0) 21 | 22 | def __repr__(self) -> str: 23 | return "" 24 | 25 | def __str__(self) -> str: 26 | return "UNSET" 27 | 28 | def __getattribute__(self, name: str) -> Any: 29 | # Allow the few methods/properties needed to make printing work 30 | if name in { 31 | "__class__", 32 | "__getattribute__", 33 | "__getstate__", 34 | "__reduce__", 35 | "__reduce_ex__", 36 | "__repr__", 37 | "__setstate__", 38 | "__str__", 39 | "int", 40 | }: 41 | return object.__getattribute__(self, name) 42 | elif name in { 43 | "__copy__", 44 | "__deepcopy__", 45 | }: 46 | raise AttributeError(name) 47 | else: 48 | raise ValueError(f"_UnsetUUID.{name}: id is not set") 49 | 50 | def __getstate__(self) -> object: 51 | return {"int": 0} 52 | 53 | 54 | # single shared sentinel 55 | UNSET_UUID: uuid.UUID = _UnsetUUID() 56 | -------------------------------------------------------------------------------- /gel/_internal/_utils.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | 5 | """Miscellaneous utilities.""" 6 | 7 | from typing import Any, TypeVar, final, overload 8 | 9 | import sys 10 | import types 11 | 12 | 13 | @final 14 | class UnspecifiedType: 15 | """A type used as a sentinel for unspecified values.""" 16 | 17 | 18 | Unspecified = UnspecifiedType() 19 | 20 | 21 | def type_repr(t: type[Any]) -> str: 22 | if isinstance(t, type): 23 | if t.__module__ == "builtins": 24 | return t.__qualname__ 25 | else: 26 | return f"{t.__module__}.{t.__qualname__}" 27 | else: 28 | return repr(t) 29 | 30 | 31 | def is_dunder(attr: str) -> bool: 32 | return attr.startswith("__") and attr.endswith("__") 33 | 34 | 35 | def module_of(obj: object) -> types.ModuleType | None: 36 | if isinstance(obj, types.ModuleType): 37 | return obj 38 | else: 39 | module_name = getattr(obj, "__module__", None) 40 | if module_name: 41 | return sys.modules.get(module_name) 42 | else: 43 | return None 44 | 45 | 46 | def module_ns_of(obj: object) -> dict[str, Any]: 47 | """Return the namespace of the module where *obj* is defined.""" 48 | module = module_of(obj) 49 | return module.__dict__ if module is not None else {} 50 | 51 | 52 | _T = TypeVar("_T") 53 | 54 | 55 | @overload 56 | def maybe_get_descriptor( 57 | cls: type, 58 | name: str, 59 | of_type: type[_T], 60 | ) -> _T | None: ... 61 | 62 | 63 | @overload 64 | def maybe_get_descriptor( 65 | cls: type, 66 | name: str, 67 | of_type: None = None, 68 | ) -> Any | None: ... 69 | 70 | 71 | def maybe_get_descriptor( 72 | cls: type, 73 | name: str, 74 | of_type: type | None = None, 75 | ) -> Any | None: 76 | if of_type is None: 77 | of_type = types.MethodDescriptorType 78 | 79 | for ancestor in cls.__mro__: 80 | desc = ancestor.__dict__.get(name, Unspecified) 81 | if desc is not Unspecified and isinstance(desc, of_type): 82 | return desc 83 | 84 | return None 85 | -------------------------------------------------------------------------------- /gel/_internal/ruff.toml: -------------------------------------------------------------------------------- 1 | extend = "../../pyproject.toml" 2 | 3 | [lint] 4 | preview = true 5 | extend-select = [ 6 | "A", # flake8-builtins 7 | "B", # flake8-bugbear 8 | "C4", # flake8-comprehensions 9 | "COM", # flake8-commas 10 | "DTZ", # flake8-datetimez 11 | "E", # pycodestyle 12 | "ERA", # flake8-eradicate 13 | "F", # pyflakes 14 | "FA", # flake8-future-annotations 15 | "FBT", # flake8-boolean-trap 16 | "FURB", # refurb 17 | "G", # flake8-logging-format 18 | "ICN", # flake8-import-conventions 19 | "ISC", # flake8-implicit-str-concat 20 | "LOG", # flake8-logging 21 | "N", # pep8-naming 22 | "PERF", # perflint 23 | "PGH", # pygrep-hooks 24 | "PIE", # flake8-pie 25 | "PL", # pylint 26 | "PYI", # flake8-pyi 27 | "Q", # flake8-quotes 28 | "RUF", # ruff specific 29 | "S", # flake8-bandit 30 | "SIM", # flake8-simplify 31 | "SLOT", # flake8-slots 32 | "T20", # flake8-print 33 | "TC", # flake8-type-checking 34 | "UP", # pyupgrade 35 | "W", # warning 36 | ] 37 | extend-ignore = [ 38 | "C408", # unnecessary-collection-call 39 | "COM812", # missing-trailing-comma 40 | "ISC002", # multi-line-implicit-string-concatenation 41 | "PLC0105", # type-name-incorrect-variance 42 | "PLC0414", # useless-import-alias 43 | "PLR0904", # too-many-public-methods 44 | "PLR0911", # too-many-return-statements 45 | "PLR0912", # too-many-branches 46 | "PLR0913", # too-many-arguments 47 | "PLR0914", # too-many-local-variables 48 | "PLR0915", # too-many-statements 49 | "PLR1702", # too-many-nested-blocks 50 | "PLR6301", # no-self-use 51 | "PLW3201", # bad-dunder-method-name 52 | "S101", # assert 53 | "S404", # suspicious-subprocess-import 54 | "S603", # subprocess-without-shell-equals-true 55 | "SIM117", # multiple-with-statements 56 | ] 57 | -------------------------------------------------------------------------------- /gel/_version.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | # This file MUST NOT contain anything but the __version__ assignment. 20 | # 21 | # When making a release, change the value of __version__ 22 | # to an appropriate value, and open a pull request against 23 | # the correct branch (master if making a new feature release). 24 | # The commit message MUST contain a properly formatted release 25 | # log, and the commit must be signed. 26 | # 27 | # The release automation will: build and test the packages for the 28 | # supported platforms, publish the packages on PyPI, merge the PR 29 | # to the target branch, create a Git tag pointing to the commit. 30 | 31 | __version__ = "3.1.0" 32 | -------------------------------------------------------------------------------- /gel/ai/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2024-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | from .types import RAGOptions, ChatParticipantRole, Prompt, QueryContext 20 | from .core import create_rag_client, RAGClient 21 | from .core import create_async_rag_client, AsyncRAGClient 22 | 23 | __all__ = [ 24 | "RAGOptions", 25 | "ChatParticipantRole", 26 | "Prompt", 27 | "QueryContext", 28 | "create_rag_client", 29 | "RAGClient", 30 | "create_async_rag_client", 31 | "AsyncRAGClient", 32 | ] 33 | -------------------------------------------------------------------------------- /gel/ai/types.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2024-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | import typing 20 | 21 | import dataclasses as dc 22 | import enum 23 | 24 | 25 | class ChatParticipantRole(enum.Enum): 26 | SYSTEM = "system" 27 | USER = "user" 28 | ASSISTANT = "assistant" 29 | TOOL = "tool" 30 | 31 | 32 | class Custom(typing.TypedDict): 33 | role: ChatParticipantRole 34 | content: str 35 | 36 | 37 | class Prompt: 38 | name: typing.Optional[str] 39 | id: typing.Optional[str] 40 | custom: typing.Optional[typing.List[Custom]] 41 | 42 | 43 | @dc.dataclass 44 | class RAGOptions: 45 | model: str 46 | prompt: typing.Optional[Prompt] = None 47 | 48 | def derive(self, kwargs): 49 | return RAGOptions(**{**dc.asdict(self), **kwargs}) 50 | 51 | 52 | @dc.dataclass 53 | class QueryContext: 54 | query: str = "" 55 | variables: typing.Optional[typing.Dict[str, typing.Any]] = None 56 | globals: typing.Optional[typing.Dict[str, typing.Any]] = None 57 | max_object_count: typing.Optional[int] = None 58 | 59 | def derive(self, kwargs): 60 | return QueryContext(**{**dc.asdict(self), **kwargs}) 61 | 62 | 63 | @dc.dataclass 64 | class RAGRequest: 65 | model: str 66 | prompt: typing.Optional[Prompt] 67 | context: QueryContext 68 | query: str 69 | stream: typing.Optional[bool] 70 | 71 | def to_httpx_request(self) -> typing.Dict[str, typing.Any]: 72 | return dict( 73 | url="/rag", 74 | headers={ 75 | "Content-Type": "application/json", 76 | "Accept": ( 77 | "text/event-stream" if self.stream else "application/json" 78 | ), 79 | }, 80 | json=dc.asdict(self), 81 | ) 82 | -------------------------------------------------------------------------------- /gel/codegen/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2022-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /gel/codegen/__main__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2022-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from .cli import main 21 | 22 | if __name__ == "__main__": 23 | main() 24 | -------------------------------------------------------------------------------- /gel/connresource.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import functools 21 | 22 | from . import errors 23 | 24 | 25 | def guarded(meth): 26 | """A decorator to add a sanity check to ConnectionResource methods.""" 27 | 28 | @functools.wraps(meth) 29 | def _check(self, *args, **kwargs): 30 | self._check_conn_validity(meth.__name__) 31 | return meth(self, *args, **kwargs) 32 | 33 | return _check 34 | 35 | 36 | class ConnectionResource: 37 | def __init__(self, connection): 38 | self._connection = connection 39 | self._con_release_ctr = connection._pool_release_ctr 40 | 41 | def _check_conn_validity(self, meth_name): 42 | con_release_ctr = self._connection._pool_release_ctr 43 | if con_release_ctr != self._con_release_ctr: 44 | raise errors.InterfaceError( 45 | "cannot call {}.{}(): " 46 | "the underlying connection has been released back " 47 | "to the pool".format(self.__class__.__name__, meth_name) 48 | ) 49 | 50 | if self._connection.is_closed(): 51 | raise errors.InterfaceError( 52 | "cannot call {}.{}(): " 53 | "the underlying connection is closed".format( 54 | self.__class__.__name__, meth_name 55 | ) 56 | ) 57 | -------------------------------------------------------------------------------- /gel/datatypes/.gitignore: -------------------------------------------------------------------------------- 1 | /datatypes.c 2 | -------------------------------------------------------------------------------- /gel/datatypes/NOTES: -------------------------------------------------------------------------------- 1 | tp_clear 2 | -------- 3 | 4 | Objects don't have tp_clear; that's because there shouldn't be 5 | a situation when there's a ref cycle between them -- the way 6 | the data is serialized on the wire precludes that. 7 | 8 | Furthermore, all gel.datatypes objects are immutable, so 9 | it's not possible to create a ref cycle with only them in the 10 | reference chain by using the public API. 11 | 12 | If we ever have an entity cache the situation might change, 13 | but for now there's no need for tp_clear. 14 | -------------------------------------------------------------------------------- /gel/datatypes/__init__.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /gel/datatypes/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /gel/datatypes/abstract.pxd: -------------------------------------------------------------------------------- 1 | cdef class CustomType: 2 | pass 3 | -------------------------------------------------------------------------------- /gel/datatypes/abstract.pyx: -------------------------------------------------------------------------------- 1 | cdef class CustomType: 2 | pass 3 | -------------------------------------------------------------------------------- /gel/datatypes/args.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This source file is part of the EdgeDB open source project. 3 | * 4 | * Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | #include "internal.h" 21 | 22 | 23 | int 24 | _Edge_NoKeywords(const char *funcname, PyObject *kwargs) 25 | { 26 | if (kwargs == NULL) { 27 | return 1; 28 | } 29 | if (!PyDict_CheckExact(kwargs)) { 30 | PyErr_BadInternalCall(); 31 | return 0; 32 | } 33 | if (PyDict_Size(kwargs) == 0) { 34 | return 1; 35 | } 36 | 37 | PyErr_Format(PyExc_TypeError, "%.200s() takes no keyword arguments", 38 | funcname); 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /gel/datatypes/comp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This source file is part of the EdgeDB open source project. 3 | * 4 | * Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | #include "internal.h" 21 | 22 | 23 | PyObject * 24 | _EdgeGeneric_RichCompareValues(PyObject **left_items, Py_ssize_t left_len, 25 | PyObject **right_items, Py_ssize_t right_len, 26 | int op) 27 | { 28 | Py_ssize_t i; 29 | 30 | if (left_len != right_len && (op == Py_EQ || op == Py_NE)) { 31 | if (op == Py_EQ) { 32 | Py_RETURN_FALSE; 33 | } 34 | else { 35 | Py_RETURN_TRUE; 36 | } 37 | } 38 | 39 | for (i = 0; i < left_len && i < right_len; i++) { 40 | int ret = PyObject_RichCompareBool( 41 | left_items[i], right_items[i], Py_EQ); 42 | 43 | if (ret < 0) { 44 | return NULL; 45 | } 46 | 47 | if (ret == 0) { 48 | /* first element that differs is found */ 49 | break; 50 | } 51 | } 52 | 53 | if (i >= left_len || i >= right_len) { 54 | /* Same logic as for Python tuple comparison */ 55 | switch (op) { 56 | case Py_EQ: 57 | if (left_len == right_len) Py_RETURN_TRUE; 58 | Py_RETURN_FALSE; 59 | case Py_NE: 60 | if (left_len != right_len) Py_RETURN_TRUE; 61 | Py_RETURN_FALSE; 62 | case Py_LT: 63 | if (left_len < right_len) Py_RETURN_TRUE; 64 | Py_RETURN_FALSE; 65 | case Py_GT: 66 | if (left_len > right_len) Py_RETURN_TRUE; 67 | Py_RETURN_FALSE; 68 | case Py_LE: 69 | if (left_len <= right_len) Py_RETURN_TRUE; 70 | Py_RETURN_FALSE; 71 | case Py_GE: 72 | if (left_len >= right_len) Py_RETURN_TRUE; 73 | Py_RETURN_FALSE; 74 | default: 75 | abort(); 76 | } 77 | } 78 | 79 | if (op == Py_EQ) { 80 | Py_RETURN_FALSE; 81 | } 82 | if (op == Py_NE) { 83 | Py_RETURN_TRUE; 84 | } 85 | 86 | return PyObject_RichCompare(left_items[i], right_items[i], op); 87 | } 88 | -------------------------------------------------------------------------------- /gel/datatypes/config_memory.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from libc.stdint cimport int64_t 21 | 22 | 23 | cdef class ConfigMemory(CustomType): 24 | 25 | cdef: 26 | readonly int64_t _bytes 27 | 28 | 29 | cdef new_config_memory(int64_t bytes) 30 | -------------------------------------------------------------------------------- /gel/datatypes/config_memory.pyx: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import typing 21 | 22 | from libc.stdint cimport int64_t 23 | 24 | DEF KiB = 1024; 25 | DEF MiB = 1024 * KiB; 26 | DEF GiB = 1024 * MiB; 27 | DEF TiB = 1024 * GiB; 28 | DEF PiB = 1024 * TiB; 29 | 30 | 31 | cdef class ConfigMemory(CustomType): 32 | __gel_type_name__: typing.ClassVar[str] = "cfg::memory" 33 | 34 | def __init__(self, int64_t bytes): 35 | self._bytes = bytes 36 | 37 | def __eq__(self, other): 38 | if type(other) is not ConfigMemory: 39 | return NotImplemented 40 | 41 | return self._bytes == (other)._bytes 42 | 43 | def __hash__(self): 44 | return hash((ConfigMemory, self._bytes)) 45 | 46 | def __repr__(self): 47 | return f'' 48 | 49 | @cython.cdivision(True) 50 | def __str__(self): 51 | cdef: 52 | int64_t bytes = self._bytes 53 | 54 | if bytes >= PiB and bytes % PiB == 0: 55 | return f'{bytes // PiB}PiB' 56 | if bytes >= TiB and bytes % TiB == 0: 57 | return f'{bytes // TiB}TiB' 58 | if bytes >= GiB and bytes % GiB == 0: 59 | return f'{bytes // GiB}GiB' 60 | if bytes >= MiB and bytes % MiB == 0: 61 | return f'{bytes // MiB}MiB' 62 | if bytes >= KiB and bytes % KiB == 0: 63 | return f'{bytes // KiB}KiB' 64 | return f'{bytes}B' 65 | 66 | def as_bytes(self): 67 | return self._bytes 68 | 69 | 70 | cdef new_config_memory(int64_t bytes): 71 | cdef ConfigMemory mem = ConfigMemory.__new__(ConfigMemory) 72 | 73 | mem._bytes = bytes 74 | 75 | return mem 76 | -------------------------------------------------------------------------------- /gel/datatypes/datatypes.pyi: -------------------------------------------------------------------------------- 1 | from typing import ClassVar 2 | 3 | class CustomType: 4 | __gel_type_name__: ClassVar[str] 5 | 6 | class DateDuration(CustomType): 7 | pass 8 | 9 | class RelativeDuration(CustomType): 10 | pass 11 | 12 | class ConfigMemory(CustomType): 13 | pass 14 | -------------------------------------------------------------------------------- /gel/datatypes/date_duration.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from libc.stdint cimport int64_t, int32_t 21 | 22 | 23 | cdef class DateDuration(CustomType): 24 | 25 | cdef: 26 | readonly int32_t days 27 | readonly int32_t months 28 | 29 | 30 | cdef new_date_duration(int32_t days, int32_t months) 31 | -------------------------------------------------------------------------------- /gel/datatypes/date_duration.pyx: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from libc.stdint cimport int64_t, int32_t 21 | 22 | 23 | DEF MONTHS_PER_YEAR = 12 24 | 25 | 26 | cdef class DateDuration(CustomType): 27 | __gel_type_name__: typing.ClassVar[str] = "std::cal::date_duration" 28 | 29 | def __init__(self, *, int32_t days=0, int32_t months=0): 30 | self.days = days 31 | self.months = months 32 | 33 | def __eq__(self, other): 34 | if type(other) is not DateDuration: 35 | return NotImplemented 36 | 37 | return ( 38 | self.days == (other).days and 39 | self.months == (other).months 40 | ) 41 | 42 | def __hash__(self): 43 | return hash((DateDuration, self.days, self.months)) 44 | 45 | def __repr__(self): 46 | return f'' 47 | 48 | @cython.cdivision(True) 49 | def __str__(self): 50 | # This is closely modeled after interval_out(). 51 | cdef: 52 | int64_t year = self.months / MONTHS_PER_YEAR 53 | int64_t mon = self.months % MONTHS_PER_YEAR 54 | list buf = [] 55 | 56 | if not self.months and not self.days: 57 | return 'P0D' 58 | 59 | buf.append('P') 60 | 61 | if year: 62 | buf.append(f'{year}Y') 63 | 64 | if mon: 65 | buf.append(f'{mon}M') 66 | 67 | if self.days: 68 | buf.append(f'{self.days}D') 69 | 70 | return ''.join(buf) 71 | 72 | 73 | cdef new_date_duration(int32_t days, int32_t months): 74 | cdef DateDuration dur = DateDuration.__new__(DateDuration) 75 | 76 | dur.days = days 77 | dur.months = months 78 | 79 | return dur 80 | -------------------------------------------------------------------------------- /gel/datatypes/enum.pyx: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | import enum 20 | 21 | 22 | class EnumValue(enum.Enum): 23 | 24 | def __str__(self): 25 | return self._value_ 26 | 27 | def __repr__(self): 28 | return f'' 29 | 30 | @classmethod 31 | def _try_from(cls, value): 32 | if isinstance(value, EnumValue): 33 | return value 34 | elif isinstance(value, enum.Enum): 35 | return cls(value.value) 36 | elif isinstance(value, str): 37 | return cls(value) 38 | else: 39 | return None 40 | 41 | def __lt__(self, other): 42 | other = self._try_from(other) 43 | if not other or self.__tid__ != other.__tid__: 44 | return NotImplemented 45 | return self._index_ < other._index_ 46 | 47 | def __gt__(self, other): 48 | other = self._try_from(other) 49 | if not other or self.__tid__ != other.__tid__: 50 | return NotImplemented 51 | return self._index_ > other._index_ 52 | 53 | def __le__(self, other): 54 | other = self._try_from(other) 55 | if not other or self.__tid__ != other.__tid__: 56 | return NotImplemented 57 | return self._index_ <= other._index_ 58 | 59 | def __ge__(self, other): 60 | other = self._try_from(other) 61 | if not other or self.__tid__ != other.__tid__: 62 | return NotImplemented 63 | return self._index_ >= other._index_ 64 | 65 | def __eq__(self, other): 66 | other = self._try_from(other) 67 | return self is other 68 | 69 | def __hash__(self): 70 | return hash(self._value_) 71 | -------------------------------------------------------------------------------- /gel/datatypes/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * This source file is part of the EdgeDB open source project. 3 | * 4 | * Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | #include "Python.h" 20 | 21 | #include "datatypes.h" 22 | 23 | 24 | Py_hash_t 25 | _EdgeGeneric_HashString(const char *s) 26 | { 27 | PyObject *o = PyUnicode_FromString(s); 28 | if (o == NULL) { 29 | return -1; 30 | } 31 | 32 | Py_hash_t res = PyObject_Hash(o); 33 | Py_DECREF(o); 34 | return res; 35 | } 36 | -------------------------------------------------------------------------------- /gel/datatypes/internal.h: -------------------------------------------------------------------------------- 1 | /* 2 | * This source file is part of the EdgeDB open source project. 3 | * 4 | * Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | */ 18 | 19 | 20 | #ifndef EDGE_INTERNAL_H 21 | #define EDGE_INTERNAL_H 22 | 23 | 24 | #include /* For offsetof */ 25 | 26 | #include 27 | 28 | #include "datatypes.h" 29 | 30 | 31 | int _Edge_NoKeywords(const char *, PyObject *); 32 | 33 | Py_hash_t _EdgeGeneric_HashString(const char *); 34 | 35 | PyObject * _EdgeGeneric_RenderObject(PyObject *obj); 36 | 37 | int _EdgeGeneric_RenderValues( 38 | _PyUnicodeWriter *, PyObject *, PyObject **, Py_ssize_t); 39 | 40 | PyObject * _EdgeGeneric_RichCompareValues(PyObject **, Py_ssize_t, 41 | PyObject **, Py_ssize_t, 42 | int); 43 | 44 | 45 | #define EDGE_RENDER_NAMES 0x1 46 | #define EDGE_RENDER_LINK_PROPS 0x2 47 | #define EDGE_RENDER_IMPLICIT 0x4 48 | #define EDGE_RENDER_DEFAULT 0 49 | 50 | int _EdgeGeneric_RenderItems(_PyUnicodeWriter *, 51 | PyObject *, PyObject *, 52 | PyObject **, Py_ssize_t, 53 | int); 54 | 55 | #ifndef _PyList_CAST 56 | # define _PyList_CAST(op) (assert(PyList_Check(op)), (PyListObject *)(op)) 57 | #endif 58 | 59 | #ifndef _PyList_ITEMS 60 | # define _PyList_ITEMS(op) (_PyList_CAST(op)->ob_item) 61 | #endif 62 | 63 | #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 8 64 | # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_BEGIN(op, dealloc) 65 | # define CPy_TRASHCAN_END(op) Py_TRASHCAN_END 66 | #else 67 | # define CPy_TRASHCAN_BEGIN(op, dealloc) Py_TRASHCAN_SAFE_BEGIN(op) 68 | # define CPy_TRASHCAN_END(op) Py_TRASHCAN_SAFE_END(op) 69 | #endif 70 | 71 | #endif 72 | -------------------------------------------------------------------------------- /gel/datatypes/relative_duration.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from libc.stdint cimport int64_t, int32_t 21 | 22 | 23 | cdef class RelativeDuration(CustomType): 24 | 25 | cdef: 26 | readonly int64_t microseconds 27 | readonly int32_t days 28 | readonly int32_t months 29 | 30 | 31 | cdef new_duration(int64_t microseconds, int32_t days, int32_t months) 32 | -------------------------------------------------------------------------------- /gel/describe.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2022-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import dataclasses 21 | import typing 22 | import uuid 23 | 24 | from . import enums 25 | 26 | 27 | @dataclasses.dataclass(frozen=True) 28 | class AnyType: 29 | desc_id: uuid.UUID 30 | name: typing.Optional[str] 31 | 32 | 33 | @dataclasses.dataclass(frozen=True) 34 | class Element: 35 | type: AnyType 36 | cardinality: enums.Cardinality 37 | is_implicit: bool 38 | kind: enums.ElementKind 39 | 40 | 41 | @dataclasses.dataclass(frozen=True) 42 | class SequenceType(AnyType): 43 | element_type: AnyType 44 | 45 | 46 | @dataclasses.dataclass(frozen=True) 47 | class SetType(SequenceType): 48 | pass 49 | 50 | 51 | @dataclasses.dataclass(frozen=True) 52 | class ObjectType(AnyType): 53 | elements: typing.Dict[str, Element] 54 | 55 | 56 | @dataclasses.dataclass(frozen=True) 57 | class BaseScalarType(AnyType): 58 | name: str 59 | 60 | 61 | @dataclasses.dataclass(frozen=True) 62 | class ScalarType(AnyType): 63 | base_type: BaseScalarType 64 | 65 | 66 | @dataclasses.dataclass(frozen=True) 67 | class TupleType(AnyType): 68 | element_types: typing.Tuple[AnyType] 69 | 70 | 71 | @dataclasses.dataclass(frozen=True) 72 | class NamedTupleType(AnyType): 73 | element_types: typing.Dict[str, AnyType] 74 | 75 | 76 | @dataclasses.dataclass(frozen=True) 77 | class ArrayType(SequenceType): 78 | pass 79 | 80 | 81 | @dataclasses.dataclass(frozen=True) 82 | class EnumType(AnyType): 83 | members: typing.Tuple[str] 84 | 85 | 86 | @dataclasses.dataclass(frozen=True) 87 | class SparseObjectType(ObjectType): 88 | pass 89 | 90 | 91 | @dataclasses.dataclass(frozen=True) 92 | class RangeType(AnyType): 93 | value_type: AnyType 94 | 95 | 96 | @dataclasses.dataclass(frozen=True) 97 | class MultiRangeType(AnyType): 98 | value_type: AnyType 99 | -------------------------------------------------------------------------------- /gel/enums.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2021-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import enum 21 | 22 | 23 | class Capability(enum.IntFlag): 24 | NONE = 0 # noqa 25 | MODIFICATIONS = 1 << 0 # noqa 26 | SESSION_CONFIG = 1 << 1 # noqa 27 | TRANSACTION = 1 << 2 # noqa 28 | DDL = 1 << 3 # noqa 29 | PERSISTENT_CONFIG = 1 << 4 # noqa 30 | 31 | ALL = 0xFFFF_FFFF_FFFF_FFFF # noqa 32 | EXECUTE = ALL & ~TRANSACTION & ~SESSION_CONFIG # noqa 33 | LEGACY_EXECUTE = ALL & ~TRANSACTION # noqa 34 | 35 | 36 | class CompilationFlag(enum.IntFlag): 37 | INJECT_OUTPUT_TYPE_IDS = 1 << 0 # noqa 38 | INJECT_OUTPUT_TYPE_NAMES = 1 << 1 # noqa 39 | INJECT_OUTPUT_OBJECT_IDS = 1 << 2 # noqa 40 | 41 | 42 | class Cardinality(enum.Enum): 43 | # Cardinality isn't applicable for the query: 44 | # * the query is a command like CONFIGURE that 45 | # does not return any data; 46 | # * the query is composed of multiple queries. 47 | NO_RESULT = 0x6E 48 | 49 | # Cardinality is 1 or 0 50 | AT_MOST_ONE = 0x6F 51 | 52 | # Cardinality is 1 53 | ONE = 0x41 54 | 55 | # Cardinality is >= 0 56 | MANY = 0x6D 57 | 58 | # Cardinality is >= 1 59 | AT_LEAST_ONE = 0x4D 60 | 61 | def is_single(self) -> bool: 62 | return self in {Cardinality.AT_MOST_ONE, Cardinality.ONE} 63 | 64 | def is_multi(self) -> bool: 65 | return self in {Cardinality.AT_LEAST_ONE, Cardinality.MANY} 66 | 67 | 68 | class ElementKind(enum.Enum): 69 | LINK = 1 # noqa 70 | PROPERTY = 2 # noqa 71 | LINK_PROPERTY = 3 # noqa 72 | -------------------------------------------------------------------------------- /gel/errors/tags.py: -------------------------------------------------------------------------------- 1 | __all__ = [ 2 | "Tag", 3 | "SHOULD_RECONNECT", 4 | "SHOULD_RETRY", 5 | ] 6 | 7 | 8 | class Tag(object): 9 | """Error tag 10 | 11 | Tags are used to differentiate certain properties of errors that apply to 12 | error classes across hierarchy. 13 | 14 | Use ``error.has_tag(tag_name)`` to check for a tag. 15 | """ 16 | 17 | def __init__(self, name): 18 | self.name = name 19 | 20 | def __repr__(self): 21 | return f"" 22 | 23 | 24 | SHOULD_RECONNECT = Tag("SHOULD_RECONNECT") 25 | SHOULD_RETRY = Tag("SHOULD_RETRY") 26 | -------------------------------------------------------------------------------- /gel/introspect.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | # IMPORTANT: this private API is subject to change. 21 | 22 | 23 | import functools 24 | import typing 25 | 26 | from gel.datatypes import datatypes as dt 27 | from gel.enums import ElementKind 28 | 29 | 30 | class PointerDescription(typing.NamedTuple): 31 | name: str 32 | kind: ElementKind 33 | implicit: bool 34 | 35 | 36 | class ObjectDescription(typing.NamedTuple): 37 | pointers: typing.Tuple[PointerDescription, ...] 38 | 39 | 40 | @functools.lru_cache() 41 | def _introspect_object_desc(desc) -> ObjectDescription: 42 | pointers = [] 43 | # Call __dir__ directly as dir() scrambles the order. 44 | for name in desc.__dir__(): 45 | if desc.is_link(name): 46 | kind = ElementKind.LINK 47 | elif desc.is_linkprop(name): 48 | continue 49 | else: 50 | kind = ElementKind.PROPERTY 51 | 52 | pointers.append( 53 | PointerDescription( 54 | name=name, kind=kind, implicit=desc.is_implicit(name) 55 | ) 56 | ) 57 | 58 | return ObjectDescription(pointers=tuple(pointers)) 59 | 60 | 61 | def introspect_object(obj) -> ObjectDescription: 62 | return _introspect_object_desc(dt.get_object_descriptor(obj)) 63 | -------------------------------------------------------------------------------- /gel/models/__init__.py: -------------------------------------------------------------------------------- 1 | # SPDX-PackageName: gel-python 2 | # SPDX-License-Identifier: Apache-2.0 3 | # SPDX-FileCopyrightText: Copyright Gel Data Inc. and the contributors. 4 | -------------------------------------------------------------------------------- /gel/models/ruff.toml: -------------------------------------------------------------------------------- 1 | extend = "../../pyproject.toml" 2 | 3 | [lint] 4 | preview = true 5 | extend-select = [ 6 | "A", # flake8-builtins 7 | "B", # flake8-bugbear 8 | "C4", # flake8-comprehensions 9 | "COM", # flake8-commas 10 | "DTZ", # flake8-datetimez 11 | "E", # pycodestyle 12 | "ERA", # flake8-eradicate 13 | "F", # pyflakes 14 | "FA", # flake8-future-annotations 15 | "FBT", # flake8-boolean-trap 16 | "FURB", # refurb 17 | "G", # flake8-logging-format 18 | "ICN", # flake8-import-conventions 19 | "ISC", # flake8-implicit-str-concat 20 | "LOG", # flake8-logging 21 | "N", # pep8-naming 22 | "PERF", # perflint 23 | "PGH", # pygrep-hooks 24 | "PIE", # flake8-pie 25 | "PL", # pylint 26 | "PYI", # flake8-pyi 27 | "Q", # flake8-quotes 28 | "RUF", # ruff specific 29 | "S", # flake8-bandit 30 | "SIM", # flake8-simplify 31 | "SLOT", # flake8-slots 32 | "T20", # flake8-print 33 | "TC", # flake8-type-checking 34 | "UP", # pyupgrade 35 | "W", # warning 36 | ] 37 | extend-ignore = [ 38 | "S101", # assert 39 | "COM812", # missing-trailing-comma 40 | "ISC002", # multi-line-implicit-string-concatenation 41 | "PLC0105", # type-name-incorrect-variance 42 | "PLC0414", # useless-import-alias 43 | "PLR0904", # too-many-public-methods 44 | "PLW3201", # bad-dunder-method-name 45 | ] 46 | -------------------------------------------------------------------------------- /gel/orm/__init__.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | # No tests here, but we want to skip the unittest loader from attempting to 4 | # import ORM packages which may not have been installed (like Django that has 5 | # a few custom adjustments to make our models work). 6 | def load_tests(loader, tests, pattern): 7 | return tests 8 | -------------------------------------------------------------------------------- /gel/orm/django/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/gel/orm/django/__init__.py -------------------------------------------------------------------------------- /gel/orm/django/gelmodels/__init__.py: -------------------------------------------------------------------------------- 1 | import django 2 | 3 | __version__ = "0.0.1" 4 | -------------------------------------------------------------------------------- /gel/orm/django/gelmodels/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class GelPGModel(AppConfig): 5 | name = "gel.orm.django.gelmodels" 6 | 7 | def ready(self): 8 | from django.db import connections, utils 9 | 10 | gel_compiler_module = "gel.orm.django.gelmodels.compiler" 11 | 12 | # Change the current compiler_module 13 | for c in connections: 14 | connections[c].ops.compiler_module = gel_compiler_module 15 | 16 | # Update the load_backend to use our DatabaseWrapper 17 | orig_load_backend = utils.load_backend 18 | 19 | def custom_load_backend(*args, **kwargs): 20 | backend = orig_load_backend(*args, **kwargs) 21 | 22 | class GelPGBackend: 23 | @staticmethod 24 | def DatabaseWrapper(*args2, **kwargs2): 25 | connection = backend.DatabaseWrapper(*args2, **kwargs2) 26 | connection.ops.compiler_module = gel_compiler_module 27 | return connection 28 | 29 | return GelPGBackend 30 | 31 | utils.load_backend = custom_load_backend -------------------------------------------------------------------------------- /gel/orm/django/gelmodels/compiler.py: -------------------------------------------------------------------------------- 1 | from django.db.models.sql.compiler import ( # noqa 2 | SQLAggregateCompiler, 3 | SQLCompiler, 4 | SQLDeleteCompiler, 5 | ) 6 | from django.db.models.sql.compiler import ( # noqa 7 | SQLInsertCompiler as BaseSQLInsertCompiler, 8 | ) 9 | from django.db.models.sql.compiler import ( # noqa 10 | SQLUpdateCompiler as BaseSQLUpdateCompiler, 11 | ) 12 | 13 | 14 | class GelSQLCompilerMixin: 15 | ''' 16 | The reflected models have two special fields: `id` and `obj_type`. Both of 17 | those fields should be read-only as they are populated automatically by 18 | Gel and must not be modified. 19 | ''' 20 | @property 21 | def readonly_gel_fields(self): 22 | try: 23 | # Verify that this is a Gel model reflected via Postgres protocol. 24 | gel_pg_meta = getattr(self.query.model, "GelPGMeta") 25 | except AttributeError: 26 | return set() 27 | else: 28 | return {'id', 'gel_type_id'} 29 | 30 | def as_sql(self): 31 | readonly_gel_fields = self.readonly_gel_fields 32 | if readonly_gel_fields: 33 | self.remove_readonly_gel_fields(readonly_gel_fields) 34 | return super().as_sql() 35 | 36 | 37 | class SQLUpdateCompiler(GelSQLCompilerMixin, BaseSQLUpdateCompiler): 38 | def remove_readonly_gel_fields(self, names): 39 | ''' 40 | Remove the values corresponding to the read-only fields. 41 | ''' 42 | values = self.query.values 43 | # The tuple is (field, model, value) 44 | values[:] = (tup for tup in values if tup[0].name not in names) 45 | 46 | 47 | class SQLInsertCompiler(GelSQLCompilerMixin, BaseSQLInsertCompiler): 48 | def remove_readonly_gel_fields(self, names): 49 | ''' 50 | Remove the read-only fields. 51 | ''' 52 | fields = self.query.fields 53 | 54 | try: 55 | fields[:] = (f for f in fields if f.name not in names) 56 | except AttributeError: 57 | # When deserializing, we might get an attribute error because this 58 | # list shoud be copied first: 59 | # 60 | # "AttributeError: The return type of 'local_concrete_fields' 61 | # should never be mutated. If you want to manipulate this list for 62 | # your own use, make a copy first." 63 | 64 | self.query.fields = [f for f in fields if f.name not in names] 65 | -------------------------------------------------------------------------------- /gel/protocol/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | /*.c 3 | -------------------------------------------------------------------------------- /gel/protocol/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /gel/protocol/asyncio_proto.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from . cimport protocol 21 | 22 | from gel.pgproto.debug cimport PG_DEBUG 23 | 24 | 25 | cdef class AsyncIOProtocol(protocol.SansIOProtocolBackwardsCompatible): 26 | 27 | cdef: 28 | object transport 29 | 30 | object connected_fut 31 | object disconnected_fut 32 | 33 | object loop 34 | object msg_waiter 35 | object writable 36 | -------------------------------------------------------------------------------- /gel/protocol/blocking_proto.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from . cimport protocol 21 | 22 | from gel.pgproto.debug cimport PG_DEBUG 23 | 24 | 25 | cdef class BlockingIOProtocol(protocol.SansIOProtocolBackwardsCompatible): 26 | 27 | cdef: 28 | readonly object sock 29 | float deadline 30 | readonly object last_active_timestamp 31 | 32 | cdef _disconnect(self) 33 | -------------------------------------------------------------------------------- /gel/protocol/codecs/array.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | cdef class BaseArrayCodec(BaseCodec): 21 | 22 | cdef: 23 | BaseCodec sub_codec 24 | int32_t cardinality 25 | 26 | cdef _decode_array(self, bint is_set, object return_type, FRBuffer *buf) 27 | 28 | 29 | @cython.final 30 | cdef class ArrayCodec(BaseArrayCodec): 31 | 32 | @staticmethod 33 | cdef BaseCodec new(bytes tid, BaseCodec sub_codec, int32_t cardinality) 34 | -------------------------------------------------------------------------------- /gel/protocol/codecs/base.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | cdef class BaseCodec: 21 | 22 | cdef: 23 | bytes tid 24 | str name 25 | str type_name 26 | 27 | cdef inline bytes get_tid(self): 28 | return self.tid 29 | 30 | cdef encode(self, WriteBuffer buf, object obj) 31 | cdef decode(self, object return_type, FRBuffer *buf) 32 | 33 | cdef dump(self, int level=?) 34 | 35 | 36 | cdef class CodecPythonOverride(BaseCodec): 37 | 38 | cdef: 39 | BaseCodec codec 40 | object encoder 41 | object decoder 42 | 43 | @staticmethod 44 | cdef BaseCodec new(bytes tid, 45 | BaseCodec basecodec, 46 | object encoder, 47 | object decoder) 48 | 49 | 50 | cdef class BaseRecordCodec(BaseCodec): 51 | 52 | cdef: 53 | tuple fields_codecs 54 | uint64_t encoder_flags 55 | 56 | cdef _check_encoder(self) 57 | 58 | 59 | cdef class EmptyTupleCodec(BaseCodec): 60 | 61 | cdef: 62 | object empty_tup 63 | 64 | 65 | cdef class NullCodec(BaseCodec): 66 | pass 67 | 68 | 69 | cdef class BaseNamedRecordCodec(BaseRecordCodec): 70 | 71 | cdef: 72 | object descriptor 73 | 74 | 75 | @cython.final 76 | cdef class EdegDBCodecContext(pgproto.CodecContext): 77 | 78 | cdef: 79 | object _codec 80 | -------------------------------------------------------------------------------- /gel/protocol/codecs/codecs.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | include "./base.pxd" 21 | include "./scalar.pxd" 22 | include "./tuple.pxd" 23 | include "./namedtuple.pxd" 24 | include "./object.pxd" 25 | include "./array.pxd" 26 | include "./range.pxd" 27 | include "./set.pxd" 28 | include "./enum.pxd" 29 | include "./record.pxd" 30 | 31 | 32 | cdef class CodecsRegistry: 33 | 34 | cdef: 35 | LRUMapping codecs_build_cache 36 | LRUMapping codecs 37 | dict base_codec_overrides 38 | 39 | cdef BaseCodec _build_codec(self, FRBuffer *spec, list codecs_list, 40 | protocol_version) 41 | cdef BaseCodec build_codec(self, bytes spec, protocol_version) 42 | 43 | cdef has_codec(self, bytes type_id) 44 | cdef BaseCodec get_codec(self, bytes type_id) 45 | -------------------------------------------------------------------------------- /gel/protocol/codecs/edb_types.pxi: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM "edb/api/types.txt" WITH 2 | # $ edb gen-types 3 | 4 | 5 | import uuid 6 | 7 | 8 | TYPE_IDS = { 9 | 'anytype': uuid.UUID('00000000-0000-0000-0000-000000000001'), 10 | 'anytuple': uuid.UUID('00000000-0000-0000-0000-000000000002'), 11 | 'std': uuid.UUID('00000000-0000-0000-0000-0000000000f0'), 12 | 'empty-tuple': uuid.UUID('00000000-0000-0000-0000-0000000000ff'), 13 | 'std::uuid': uuid.UUID('00000000-0000-0000-0000-000000000100'), 14 | 'std::str': uuid.UUID('00000000-0000-0000-0000-000000000101'), 15 | 'std::bytes': uuid.UUID('00000000-0000-0000-0000-000000000102'), 16 | 'std::int16': uuid.UUID('00000000-0000-0000-0000-000000000103'), 17 | 'std::int32': uuid.UUID('00000000-0000-0000-0000-000000000104'), 18 | 'std::int64': uuid.UUID('00000000-0000-0000-0000-000000000105'), 19 | 'std::float32': uuid.UUID('00000000-0000-0000-0000-000000000106'), 20 | 'std::float64': uuid.UUID('00000000-0000-0000-0000-000000000107'), 21 | 'std::decimal': uuid.UUID('00000000-0000-0000-0000-000000000108'), 22 | 'std::bool': uuid.UUID('00000000-0000-0000-0000-000000000109'), 23 | 'std::datetime': uuid.UUID('00000000-0000-0000-0000-00000000010a'), 24 | 'cal::local_datetime': uuid.UUID('00000000-0000-0000-0000-00000000010b'), 25 | 'cal::local_date': uuid.UUID('00000000-0000-0000-0000-00000000010c'), 26 | 'cal::local_time': uuid.UUID('00000000-0000-0000-0000-00000000010d'), 27 | 'std::duration': uuid.UUID('00000000-0000-0000-0000-00000000010e'), 28 | 'std::json': uuid.UUID('00000000-0000-0000-0000-00000000010f'), 29 | 'std::bigint': uuid.UUID('00000000-0000-0000-0000-000000000110'), 30 | 'cal::relative_duration': uuid.UUID('00000000-0000-0000-0000-000000000111'), 31 | 'cal::date_duration': uuid.UUID('00000000-0000-0000-0000-000000000112'), 32 | 'cfg::memory': uuid.UUID('00000000-0000-0000-0000-000000000130'), 33 | 'fts::language': uuid.UUID('00000000-0000-0000-0000-000000000140'), 34 | 'std::pg::json': uuid.UUID('00000000-0000-0000-0000-000001000001'), 35 | 'std::pg::timestamptz': uuid.UUID('00000000-0000-0000-0000-000001000002'), 36 | 'std::pg::timestamp': uuid.UUID('00000000-0000-0000-0000-000001000003'), 37 | 'std::pg::date': uuid.UUID('00000000-0000-0000-0000-000001000004'), 38 | 'std::pg::interval': uuid.UUID('00000000-0000-0000-0000-000001000005'), 39 | } 40 | -------------------------------------------------------------------------------- /gel/protocol/codecs/enum.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class EnumCodec(BaseCodec): 22 | 23 | cdef: 24 | object cls 25 | 26 | @staticmethod 27 | cdef BaseCodec new(bytes tid, tuple enum_labels) 28 | -------------------------------------------------------------------------------- /gel/protocol/codecs/enum.pyx: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | import enum 20 | 21 | 22 | @cython.final 23 | cdef class EnumCodec(BaseCodec): 24 | 25 | cdef encode(self, WriteBuffer buf, object obj): 26 | if not isinstance(obj, (self.cls, str)): 27 | try: 28 | obj = self.cls._try_from(obj) 29 | except (TypeError, ValueError): 30 | obj = None 31 | if obj is None: 32 | raise TypeError( 33 | f'a str or gel.EnumValue(__tid__={self.cls.__tid__}) ' 34 | f'is expected as a valid enum argument, ' 35 | f'got {type(obj).__name__}') from None 36 | pgproto.text_encode(DEFAULT_CODEC_CONTEXT, buf, str(obj)) 37 | 38 | cdef decode(self, object return_type, FRBuffer *buf): 39 | label = pgproto.text_decode(DEFAULT_CODEC_CONTEXT, buf) 40 | return self.cls(label) 41 | 42 | @staticmethod 43 | cdef BaseCodec new(bytes tid, tuple enum_labels): 44 | cdef: 45 | EnumCodec codec 46 | 47 | codec = EnumCodec.__new__(EnumCodec) 48 | 49 | codec.tid = tid 50 | codec.name = 'Enum' 51 | cls = "DerivedEnumValue" 52 | bases = (datatypes.EnumValue,) 53 | classdict = enum.EnumMeta.__prepare__(cls, bases) 54 | classdict["__module__"] = "gel" 55 | classdict["__qualname__"] = "gel.DerivedEnumValue" 56 | classdict["__tid__"] = pgproto.UUID(tid) 57 | for label in enum_labels: 58 | classdict[label.upper()] = label 59 | codec.cls = enum.EnumMeta(cls, bases, classdict) 60 | for index, label in enumerate(enum_labels): 61 | codec.cls(label)._index_ = index 62 | 63 | return codec 64 | 65 | def make_type(self, describe_context): 66 | return describe.EnumType( 67 | desc_id=uuid.UUID(bytes=self.tid), 68 | name=self.type_name, 69 | members=tuple(x.value for x in self.cls.__members__.values()) 70 | ) 71 | -------------------------------------------------------------------------------- /gel/protocol/codecs/namedtuple.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class NamedTupleCodec(BaseNamedRecordCodec): 22 | cdef object namedtuple_type 23 | 24 | @staticmethod 25 | cdef BaseCodec new(bytes tid, tuple fields_names, tuple fields_codecs) 26 | -------------------------------------------------------------------------------- /gel/protocol/codecs/object.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class ObjectCodec(BaseNamedRecordCodec): 22 | cdef: 23 | bint is_sparse 24 | object cached_dataclass_fields 25 | tuple names 26 | tuple flags 27 | 28 | dict cached_tid_map 29 | tuple cached_return_type_subcodecs 30 | tuple cached_return_type_dlists 31 | object cached_return_type_proxy 32 | object cached_return_type 33 | object cached_orig_return_type 34 | 35 | cdef encode_args(self, WriteBuffer buf, dict obj) 36 | 37 | cdef adapt_to_return_type(self, object return_type) 38 | 39 | cdef _decode_plain(self, FRBuffer *buf, Py_ssize_t elem_count) 40 | 41 | @staticmethod 42 | cdef BaseCodec new(bytes tid, tuple names, tuple flags, 43 | tuple cards, tuple codecs, bint is_sparse) 44 | -------------------------------------------------------------------------------- /gel/protocol/codecs/range.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class RangeCodec(BaseCodec): 22 | 23 | cdef: 24 | BaseCodec sub_codec 25 | 26 | @staticmethod 27 | cdef BaseCodec new(bytes tid, BaseCodec sub_codec) 28 | 29 | @staticmethod 30 | cdef encode_range(WriteBuffer buf, object obj, BaseCodec sub_codec) 31 | 32 | @staticmethod 33 | cdef decode_range(object return_type, FRBuffer *buf, BaseCodec sub_codec) 34 | 35 | 36 | @cython.final 37 | cdef class MultiRangeCodec(BaseCodec): 38 | 39 | cdef: 40 | BaseCodec sub_codec 41 | 42 | @staticmethod 43 | cdef BaseCodec new(bytes tid, BaseCodec sub_codec) 44 | -------------------------------------------------------------------------------- /gel/protocol/codecs/record.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class RecordCodec(BaseNamedRecordCodec): 22 | @staticmethod 23 | cdef BaseCodec new(bytes tid, tuple names, tuple codecs) 24 | -------------------------------------------------------------------------------- /gel/protocol/codecs/scalar.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class ScalarCodec(BaseCodec): 22 | 23 | cdef: 24 | pgproto.encode_func c_encoder 25 | pgproto.decode_func c_decoder 26 | ScalarCodec base_codec 27 | 28 | cdef derive(self, bytes tid) 29 | 30 | @staticmethod 31 | cdef BaseCodec new(bytes tid, str name, 32 | pgproto.encode_func encoder, 33 | pgproto.decode_func decoder) 34 | -------------------------------------------------------------------------------- /gel/protocol/codecs/scalar.pyx: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class ScalarCodec(BaseCodec): 22 | 23 | def __cinit__(self): 24 | self.c_encoder = NULL 25 | self.c_decoder = NULL 26 | 27 | cdef encode(self, WriteBuffer buf, object obj): 28 | self.c_encoder(DEFAULT_CODEC_CONTEXT, buf, obj) 29 | 30 | cdef decode(self, object return_type, FRBuffer *buf): 31 | return self.c_decoder(DEFAULT_CODEC_CONTEXT, buf) 32 | 33 | cdef derive(self, bytes tid): 34 | cdef ScalarCodec rv 35 | rv = ScalarCodec.new(tid, self.name, self.c_encoder, self.c_decoder) 36 | rv.base_codec = self 37 | return rv 38 | 39 | @staticmethod 40 | cdef BaseCodec new(bytes tid, str name, 41 | pgproto.encode_func encoder, 42 | pgproto.decode_func decoder): 43 | cdef: 44 | ScalarCodec codec 45 | 46 | codec = ScalarCodec.__new__(ScalarCodec) 47 | 48 | codec.tid = tid 49 | codec.name = name 50 | codec.c_encoder = encoder 51 | codec.c_decoder = decoder 52 | 53 | return codec 54 | 55 | def make_type(self, describe_context): 56 | if self.base_codec is None: 57 | return describe.BaseScalarType( 58 | desc_id=uuid.UUID(bytes=self.tid), 59 | name=self.name, 60 | ) 61 | else: 62 | return describe.ScalarType( 63 | desc_id=uuid.UUID(bytes=self.tid), 64 | name=self.type_name, 65 | base_type=self.base_codec.make_type(describe_context), 66 | ) 67 | -------------------------------------------------------------------------------- /gel/protocol/codecs/set.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class SetCodec(BaseArrayCodec): 22 | 23 | cdef inline _decode_array_set(self, object return_type, FRBuffer *buf) 24 | 25 | @staticmethod 26 | cdef BaseCodec new(bytes tid, BaseCodec sub_codec) 27 | -------------------------------------------------------------------------------- /gel/protocol/codecs/tuple.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | @cython.final 21 | cdef class TupleCodec(BaseRecordCodec): 22 | 23 | @staticmethod 24 | cdef BaseCodec new(bytes tid, tuple fields_codecs) 25 | -------------------------------------------------------------------------------- /gel/protocol/consts.pxi: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | DEF _MAXINT32 = 2**31 - 1 21 | 22 | DEF CLIENT_HANDSHAKE_MSG = b'V' 23 | DEF SERVER_HANDSHAKE_MSG = b'v' 24 | DEF SERVER_KEY_DATA_MSG = b'K' 25 | DEF ERROR_RESPONSE_MSG = b'E' 26 | DEF READY_FOR_COMMAND_MSG = b'Z' 27 | DEF SYNC_MSG = b'S' 28 | DEF FLUSH_MSG = b'H' 29 | DEF COMMAND_COMPLETE_MSG = b'C' 30 | DEF DATA_MSG = b'D' 31 | DEF COMMAND_DATA_DESC_MSG = b'T' 32 | DEF LOG_MSG = b'L' 33 | DEF PARAMETER_STATUS_MSG = b'S' 34 | DEF AUTH_REQUEST_MSG = b'R' 35 | DEF AUTH_INITIAL_RESPONSE_MSG = b'p' 36 | DEF AUTH_RESPONSE_MSG = b'r' 37 | DEF PREPARE_MSG = b'P' 38 | DEF PREPARE_COMPLETE_MSG = b'1' 39 | DEF DESCRIBE_STMT_MSG = b'D' 40 | DEF STMT_DATA_DESC_MSG = b'T' 41 | DEF STATE_DATA_DESC_MSG = b's' 42 | DEF LEGACY_EXECUTE_MSG = b'E' 43 | DEF EXECUTE_MSG = b'O' 44 | DEF EXECUTE_SCRIPT_MSG = b'Q' 45 | DEF TERMINATE_MSG = b'X' 46 | 47 | DEF DUMP_MSG = b'>' 48 | DEF DUMP_HEADER_BLOCK_MSG = b'@' 49 | DEF DUMP_BLOCK_MSG = b'=' 50 | DEF RESTORE_MSG = b'<' 51 | DEF RESTORE_READY_MSG = b'+' 52 | DEF RESTORE_EOF_MSG = b'.' 53 | 54 | DEF CARDINALITY_ONE = b'o' 55 | DEF CARDINALITY_MANY = b'm' 56 | DEF CARDINALITY_NOT_APPLICABLE = b'n' 57 | 58 | DEF DESCRIBE_ASPECT_DATA = b'T' 59 | 60 | DEF TRANS_STATUS_IDLE = b'I' 61 | DEF TRANS_STATUS_INTRANS = b'T' 62 | DEF TRANS_STATUS_ERROR = b'E' 63 | 64 | DEF PROTO_VER_MAJOR = 3 65 | DEF PROTO_VER_MINOR = 0 66 | 67 | DEF MIN_PROTO_VER_MAJOR = 0 68 | DEF MIN_PROTO_VER_MINOR = 13 69 | -------------------------------------------------------------------------------- /gel/protocol/cpythonx.pxd: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2016-present the asyncpg authors and contributors 2 | # 3 | # 4 | # This module is part of asyncpg and is released under 5 | # the Apache 2.0 License: http://www.apache.org/licenses/LICENSE-2.0 6 | 7 | 8 | cdef extern from "Python.h": 9 | int PyByteArray_Check(object) 10 | 11 | int PyMemoryView_Check(object) 12 | Py_buffer *PyMemoryView_GET_BUFFER(object) 13 | object PyMemoryView_GetContiguous(object, int buffertype, char order) 14 | 15 | Py_UCS4* PyUnicode_AsUCS4Copy(object) except NULL 16 | object PyUnicode_FromKindAndData( 17 | int kind, const void *buffer, Py_ssize_t size) 18 | 19 | int PyUnicode_4BYTE_KIND 20 | 21 | object PyUnicode_FromStringAndSize(const char *, ssize_t) 22 | -------------------------------------------------------------------------------- /gel/protocol/lru.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | cdef class LRUMapping: 21 | 22 | cdef: 23 | object _dict 24 | int _maxsize 25 | object _dict_move_to_end 26 | object _dict_get 27 | 28 | cpdef get(self, key, default) 29 | -------------------------------------------------------------------------------- /gel/protocol/protocol_v0.pxd: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | cdef class SansIOProtocolBackwardsCompatible(SansIOProtocol): 20 | cdef parse_legacy_describe_type_message(self, CodecsRegistry reg) 21 | cdef parse_legacy_command_complete_message(self) 22 | cdef legacy_write_headers(self, WriteBuffer buf, dict headers) 23 | cdef legacy_write_execute_headers( 24 | self, 25 | WriteBuffer buf, 26 | int implicit_limit, 27 | bint inline_typenames, 28 | bint inline_typeids, 29 | uint64_t allow_capabilities, 30 | ) 31 | cdef dict legacy_parse_headers(self) 32 | cdef _legacy_parse_type_data(self, CodecsRegistry reg) 33 | cdef _legacy_parse_data_messages(self, BaseCodec out_dc, result) 34 | -------------------------------------------------------------------------------- /gel/py.typed: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/gel/py.typed -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import pathlib 21 | import sys 22 | import unittest 23 | 24 | 25 | def suite(): 26 | test_loader = unittest.TestLoader() 27 | test_suite = test_loader.discover(str(pathlib.Path(__file__).parent), 28 | pattern='test_*.py') 29 | return test_suite 30 | 31 | 32 | if __name__ == '__main__': 33 | runner = unittest.runner.TextTestRunner(verbosity=2) 34 | result = runner.run(suite()) 35 | sys.exit(not result.wasSuccessful()) 36 | -------------------------------------------------------------------------------- /tests/codegen/linked/test_linked.edgeql: -------------------------------------------------------------------------------- 1 | select 42 2 | -------------------------------------------------------------------------------- /tests/codegen/linked/test_linked_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'linked/test_linked.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | async def test_linked( 10 | executor: gel.AsyncIOExecutor, 11 | ) -> int: 12 | return await executor.query_single( 13 | """\ 14 | select 42\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/linked/test_linked_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'linked/test_linked.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | def test_linked( 10 | executor: gel.Executor, 11 | ) -> int: 12 | return executor.query_single( 13 | """\ 14 | select 42\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/edgedb.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/tests/codegen/test-project1/edgedb.toml -------------------------------------------------------------------------------- /tests/codegen/test-project1/generated_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM: 2 | # 'select_optional_json.edgeql' 3 | # 'select_scalar.edgeql' 4 | # 'linked/test_linked.edgeql' 5 | # WITH: 6 | # $ gel-py --target async --file --no-skip-pydantic-validation 7 | 8 | 9 | from __future__ import annotations 10 | import dataclasses 11 | import gel 12 | import uuid 13 | 14 | 15 | @dataclasses.dataclass 16 | class SelectOptionalJsonResultItem: 17 | id: uuid.UUID 18 | snake_case: SelectOptionalJsonResultItemSnakeCase | None 19 | 20 | 21 | @dataclasses.dataclass 22 | class SelectOptionalJsonResultItemSnakeCase: 23 | id: uuid.UUID 24 | 25 | 26 | async def select_optional_json( 27 | executor: gel.AsyncIOExecutor, 28 | arg0: str | None, 29 | ) -> list[tuple[str, SelectOptionalJsonResultItem]]: 30 | return await executor.query( 31 | """\ 32 | create type TestCase { 33 | create link snake_case -> TestCase; 34 | }; 35 | 36 | select ($0, TestCase {snake_case});\ 37 | """, 38 | arg0, 39 | ) 40 | 41 | 42 | async def select_scalar( 43 | executor: gel.AsyncIOExecutor, 44 | ) -> int: 45 | return await executor.query_single( 46 | """\ 47 | select 1;\ 48 | """, 49 | ) 50 | 51 | 52 | async def test_linked( 53 | executor: gel.AsyncIOExecutor, 54 | ) -> int: 55 | return await executor.query_single( 56 | """\ 57 | select 42\ 58 | """, 59 | ) 60 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/generated_async_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | generated_async_edgeql.py.assert5 -------------------------------------------------------------------------------- /tests/codegen/test-project1/generated_async_edgeql.py.assert5: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM: 2 | # 'select_optional_json.edgeql' 3 | # 'select_scalar.edgeql' 4 | # 'linked/test_linked.edgeql' 5 | # WITH: 6 | # $ gel-py --target async --file --no-skip-pydantic-validation 7 | 8 | 9 | from __future__ import annotations 10 | import dataclasses 11 | import gel 12 | import uuid 13 | 14 | 15 | @dataclasses.dataclass 16 | class SelectOptionalJsonResultItem: 17 | id: uuid.UUID 18 | snake_case: SelectOptionalJsonResultItemSnakeCase | None 19 | 20 | 21 | @dataclasses.dataclass 22 | class SelectOptionalJsonResultItemSnakeCase: 23 | id: uuid.UUID 24 | 25 | 26 | async def select_optional_json( 27 | executor: gel.AsyncIOExecutor, 28 | arg0: str | None, 29 | ) -> list[tuple[str, SelectOptionalJsonResultItem]]: 30 | return await executor.query( 31 | """\ 32 | create type TestCase { 33 | create link snake_case -> TestCase; 34 | }; 35 | 36 | select ($0, TestCase {snake_case});\ 37 | """, 38 | arg0, 39 | ) 40 | 41 | 42 | async def select_scalar( 43 | executor: gel.AsyncIOExecutor, 44 | ) -> int: 45 | return await executor.query_single( 46 | """\ 47 | select 1;\ 48 | """, 49 | ) 50 | 51 | 52 | async def test_linked( 53 | executor: gel.AsyncIOExecutor, 54 | ) -> int: 55 | return await executor.query_single( 56 | """\ 57 | select 42\ 58 | """, 59 | ) 60 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/linked: -------------------------------------------------------------------------------- 1 | ../linked/ -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_optional_json.edgeql: -------------------------------------------------------------------------------- 1 | create type TestCase { 2 | create link snake_case -> TestCase; 3 | }; 4 | 5 | select ($0, TestCase {snake_case}); 6 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_optional_json_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'select_optional_json.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import uuid 9 | 10 | 11 | class NoPydanticValidation: 12 | @classmethod 13 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 14 | # Pydantic 2.x 15 | from pydantic_core.core_schema import any_schema 16 | return any_schema() 17 | 18 | @classmethod 19 | def __get_validators__(cls): 20 | # Pydantic 1.x 21 | from pydantic.dataclasses import dataclass as pydantic_dataclass 22 | _ = pydantic_dataclass(cls) 23 | cls.__pydantic_model__.__get_validators__ = lambda: [] 24 | return [] 25 | 26 | 27 | @dataclasses.dataclass 28 | class SelectOptionalJsonResultItem(NoPydanticValidation): 29 | id: uuid.UUID 30 | snake_case: SelectOptionalJsonResultItemSnakeCase | None 31 | 32 | 33 | @dataclasses.dataclass 34 | class SelectOptionalJsonResultItemSnakeCase(NoPydanticValidation): 35 | id: uuid.UUID 36 | 37 | 38 | async def select_optional_json( 39 | executor: gel.AsyncIOExecutor, 40 | arg0: str | None, 41 | ) -> list[tuple[str, SelectOptionalJsonResultItem]]: 42 | return await executor.query( 43 | """\ 44 | create type TestCase { 45 | create link snake_case -> TestCase; 46 | }; 47 | 48 | select ($0, TestCase {snake_case});\ 49 | """, 50 | arg0, 51 | ) 52 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_optional_json_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'select_optional_json.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import typing 9 | import uuid 10 | 11 | 12 | @dataclasses.dataclass 13 | class SelectOptionalJsonResultItem: 14 | id: uuid.UUID 15 | snake_case: typing.Optional[SelectOptionalJsonResultItemSnakeCase] 16 | 17 | 18 | @dataclasses.dataclass 19 | class SelectOptionalJsonResultItemSnakeCase: 20 | id: uuid.UUID 21 | 22 | 23 | def select_optional_json( 24 | executor: gel.Executor, 25 | arg0: typing.Optional[str], 26 | ) -> list[tuple[str, SelectOptionalJsonResultItem]]: 27 | return executor.query( 28 | """\ 29 | create type TestCase { 30 | create link snake_case -> TestCase; 31 | }; 32 | 33 | select ($0, TestCase {snake_case});\ 34 | """, 35 | arg0, 36 | ) 37 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_scalar.edgeql: -------------------------------------------------------------------------------- 1 | select 1; 2 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_scalar_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'select_scalar.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | async def select_scalar( 10 | executor: gel.AsyncIOExecutor, 11 | ) -> int: 12 | return await executor.query_single( 13 | """\ 14 | select 1;\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project1/select_scalar_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'select_scalar.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | def select_scalar( 10 | executor: gel.Executor, 11 | ) -> int: 12 | return executor.query_single( 13 | """\ 14 | select 1;\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/argnames/query_one.edgeql: -------------------------------------------------------------------------------- 1 | select $arg_name_with_underscores 2 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/argnames/query_one_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'argnames/query_one.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | async def query_one( 10 | executor: gel.AsyncIOExecutor, 11 | *, 12 | arg_name_with_underscores: int, 13 | ) -> int: 14 | return await executor.query_single( 15 | """\ 16 | select $arg_name_with_underscores\ 17 | """, 18 | arg_name_with_underscores=arg_name_with_underscores, 19 | ) 20 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/argnames/query_one_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'argnames/query_one.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | def query_one( 10 | executor: gel.Executor, 11 | *, 12 | arg_name_with_underscores: int, 13 | ) -> int: 14 | return executor.query_single( 15 | """\ 16 | select $arg_name_with_underscores\ 17 | """, 18 | arg_name_with_underscores=arg_name_with_underscores, 19 | ) 20 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/dbschema/migrations/00001.edgeqll: -------------------------------------------------------------------------------- 1 | CREATE MIGRATION m1fqtauhtvc2w56wh2676x5g26aye22ghx7b7mtnbfekxpmxmnjx2a 2 | ONTO initial 3 | { 4 | CREATE TYPE default::Person { 5 | CREATE MULTI LINK friends -> default::Person { 6 | CREATE PROPERTY strength -> std::float64; 7 | }; 8 | CREATE REQUIRED PROPERTY name -> std::str { 9 | CREATE CONSTRAINT std::exclusive; 10 | }; 11 | }; 12 | }; 13 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/edgedb.toml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/geldata/gel-python/1f4065e646ca4d1edfdb10627568ab4d79e38d7a/tests/codegen/test-project2/edgedb.toml -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/link_prop.edgeql: -------------------------------------------------------------------------------- 1 | create type Person { 2 | create required property name -> str; 3 | create property created_at -> datetime; 4 | create multi link friends -> Person { 5 | create property strength -> float64; 6 | create property created_at -> datetime; 7 | } 8 | }; 9 | 10 | select Person { 11 | name, 12 | friends: { 13 | name, 14 | @created_at, 15 | created_at, 16 | @strength, 17 | } 18 | }; 19 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/link_prop_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/link_prop.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | import typing 10 | import uuid 11 | 12 | 13 | class NoPydanticValidation: 14 | @classmethod 15 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 16 | # Pydantic 2.x 17 | from pydantic_core.core_schema import any_schema 18 | return any_schema() 19 | 20 | @classmethod 21 | def __get_validators__(cls): 22 | # Pydantic 1.x 23 | from pydantic.dataclasses import dataclass as pydantic_dataclass 24 | _ = pydantic_dataclass(cls) 25 | cls.__pydantic_model__.__get_validators__ = lambda: [] 26 | return [] 27 | 28 | 29 | @dataclasses.dataclass 30 | class LinkPropResult(NoPydanticValidation): 31 | id: uuid.UUID 32 | name: str 33 | friends: list[LinkPropResultFriendsItem] 34 | 35 | 36 | @dataclasses.dataclass 37 | class LinkPropResultFriendsItem(NoPydanticValidation): 38 | id: uuid.UUID 39 | name: str 40 | created_at: datetime.datetime | None 41 | 42 | @typing.overload 43 | def __getitem__(self, key: typing.Literal["@created_at"]) -> datetime.datetime | None: 44 | ... 45 | 46 | @typing.overload 47 | def __getitem__(self, key: typing.Literal["@strength"]) -> float | None: 48 | ... 49 | 50 | def __getitem__(self, key: str) -> typing.Any: 51 | raise NotImplementedError 52 | 53 | 54 | async def link_prop( 55 | executor: gel.AsyncIOExecutor, 56 | ) -> list[LinkPropResult]: 57 | return await executor.query( 58 | """\ 59 | create type Person { 60 | create required property name -> str; 61 | create property created_at -> datetime; 62 | create multi link friends -> Person { 63 | create property strength -> float64; 64 | create property created_at -> datetime; 65 | } 66 | }; 67 | 68 | select Person { 69 | name, 70 | friends: { 71 | name, 72 | @created_at, 73 | created_at, 74 | @strength, 75 | } 76 | };\ 77 | """, 78 | ) 79 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/link_prop_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/link_prop.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | import typing 10 | import uuid 11 | 12 | 13 | @dataclasses.dataclass 14 | class LinkPropResult: 15 | id: uuid.UUID 16 | name: str 17 | friends: list[LinkPropResultFriendsItem] 18 | 19 | 20 | @dataclasses.dataclass 21 | class LinkPropResultFriendsItem: 22 | id: uuid.UUID 23 | name: str 24 | created_at: typing.Optional[datetime.datetime] 25 | 26 | @typing.overload 27 | def __getitem__(self, key: typing.Literal["@created_at"]) -> typing.Optional[datetime.datetime]: 28 | ... 29 | 30 | @typing.overload 31 | def __getitem__(self, key: typing.Literal["@strength"]) -> typing.Optional[float]: 32 | ... 33 | 34 | def __getitem__(self, key: str) -> typing.Any: 35 | raise NotImplementedError 36 | 37 | 38 | def link_prop( 39 | executor: gel.Executor, 40 | ) -> list[LinkPropResult]: 41 | return executor.query( 42 | """\ 43 | create type Person { 44 | create required property name -> str; 45 | create property created_at -> datetime; 46 | create multi link friends -> Person { 47 | create property strength -> float64; 48 | create property created_at -> datetime; 49 | } 50 | }; 51 | 52 | select Person { 53 | name, 54 | friends: { 55 | name, 56 | @created_at, 57 | created_at, 58 | @strength, 59 | } 60 | };\ 61 | """, 62 | ) 63 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_object.edgeql: -------------------------------------------------------------------------------- 1 | select schema::Function { 2 | Name := .name, 3 | Language := .language, 4 | Params := .params { 5 | Name := .name, 6 | Default := .default, 7 | } 8 | } 9 | limit 1; 10 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_object_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/select_object.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import uuid 9 | 10 | 11 | class NoPydanticValidation: 12 | @classmethod 13 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 14 | # Pydantic 2.x 15 | from pydantic_core.core_schema import any_schema 16 | return any_schema() 17 | 18 | @classmethod 19 | def __get_validators__(cls): 20 | # Pydantic 1.x 21 | from pydantic.dataclasses import dataclass as pydantic_dataclass 22 | _ = pydantic_dataclass(cls) 23 | cls.__pydantic_model__.__get_validators__ = lambda: [] 24 | return [] 25 | 26 | 27 | @dataclasses.dataclass 28 | class SelectObjectResult(NoPydanticValidation): 29 | id: uuid.UUID 30 | Name: str 31 | Language: str 32 | Params: list[SelectObjectResultParamsItem] 33 | 34 | 35 | @dataclasses.dataclass 36 | class SelectObjectResultParamsItem(NoPydanticValidation): 37 | id: uuid.UUID 38 | Name: str 39 | Default: str | None 40 | 41 | 42 | async def select_object( 43 | executor: gel.AsyncIOExecutor, 44 | ) -> SelectObjectResult | None: 45 | return await executor.query_single( 46 | """\ 47 | select schema::Function { 48 | Name := .name, 49 | Language := .language, 50 | Params := .params { 51 | Name := .name, 52 | Default := .default, 53 | } 54 | } 55 | limit 1;\ 56 | """, 57 | ) 58 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_object_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/select_object.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import typing 9 | import uuid 10 | 11 | 12 | @dataclasses.dataclass 13 | class SelectObjectResult: 14 | id: uuid.UUID 15 | Name: str 16 | Language: str 17 | Params: list[SelectObjectResultParamsItem] 18 | 19 | 20 | @dataclasses.dataclass 21 | class SelectObjectResultParamsItem: 22 | id: uuid.UUID 23 | Name: str 24 | Default: typing.Optional[str] 25 | 26 | 27 | def select_object( 28 | executor: gel.Executor, 29 | ) -> typing.Optional[SelectObjectResult]: 30 | return executor.query_single( 31 | """\ 32 | select schema::Function { 33 | Name := .name, 34 | Language := .language, 35 | Params := .params { 36 | Name := .name, 37 | Default := .default, 38 | } 39 | } 40 | limit 1;\ 41 | """, 42 | ) 43 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_objects.edgeql: -------------------------------------------------------------------------------- 1 | select schema::Function { 2 | Name := .name, 3 | Language := .language, 4 | Params := .params { 5 | Name := .name, 6 | Default := .default, 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_objects_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/select_objects.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import uuid 9 | 10 | 11 | class NoPydanticValidation: 12 | @classmethod 13 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 14 | # Pydantic 2.x 15 | from pydantic_core.core_schema import any_schema 16 | return any_schema() 17 | 18 | @classmethod 19 | def __get_validators__(cls): 20 | # Pydantic 1.x 21 | from pydantic.dataclasses import dataclass as pydantic_dataclass 22 | _ = pydantic_dataclass(cls) 23 | cls.__pydantic_model__.__get_validators__ = lambda: [] 24 | return [] 25 | 26 | 27 | @dataclasses.dataclass 28 | class SelectObjectsResult(NoPydanticValidation): 29 | id: uuid.UUID 30 | Name: str 31 | Language: str 32 | Params: list[SelectObjectsResultParamsItem] 33 | 34 | 35 | @dataclasses.dataclass 36 | class SelectObjectsResultParamsItem(NoPydanticValidation): 37 | id: uuid.UUID 38 | Name: str 39 | Default: str | None 40 | 41 | 42 | async def select_objects( 43 | executor: gel.AsyncIOExecutor, 44 | ) -> list[SelectObjectsResult]: 45 | return await executor.query( 46 | """\ 47 | select schema::Function { 48 | Name := .name, 49 | Language := .language, 50 | Params := .params { 51 | Name := .name, 52 | Default := .default, 53 | } 54 | }\ 55 | """, 56 | ) 57 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/object/select_objects_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'object/select_objects.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import gel 8 | import typing 9 | import uuid 10 | 11 | 12 | @dataclasses.dataclass 13 | class SelectObjectsResult: 14 | id: uuid.UUID 15 | Name: str 16 | Language: str 17 | Params: list[SelectObjectsResultParamsItem] 18 | 19 | 20 | @dataclasses.dataclass 21 | class SelectObjectsResultParamsItem: 22 | id: uuid.UUID 23 | Name: str 24 | Default: typing.Optional[str] 25 | 26 | 27 | def select_objects( 28 | executor: gel.Executor, 29 | ) -> list[SelectObjectsResult]: 30 | return executor.query( 31 | """\ 32 | select schema::Function { 33 | Name := .name, 34 | Language := .language, 35 | Params := .params { 36 | Name := .name, 37 | Default := .default, 38 | } 39 | }\ 40 | """, 41 | ) 42 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args.edgeql: -------------------------------------------------------------------------------- 1 | select { 2 | Str := $arg_str, 3 | DateTime := $arg_datetime, 4 | } 5 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'parpkg/select_args.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | 10 | 11 | class NoPydanticValidation: 12 | @classmethod 13 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 14 | # Pydantic 2.x 15 | from pydantic_core.core_schema import any_schema 16 | return any_schema() 17 | 18 | @classmethod 19 | def __get_validators__(cls): 20 | # Pydantic 1.x 21 | from pydantic.dataclasses import dataclass as pydantic_dataclass 22 | _ = pydantic_dataclass(cls) 23 | cls.__pydantic_model__.__get_validators__ = lambda: [] 24 | return [] 25 | 26 | 27 | @dataclasses.dataclass 28 | class SelectArgsResult(NoPydanticValidation): 29 | Str: str 30 | DateTime: datetime.datetime 31 | 32 | 33 | async def select_args( 34 | executor: gel.AsyncIOExecutor, 35 | *, 36 | arg_str: str, 37 | arg_datetime: datetime.datetime, 38 | ) -> SelectArgsResult: 39 | return await executor.query_single( 40 | """\ 41 | select { 42 | Str := $arg_str, 43 | DateTime := $arg_datetime, 44 | }\ 45 | """, 46 | arg_str=arg_str, 47 | arg_datetime=arg_datetime, 48 | ) 49 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_async_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | select_args_async_edgeql.py.assert5 -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_async_edgeql.py.assert5: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'parpkg/select_args.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | import uuid 10 | 11 | 12 | class NoPydanticValidation: 13 | @classmethod 14 | def __get_pydantic_core_schema__(cls, _source_type, _handler): 15 | # Pydantic 2.x 16 | from pydantic_core.core_schema import any_schema 17 | return any_schema() 18 | 19 | @classmethod 20 | def __get_validators__(cls): 21 | # Pydantic 1.x 22 | from pydantic.dataclasses import dataclass as pydantic_dataclass 23 | _ = pydantic_dataclass(cls) 24 | cls.__pydantic_model__.__get_validators__ = lambda: [] 25 | return [] 26 | 27 | 28 | @dataclasses.dataclass 29 | class SelectArgsResult(NoPydanticValidation): 30 | id: uuid.UUID 31 | Str: str 32 | DateTime: datetime.datetime 33 | 34 | 35 | async def select_args( 36 | executor: gel.AsyncIOExecutor, 37 | *, 38 | arg_str: str, 39 | arg_datetime: datetime.datetime, 40 | ) -> SelectArgsResult: 41 | return await executor.query_single( 42 | """\ 43 | select { 44 | Str := $arg_str, 45 | DateTime := $arg_datetime, 46 | }\ 47 | """, 48 | arg_str=arg_str, 49 | arg_datetime=arg_datetime, 50 | ) 51 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'parpkg/select_args.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | 10 | 11 | @dataclasses.dataclass 12 | class SelectArgsResult: 13 | Str: str 14 | DateTime: datetime.datetime 15 | 16 | 17 | def select_args( 18 | executor: gel.Executor, 19 | *, 20 | arg_str: str, 21 | arg_datetime: datetime.datetime, 22 | ) -> SelectArgsResult: 23 | return executor.query_single( 24 | """\ 25 | select { 26 | Str := $arg_str, 27 | DateTime := $arg_datetime, 28 | }\ 29 | """, 30 | arg_str=arg_str, 31 | arg_datetime=arg_datetime, 32 | ) 33 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | select_args_edgeql.py.assert5 -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/select_args_edgeql.py.assert5: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'parpkg/select_args.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import dataclasses 7 | import datetime 8 | import gel 9 | import uuid 10 | 11 | 12 | @dataclasses.dataclass 13 | class SelectArgsResult: 14 | id: uuid.UUID 15 | Str: str 16 | DateTime: datetime.datetime 17 | 18 | 19 | def select_args( 20 | executor: gel.Executor, 21 | *, 22 | arg_str: str, 23 | arg_datetime: datetime.datetime, 24 | ) -> SelectArgsResult: 25 | return executor.query_single( 26 | """\ 27 | select { 28 | Str := $arg_str, 29 | DateTime := $arg_datetime, 30 | }\ 31 | """, 32 | arg_str=arg_str, 33 | arg_datetime=arg_datetime, 34 | ) 35 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/subpkg/my_query.edgeql: -------------------------------------------------------------------------------- 1 | create scalar type MyScalar extending int64; 2 | create scalar type MyEnum extending enum<'This', 'That', '1', 'f. b', 'f-b'>; 3 | 4 | select { 5 | a := $a, 6 | b := $b, 7 | c := $c, 8 | d := $d, 9 | e := $e, 10 | f := $f, 11 | g := $g, 12 | h := $h, 13 | i := $i, 14 | j := $j, 15 | k := $k, 16 | l := $l, 17 | m := $m, 18 | n := $n, 19 | o := $o, 20 | p := $p, 21 | q := $q, 22 | r := $r, 23 | s := $s, 24 | t := $t, 25 | u := $u, 26 | v := $v, 27 | w := $w, 28 | x := $x, 29 | y := $y, 30 | z := $z, 31 | aa := $aa, 32 | ab := $ab, 33 | ac := $ac, 34 | ad := $ad, 35 | ae := $ae, 36 | af := $af, 37 | ag := $ag, 38 | ah := $ah, 39 | ai := $ai, 40 | aj := $aj, 41 | ak := >$ak, 42 | al := >$al, 43 | am := >$am, 44 | an := >$an, 45 | ao := >$ao, 46 | ap := >$ap, 47 | aq := >$aq, 48 | ar := >$ar, 49 | as_ := >$as_, 50 | at := >$at, 51 | au := >$au, 52 | av := >$av, 53 | aw := >$aw, 54 | ax := >$ax, 55 | ay := 1, 56 | az := {}, 57 | ba := MyEnum.This, 58 | bb := {}, 59 | bc := $bc, 60 | bd := $bd, 61 | } 62 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/subpkg/my_query_async_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | my_query_async_edgeql.py.assert5 -------------------------------------------------------------------------------- /tests/codegen/test-project2/parpkg/subpkg/my_query_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | my_query_edgeql.py.assert5 -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/custom_vector_input.edgeql: -------------------------------------------------------------------------------- 1 | select 42 filter exists $input; 2 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/custom_vector_input_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/custom_vector_input.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | import typing 8 | 9 | 10 | V3 = typing.Sequence[float] 11 | 12 | 13 | async def custom_vector_input( 14 | executor: gel.AsyncIOExecutor, 15 | *, 16 | input: V3 | None = None, 17 | ) -> int | None: 18 | return await executor.query_single( 19 | """\ 20 | select 42 filter exists $input;\ 21 | """, 22 | input=input, 23 | ) 24 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/custom_vector_input_async_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/custom_vector_input.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | import typing 8 | 9 | 10 | Input = typing.Sequence[float] 11 | 12 | 13 | async def custom_vector_input( 14 | executor: gel.AsyncIOExecutor, 15 | *, 16 | input: Input | None = None, 17 | ) -> int | None: 18 | return await executor.query_single( 19 | """\ 20 | select 42 filter exists $input;\ 21 | """, 22 | input=input, 23 | ) 24 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/custom_vector_input_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/custom_vector_input.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | import typing 8 | 9 | 10 | V3 = typing.Sequence[float] 11 | 12 | 13 | def custom_vector_input( 14 | executor: gel.Executor, 15 | *, 16 | input: typing.Optional[V3] = None, 17 | ) -> typing.Optional[int]: 18 | return executor.query_single( 19 | """\ 20 | select 42 filter exists $input;\ 21 | """, 22 | input=input, 23 | ) 24 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/custom_vector_input_edgeql.py.assert3: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/custom_vector_input.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | import typing 8 | 9 | 10 | Input = typing.Sequence[float] 11 | 12 | 13 | def custom_vector_input( 14 | executor: gel.Executor, 15 | *, 16 | input: typing.Optional[Input] = None, 17 | ) -> typing.Optional[int]: 18 | return executor.query_single( 19 | """\ 20 | select 42 filter exists $input;\ 21 | """, 22 | input=input, 23 | ) 24 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalar.edgeql: -------------------------------------------------------------------------------- 1 | select 1; 2 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalar_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/select_scalar.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | async def select_scalar( 10 | executor: gel.AsyncIOExecutor, 11 | ) -> int: 12 | return await executor.query_single( 13 | """\ 14 | select 1;\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalar_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/select_scalar.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | def select_scalar( 10 | executor: gel.Executor, 11 | ) -> int: 12 | return executor.query_single( 13 | """\ 14 | select 1;\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalars.edgeql: -------------------------------------------------------------------------------- 1 | select {1, 2, 3}; 2 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalars_async_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/select_scalars.edgeql' WITH: 2 | # $ gel-py 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | async def select_scalars( 10 | executor: gel.AsyncIOExecutor, 11 | ) -> list[gel.ConfigMemory]: 12 | return await executor.query( 13 | """\ 14 | select {1, 2, 3};\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/codegen/test-project2/scalar/select_scalars_edgeql.py.assert: -------------------------------------------------------------------------------- 1 | # AUTOGENERATED FROM 'scalar/select_scalars.edgeql' WITH: 2 | # $ gel-py --target blocking --no-skip-pydantic-validation 3 | 4 | 5 | from __future__ import annotations 6 | import gel 7 | 8 | 9 | def select_scalars( 10 | executor: gel.Executor, 11 | ) -> list[gel.ConfigMemory]: 12 | return executor.query( 13 | """\ 14 | select {1, 2, 3};\ 15 | """, 16 | ) 17 | -------------------------------------------------------------------------------- /tests/credentials1.json: -------------------------------------------------------------------------------- 1 | { 2 | "port": 10702, 3 | "user": "test3n", 4 | "password": "lZTBy1RVCfOpBAOwSCwIyBIR", 5 | "database": "test3n" 6 | } 7 | -------------------------------------------------------------------------------- /tests/datatypes/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | -------------------------------------------------------------------------------- /tests/dbsetup/base.edgeql: -------------------------------------------------------------------------------- 1 | insert User {name := 'Alice'}; 2 | insert User {name := 'Billie'}; 3 | insert User {name := 'Cameron'}; 4 | insert User {name := 'Dana'}; 5 | insert User {name := 'Elsa'}; 6 | insert User {name := 'Zoe'}; 7 | 8 | insert UserGroup { 9 | name := 'red', 10 | users := (select User filter .name not in {'Elsa', 'Zoe'}), 11 | }; 12 | insert UserGroup { 13 | name := 'green', 14 | users := (select User filter .name in {'Alice', 'Billie'}), 15 | }; 16 | insert UserGroup { 17 | name := 'blue', 18 | }; 19 | 20 | insert GameSession { 21 | num := 123, 22 | players := (select User filter .name in {'Alice', 'Billie'}), 23 | }; 24 | insert GameSession { 25 | num := 456, 26 | players := (select User filter .name in {'Dana'}), 27 | }; 28 | 29 | insert Post { 30 | author := assert_single((select User filter .name = 'Alice')), 31 | body := 'Hello', 32 | }; 33 | insert Post { 34 | author := assert_single((select User filter .name = 'Alice')), 35 | body := "I'm Alice", 36 | }; 37 | insert Post { 38 | author := assert_single((select User filter .name = 'Cameron')), 39 | body := "I'm Cameron", 40 | }; 41 | insert Post { 42 | author := assert_single((select User filter .name = 'Elsa')), 43 | body := '*magic stuff*', 44 | }; 45 | 46 | insert AssortedScalars { 47 | name:= 'hello world', 48 | vals := ['brown', 'fox'], 49 | bstr := b'word\x00\x0b', 50 | time := '20:13:45.678', 51 | date:= '2025-01-26', 52 | ts:='2025-01-26T20:13:45+00:00', 53 | lts:='2025-01-26T20:13:45', 54 | }; -------------------------------------------------------------------------------- /tests/dbsetup/base.esdl: -------------------------------------------------------------------------------- 1 | abstract type Named { 2 | required name: str; 3 | nickname: str; 4 | } 5 | 6 | type UserGroup extending Named { 7 | # many-to-many 8 | multi link users: User; 9 | } 10 | 11 | type GameSession { 12 | required num: int64; 13 | # one-to-many 14 | multi link players: User { 15 | constraint exclusive; 16 | property is_tall_enough: bool; 17 | }; 18 | } 19 | 20 | type User extending Named { 21 | # test computed backlink 22 | groups := .; 33 | 34 | date: cal::local_date; 35 | time: cal::local_time; 36 | ts: datetime; 37 | lts: cal::local_datetime; 38 | bstr: bytes; 39 | } 40 | -------------------------------------------------------------------------------- /tests/dbsetup/features.edgeql: -------------------------------------------------------------------------------- 1 | insert Child {num := 0}; 2 | insert Child {num := 1}; 3 | 4 | insert HasLinkPropsA { 5 | child := (select Child{@a := 'single'} filter .num = 0) 6 | }; 7 | 8 | insert HasLinkPropsB; 9 | update HasLinkPropsB 10 | set { 11 | children += (select Child{@b := 'hello'} filter .num = 0) 12 | }; 13 | update HasLinkPropsB 14 | set { 15 | children += (select Child{@b := 'world'} filter .num = 1) 16 | }; 17 | 18 | insert MultiProp { 19 | name := 'got one', 20 | tags := {'solo tag'}, 21 | }; 22 | 23 | insert MultiProp { 24 | name := 'got many', 25 | tags := {'one', 'two', 'three'}, 26 | }; 27 | 28 | insert other::nested::Leaf { 29 | num := 10 30 | }; 31 | 32 | insert other::nested::Leaf { 33 | num := 20 34 | }; 35 | 36 | insert other::nested::Leaf { 37 | num := 30 38 | }; 39 | 40 | insert other::Branch { 41 | val := 'big', 42 | leaves := (select other::nested::Leaf filter .num != 10), 43 | }; 44 | 45 | insert other::Branch { 46 | val := 'small', 47 | leaves := (select other::nested::Leaf filter .num = 10), 48 | }; 49 | 50 | insert Theme { 51 | color := 'green', 52 | branch := ( 53 | select other::Branch{@note := 'fresh'} filter .val = 'big' 54 | ) 55 | }; 56 | 57 | insert Theme { 58 | color := 'orange', 59 | branch := ( 60 | select other::Branch{@note := 'fall'} filter .val = 'big' 61 | ) 62 | }; 63 | 64 | insert Foo { 65 | name := 'foo' 66 | }; 67 | 68 | insert Foo { 69 | name := 'oof' 70 | }; 71 | 72 | insert Bar { 73 | n := 123, 74 | foo := assert_single((select Foo filter .name = 'foo')), 75 | many_foo := Foo, 76 | }; 77 | 78 | insert Who { 79 | x := 456, 80 | foo := assert_single((select Foo filter .name = 'oof')), 81 | many_foo := (select Foo{@note := 'just one'} filter .name = 'foo'), 82 | }; -------------------------------------------------------------------------------- /tests/dbsetup/features_default.esdl: -------------------------------------------------------------------------------- 1 | type Child { 2 | required property num: int64 { 3 | constraint exclusive; 4 | } 5 | }; 6 | 7 | type HasLinkPropsA { 8 | link child: Child { 9 | property a: str; 10 | } 11 | }; 12 | 13 | type HasLinkPropsB { 14 | multi link children: Child { 15 | property b: str; 16 | } 17 | }; 18 | 19 | type MultiProp { 20 | required property name: str; 21 | multi property tags: str; 22 | }; 23 | 24 | type Theme { 25 | required property color: str; 26 | link branch: other::Branch { 27 | property note: str; 28 | } 29 | }; 30 | 31 | type Foo { 32 | required property name: str; 33 | }; 34 | 35 | type Bar { 36 | link foo: Foo; 37 | multi link many_foo: Foo; 38 | required property n: int64; 39 | }; 40 | 41 | type Who { 42 | link foo: Foo; 43 | multi link many_foo: Foo { 44 | property note: str; 45 | }; 46 | required property x: int64; 47 | }; 48 | -------------------------------------------------------------------------------- /tests/dbsetup/features_other.esdl: -------------------------------------------------------------------------------- 1 | type Branch { 2 | required property val: str { 3 | constraint exclusive; 4 | } 5 | 6 | multi link leaves: other::nested::Leaf; 7 | }; 8 | -------------------------------------------------------------------------------- /tests/dbsetup/features_other_nested.esdl: -------------------------------------------------------------------------------- 1 | type Leaf { 2 | required property num: int64 { 3 | constraint exclusive; 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /tests/dbsetup/orm.edgeql: -------------------------------------------------------------------------------- 1 | insert User {name := 'Alice'}; 2 | insert User {name := 'Billie'}; 3 | insert User {name := 'Cameron'}; 4 | insert User {name := 'Dana'}; 5 | insert User {name := 'Elsa'}; 6 | insert User {name := 'Zoe'}; 7 | 8 | insert UserGroup { 9 | name := 'red', 10 | users := (select User filter .name not in {'Elsa', 'Zoe'}), 11 | }; 12 | insert UserGroup { 13 | name := 'green', 14 | users := (select User filter .name in {'Alice', 'Billie'}), 15 | }; 16 | insert UserGroup { 17 | name := 'blue', 18 | }; 19 | 20 | insert GameSession { 21 | num := 123, 22 | players := (select User filter .name in {'Alice', 'Billie'}), 23 | }; 24 | insert GameSession { 25 | num := 456, 26 | players := (select User filter .name in {'Dana'}), 27 | }; 28 | 29 | insert Post { 30 | author := assert_single((select User filter .name = 'Alice')), 31 | body := 'Hello', 32 | }; 33 | insert Post { 34 | author := assert_single((select User filter .name = 'Alice')), 35 | body := "I'm Alice", 36 | }; 37 | insert Post { 38 | author := assert_single((select User filter .name = 'Cameron')), 39 | body := "I'm Cameron", 40 | }; 41 | insert Post { 42 | author := assert_single((select User filter .name = 'Elsa')), 43 | body := '*magic stuff*', 44 | }; 45 | 46 | insert AssortedScalars { 47 | name:= 'hello world', 48 | vals := ['brown', 'fox'], 49 | bstr := b'word\x00\x0b', 50 | time := '20:13:45.678', 51 | date:= '2025-01-26', 52 | ts:='2025-01-26T20:13:45+00:00', 53 | lts:='2025-01-26T20:13:45', 54 | }; 55 | -------------------------------------------------------------------------------- /tests/dbsetup/orm.gel: -------------------------------------------------------------------------------- 1 | abstract type Named { 2 | required name: str; 3 | name_len := len(.name); 4 | nickname: str; 5 | nickname_len := len(.nickname); 6 | } 7 | 8 | type UserGroup extending Named { 9 | # many-to-many 10 | multi link users: User; 11 | } 12 | 13 | type GameSession { 14 | required num: int64; 15 | # one-to-many 16 | multi link players: User { 17 | constraint exclusive; 18 | property is_tall_enough: bool; 19 | }; 20 | } 21 | 22 | type User extending Named { 23 | # test computed backlink 24 | groups := .; 35 | 36 | date: cal::local_date; 37 | time: cal::local_time; 38 | ts: datetime; 39 | lts: cal::local_datetime; 40 | bstr: bytes; 41 | } 42 | 43 | module sub { 44 | type TypeInSub { 45 | post: default::Post; 46 | subsub: default::sub::subsub::TypeInSubSub; 47 | ntup: tuple>; 48 | } 49 | 50 | module subsub { 51 | type TypeInSubSub; 52 | } 53 | } 54 | 55 | module emptysub { 56 | } 57 | -------------------------------------------------------------------------------- /tests/test_array.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | import unittest 20 | 21 | from gel import errors 22 | from gel import _testbase as tb 23 | 24 | 25 | class TestArrayOfArray(tb.SyncQueryTestCase): 26 | def setUp(self): 27 | super().setUp() 28 | 29 | try: 30 | self.client.query_required_single("select >>[]") 31 | except errors.UnsupportedFeatureError: 32 | raise unittest.SkipTest( 33 | "nested arrays unsupported by server" 34 | ) from None 35 | 36 | async def test_array_of_array_01(self): 37 | # basic array of array 38 | self.assertEqual( 39 | self.client.query_single( 40 | 'select >>[]' 41 | ), 42 | [], 43 | ) 44 | self.assertEqual( 45 | self.client.query_single( 46 | 'select [[1]]' 47 | ), 48 | [[1]], 49 | ) 50 | self.assertEqual( 51 | self.client.query_single( 52 | 'select [[[1]]]' 53 | ), 54 | [[[1]]], 55 | ) 56 | self.assertEqual( 57 | self.client.query_single( 58 | 'select [[[[1]]]]' 59 | ), 60 | [[[[1]]]], 61 | ) 62 | self.assertEqual( 63 | self.client.query_single( 64 | 'select [[1], [2, 3], [4, 5, 6, 7]]' 65 | ), 66 | [[1], [2, 3], [4, 5, 6, 7]], 67 | ) 68 | 69 | async def test_array_of_array_02(self): 70 | # check that array tuple array still works 71 | self.assertEqual( 72 | self.client.query_single( 73 | 'select [([1],)]' 74 | ), 75 | [([1],)], 76 | ) 77 | 78 | async def test_array_of_array_03(self): 79 | # check encoding array of array 80 | self.assertEqual( 81 | self.client.query_single( 82 | 'select >>$0', 83 | [[1]], 84 | ), 85 | [[1]], 86 | ) 87 | -------------------------------------------------------------------------------- /tests/test_errors.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import unittest 21 | 22 | 23 | from gel import errors 24 | from gel.errors import _base as base_errors 25 | 26 | 27 | class TestErrors(unittest.TestCase): 28 | 29 | def test_errors_1(self): 30 | new = base_errors.EdgeDBError._from_code 31 | 32 | e = new(0x_04_00_00_00, 'aa') 33 | self.assertIs(type(e), errors.QueryError) 34 | self.assertEqual(e.get_code(), 0x_04_00_00_00) 35 | 36 | e = new(0x_04_01_00_00, 'aa') 37 | self.assertIs(type(e), errors.InvalidSyntaxError) 38 | self.assertEqual(e.get_code(), 0x_04_01_00_00) 39 | 40 | e = new(0x_04_01_01_00, 'aa') 41 | self.assertIs(type(e), errors.EdgeQLSyntaxError) 42 | self.assertEqual(e.get_code(), 0x_04_01_01_00) 43 | 44 | e = new(0x_04_01_01_FF, 'aa') 45 | self.assertIs(type(e), errors.EdgeQLSyntaxError) 46 | self.assertEqual(e.get_code(), 0x_04_01_01_FF) 47 | 48 | e = new(0x_04_01_FF_FF, 'aa') 49 | self.assertIs(type(e), errors.InvalidSyntaxError) 50 | self.assertEqual(e.get_code(), 0x_04_01_FF_FF) 51 | 52 | e = new(0x_04_00_FF_FF, 'aa') 53 | self.assertIs(type(e), errors.QueryError) 54 | self.assertEqual(e.get_code(), 0x_04_00_FF_FF) 55 | 56 | def test_errors_2(self): 57 | new = base_errors.EdgeDBError._from_code 58 | 59 | e = new(0x_F9_1E_FF_F1, 'aa') 60 | self.assertEqual(e.get_code(), 0x_F9_1E_FF_F1) 61 | self.assertIs(type(e), errors.EdgeDBError) 62 | -------------------------------------------------------------------------------- /tests/test_memory.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | from gel import _testbase as tb 20 | 21 | 22 | class TestConfigMemory(tb.SyncQueryTestCase): 23 | 24 | async def test_config_memory_01(self): 25 | if ( 26 | self.client.query_required_single( 27 | "select exists " 28 | "(select schema::Type filter .name = 'cfg::memory')" 29 | ) is False 30 | ): 31 | self.skipTest("feature not implemented") 32 | 33 | mem_strs = [ 34 | "0B", 35 | "0GiB", 36 | "1024MiB", 37 | "9223372036854775807B", 38 | "123KiB", 39 | "9MiB", 40 | "102938GiB", 41 | "108TiB", 42 | "42PiB", 43 | ] 44 | 45 | # Test that ConfigMemory.__str__ formats the 46 | # same as 47 | mem_tuples = self.client.query(''' 48 | WITH args := array_unpack(>$0) 49 | SELECT ( 50 | args, 51 | args, 52 | args 53 | ); 54 | ''', mem_strs) 55 | 56 | mem_vals = [t[0] for t in mem_tuples] 57 | 58 | # Test encode/decode roundtrip 59 | roundtrip = self.client.query(''' 60 | WITH args := array_unpack(>$0) 61 | SELECT args; 62 | ''', mem_vals) 63 | 64 | self.assertEqual( 65 | [str(t[0]) for t in mem_tuples], 66 | [t[1] for t in mem_tuples] 67 | ) 68 | self.assertEqual( 69 | [t[0].as_bytes() for t in mem_tuples], 70 | [t[2] for t in mem_tuples] 71 | ) 72 | self.assertEqual(list(roundtrip), mem_vals) 73 | -------------------------------------------------------------------------------- /tests/test_namedtuples.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2019-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | from collections import namedtuple, UserDict 21 | 22 | import gel 23 | from gel import _testbase as tb 24 | 25 | 26 | class TestNamedTupleTypes(tb.SyncQueryTestCase): 27 | 28 | async def test_namedtuple_01(self): 29 | NT1 = namedtuple('NT2', ['x', 'y']) 30 | NT2 = namedtuple('NT2', ['y', 'x']) 31 | 32 | ctors = [dict, UserDict, NT1, NT2] 33 | for ctor in ctors: 34 | val = ctor(x=10, y='y') 35 | res = self.client.query_single(''' 36 | select >$0 37 | ''', val) 38 | 39 | self.assertEqual(res, (10, 'y')) 40 | 41 | async def test_namedtuple_02(self): 42 | NT1 = namedtuple('NT2', ['x', 'z']) 43 | 44 | with self.assertRaisesRegex(gel.InvalidArgumentError, 'is missing'): 45 | self.client.query_single(''' 46 | select >$0 47 | ''', dict(x=20, z='test')) 48 | 49 | with self.assertRaisesRegex(gel.InvalidArgumentError, 'is missing'): 50 | self.client.query_single(''' 51 | select >$0 52 | ''', NT1(x=20, z='test')) 53 | -------------------------------------------------------------------------------- /tools/gen_init.py: -------------------------------------------------------------------------------- 1 | # 2 | # This source file is part of the EdgeDB open source project. 3 | # 4 | # Copyright 2016-present MagicStack Inc. and the EdgeDB authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | 20 | import pathlib 21 | import re 22 | 23 | 24 | if __name__ == '__main__': 25 | this = pathlib.Path(__file__) 26 | 27 | errors_fn = this.parent.parent / 'gel' / 'errors' / '__init__.py' 28 | init_fn = this.parent.parent / 'gel' / '__init__.py' 29 | 30 | with open(errors_fn, 'rt') as f: 31 | errors_txt = f.read() 32 | 33 | names = re.findall(r'^class\s+(?P\w+)', errors_txt, re.M) 34 | names.sort() 35 | names_list = '\n'.join(f' {name},' for name in names) 36 | all_list = '\n'.join(f' "{name}",' for name in names) 37 | code = ( 38 | f'''from .errors import (\n{names_list}\n)\n''' 39 | f'''\n__all__.extend(\n [\n{all_list}\n ]\n)\n''' 40 | ).splitlines() 41 | 42 | with open(init_fn, 'rt') as f: 43 | lines = f.read().splitlines() 44 | start = end = -1 45 | for no, line in enumerate(lines): 46 | if line.startswith('# '): 47 | start = no 48 | elif line.startswith('# '): 49 | end = no 50 | 51 | if start == -1: 52 | raise RuntimeError('could not find the tag') 53 | 54 | if end == -1: 55 | raise RuntimeError('could not find the tag') 56 | 57 | lines[start + 1:end] = code 58 | 59 | with open(init_fn, 'w') as f: 60 | f.write('\n'.join(lines)) 61 | f.write('\n') 62 | -------------------------------------------------------------------------------- /tools/make_import_shims.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | MODS = sorted(['gel', 'gel._version', 'gel.abstract', 'gel.ai', 'gel.ai.core', 'gel.ai.types', 'gel.asyncio_client', 'gel.base_client', 'gel.blocking_client', 'gel.codegen', 'gel.con_utils', 'gel.credentials', 'gel.datatypes', 'gel.datatypes.datatypes', 'gel.datatypes.range', 'gel.describe', 'gel.enums', 'gel.errors', 'gel.errors._base', 'gel.errors.tags', 'gel.introspect', 'gel.options', 'gel.pgproto', 'gel.pgproto.pgproto', 'gel.pgproto.types', 'gel.protocol', 'gel.protocol.asyncio_proto', 'gel.protocol.blocking_proto', 'gel.protocol.protocol', 'gel.scram', 'gel.scram.saslprep', 'gel.transaction']) 4 | COMPAT = { 5 | 'gel.ai': { 6 | 'create_ai': 'create_rag_client', 7 | 'EdgeDBAI': 'RAGClient', 8 | 'create_async_ai': 'create_async_rag_client', 9 | 'AsyncEdgeDBAI': 'AsyncRAGClient', 10 | 'AIOptions': 'RAGOptions', 11 | }, 12 | } 13 | 14 | 15 | def main(): 16 | for mod in MODS: 17 | is_package = any(k.startswith(mod + '.') for k in MODS) 18 | 19 | nmod = 'edgedb' + mod[len('gel'):] 20 | slash_name = nmod.replace('.', '/') 21 | if is_package: 22 | try: 23 | os.mkdir(slash_name) 24 | except FileExistsError: 25 | pass 26 | fname = slash_name + '/__init__.py' 27 | else: 28 | fname = slash_name + '.py' 29 | 30 | # import * skips things not in __all__ or with underscores at 31 | # the start, so we have to do some nonsense. 32 | with open(fname, 'w') as f: 33 | f.write(f'''\ 34 | # Auto-generated shim 35 | TYPE_CHECKING = False 36 | if TYPE_CHECKING: 37 | from {mod} import * # noqa 38 | ''') 39 | if mod in COMPAT: 40 | for k, v in COMPAT[mod].items(): 41 | f.write(f' {k} = {v} # noqa\n') 42 | f.write(f'''\ 43 | import {mod} as _mod 44 | import sys as _sys 45 | _cur = _sys.modules['{nmod}'] 46 | for _k in vars(_mod): 47 | if not _k.startswith('__') or _k in ('__all__', '__doc__'): 48 | setattr(_cur, _k, getattr(_mod, _k)) 49 | ''') 50 | if mod in COMPAT: 51 | for k, v in COMPAT[mod].items(): 52 | f.write(f"_cur.{k} = _mod.{v}\n") 53 | f.write(f'''\ 54 | if hasattr(_cur, '__all__'): 55 | _cur.__all__ = _cur.__all__ + [ 56 | {',\n '.join(repr(k) for k in COMPAT[mod])}, 57 | ] 58 | ''') 59 | f.write(f'''\ 60 | del _cur 61 | del _sys 62 | del _mod 63 | del _k 64 | ''') 65 | 66 | with open('edgedb/py.typed', 'w') as f: 67 | pass 68 | 69 | 70 | if __name__ == '__main__': 71 | main() 72 | --------------------------------------------------------------------------------