{"id":14976250,"url":"https://github.com/valiot/pygqlc","last_synced_at":"2025-10-27T18:30:51.962Z","repository":{"id":35093318,"uuid":"205574241","full_name":"valiot/pygqlc","owner":"valiot","description":"Python GraphQL Client - PyGQLC","archived":false,"fork":false,"pushed_at":"2025-01-25T21:58:09.000Z","size":6228,"stargazers_count":12,"open_issues_count":1,"forks_count":4,"subscribers_count":13,"default_branch":"main","last_synced_at":"2025-02-05T21:35:38.264Z","etag":null,"topics":["graphql-apis","graphql-client","mutations","python","python-client","queries","subscriptions"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/valiot.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-31T17:15:04.000Z","updated_at":"2025-01-25T21:32:21.000Z","dependencies_parsed_at":"2024-09-14T20:29:53.283Z","dependency_job_id":"a08aa247-03f3-4899-9984-7bea469fb872","html_url":"https://github.com/valiot/pygqlc","commit_stats":{"total_commits":127,"total_committers":10,"mean_commits":12.7,"dds":0.5196850393700787,"last_synced_commit":"0852510c149ae74c08b0ca1f2380369c415421c1"},"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fpygqlc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fpygqlc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fpygqlc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/valiot%2Fpygqlc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/valiot","download_url":"https://codeload.github.com/valiot/pygqlc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":238536146,"owners_count":19488666,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["graphql-apis","graphql-client","mutations","python","python-client","queries","subscriptions"],"created_at":"2024-09-24T13:53:34.597Z","updated_at":"2025-10-27T18:30:51.957Z","avatar_url":"https://github.com/valiot.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pygqlc\n\nPython client for graphql APIs\n\n### Scope\n\nThis is an open source project, please feel free to fork it and PR to contribute with the community!\nRepo for the project: https://github.com/valiot/pygqlc\n\n### Features\n\n- Fast and efficient GraphQL client\n- Support for queries, mutations, and subscriptions\n- Async capabilities for modern Python applications\n- Connection pooling for better performance\n- IPv4/IPv6 network flexibility\n- Intelligent error handling and reporting\n- Easy-to-use API with minimal boilerplate\n- Optional structured logging with valiotlogging\n\n### Installation\n\nRequirements:\n\n- Python 3.9+\n- Pipenv\n\nInstall directly from pypi:\n\n```\n$ cd \u003cmy-project-dir\u003e\n$ pipenv --python 3.7 # or 3.6\n$ pipenv shell\n$ pipenv install pygqlc\n$ python\n$ \u003e\u003e import pygqlc\n$ \u003e\u003e print(pygqlc.name)\n```\n\nIf you get \"pygqlc\" printed in the python repl, the installation succeded!\n\n#### Optional: Enhanced Logging with valiotlogging\n\nIf you're using this library in a Valiot project, you can install it with the valiotlogging dependency for enhanced structured logging:\n\n```\npip install pygqlc[valiotlogging]\n```\n\nOr in your pyproject.toml:\n\n```toml\n[tool.poetry.dependencies]\npygqlc = {version = \"^3.5.3\", extras = [\"valiotlogging\"]}\n\n[[tool.poetry.source]]\nname = \"valiot\"\nurl = \"https://pypi.valiot.io/\"\npriority = \"supplemental\"\n```\n\nThe library will automatically use valiotlogging if available, and will fall back to standard logging if not.\n\n### Usage\n\n```python\nimport os\nfrom pygqlc import GraphQLClient\ngql = GraphQLClient()\ngql.addEnvironment(\n    'dev',\n    url=os.environ.get('API'), # should be an https url\n    wss=os.environ.get('WSS'), # should be an ws/wss url\n    headers={'Authorization': f\"Bearer {os.environ.get('TOKEN')}\"},\n    ipv4_only=False,  # Set to True to force IPv4 connections (useful for environments with problematic IPv6)\n    default=True)\n```\n\n#### From now on, you can access to the main API:\n\n`gql.query, gql.mutate, gql.subscribe`\n\nFor queries:\n\n```python\nquery = '''\nquery{\n  authors{\n    name\n  }\n}\n'''\ndata, errors = gql.query( query )\n```\n\nFor mutations:\n\n```python\ncreate_author = '''\nmutation {\n  createAuthor(){\n    successful\n    messages{field message}\n    result{id insertedAt}\n  }\n}\n'''\ndata, errors = gql.mutate( create_author )\n```\n\nFor subscriptions:\n\n```python\ndef on_auth_created(message):\n  print(message)\n\nsub_author_created = '''\nsubscription{\n  authorCreated{\n    successful\n    messages{field message}\n    result{id insertedAt}\n  }\n}\n'''\n# unsub may be None if subscription fails (no internet connection, host unreachable, bad subscription doc, etc)\nunsub = gql.subscribe(sub_author_created, callback=on_auth_created)\n...\n# when finishing the subscription:\nunsub()\n# when finishing all subscriptions:\ngql.close()\n```\n\n#### Exception Handling\n\nYou can directly import the `GQLResponseException` for better error handling:\n\n```python\nfrom pygqlc import GraphQLClient, GQLResponseException\n\ngql = GraphQLClient()\n# ... configure client ...\n\ntry:\n    data, errors = gql.query('{ invalidQuery }')\n    # Process data if no errors\nexcept GQLResponseException as e:\n    print(f\"GraphQL error: {e.message}, Status: {e.status_code}\")\n    # Handle the exception appropriately\n```\n\nThe subscribe method, returns an `unsubscribe` function,\nthis allows to stop subscriptions whenever needed.\n\nAfter finishing all subscriptions, the method\n`GraphQLClient.close()` should be called to close correctly the open GQL/websocket connections.\n\nTo reset all subscriptions and websocket connection use the method `GraphQLClient.resetSubsConnection()`.\n\nTo be noted:\n\nAll main methods from the API accept a `variables` param.\nit is a dictionary type and may include variables from your queries or mutations:\n\n```python\nquery_with_vars = '''\nquery CommentsFromAuthor(\n  $authorName: String!\n  $limit: Int\n){\n  author(\n    findBy:{ name: $authorName }\n  ){\n    id\n    name\n    comments(\n      orderBy:{desc: ID}\n      limit: $limit\n    ){\n      id\n      blogPost{name}\n      body\n    }\n  }\n}\n'''\n\ndata, errors = gql.query(\n  query=query_with_vars,\n  variables={\n    \"authorName\": \"Baruc\",\n    \"limit\": 10\n  }\n)\n```\n\nThere is also an optional parameter `flatten` that simplifies the response format:\n\n```python\n# From this:\nresponse = {\n  'data': {\n    'authors': [\n      { 'name': 'Baruc' },\n      { 'name': 'Juan' },\n      { 'name': 'Gerardo' }\n    ]\n  }\n}\n# To this:\nauthors = [\n  { 'name': 'Baruc' },\n  { 'name': 'Juan' },\n  { 'name': 'Gerardo' }\n]\n```\n\nSimplifying the data access from this:\n\n`response['data']['authors'][0]['name']`\n\nto this:\n\n`authors[0]['name']`\n\nIt is `query(query, variables, flatten=True)` by default, to avoid writing it down everytime\n\nThe `(_, errors)` part of the response, is the combination of GraphQL errors, and communication errors, simplifying validations, it has this form:\n\n```python\nerrors = [\n  {\"field\": \u003cvalue\u003e, \"message\":\u003cmsg\u003e},\n  {\"field\": \u003cvalue\u003e, \"message\":\u003cmsg\u003e},\n  {\"field\": \u003cvalue\u003e, \"message\":\u003cmsg\u003e},\n  ...\n]\n```\n\nThe field Attribute it's only available for GraphQL errors, when it is included in the response, so it's suggested that every mutation has at least this parameters in the response:\n\n```\nmutation{\n  myMutation(\u003cmutationParams\u003e){\n    successful\n    messages{\n      field\n      message\n    }\n    result{\n      \u003cdata of interest\u003e\n    }\n  }\n}\n```\n\n### Post timeout:\n\nYou can set a post timeout to avoid an inactive process.\n\nUse `gql.setPostTimeout(seconds)`, or directly in the environment `gql.addEnvironment(post_timeout=seconds)`. Default port_timeout is 60 seconds\n\n### Websocket timeout:\n\nYou can set a websocket timeout to keep subscriptions alive.\n\nUse `gql.setTimeoutWebsocket(seconds)`, or directly in the environment `gql.addEnvironment(timeoutWebsocket=seconds)`. Default timeoutWebsocket is 60 seconds\n\n### IPv4 Only Connections\n\nIn some network environments, particularly on Linux systems, IPv6 connectivity issues can cause slow requests. To force the client to use IPv4 connections only, you can set the `ipv4_only` parameter when adding an environment:\n\n```python\ngql.addEnvironment(\n    'dev',\n    url=\"https://api.example.com/graphql\",\n    ipv4_only=True  # Force IPv4 connections\n)\n```\n\nThis can resolve connectivity issues in networks with suboptimal IPv6 configurations.\n\n### Custom Logging\n\nYou can customize the logging behavior of pygqlc by using the `set_logger` function:\n\n```python\nfrom pygqlc.logging import set_logger, LogLevel\n\n# Example: Create a custom logger that writes to a file\ndef my_custom_logger(level, message, extra=None):\n    with open('pygqlc.log', 'a') as f:\n        f.write(f\"[{level.value}] {message}\\n\")\n\n# Set the custom logger\nset_logger(my_custom_logger)\n```\n\nThe default logger will use valiotlogging if available, otherwise it will use a simple print-based logger.\n\n### for mantainers:\n\n#### Initial configuration\n\nfirst of all, ensure you have configured poetry repositories correctly:\n`poetry config repositories.valiot https://pypi.valiot.io/`\n\nand their credentials:\n\nFor private valiot's pypi:\n\n`poetry config http-basic.valiot \u003cusername\u003e \u003cpassword\u003e`\n\n(_ask adrian to send you the proper username and password for this step_)\n\nAnd for public pypi:\n\n`poetry config pypi-token.pypi \u003cpypi-token\u003e`\n\n(_ask adrian or baruc to generate a token for you_)\n\nthen,\n\n#### regular publish steps (after initial configuration)\n\ndeploy using:\n\n`poetry version \u003cpatch | minor | major\u003e`\n\nthen publish to valiot's private pypi:\n\n`poetry publish --build -r valiot # build and PUBLISH TO PRIVATE VALIOTs PYPI`\n\nor:\n\n`poetry publish -r valiot`\n\n(if you already built the package)\n\nthen publish to public pypi:\n\n`poetry publish`\n\nAfter release, publish to github:\n\n`cat pygqlc/__version__.py`\n\n`gh release create`\n\n`gh release upload v\u003c#.#.#\u003e ./dist/pygqlc-\u003c#.#.#\u003e-py3-none-any.whl`\n\nand don't forget to keep the `CHANGELOG.md` updated!\n\n## Async Usage\n\nPython 3.10+ supports async/await syntax for asynchronous programming. The GraphQLClient class provides async versions of the main methods:\n\n```python\nimport asyncio\nfrom pygqlc import GraphQLClient\n\nasync def main():\n    client = GraphQLClient()\n    client.addEnvironment('dev', \"https://api.example.com/graphql\")\n\n    # Async query\n    data, errors = await client.async_query('''\n        query {\n            users {\n                id\n                name\n            }\n        }\n    ''')\n\n    if not errors:\n        print(\"Users:\", data)\n\n    # Async mutation\n    data, errors = await client.async_mutate('''\n        mutation {\n            createUser(input: {name: \"John Doe\"}) {\n                user {\n                    id\n                    name\n                }\n            }\n        }\n    ''')\n\n    if not errors:\n        print(\"Created user:\", data)\n\nif __name__ == \"__main__\":\n    asyncio.run(main())\n```\n\nThe async methods are:\n\n- `async_execute`: Low-level method to execute GraphQL operations\n- `async_query`: For GraphQL queries\n- `async_query_one`: For queries that return a single item\n- `async_mutate`: For GraphQL mutations\n\nThese methods can be used with `await` in async functions and provide the same functionality as their synchronous counterparts, but with the benefits of asynchronous execution.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaliot%2Fpygqlc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvaliot%2Fpygqlc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvaliot%2Fpygqlc/lists"}