]> git.ipfire.org Git - thirdparty/httpx.git/commitdiff
Use nox for automation and CI (#128)
authorSeth Michael Larson <sethmichaellarson@gmail.com>
Tue, 13 Aug 2019 13:39:35 +0000 (08:39 -0500)
committerGitHub <noreply@github.com>
Tue, 13 Aug 2019 13:39:35 +0000 (08:39 -0500)
15 files changed:
.gitignore
.isort.cfg [new file with mode: 0644]
.travis.yml
httpx/__init__.py
httpx/exceptions.py
httpx/interfaces.py
httpx/models.py
httpx/utils.py
noxfile.py [new file with mode: 0644]
scripts/install [deleted file]
scripts/lint [deleted file]
scripts/test [deleted file]
test-requirements.txt [moved from requirements.txt with 77% similarity]
tests/models/test_url.py
tests/test_utils.py

index 938e2d157f6859521b0b0d97f64612cfd51d0d9e..90690006b3d230e8e8031b636681899923be60d1 100644 (file)
@@ -6,3 +6,4 @@ __pycache__/
 htmlcov/
 *.egg-info/
 venv/
+.nox
diff --git a/.isort.cfg b/.isort.cfg
new file mode 100644 (file)
index 0000000..83cfd95
--- /dev/null
@@ -0,0 +1,3 @@
+[settings]
+known_first_party = httpx
+known_third_party = brotli,certifi,chardet,cryptography,h11,h2,hstspreload,nox,pytest,rfc3986,setuptools,trustme,uvicorn
index 5554990983b5a6dc7b3467411654aa91a074b6d4..d702022c7d9b9f6a7397a1740331e75793b8a92e 100644 (file)
@@ -4,16 +4,35 @@ language: python
 
 cache: pip
 
-python:
-    - "3.6"
-    - "3.7"
+branches:
+  only:
+    - master
+
+matrix:
+  include:
+    - python: 3.7
+      env: NOX_SESSION=check
+    - python: 3.7
+      env: NOX_SESSION=docs
+
+    - python: 3.6
+      env: NOX_SESSION=test-3.6
+    - python: 3.7
+      env: NOX_SESSION=test-3.7
+    - python: 3.8-dev
+      env: NOX_SESSION=test-3.8
+
+  allow_failures:
+    - python: 3.8-dev
 
 install:
-    - pip install -U -r requirements.txt
+  - pip install --upgrade nox
 
 script:
-    - scripts/test
+  - nox -s ${NOX_SESSION}
 
 after_script:
-    - pip install codecov
-    - codecov
+  - if [ -f .coverage ]; then
+      python -m pip install codecov;
+      codecov;
+    fi
index 39b44aae77fbd2b2a72157690c78098e0ef11a13..dec5cff19c749bf77a819e28ae86856234d50dcf 100644 (file)
@@ -86,6 +86,8 @@ __all__ = [
     "TimeoutConfig",
     "VerifyTypes",
     "HTTPConnection",
+    "BasePoolSemaphore",
+    "BaseBackgroundManager",
     "ConnectionPool",
     "ConnectTimeout",
     "CookieConflict",
index ddccbf8c2afb1f85d4ad7d854a94b1d90b497a3f..7ca9055b0cefbd8e963ccb9dbd8e7efecc3745c0 100644 (file)
@@ -1,6 +1,6 @@
-from typing import TYPE_CHECKING
+import typing
 
-if TYPE_CHECKING:
+if typing.TYPE_CHECKING:
     from .models import BaseRequest, BaseResponse  # pragma: nocover
 
 
@@ -10,7 +10,10 @@ class HTTPError(Exception):
     """
 
     def __init__(
-        self, request: "BaseRequest" = None, response: "BaseResponse" = None, *args
+        self,
+        *args: typing.Any,
+        request: "BaseRequest" = None,
+        response: "BaseResponse" = None,
     ) -> None:
         self.response = response
         self.request = request or getattr(self.response, "request", None)
index 0a17f99c15dfcd295a96195c47639ec2b49c472a..6c79c9e22e274601b9c2eae0b6e804c834a88c15 100644 (file)
@@ -41,7 +41,7 @@ class AsyncDispatcher:
         headers: HeaderTypes = None,
         verify: VerifyTypes = None,
         cert: CertTypes = None,
-        timeout: TimeoutTypes = None
+        timeout: TimeoutTypes = None,
     ) -> AsyncResponse:
         request = AsyncRequest(method, url, data=data, params=params, headers=headers)
         return await self.send(request, verify=verify, cert=cert, timeout=timeout)
@@ -89,7 +89,7 @@ class Dispatcher:
         headers: HeaderTypes = None,
         verify: VerifyTypes = None,
         cert: CertTypes = None,
-        timeout: TimeoutTypes = None
+        timeout: TimeoutTypes = None,
     ) -> Response:
         request = Request(method, url, data=data, params=params, headers=headers)
         return self.send(request, verify=verify, cert=cert, timeout=timeout)
index f397e780a82cba82be0c0fa3109b9715763c6fe3..4437bcc3514c38075d77f38e550a5413e4429636 100644 (file)
@@ -36,7 +36,7 @@ from .utils import (
     str_query_param,
 )
 
-PrimitiveData = typing.Union[str, int, float, bool, type(None)]
+PrimitiveData = typing.Optional[typing.Union[str, int, float, bool]]
 
 URLTypes = typing.Union["URL", str]
 
@@ -92,6 +92,16 @@ class URL:
         else:
             self._uri_reference = url._uri_reference
 
+        # Handle IDNA domain names.
+        if self._uri_reference.authority:
+            idna_authority = self._uri_reference.authority.encode("idna").decode(
+                "ascii"
+            )
+            if idna_authority != self._uri_reference.authority:
+                self._uri_reference = self._uri_reference.copy_with(
+                    authority=idna_authority
+                )
+
         # Normalize scheme and domain name.
         if self.is_absolute_url:
             self._uri_reference = self._uri_reference.normalize()
@@ -170,7 +180,7 @@ class URL:
         # URLs with a fragment portion as not absolute.
         # What we actually care about is if the URL provides
         # a scheme and hostname to which connections should be made.
-        return self.scheme and self.host
+        return bool(self.scheme and self.host)
 
     @property
     def is_relative_url(self) -> bool:
@@ -252,7 +262,7 @@ class QueryParams(typing.Mapping[str, str]):
         elif isinstance(value, QueryParams):
             items = value.multi_items()
         elif isinstance(value, list):
-            items = value
+            items = value  # type: ignore
         else:
             items = value.items()  # type: ignore
 
index e3acfd77ec51ca2abe564a60fbfe9dd0486cc3c8..ff39935688637f44115866067d33a8ff7d5af252 100644 (file)
@@ -23,7 +23,7 @@ def normalize_header_value(value: typing.AnyStr, encoding: str = None) -> bytes:
     return value.encode(encoding or "ascii")
 
 
-def str_query_param(value: typing.Union[str, int, float, bool, type(None)]) -> str:
+def str_query_param(value: typing.Optional[typing.Union[str, int, float, bool]]) -> str:
     """
     Coerce a primitive data type into a string value for query params.
 
@@ -100,5 +100,5 @@ def get_netrc_login(host: str) -> typing.Optional[typing.Tuple[str, str, str]]:
     if netrc_path is None:
         return None
 
-    netrc_info = netrc.netrc(netrc_path)
+    netrc_info = netrc.netrc(str(netrc_path))
     return netrc_info.authenticators(host)  # type: ignore
diff --git a/noxfile.py b/noxfile.py
new file mode 100644 (file)
index 0000000..a63d620
--- /dev/null
@@ -0,0 +1,60 @@
+import nox
+
+source_files = ("httpx", "tests", "setup.py", "noxfile.py")
+
+
+@nox.session(reuse_venv=True)
+def lint(session):
+    session.install("autoflake", "black", "flake8", "isort", "seed-isort-config")
+
+    session.run("autoflake", "--in-place", "--recursive", *source_files)
+    session.run("seed-isort-config", "--application-directories=httpx")
+    session.run(
+        "isort",
+        "--project=httpx",
+        "--multi-line=3",
+        "--trailing-comma",
+        "--force-grid-wrap=0",
+        "--combine-as",
+        "--line-width=88",
+        "--recursive",
+        "--apply",
+        *source_files,
+    )
+    session.run("black", "--target-version=py36", *source_files)
+
+    check(session)
+
+
+@nox.session(reuse_venv=True)
+def check(session):
+    session.install("black", "flake8", "flake8-bugbear", "mypy")
+
+    session.run("black", "--check", "--target-version=py36", *source_files)
+    session.run(
+        "flake8", "--max-line-length=88", "--ignore=W503,E203,B305", *source_files
+    )
+    session.run("mypy", "httpx", "--ignore-missing-imports", "--disallow-untyped-defs")
+
+
+@nox.session(reuse_venv=True)
+def docs(session):
+    session.install("mkdocs", "mkdocs-material")
+
+    session.run("mkdocs", "build")
+
+
+@nox.session(python=["3.6", "3.7", "3.8"])
+def test(session):
+    session.install("-r", "test-requirements.txt")
+
+    session.run(
+        "coverage",
+        "run",
+        "--omit='*'",
+        "-m",
+        "pytest",
+        "--cov=httpx",
+        "--cov=tests",
+        "--cov-report=term-missing",
+    )
diff --git a/scripts/install b/scripts/install
deleted file mode 100755 (executable)
index d263b44..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/sh -e
-
-# Use the Python executable provided from the `-p` option, or a default.
-[[ $1 = "-p" ]] && PYTHON=$2 || PYTHON="python3"
-
-MIN_VERSION="(3, 6)"
-VERSION_OK=`"$PYTHON" -c "import sys; print(sys.version_info[0:2] >= $MIN_VERSION and '1' or '');"`
-
-if [[ -z "$VERSION_OK" ]] ; then
-    PYTHON_VERSION=`"$PYTHON" -c "import sys; print('%s.%s' % sys.version_info[0:2]);"`
-    DISP_MIN_VERSION=`"$PYTHON" -c "print('%s.%s' % $MIN_VERSION)"`
-    echo "ERROR: Python $PYTHON_VERSION detected, but $DISP_MIN_VERSION+ is required."
-    echo "Please upgrade your Python distribution to install Databases."
-    exit 1
-fi
-
-REQUIREMENTS="requirements.txt"
-VENV="venv"
-PIP="$VENV/bin/pip"
-
-set -x
-"$PYTHON" -m venv "$VENV"
-"$PIP" install -r "$REQUIREMENTS"
-"$PIP" install -e .
diff --git a/scripts/lint b/scripts/lint
deleted file mode 100755 (executable)
index a1b85cc..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh -e
-
-export PREFIX=""
-if [ -d 'venv' ] ; then
-    export PREFIX="venv/bin/"
-fi
-
-set -x
-
-${PREFIX}autoflake --in-place --recursive httpx tests setup.py
-${PREFIX}isort --multi-line=3 --trailing-comma --force-grid-wrap=0 --combine-as --line-width 88 --recursive --apply httpx tests setup.py
-${PREFIX}black httpx tests setup.py
-${PREFIX}flake8 --max-line-length=88 --ignore=W503,E203,B305 httpx tests setup.py
-${PREFIX}mypy httpx --ignore-missing-imports --disallow-untyped-defs
-
-scripts/clean
diff --git a/scripts/test b/scripts/test
deleted file mode 100755 (executable)
index 626d43e..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/sh -e
-
-export PACKAGE="httpx"
-export PREFIX=""
-if [ -d 'venv' ] ; then
-    export PREFIX="venv/bin/"
-fi
-
-set -x
-
-PYTHONPATH=. ${PREFIX}pytest --ignore venv --cov tests --cov ${PACKAGE} --cov-report= ${@}
-${PREFIX}coverage report --show-missing --fail-under=100
similarity index 77%
rename from requirements.txt
rename to test-requirements.txt
index e7400b09ffec2691b5719aa46d06ace8130c36c2..089189b389c204ac82b5ba99930fdb02f58547e7 100644 (file)
@@ -9,13 +9,6 @@ rfc3986==1.*
 # Optional
 brotlipy==0.7.*
 
-# Documentation
-mkdocs
-mkdocs-material
-
-# Testing
-autoflake
-black
 cryptography
 flake8
 flake8-bugbear
index 7cbfc1c9ebdeded0a2e29c5f9155f8bba1ab5db9..80542db925b3cef67925b7940a590217d5b6d8fb 100644 (file)
@@ -1,5 +1,4 @@
 import pytest
-import rfc3986
 
 from httpx import URL
 from httpx.exceptions import InvalidURL
index 96d186b56153bda3e4e43c87a60646e1d0728025..a6085fc7cd483b3f26e9068a4cf9ac93828ff0c1 100644 (file)
@@ -37,7 +37,7 @@ def test_bad_utf_like_encoding():
     ),
 )
 def test_guess_by_bom(encoding, expected):
-    data = u"\ufeff{}".encode(encoding)
+    data = "\ufeff{}".encode(encoding)
     assert guess_json_utf(data) == expected