Skip to content
This repository has been archived by the owner on Dec 13, 2020. It is now read-only.

Commit

Permalink
v1.0.5: Fixed stdin bug.
Browse files Browse the repository at this point in the history
Running tox on Python 3.5 on AppVeyor.

Fixed stdin bug. On Python 3.x an exception was raised related to
reading a closed file. Python 2.7 instead ignored most of the file.
Fixed all Python versions.

Fixes #2
  • Loading branch information
Robpol86 committed Nov 30, 2015
1 parent bade1b4 commit b10527c
Show file tree
Hide file tree
Showing 9 changed files with 161 additions and 13 deletions.
6 changes: 6 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@ Changelog

This project adheres to `Semantic Versioning <http://semver.org/>`_.

1.0.5 - 2015-11-29
------------------

Fixed
* Standard input (piped in data) bug.

1.0.4 - 2015-11-14
------------------

Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
init:
- set PATH=C:\Python34-x64;C:\Python34-x64\Scripts;%PATH%
- set PATH=C:\Python35-x64;C:\Python35-x64\Scripts;%PATH%

artifacts:
- path: .coverage
Expand Down
15 changes: 13 additions & 2 deletions flake8_pep257.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"""

import codecs
import gc
import os

import pep257
Expand All @@ -15,15 +16,25 @@
def load_file(filename):
"""Read file to memory.
From: https://github.com/public/flake8-import-order/blob/620a376/flake8_import_order/__init__.py#L201
For stdin sourced files, this function does something super duper incredibly hacky and shameful. So so shameful. I'm
obtaining the original source code of the target module from the only instance of pep8.Checker through the Python
garbage collector. Flake8's API doesn't give me the original source code of the module we are checking. Instead it
has pep8 give me an AST object of the module (already parsed). This unfortunately loses valuable information like
the kind of quotes used for strings (no way to know if a docstring was surrounded by triple double quotes or just
one single quote, thereby rendering pep257's D300 error as unusable).
This will break one day. I'm sure of it. For now it fixes https://github.com/Robpol86/flake8-pep257/issues/2
:param str filename: File path or 'stdin'. From Main().filename.
:return: First item is the filename or 'stdin', second are the contents of the file.
:rtype: tuple
"""
if filename in ('stdin', '-', None):
return 'stdin', pep8.stdin_get_value()
instances = [i for i in gc.get_objects() if isinstance(i, pep8.Checker)]
if len(instances) != 1:
raise ValueError('Expected only 1 instance of pep8.Checker, got {0} instead.'.format(len(instances)))
return 'stdin', ''.join(instances[0].lines)
with codecs.open(filename, encoding='utf-8') as handle:
return filename, handle.read()

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ def safe_read(path):
name='flake8-pep257',
py_modules=['flake8_pep257'],
url='https://github.com/Robpol86/flake8-pep257',
version='1.0.4',
version='1.0.5',
zip_safe=True,
)
11 changes: 11 additions & 0 deletions tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"""Non-fixture code shared among test modules."""


try:
from subprocess import check_output, STDOUT
except ImportError:
from subprocess32 import check_output, STDOUT


assert check_output
assert STDOUT
38 changes: 36 additions & 2 deletions tests/test_default.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Test against sample modules using the default options."""

import os
from distutils.spawn import find_executable

import flake8.main
import pytest

from tests import check_output, STDOUT

EXPECTED = """\
./sample.py:1:1: D100 Missing docstring in public module
./sample.py:5:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)
Expand All @@ -17,7 +20,7 @@
./sample_unicode.py:15:1: D401 First line should be in imperative mood ('Print', not 'Prints')
./sample_unicode.py:24:1: D203 1 blank line required before class docstring (found 0)
./sample_unicode.py:24:1: D204 1 blank line required after class docstring (found 0)
./sample_unicode.py:24:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)
./sample_unicode.py:24:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)\
"""


Expand All @@ -42,11 +45,42 @@ def test_direct(capsys, monkeypatch, tempdir, stdin):
out, err = capsys.readouterr()
assert not err

# Clean.
if stdin:
expected = '\n'.join('stdin:' + l.split(':', 1)[-1] for l in EXPECTED.splitlines() if stdin in l)
elif os.name == 'nt':
expected = EXPECTED.replace('./sample', r'.\sample')
else:
expected = EXPECTED
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert out == expected


@pytest.mark.parametrize('stdin', ['', 'sample_unicode.py', 'sample.py'])
def test_subprocess(tempdir, stdin):
"""Test by calling flake8 through subprocess using a dedicated python process.
:param tempdir: conftest fixture.
:param str stdin: Pipe this file to stdin of flake8.
"""
# Prepare.
cwd = str(tempdir.join('empty' if stdin else ''))
stdin_handle = tempdir.join(stdin).open() if stdin else None

# Execute.
command = [find_executable('flake8'), '--exit-zero', '-' if stdin else '.']
environ = os.environ.copy()
environ['COV_CORE_DATAFILE'] = '' # Disable pytest-cov's subprocess coverage feature. Doesn't work right now.
out = check_output(command, stderr=STDOUT, cwd=cwd, stdin=stdin_handle, env=environ).decode('utf-8')

# Clean.
if stdin:
expected = '\n'.join('stdin:' + l.split(':', 1)[-1] for l in EXPECTED.splitlines() if stdin in l)
elif os.name == 'nt':
expected = EXPECTED.replace('./sample', r'.\sample')
else:
expected = EXPECTED
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert expected.strip() == out.strip()
assert out == expected
52 changes: 47 additions & 5 deletions tests/test_explain.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"""Test against sample modules using the explain option in all supported config sources."""

import os
import re
from distutils.spawn import find_executable

import flake8.main
import pytest

from tests import check_output, STDOUT

EXPECTED = list()
EXPECTED.append("""\
./sample.py:1:1: D100 Missing docstring in public module
Expand Down Expand Up @@ -61,6 +63,7 @@
Note: Exception to this is made if the docstring contains
\"\"\" quotes in its body.
""")
EXPECTED.append("""\
./sample_unicode.py:1:1: D100 Missing docstring in public module
Expand Down Expand Up @@ -116,6 +119,7 @@
Note: Exception to this is made if the docstring contains
\"\"\" quotes in its body.
""")


Expand Down Expand Up @@ -148,12 +152,50 @@ def test_direct(capsys, monkeypatch, tempdir, stdin, which_cfg):
out, err = capsys.readouterr()
assert not err

# Clean.
if stdin:
expected = EXPECTED[0 if stdin == 'sample.py' else 1].replace('./{0}:'.format(stdin), 'stdin:')
elif os.name == 'nt':
expected = '\n'.join(EXPECTED).replace('./sample', r'.\sample')
else:
expected = '\n'.join(EXPECTED)
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert out == expected


@pytest.mark.parametrize('stdin', ['', 'sample_unicode.py', 'sample.py'])
@pytest.mark.parametrize('which_cfg', ['tox.ini', 'tox.ini flake8', 'setup.cfg', '.pep257'])
def test_subprocess(tempdir, stdin, which_cfg):
"""Test by calling flake8 through subprocess using a dedicated python process.
:param tempdir: conftest fixture.
:param str stdin: Pipe this file to stdin of flake8.
:param str which_cfg: Which config file to test with.
"""
# Prepare.
cwd = str(tempdir.join('empty' if stdin else ''))
stdin_handle = tempdir.join(stdin).open() if stdin else None

# Write configuration.
cfg = which_cfg.split()
section = cfg[1] if len(cfg) > 1 else 'pep257'
key = 'show-pep257' if section == 'flake8' else 'explain'
tempdir.join('empty' if stdin else '', cfg[0]).write('[{0}]\n{1} = True\n'.format(section, key))

# Execute.
command = [find_executable('flake8'), '--exit-zero', '-' if stdin else '.']
environ = os.environ.copy()
environ['COV_CORE_DATAFILE'] = '' # Disable pytest-cov's subprocess coverage feature. Doesn't work right now.
out = check_output(command, stderr=STDOUT, cwd=cwd, stdin=stdin_handle, env=environ).decode('utf-8')

# Clean.
if stdin:
expected = EXPECTED[0 if stdin == 'sample.py' else 1].replace('./{0}:'.format(stdin), 'stdin:')
elif os.name == 'nt':
expected = '\n\n'.join(EXPECTED).replace('./sample', r'.\sample')
expected = '\n'.join(EXPECTED).replace('./sample', r'.\sample')
else:
expected = '\n\n'.join(EXPECTED)
out = re.sub(r'\n[\t ]+\n', r'\n\n', out)
expected = '\n'.join(EXPECTED)
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert expected.strip() == out.strip()
assert out == expected
47 changes: 45 additions & 2 deletions tests/test_ignore.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
"""Test against sample modules using the ignore option in all supported config sources."""

import os
from distutils.spawn import find_executable

import flake8.main
import pytest

from tests import check_output, STDOUT

EXPECTED = """\
./sample.py:1:1: D100 Missing docstring in public module
./sample.py:5:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)
Expand All @@ -13,7 +16,7 @@
./sample_unicode.py:1:1: D100 Missing docstring in public module
./sample_unicode.py:15:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)
./sample_unicode.py:15:1: D401 First line should be in imperative mood ('Print', not 'Prints')
./sample_unicode.py:24:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)
./sample_unicode.py:24:1: D300 Use \"\"\"triple double quotes\"\"\" (found '''-quotes)\
"""


Expand Down Expand Up @@ -47,11 +50,51 @@ def test_direct(capsys, monkeypatch, tempdir, ignore, stdin, which_cfg):
out, err = capsys.readouterr()
assert not err

# Clean.
if stdin:
expected = '\n'.join('stdin:' + l.split(':', 1)[-1] for l in EXPECTED.splitlines() if stdin in l)
elif os.name == 'nt':
expected = EXPECTED.replace('./sample', r'.\sample')
else:
expected = EXPECTED
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert out == expected


@pytest.mark.parametrize('ignore', ['D203,D204', 'D2'])
@pytest.mark.parametrize('stdin', ['', 'sample_unicode.py', 'sample.py'])
@pytest.mark.parametrize('which_cfg', ['tox.ini', 'tox.ini flake8', 'setup.cfg', '.pep257'])
def test_subprocess(tempdir, ignore, stdin, which_cfg):
"""Test by calling flake8 through subprocess using a dedicated python process.
:param tempdir: conftest fixture.
:param str ignore: Config value for ignore option.
:param str stdin: Pipe this file to stdin of flake8.
:param str which_cfg: Which config file to test with.
"""
# Prepare.
cwd = str(tempdir.join('empty' if stdin else ''))
stdin_handle = tempdir.join(stdin).open() if stdin else None

# Write configuration.
cfg = which_cfg.split()
section = cfg[1] if len(cfg) > 1 else 'pep257'
tempdir.join('empty' if stdin else '', cfg[0]).write('[{0}]\nignore = {1}\n'.format(section, ignore))

# Execute.
command = [find_executable('flake8'), '--exit-zero', '-' if stdin else '.']
environ = os.environ.copy()
environ['COV_CORE_DATAFILE'] = '' # Disable pytest-cov's subprocess coverage feature. Doesn't work right now.
out = check_output(command, stderr=STDOUT, cwd=cwd, stdin=stdin_handle, env=environ).decode('utf-8')

# Clean.
if stdin:
expected = '\n'.join('stdin:' + l.split(':', 1)[-1] for l in EXPECTED.splitlines() if stdin in l)
elif os.name == 'nt':
expected = EXPECTED.replace('./sample', r'.\sample')
else:
expected = EXPECTED
out = '\n'.join(l.rstrip() for l in out.splitlines())

assert expected.strip() == out.strip()
assert out == expected
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ commands =
{posargs:tests}
deps =
pytest-cov
py26: subprocess32
usedevelop = True

[testenv:py35x64]
Expand Down

0 comments on commit b10527c

Please sign in to comment.