From bc71594c2721ec71f53c4ebf71f801241a9f514a9aa7f49e7749053953de5384 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Chv=C3=A1tal?= Date: Wed, 13 Feb 2019 12:31:42 +0000 Subject: [PATCH] Accepting request 674528 from home:jayvdb:coala:python3-bears - Activate tests - Update to v1.0 - Fix %check - Remove unneeded build dependency on python-devel OBS-URL: https://build.opensuse.org/request/show/674528 OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-eradicate?expand=0&rev=1 --- .gitattributes | 23 +++ .gitignore | 1 + eradicate-1.0.tar.gz | 3 + python-eradicate.changes | 12 ++ python-eradicate.spec | 73 +++++++ test_eradicate.py | 424 +++++++++++++++++++++++++++++++++++++++ 6 files changed, 536 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 eradicate-1.0.tar.gz create mode 100644 python-eradicate.changes create mode 100644 python-eradicate.spec create mode 100644 test_eradicate.py diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9b03811 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,23 @@ +## Default LFS +*.7z filter=lfs diff=lfs merge=lfs -text +*.bsp filter=lfs diff=lfs merge=lfs -text +*.bz2 filter=lfs diff=lfs merge=lfs -text +*.gem filter=lfs diff=lfs merge=lfs -text +*.gz filter=lfs diff=lfs merge=lfs -text +*.jar filter=lfs diff=lfs merge=lfs -text +*.lz filter=lfs diff=lfs merge=lfs -text +*.lzma filter=lfs diff=lfs merge=lfs -text +*.obscpio filter=lfs diff=lfs merge=lfs -text +*.oxt filter=lfs diff=lfs merge=lfs -text +*.pdf filter=lfs diff=lfs merge=lfs -text +*.png filter=lfs diff=lfs merge=lfs -text +*.rpm filter=lfs diff=lfs merge=lfs -text +*.tbz filter=lfs diff=lfs merge=lfs -text +*.tbz2 filter=lfs diff=lfs merge=lfs -text +*.tgz filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.txz filter=lfs diff=lfs merge=lfs -text +*.whl filter=lfs diff=lfs merge=lfs -text +*.xz filter=lfs diff=lfs merge=lfs -text +*.zip filter=lfs diff=lfs merge=lfs -text +*.zst filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..57affb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.osc diff --git a/eradicate-1.0.tar.gz b/eradicate-1.0.tar.gz new file mode 100644 index 0000000..291db79 --- /dev/null +++ b/eradicate-1.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ffda82aae6fd49dfffa777a857cb758d77502a1f2e0f54c9ac5155a39d2d01a +size 4644 diff --git a/python-eradicate.changes b/python-eradicate.changes new file mode 100644 index 0000000..0bbbc0d --- /dev/null +++ b/python-eradicate.changes @@ -0,0 +1,12 @@ +------------------------------------------------------------------- +Mon Feb 11 23:10:51 UTC 2019 - John Vandenberg + +- Activate tests +- Update to v1.0 +- Fix %check +- Remove unneeded build dependency on python-devel + +------------------------------------------------------------------- +Fri Oct 20 16:14:51 UTC 2017 - toddrme2178@gmail.com + +- initial version for 0.2.1 diff --git a/python-eradicate.spec b/python-eradicate.spec new file mode 100644 index 0000000..aad2ab8 --- /dev/null +++ b/python-eradicate.spec @@ -0,0 +1,73 @@ +# +# spec file for package python-eradicate +# +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# +# All modifications and additions to the file contributed by third parties +# remain the property of their copyright owners, unless otherwise agreed +# upon. The license for this file, and modifications and additions to the +# file, is the same license as for the pristine package itself (unless the +# license for the pristine package is not an Open Source License, in which +# case the license is the MIT License). An "Open Source License" is a +# license that conforms to the Open Source Definition (Version 1.9) +# published by the Open Source Initiative. + +# Please submit bugfixes or comments via https://bugs.opensuse.org/ +# + + +%{?!python_module:%define python_module() python-%{**} python3-%{**}} +Name: python-eradicate +Version: 1.0 +Release: 0 +Summary: Removes commented-out code +License: MIT +Group: Development/Languages/Python +URL: https://github.com/myint/eradicate +Source: https://files.pythonhosted.org/packages/source/e/eradicate/eradicate-%{version}.tar.gz +Source1: https://raw.githubusercontent.com/myint/eradicate/v%{version}/test_eradicate.py +BuildRequires: %{python_module setuptools} +BuildRequires: fdupes +BuildRequires: python-rpm-macros +Requires(post): update-alternatives +Requires(postun): update-alternatives +BuildArch: noarch +%python_subpackages + +%description +With modern revision control available, there is no reason to save +commented-out code to your repository. ``eradicate`` helps cleans up +existing junk comments. It does this by detecting block comments that +contain valid Python syntax that are likely to be commented out code. +(It avoids false positives like the sentence ``this is not good``, +which is valid Python syntax, but is probably not code.) + +%prep +%setup -q -n eradicate-%{version} +cp %{SOURCE1} . + +%build +%python_build + +%install +%python_install +%python_expand %fdupes %{buildroot}%{$python_sitelib} + +%python_clone -a %{buildroot}%{_bindir}/eradicate + +%post +%python_install_alternative eradicate + +%postun +%python_uninstall_alternative eradicate + +%check +export PYTHONPATH=. +%python_exec %{SOURCE1} + +%files %{python_files} +%doc README.rst +%python_alternative %{_bindir}/eradicate +%{python_sitelib}/* + +%changelog diff --git a/test_eradicate.py b/test_eradicate.py new file mode 100644 index 0000000..41b2899 --- /dev/null +++ b/test_eradicate.py @@ -0,0 +1,424 @@ +#!/usr/bin/env python + +"""Test suite for eradicate.""" + +from __future__ import unicode_literals + +import contextlib +import io +import subprocess +import sys +import tempfile +import unittest + +import eradicate + + +class UnitTests(unittest.TestCase): + + def test_comment_contains_code(self): + self.assertFalse(eradicate.comment_contains_code( + '#')) + + self.assertFalse(eradicate.comment_contains_code( + '# This is a (real) comment.')) + + self.assertFalse(eradicate.comment_contains_code( + '# 123')) + + self.assertFalse(eradicate.comment_contains_code( + '# 123.1')) + + self.assertFalse(eradicate.comment_contains_code( + '# 1, 2, 3')) + + self.assertFalse(eradicate.comment_contains_code( + 'x = 1 # x = 1')) + + self.assertFalse(eradicate.comment_contains_code( + '# pylint: disable=redefined-outer-name')) + + self.assertFalse(eradicate.comment_contains_code( + '# Issue #999: This is not code')) + + self.assertTrue(eradicate.comment_contains_code( + '# x = 1')) + + self.assertTrue(eradicate.comment_contains_code( + '#from foo import eradicate')) + + self.assertTrue(eradicate.comment_contains_code( + '#import eradicate')) + + self.assertTrue(eradicate.comment_contains_code( + '#"key": value,')) + + self.assertTrue(eradicate.comment_contains_code( + '#"key": "value",')) + + self.assertTrue(eradicate.comment_contains_code( + '#"key": 1 + 1,')) + + self.assertTrue(eradicate.comment_contains_code( + "#'key': 1 + 1,")) + + self.assertTrue(eradicate.comment_contains_code( + '#"key": {')) + + self.assertTrue(eradicate.comment_contains_code( + '#}')) + + self.assertTrue(eradicate.comment_contains_code( + '#} )]')) + + self.assertTrue(eradicate.comment_contains_code( + '#},')) + + def test_comment_contains_code_with_print(self): + self.assertTrue(eradicate.comment_contains_code( + '#print')) + + self.assertTrue(eradicate.comment_contains_code( + '#print(1)')) + + self.assertTrue(eradicate.comment_contains_code( + '#print 1')) + + self.assertFalse(eradicate.comment_contains_code( + '#to print')) + + def test_comment_contains_code_with_return(self): + self.assertTrue(eradicate.comment_contains_code( + '#return x')) + + self.assertFalse(eradicate.comment_contains_code( + '#to return')) + + def test_comment_contains_code_with_multi_line(self): + self.assertTrue(eradicate.comment_contains_code( + '#def foo():')) + + self.assertTrue(eradicate.comment_contains_code( + '#else:')) + + self.assertTrue(eradicate.comment_contains_code( + '# else : ')) + + self.assertTrue(eradicate.comment_contains_code( + '# "foo %d" % \\')) + + self.assertTrue(eradicate.comment_contains_code( + '#elif True:')) + + self.assertTrue(eradicate.comment_contains_code( + '#x = foo(')) + + self.assertTrue(eradicate.comment_contains_code( + '#except Exception:')) + + self.assertFalse(eradicate.comment_contains_code( + '# this is = to that :(')) + + self.assertFalse(eradicate.comment_contains_code( + '#else')) + + self.assertFalse(eradicate.comment_contains_code( + '#or else:')) + + self.assertFalse(eradicate.comment_contains_code( + '#else True:')) + + def test_comment_contains_code_with_sentences(self): + self.assertFalse(eradicate.comment_contains_code( + '#code is good')) + + def test_comment_contains_code_with_encoding(self): + self.assertFalse(eradicate.comment_contains_code( + '# coding=utf-8')) + + self.assertFalse(eradicate.comment_contains_code( + '#coding= utf-8')) + + self.assertFalse(eradicate.comment_contains_code( + '# coding: utf-8')) + + self.assertFalse(eradicate.comment_contains_code( + '# encoding: utf8')) + + self.assertTrue(eradicate.comment_contains_code( + '# codings=utf-8')) + + def test_commented_out_code_line_numbers(self): + self.assertEqual( + [1, 3], + list(eradicate.commented_out_code_line_numbers( + """\ +# print(5) +# This is a comment. +# x = 1 + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +"""))) + + def test_commented_out_code_line_numbers_with_errors(self): + self.assertEqual( + [1, 3], + list(eradicate.commented_out_code_line_numbers( + """\ +# print(5) +# This is a comment. +# x = 1 + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +def foo(): + 1 + 2 +"""))) + + def test_commented_out_code_line_numbers_with_with_statement(self): + self.assertEqual( + [1, 2], + list(eradicate.commented_out_code_line_numbers("""\ +# with open('filename', 'w') as out_file: +# json.dump(objects, out_file) +# +"""))) + + def test_commented_out_code_line_numbers_with_for_statement(self): + self.assertEqual( + [1, 2], + list(eradicate.commented_out_code_line_numbers("""\ +# for x in y: +# oops = x.ham +"""))) + + def test_filter_commented_out_code(self): + self.assertEqual( + """\ +# This is a comment. + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +""", + ''.join(eradicate.filter_commented_out_code( + """\ +# print(5) +# This is a comment. +# x = 1 + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +# try: +# x = 1 +# finally: +# x = 0 +"""))) + + def test_filter_commented_out_code_should_avoid_escaped_newlines(self): + line = """\ +if False: \\ +# print(3) + print(2) + print(3) +""" + self.assertEqual( + line, + ''.join(eradicate.filter_commented_out_code(line))) + + def test_filter_commented_out_code_with_larger_example(self): + self.assertEqual( + """\ +# This is a comment. + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +""", + ''.join(eradicate.filter_commented_out_code( + """\ +# print(5) +# This is a comment. +# x = 1 + +y = 1 # x = 3 + +# The below is another comment. +# 3 / 2 + 21 +"""))) + + def test_filter_commented_out_code_without_aggressive(self): + code = """\ +# iterate through choices inside of parenthesis (separated by '|'): + +# if the Optional takes a value, format is: +# -s ARGS, --long ARGS +""" + self.assertEqual( + code, + ''.join(eradicate.filter_commented_out_code(code, + aggressive=False))) + + def test_filter_commented_out_code_with_annotation(self): + self.assertEqual( + '\n\n\n', + ''.join(eradicate.filter_commented_out_code("""\ +# class CommentedClass(object): +# def __init__(self, prop: int) -> None: +# self.property = prop + +# def __str__(self) -> str: +# return self.__class__.__name__ + +# def set_prop(self, prop: int): +# self.prop = prop + +# def get_prop(self): +# return self.prop +"""))) + + def test_detect_encoding_with_bad_encoding(self): + with temporary_file('# -*- coding: blah -*-\n') as filename: + self.assertEqual('latin-1', + eradicate.detect_encoding(filename)) + + +class SystemTests(unittest.TestCase): + + def test_diff(self): + with temporary_file("""\ +# x * 3 == False +# x is a variable +""") as filename: + output_file = io.StringIO() + eradicate.main(argv=['my_fake_program', filename], + standard_out=output_file, + standard_error=None) + self.assertEqual("""\ +@@ -1,2 +1 @@ +-# x * 3 == False + # x is a variable +""", '\n'.join(output_file.getvalue().split('\n')[2:])) + + def test_recursive(self): + with temporary_directory() as directory: + + with temporary_file("""\ +# x * 3 == False +# x is a variable +""", directory=directory): + + output_file = io.StringIO() + eradicate.main(argv=['my_fake_program', + '--recursive', + directory], + standard_out=output_file, + standard_error=None) + self.assertEqual("""\ +@@ -1,2 +1 @@ +-# x * 3 == False + # x is a variable +""", '\n'.join(output_file.getvalue().split('\n')[2:])) + + def test_ignore_hidden_directories(self): + with temporary_directory() as directory: + with temporary_directory(prefix='.', + directory=directory) as inner_directory: + + with temporary_file("""\ +# x * 3 == False +# x is a variable +""", directory=inner_directory): + + output_file = io.StringIO() + eradicate.main(argv=['my_fake_program', + '--recursive', + directory], + standard_out=output_file, + standard_error=None) + self.assertEqual( + '', + output_file.getvalue().strip()) + + def test_in_place(self): + with temporary_file("""\ +# x * 3 == False +# x is a variable +""") as filename: + output_file = io.StringIO() + eradicate.main(argv=['my_fake_program', '--in-place', filename], + standard_out=output_file, + standard_error=None) + with open(filename) as f: + self.assertEqual("""\ +# x is a variable +""", f.read()) + + def test_with_missing_file(self): + output_file = io.StringIO() + ignore = StubFile() + eradicate.main(argv=['my_fake_program', '--in-place', '.fake'], + standard_out=output_file, + standard_error=ignore) + self.assertFalse(output_file.getvalue()) + + def test_end_to_end(self): + with temporary_file("""\ +# x * 3 == False +# x is a variable +""") as filename: + process = subprocess.Popen([sys.executable, + './eradicate', filename], + stdout=subprocess.PIPE) + self.assertEqual("""\ +@@ -1,2 +1 @@ +-# x * 3 == False + # x is a variable +""", '\n'.join(process.communicate()[0].decode().split('\n')[2:])) + + +@contextlib.contextmanager +def temporary_file(contents, directory='.', prefix=''): + """Write contents to temporary file and yield it.""" + f = tempfile.NamedTemporaryFile(suffix='.py', prefix=prefix, + delete=False, dir=directory) + try: + f.write(contents.encode()) + f.close() + yield f.name + finally: + import os + os.remove(f.name) + + +@contextlib.contextmanager +def temporary_directory(directory='.', prefix=''): + """Create temporary directory and yield its path.""" + temp_directory = tempfile.mkdtemp(prefix=prefix, dir=directory) + try: + yield temp_directory + finally: + import shutil + shutil.rmtree(temp_directory) + + +class StubFile(object): + + """Fake file that ignores everything.""" + + def write(*_): + """Ignore.""" + + +if __name__ == '__main__': + unittest.main()