Skip to content

Commit c815e21

Browse files
authored
Fix time elapsed (#1277)
* Show the actual time elapsed; add docs * `requests.Response._headers_parsed_at` → `requests.Response._httpie_headers_parsed_at` * Add `ELAPSED_TIME_LABEL` constant * Tweak docs * Tweak docs * Allow multiple blank lines in Markdown files * Add rudimentary tests for --meta with different --style’s * Cleanup tests * Cleanup tests * Cleanup tests
1 parent 8a03b7a commit c815e21

File tree

10 files changed

+105
-61
lines changed

10 files changed

+105
-61
lines changed

docs/README.md

+54-45
Large diffs are not rendered by default.

docs/markdownlint.rb

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@
2020
# MD028 Blank line inside blockquote
2121
exclude_rule 'MD028'
2222

23+
# MD012 Multiple consecutive blank lines
24+
exclude_rule 'MD012'
25+
2326
# Tell the linter to use ordered lists:
2427
# 1. Foo
2528
# 2. Bar

httpie/client.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import json
44
import sys
55
from contextlib import contextmanager
6+
from time import monotonic
67
from typing import Any, Dict, Callable, Iterable
78
from urllib.parse import urlparse, urlunparse
89

@@ -108,7 +109,7 @@ def collect_messages(
108109
**send_kwargs_merged,
109110
**send_kwargs,
110111
)
111-
112+
response._httpie_headers_parsed_at = monotonic()
112113
expired_cookies += get_expired_cookies(
113114
response.headers.get('Set-Cookie', '')
114115
)

httpie/models.py

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
from time import monotonic
2+
13
import requests
24

35
from enum import Enum, auto
@@ -15,6 +17,9 @@
1517
from .utils import split_cookies, parse_content_type_header
1618

1719

20+
ELAPSED_TIME_LABEL = 'Elapsed time'
21+
22+
1823
class HTTPMessage:
1924
"""Abstract class for HTTP messages."""
2025

@@ -96,7 +101,13 @@ def headers(self):
96101
@property
97102
def metadata(self) -> str:
98103
data = {}
99-
data['Elapsed time'] = str(self._orig.elapsed.total_seconds()) + 's'
104+
time_to_parse_headers = self._orig.elapsed.total_seconds()
105+
# noinspection PyProtectedMember
106+
time_since_headers_parsed = monotonic() - self._orig._httpie_headers_parsed_at
107+
time_elapsed = time_to_parse_headers + time_since_headers_parsed
108+
# data['Headers time'] = str(round(time_to_parse_headers, 5)) + 's'
109+
# data['Body time'] = str(round(time_since_headers_parsed, 5)) + 's'
110+
data[ELAPSED_TIME_LABEL] = str(round(time_elapsed, 10)) + 's'
100111
return '\n'.join(
101112
f'{key}: {value}'
102113
for key, value in data.items()

httpie/output/formatters/colors.py

+1
Original file line numberDiff line numberDiff line change
@@ -383,4 +383,5 @@ def make_styles():
383383

384384

385385
PIE_STYLES = make_styles()
386+
PIE_STYLE_NAMES = list(PIE_STYLES.keys())
386387
BUNDLED_STYLES |= PIE_STYLES.keys()

httpie/output/lexers/metadata.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
import pygments
2+
3+
from httpie.models import ELAPSED_TIME_LABEL
24
from httpie.output.lexers.common import precise
35

46
SPEED_TOKENS = {
@@ -34,7 +36,7 @@ class MetadataLexer(pygments.lexer.RegexLexer):
3436
tokens = {
3537
'root': [
3638
(
37-
r'(Elapsed time)( *)(:)( *)(\d+\.\d+)(s)', pygments.lexer.bygroups(
39+
fr'({ELAPSED_TIME_LABEL})( *)(:)( *)(\d+\.\d+)(s)', pygments.lexer.bygroups(
3840
pygments.token.Name.Decorator, # Name
3941
pygments.token.Text,
4042
pygments.token.Operator, # Colon

httpie/output/ui/palette.py

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
# Copy the brand palette
21
from typing import Optional
32

3+
STYLE_PIE = 'pie'
4+
STYLE_PIE_DARK = 'pie-dark'
5+
STYLE_PIE_LIGHT = 'pie-light'
6+
7+
48
COLOR_PALETTE = {
9+
# Copy the brand palette
510
'transparent': 'transparent',
611
'current': 'currentColor',
712
'white': '#F5F5F0',
@@ -138,10 +143,11 @@
138143

139144
COLOR_PALETTE['secondary'] = {'700': '#37523C', '600': '#6c6969', '500': '#6c6969'}
140145

146+
141147
SHADE_NAMES = {
142-
'500': 'pie-dark',
143-
'600': 'pie',
144-
'700': 'pie-light'
148+
'500': STYLE_PIE_DARK,
149+
'600': STYLE_PIE,
150+
'700': STYLE_PIE_LIGHT
145151
}
146152

147153
SHADES = [

tests/test_meta.py

+15-5
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
1-
from .utils import http
1+
import pytest
22

3+
from httpie.models import ELAPSED_TIME_LABEL
4+
from httpie.output.formatters.colors import PIE_STYLE_NAMES
5+
from .utils import http, MockEnvironment, COLOR
36

4-
def test_meta_elapsed_time(httpbin, monkeypatch):
5-
r = http('--meta', httpbin + '/get')
6-
for line in r.splitlines():
7-
assert 'Elapsed time' in r
7+
8+
def test_meta_elapsed_time(httpbin):
9+
r = http('--meta', httpbin + '/delay/1')
10+
assert f'{ELAPSED_TIME_LABEL}: 1.' in r
11+
12+
13+
@pytest.mark.parametrize('style', ['auto', 'fruity', *PIE_STYLE_NAMES])
14+
def test_meta_elapsed_time_colors(httpbin, style):
15+
r = http('--style', style, '--meta', httpbin + '/get', env=MockEnvironment(colors=256))
16+
assert COLOR in r
17+
assert ELAPSED_TIME_LABEL in r

tests/test_output.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
)
1818
from httpie.cli.definition import parser
1919
from httpie.encoding import UTF8
20-
from httpie.output.formatters.colors import PIE_STYLES, get_lexer
20+
from httpie.output.formatters.colors import get_lexer, PIE_STYLE_NAMES
2121
from httpie.status import ExitStatus
2222
from .fixtures import XML_DATA_RAW, XML_DATA_FORMATTED
2323
from .utils import COLOR, CRLF, HTTP_OK, MockEnvironment, http, DUMMY_URL
@@ -227,7 +227,7 @@ def test_ensure_contents_colored(httpbin, endpoint):
227227
assert COLOR in r
228228

229229

230-
@pytest.mark.parametrize('style', PIE_STYLES.keys())
230+
@pytest.mark.parametrize('style', PIE_STYLE_NAMES)
231231
def test_ensure_meta_is_colored(httpbin, style):
232232
env = MockEnvironment(colors=256)
233233
r = http('--meta', '--style', style, 'GET', httpbin + '/get', env=env)

tests/utils/matching/test_matching.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Here we test our output parsing and matching implementation, not HTTPie itself.
33
44
"""
5+
from httpie.models import ELAPSED_TIME_LABEL
56
from httpie.output.writer import MESSAGE_SEPARATOR
67
from ...utils import CRLF
78
from . import assert_output_does_not_match, assert_output_matches, Expect
@@ -111,7 +112,7 @@ def test_assert_output_matches_response_meta():
111112
assert_output_matches(
112113
(
113114
'Key: Value\n'
114-
'Elapsed Time: 3.3s'
115+
f'{ELAPSED_TIME_LABEL}: 3.3s'
115116
),
116117
[Expect.RESPONSE_META]
117118
)
@@ -124,7 +125,7 @@ def test_assert_output_matches_whole_response():
124125
f'AAA:BBB{CRLF}'
125126
f'{CRLF}'
126127
f'CCC{MESSAGE_SEPARATOR}'
127-
'Elapsed Time: 3.3s'
128+
f'{ELAPSED_TIME_LABEL}: 3.3s'
128129
),
129130
[Expect.RESPONSE_HEADERS, Expect.BODY, Expect.RESPONSE_META]
130131
)

0 commit comments

Comments
 (0)