Skip to content

Commit c202cca

Browse files
authored
replace use of scripts with entry_points (#311)
Increase test coverage to the script itself. Fix windows gql-cli signal issue found by the new tests.
1 parent f0790ae commit c202cca

File tree

9 files changed

+104
-46
lines changed

9 files changed

+104
-46
lines changed

.github/workflows/lint.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
python-version: 3.8
1515
- name: Install dependencies
1616
run: |
17-
python -m pip install --upgrade pip
17+
python -m pip install --upgrade pip wheel
1818
pip install tox
1919
- name: Run lint and static type checks
2020
run: tox

.github/workflows/tests.yml

+5-5
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ jobs:
3030
python-version: ${{ matrix.python-version }}
3131
- name: Install dependencies
3232
run: |
33-
python -m pip install --upgrade pip
33+
python -m pip install --upgrade pip wheel
3434
pip install tox tox-gh-actions
3535
- name: Test with tox
3636
run: tox
@@ -52,7 +52,7 @@ jobs:
5252
python-version: 3.8
5353
- name: Install dependencies with only ${{ matrix.dependency }} extra dependency
5454
run: |
55-
python -m pip install --upgrade pip
55+
python -m pip install --upgrade pip wheel
5656
pip install .[${{ matrix.dependency }},test_no_transport]
5757
- name: Test with --${{ matrix.dependency }}-only
5858
run: pytest tests --${{ matrix.dependency }}-only
@@ -68,9 +68,9 @@ jobs:
6868
python-version: 3.8
6969
- name: Install test dependencies
7070
run: |
71-
python -m pip install --upgrade pip
72-
pip install .[test]
71+
python -m pip install --upgrade pip wheel
72+
pip install -e.[test]
7373
- name: Test with coverage
74-
run: pytest --cov=gql --cov-report=xml tests
74+
run: pytest --cov=gql --cov-report=xml --cov-report=term-missing tests
7575
- name: Upload coverage to Codecov
7676
uses: codecov/codecov-action@v1

MANIFEST.in

-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ include Makefile
1111

1212
include tox.ini
1313

14-
include scripts/gql-cli
15-
1614
include gql/py.typed
1715

1816
recursive-include tests *.py *.graphql *.cnf *.yaml *.pem

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.PHONY: clean tests docs
22

3-
SRC_PYTHON := gql tests scripts/gql-cli docs/code_examples
3+
SRC_PYTHON := gql tests docs/code_examples
44

55
dev-setup:
66
python pip install -e ".[test]"

gql/cli.py

+45
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
1+
import asyncio
12
import json
23
import logging
4+
import signal as signal_module
35
import sys
46
from argparse import ArgumentParser, Namespace, RawDescriptionHelpFormatter
57
from typing import Any, Dict, Optional
@@ -407,3 +409,46 @@ async def main(args: Namespace) -> int:
407409
exit_code = 1
408410

409411
return exit_code
412+
413+
414+
def gql_cli() -> None:
415+
"""Synchronously invoke ``main`` with the parsed command line arguments.
416+
417+
Formerly ``scripts/gql-cli``, now registered as an ``entry_point``
418+
"""
419+
# Get arguments from command line
420+
parser = get_parser(with_examples=True)
421+
args = parser.parse_args()
422+
423+
try:
424+
# Create a new asyncio event loop
425+
loop = asyncio.new_event_loop()
426+
asyncio.set_event_loop(loop)
427+
428+
# Create a gql-cli task with the supplied arguments
429+
main_task = asyncio.ensure_future(main(args), loop=loop)
430+
431+
# Add signal handlers to close gql-cli cleanly on Control-C
432+
for signal_name in ["SIGINT", "SIGTERM", "CTRL_C_EVENT", "CTRL_BREAK_EVENT"]:
433+
signal = getattr(signal_module, signal_name, None)
434+
435+
if signal is None:
436+
continue
437+
438+
try:
439+
loop.add_signal_handler(signal, main_task.cancel)
440+
except NotImplementedError: # pragma: no cover
441+
# not all signals supported on all platforms
442+
pass
443+
444+
# Run the asyncio loop to execute the task
445+
exit_code = 0
446+
try:
447+
exit_code = loop.run_until_complete(main_task)
448+
finally:
449+
loop.close()
450+
451+
# Return with the correct exit code
452+
sys.exit(exit_code)
453+
except KeyboardInterrupt: # pragma: no cover
454+
pass

scripts/gql-cli

-34
This file was deleted.

setup.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,15 @@
77
"yarl>=1.6,<2.0",
88
]
99

10-
scripts = [
11-
"scripts/gql-cli",
10+
console_scripts = [
11+
"gql-cli=gql.cli:gql_cli",
1212
]
1313

1414
tests_requires = [
1515
"parse==1.15.0",
1616
"pytest==6.2.5",
1717
"pytest-asyncio==0.16.0",
18+
"pytest-console-scripts==1.3.1",
1819
"pytest-cov==3.0.0",
1920
"mock==4.0.2",
2021
"vcrpy==4.0.2",
@@ -106,5 +107,5 @@
106107
include_package_data=True,
107108
zip_safe=False,
108109
platforms="any",
109-
scripts=scripts,
110+
entry_points={"console_scripts": console_scripts},
110111
)

tests/test_aiohttp.py

+38
Original file line numberDiff line numberDiff line change
@@ -1016,6 +1016,44 @@ async def handler(request):
10161016
assert received_answer == expected_answer
10171017

10181018

1019+
@pytest.mark.asyncio
1020+
@pytest.mark.script_launch_mode("subprocess")
1021+
async def test_aiohttp_using_cli_ep(
1022+
event_loop, aiohttp_server, monkeypatch, script_runner, run_sync_test
1023+
):
1024+
from aiohttp import web
1025+
1026+
async def handler(request):
1027+
return web.Response(text=query1_server_answer, content_type="application/json")
1028+
1029+
app = web.Application()
1030+
app.router.add_route("POST", "/", handler)
1031+
server = await aiohttp_server(app)
1032+
1033+
url = str(server.make_url("/"))
1034+
1035+
def test_code():
1036+
1037+
monkeypatch.setattr("sys.stdin", io.StringIO(query1_str))
1038+
1039+
ret = script_runner.run(
1040+
"gql-cli", url, "--verbose", stdin=io.StringIO(query1_str)
1041+
)
1042+
1043+
assert ret.success
1044+
1045+
# Check that the result has been printed on stdout
1046+
captured_out = str(ret.stdout).strip()
1047+
1048+
expected_answer = json.loads(query1_server_answer_data)
1049+
print(f"Captured: {captured_out}")
1050+
received_answer = json.loads(captured_out)
1051+
1052+
assert received_answer == expected_answer
1053+
1054+
await run_sync_test(event_loop, server, test_code)
1055+
1056+
10191057
@pytest.mark.asyncio
10201058
async def test_aiohttp_using_cli_invalid_param(
10211059
event_loop, aiohttp_server, monkeypatch, capsys

tests/test_cli.py

+10
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import pytest
44

5+
from gql import __version__
56
from gql.cli import (
67
get_execute_args,
78
get_parser,
@@ -347,3 +348,12 @@ def test_cli_get_transport_no_protocol(parser):
347348

348349
with pytest.raises(ValueError):
349350
get_transport(args)
351+
352+
353+
def test_cli_ep_version(script_runner):
354+
ret = script_runner.run("gql-cli", "--version")
355+
356+
assert ret.success
357+
358+
assert ret.stdout == f"v{__version__}\n"
359+
assert ret.stderr == ""

0 commit comments

Comments
 (0)