Skip to content
This repository has been archived by the owner on Mar 29, 2022. It is now read-only.

Commit

Permalink
Revise Python versions; upgrade Pylint and employ it more
Browse files Browse the repository at this point in the history
Python 2 will reach "end of life" by the end of the year.
Already now it's increasingly a hassle to support.
For example, there seems to be no version of Pylint/Astroid
that would work under both Python 2.7 and Python 3.7.
  • Loading branch information
vfaronov committed Mar 2, 2019
1 parent ea142c8 commit 94fb32c
Show file tree
Hide file tree
Showing 40 changed files with 271 additions and 375 deletions.
4 changes: 0 additions & 4 deletions .isort.cfg
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
[isort]

# Python 2.x/3.x standard library shims should be intermingled
# with the actual standard library.
known_standard_library=six.moves,httpolice.util.moves

# ``from ... import`` should be intermingled with ``import ...``.
force_sort_within_sections=true

Expand Down
30 changes: 17 additions & 13 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
language: python
dist: trusty
dist: xenial
sudo: false

addons:
apt:
packages:
- xmlstarlet

python:
- "2.7"
- "pypy"
- "3.4"
- "3.5"
- "3.6"

env:
- REQUIRES=minimum
- REQUIRES=normal
matrix:
include:
- python: "3.4"
env: REQUIRES=normal
- python: "3.5"
env: REQUIRES=normal
- python: "pypy3.5"
env: REQUIRES=normal
- python: "3.6"
env: REQUIRES=normal
- python: "3.6"
env: REQUIRES=minimum
- python: "3.7"
env: REQUIRES=normal

install:
- if [ "$REQUIRES" = minimum ]; then tools/minimum_requires.sh; fi
Expand All @@ -33,7 +37,7 @@ script:

# Basic stuff.
- python setup.py check --strict --restructuredtext
- tools/pylint_all.sh -j 2
- tools/pylint_all.sh -j 2 --reports=no --score=no
- pytest

# Although the main docs (``doc/``) are processed by Read the Docs,
Expand All @@ -57,7 +61,7 @@ deploy:
on:
tags: true
# Only release from one of the environments.
python: "3.5"
python: "3.6"
condition: $REQUIRES = normal
provider: pypi
user: vfaronov
Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ History of changes
==================


Unreleased
~~~~~~~~~~
- Dropped Python 2 support. If you need it, use the older versions.
- HTTPolice no longer requires `six` nor `singledispatch`.


0.7.0 - 2018-03-31
~~~~~~~~~~~~~~~~~~

Expand Down
4 changes: 2 additions & 2 deletions HACKING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Development environment
~~~~~~~~~~~~~~~~~~~~~~~
Set up::

$ virtualenv /path/to/env
$ source /path/to/env/bin/activate
$ python3 -m venv /path/to/env
$ . /path/to/env/bin/activate
$ pip install -e .
$ pip install -r tools/requirements.txt
$ pip install ... # any extra tools you like to have
Expand Down
5 changes: 2 additions & 3 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ __ https://httpolice.readthedocs.io/page/showcase.html

As a command-line tool, it can read `HAR files`__ or raw HTTP/1.x TCP streams.
It can integrate with `mitmproxy`__ for TLS-encrypted and HTTP/2 traffic.
Or you can use it as a Python library (for Python 2.7 and 3.4+),
with optional `Django`__ integration.
There is also a third-party `Chrome extension`__.
Or you can use it as a Python (3.4+) library.
There is a `Django`__ integration package and a third-party `Chrome extension`__.

__ https://en.wikipedia.org/wiki/.har
__ https://mitmproxy.org/
Expand Down
4 changes: 2 additions & 2 deletions doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ Installation

.. highlight:: console

HTTPolice is a Python package that requires `Python`__ 2.7 or 3.4+.
`PyPy`__ is also supported (reasonably recent versions; 5.3.1 is OK).
HTTPolice is a Python package that requires `Python`__ 3.4+.
`PyPy`__ is also supported.

__ https://www.python.org/
__ http://pypy.org/
Expand Down
5 changes: 2 additions & 3 deletions doc/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,9 @@ Quickstart
Installation
------------

HTTPolice is a Python package that can be installed with pip
(on Python 2.7 or 3.4+)::
HTTPolice is a Python package that can be installed with pip (on Python 3.4+)::

$ pip install HTTPolice
$ pip3 install HTTPolice

If you’re not familiar with pip, check the manual’s :doc:`install` section.

Expand Down
2 changes: 1 addition & 1 deletion httpolice/blackboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def severity(self):
return self.notice.severity


class Blackboard(object):
class Blackboard:

"""Shared state that various parts of the code can "write upon".
Expand Down
10 changes: 3 additions & 7 deletions httpolice/citation.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
# -*- coding: utf-8; -*-

import six


@six.python_2_unicode_compatible
class Citation(object):
class Citation:

"""A reference to a relevant document."""

Expand Down Expand Up @@ -42,8 +38,8 @@ class RFC(Citation):
def __init__(self, num, section=None, appendix=None, errata=None):
assert bool(section) + bool(appendix) + bool(errata) <= 1
self.num = num = int(num)
self.section = section = six.text_type(section) if section else None
self.appendix = appendix = six.text_type(appendix) if appendix else None
self.section = section = str(section) if section else None
self.appendix = appendix = str(appendix) if appendix else None
self.errata = errata = int(errata) if errata else None
title = u'RFC %d' % num # no-break space
if errata:
Expand Down
6 changes: 2 additions & 4 deletions httpolice/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
from httpolice import inputs, reports
from httpolice.exchange import check_exchange
from httpolice.notice import Severity
from httpolice.util.text import stdio_as_bytes


def parse_args(argv):
Expand Down Expand Up @@ -52,16 +51,15 @@ def generate_exchanges():
yield exch

try:
# We can't use stdout opened as text (as in Python 3)
# because it may not be UTF-8 (especially on Windows).
# Can't use stdout as text because it may not be UTF-8 (on Windows).
# Our HTML reports are meant for redirection
# and are always UTF-8, which is declared in ``meta``.
# As for text reports, they are mostly ASCII,
# but when they do contain a non-ASCII character
# (perhaps from pieces of input data),
# we don't want to trip over Unicode errors.
# So we encode all text into UTF-8 and write directly as bytes.
report(generate_exchanges(), stdio_as_bytes(stdout))
report(generate_exchanges(), stdout.buffer)
except (EnvironmentError, inputs.InputError) as exc:
if args.full_traceback:
traceback.print_exc(file=stderr)
Expand Down
11 changes: 5 additions & 6 deletions httpolice/framing1.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def _decode_transfer_coding(msg, coding):
# The outermost chunked has already been peeled off at this point.
msg.complain(1002)
msg.body = Unavailable(msg.body)
elif coding == tc.gzip or coding == tc.x_gzip:
elif coding in [tc.gzip, tc.x_gzip]:
try:
msg.body = decode_gzip(msg.body)
except Exception as e:
Expand Down Expand Up @@ -307,13 +307,12 @@ def _parse_chunk(stream, data):
raise stream.error(pos)
if size == 0:
return False
elif size + current_size > MAX_BODY_SIZE:
if size + current_size > MAX_BODY_SIZE:
stream.sane = False
raise BodyTooLongError(size + current_size, MAX_BODY_SIZE)
else:
data.append(stream.read(size))
stream.readlineend()
return True
data.append(stream.read(size))
stream.readlineend()
return True


def _parse_chunked(msg, stream):
Expand Down
15 changes: 5 additions & 10 deletions httpolice/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,6 @@
import operator
import sys

import six

from httpolice import known
from httpolice.known import HeaderRule, h
from httpolice.parse import parse
Expand All @@ -29,7 +27,7 @@
from httpolice.util.data import duplicates


class HeadersView(object):
class HeadersView:

"""Wraps all headers of a single message, exposing them as attributes."""

Expand All @@ -40,7 +38,7 @@ def special_case(cls, view_cls):
assert view_cls.name not in cls.special_cases
cls.special_cases[view_cls.name] = view_cls
return view_cls

def __init__(self, message):
self._message = message
self._cache = {}
Expand Down Expand Up @@ -100,7 +98,7 @@ def clearly(self, predicate):
return set(name for name in self.names if predicate(name))


class HeaderView(object):
class HeaderView:

"""Wraps all headers with a particular name in a given message.
Expand Down Expand Up @@ -165,7 +163,7 @@ def _check_quoted_delims(self, entry, parsed):
comma, semicolon = known.header.bad_quoted_delims(self.name)
if comma or semicolon:
def check(v):
if isinstance(v, six.text_type):
if isinstance(v, str):
if comma and u',' in v:
self.message.complain(1299, entry=entry)
if semicolon and u';' in v:
Expand Down Expand Up @@ -222,7 +220,6 @@ def __contains__(self, other):
# ignoring its parameters.
# This is handled by :meth:`Parametrized.__eq__`,
# but it's only invoked when the `Parametrized` is on the left side.
# pylint: disable=not-an-iterable
return any(val == other for val in self)

def _compare(self, other, op):
Expand All @@ -246,8 +243,7 @@ def _compare(self, other, op):

if isinstance(other, HeaderView):
return NotImplemented
else:
return self.is_okay and okay(other) and op(self.value, other)
return self.is_okay and okay(other) and op(self.value, other)

def __lt__(self, other):
return self._compare(other, operator.lt)
Expand Down Expand Up @@ -328,7 +324,6 @@ def _parse(self):
self._entries = entries

def __iter__(self):
# pylint: disable=not-an-iterable
return iter(v for v in self.value if okay(v))


Expand Down
4 changes: 1 addition & 3 deletions httpolice/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

"""Functions that may be useful for integrating with HTTPolice."""

import six

from httpolice.util.text import force_bytes, force_unicode


Expand Down Expand Up @@ -67,6 +65,6 @@ def _header_name_from_cgi(cgi_name):


def _header_value_from_cgi(value):
if not isinstance(value, (six.text_type, bytes)):
if not isinstance(value, (str, bytes)):
value = str(value)
return force_bytes(value)
14 changes: 4 additions & 10 deletions httpolice/inputs/har.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@
import base64
import io
import json
from six.moves.urllib.parse import urlparse # pylint: disable=import-error
import re

import six
from urllib.parse import urlparse

from httpolice import framing1
from httpolice.exchange import Exchange
Expand All @@ -30,18 +28,14 @@ def har_input(paths):
try:
data = json.load(f)
except ValueError as exc:
six.raise_from(
InputError(u'%s: bad HAR file: %s' % (path, exc)),
exc)
raise InputError('%s: bad HAR file: %s' % (path, exc)) from exc
try:
creator = CreatorInfo(data['log']['creator'])
for entry in data['log']['entries']:
yield _process_entry(entry, creator, path)
except (TypeError, KeyError) as exc:
six.raise_from(
InputError(u'%s: cannot understand HAR file: %r' %
(path, exc)),
exc)
raise InputError('%s: cannot understand HAR file: %r' %
(path, exc)) from exc


def _process_entry(data, creator, path):
Expand Down
18 changes: 7 additions & 11 deletions httpolice/inputs/streams.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
import os
import re

import six

from httpolice.exchange import complaint_box
from httpolice.framing1 import parse_streams
from httpolice.inputs.common import InputError
Expand Down Expand Up @@ -284,7 +282,7 @@ def _rearrange_by_time(sequences):
(time, exchange) = position[i]
if exchange is None:
# Start iterating over this sequence.
exchange = next(sequences[i][0])
exchange = next(sequences[i][0], None)
new_time = _exchange_time(exchange, time)
if time is None or new_time > time:
# So this sequence actually starts at a later time than
Expand Down Expand Up @@ -317,22 +315,20 @@ def _exchange_time(exchange, hint):
if resp.headers.age.is_okay:
return (resp.headers.date.value +
timedelta(seconds=resp.headers.age.value))
else:
return resp.headers.date.value
return resp.headers.date.value
return hint


def _sniff_direction(path1, path2): # pragma: no cover
if path1 and _sniff_outbound(path1):
return (path2, path1)
elif path2 and _sniff_outbound(path2):
if path2 and _sniff_outbound(path2):
return (path1, path2)
elif path1 and _sniff_inbound(path1):
if path1 and _sniff_inbound(path1):
return (path1, path2)
elif path2 and _sniff_inbound(path2):
if path2 and _sniff_inbound(path2):
return (path2, path1)
else:
return None
return None


def _sniff_outbound(path):
Expand Down Expand Up @@ -372,7 +368,7 @@ def parse_combined(path):
try:
preamble = preamble.decode('utf-8')
except UnicodeError as exc: # pragma: no cover
six.raise_from(InputError(u'%s: invalid UTF-8 in preamble' % path), exc)
raise InputError(u'%s: invalid UTF-8 in preamble' % path) from exc
parts2 = rest.split(b'======== BEGIN OUTBOUND STREAM ========\r\n', 1)
if len(parts2) != 2: # pragma: no cover
raise InputError(u'%s: bad combined file: no outbound marker' % path)
Expand Down
Loading

0 comments on commit 94fb32c

Please sign in to comment.