Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop request.timer attribute. #1249

Merged
merged 5 commits into from
Sep 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions httpx/_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
)
from ._utils import (
NetRCInfo,
Timer,
URLPattern,
get_environment_proxies,
get_logger,
Expand Down Expand Up @@ -811,6 +812,8 @@ def _send_single_request(self, request: Request, timeout: Timeout) -> Response:
Sends a single request, without handling any redirections.
"""
transport = self._transport_for_url(request.url)
timer = Timer()
timer.sync_start()

with map_exceptions(HTTPCORE_EXC_MAP, request=request):
(
Expand All @@ -832,6 +835,7 @@ def _send_single_request(self, request: Request, timeout: Timeout) -> Response:
headers=headers,
stream=stream, # type: ignore
request=request,
elapsed_func=timer.sync_elapsed,
)

self.cookies.extract_cookies(response)
Expand Down Expand Up @@ -1434,6 +1438,8 @@ async def _send_single_request(
Sends a single request, without handling any redirections.
"""
transport = self._transport_for_url(request.url)
timer = Timer()
await timer.async_start()

with map_exceptions(HTTPCORE_EXC_MAP, request=request):
(
Expand All @@ -1455,6 +1461,7 @@ async def _send_single_request(
headers=headers,
stream=stream, # type: ignore
request=request,
elapsed_func=timer.async_elapsed,
)

self.cookies.extract_cookies(response)
Expand Down
14 changes: 7 additions & 7 deletions httpx/_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@
URLTypes,
)
from ._utils import (
ElapsedTimer,
flatten_queryparams,
guess_json_utf,
is_known_encoding,
Expand Down Expand Up @@ -606,7 +605,6 @@ def __init__(
else:
self.stream = encode(data, files, json)

self.timer = ElapsedTimer()
self.prepare()

def prepare(self) -> None:
Expand Down Expand Up @@ -678,6 +676,7 @@ def __init__(
stream: ContentStream = None,
content: bytes = None,
history: typing.List["Response"] = None,
elapsed_func: typing.Callable = None,
):
self.status_code = status_code
self.http_version = http_version
Expand All @@ -688,6 +687,7 @@ def __init__(
self.call_next: typing.Optional[typing.Callable] = None

self.history = [] if history is None else list(history)
self._elapsed_func = elapsed_func

self.is_closed = False
self.is_stream_consumed = False
Expand All @@ -708,7 +708,7 @@ def elapsed(self) -> datetime.timedelta:
"'.elapsed' may only be accessed after the response "
"has been read or closed."
)
return self._elapsed
return datetime.timedelta(seconds=self._elapsed)

@property
def request(self) -> Request:
Expand Down Expand Up @@ -976,8 +976,8 @@ def close(self) -> None:
"""
if not self.is_closed:
self.is_closed = True
if self._request is not None:
self._elapsed = self.request.timer.elapsed
if self._elapsed_func is not None:
self._elapsed = self._elapsed_func()
self._raw_stream.close()

async def aread(self) -> bytes:
Expand Down Expand Up @@ -1056,8 +1056,8 @@ async def aclose(self) -> None:
"""
if not self.is_closed:
self.is_closed = True
if self._request is not None:
self._elapsed = self.request.timer.elapsed
if self._elapsed_func is not None:
self._elapsed = await self._elapsed_func()
await self._raw_stream.aclose()


Expand Down
51 changes: 29 additions & 22 deletions httpx/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import os
import re
import sys
import time
import typing
import warnings
from datetime import timedelta
from pathlib import Path
from time import perf_counter
from types import TracebackType
from urllib.request import getproxies

import sniffio

from ._types import PrimitiveData

if typing.TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -392,28 +392,35 @@ def flatten_queryparams(
return items


class ElapsedTimer:
def __init__(self) -> None:
self.start: float = perf_counter()
self.end: typing.Optional[float] = None
class Timer:
async def _get_time(self) -> float:
library = sniffio.current_async_library()
if library == "trio":
import trio

def __enter__(self) -> "ElapsedTimer":
self.start = perf_counter()
return self
return trio.current_time()
elif library == "curio": # pragma: nocover
import curio

def __exit__(
self,
exc_type: typing.Type[BaseException] = None,
exc_value: BaseException = None,
traceback: TracebackType = None,
) -> None:
self.end = perf_counter()
return await curio.clock()

@property
def elapsed(self) -> timedelta:
if self.end is None:
return timedelta(seconds=perf_counter() - self.start)
return timedelta(seconds=self.end - self.start)
import asyncio

return asyncio.get_event_loop().time()

def sync_start(self) -> None:
self.started = time.perf_counter()

async def async_start(self) -> None:
self.started = await self._get_time()

def sync_elapsed(self) -> float:
now = time.perf_counter()
return now - self.started

async def async_elapsed(self) -> float:
now = await self._get_time()
return now - self.started


class URLPattern:
Expand Down
2 changes: 0 additions & 2 deletions tests/models/test_responses.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import datetime
import json
from unittest import mock

Expand Down Expand Up @@ -31,7 +30,6 @@ def test_response():
assert response.text == "Hello, world!"
assert response.request.method == "GET"
assert response.request.url == "https://example.org"
assert response.elapsed >= datetime.timedelta(0)
tomchristie marked this conversation as resolved.
Show resolved Hide resolved
assert not response.is_error


Expand Down
13 changes: 0 additions & 13 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import asyncio
import os
import random

import pytest

import httpx
from httpx._utils import (
ElapsedTimer,
NetRCInfo,
URLPattern,
get_ca_bundle_from_env,
Expand Down Expand Up @@ -177,17 +175,6 @@ def test_get_ssl_cert_file():
assert get_ca_bundle_from_env() is None


@pytest.mark.asyncio
async def test_elapsed_timer():
with ElapsedTimer() as timer:
assert timer.elapsed.total_seconds() == pytest.approx(0, abs=0.05)
await asyncio.sleep(0.1)
await asyncio.sleep(
0.1
) # test to ensure time spent after timer exits isn't accounted for.
assert timer.elapsed.total_seconds() == pytest.approx(0.1, abs=0.05)


@pytest.mark.parametrize(
["environment", "proxies"],
[
Expand Down