diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 00000000..f052f5bc --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,13 @@ +# Please see the documentation for all configuration options: +# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: weekly + - package-ecosystem: "pip" + directory: "/" + schedule: + interval: weekly diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ca2a8b86..de5a6fbe 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,10 +32,10 @@ jobs: - name: Install dependencies run: | - python3 -m pip install --upgrade pip - python3 -m pip install --upgrade setuptools wheel setuptools_scm ruff - python3 -m pip install sphinx - python3 -m pip install ".[test,twisted]" + python -m pip install --upgrade pip + python -m pip install --upgrade setuptools wheel setuptools_scm + python -m pip install sphinx + python -m pip install ".[test,twisted,dev]" - name: Ruff run: | diff --git a/pyproject.toml b/pyproject.toml index 9f2030ca..d2e56228 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -54,13 +54,6 @@ include-package-data = false include = ["testtools"] exclude = ["man*"] -[tool.extras] -test = """ -testscenarios -testresources""" -twisted = """ -Twisted""" - [tool.files] packages = "testtools" @@ -79,3 +72,4 @@ __version__ = {version_tuple!r} [project.optional-dependencies] test = ["testscenarios", "testresources"] twisted = ["Twisted", "fixtures"] +dev = ["ruff==0.4.4"] diff --git a/testtools/tests/matchers/test_basic.py b/testtools/tests/matchers/test_basic.py index 07ae59cb..b0ebf077 100644 --- a/testtools/tests/matchers/test_basic.py +++ b/testtools/tests/matchers/test_basic.py @@ -230,8 +230,8 @@ def test_describe(self): self.assertEqual("'fo' does not start with 'bo'.", mismatch.describe()) def test_describe_non_ascii_unicode(self): - string = "A\xA7" - suffix = "B\xA7" + string = "A\xa7" + suffix = "B\xa7" mismatch = DoesNotStartWith(string, suffix) self.assertEqual( "{} does not start with {}.".format(text_repr(string), text_repr(suffix)), @@ -239,8 +239,8 @@ def test_describe_non_ascii_unicode(self): ) def test_describe_non_ascii_bytes(self): - string = _b("A\xA7") - suffix = _b("B\xA7") + string = _b("A\xa7") + suffix = _b("B\xa7") mismatch = DoesNotStartWith(string, suffix) self.assertEqual( f"{string!r} does not start with {suffix!r}.", mismatch.describe() @@ -255,12 +255,12 @@ def test_str(self): self.assertEqual("StartsWith('bar')", str(matcher)) def test_str_with_bytes(self): - b = _b("\xA7") + b = _b("\xa7") matcher = StartsWith(b) self.assertEqual(f"StartsWith({b!r})", str(matcher)) def test_str_with_unicode(self): - u = "\xA7" + u = "\xa7" matcher = StartsWith(u) self.assertEqual(f"StartsWith({u!r})", str(matcher)) @@ -291,8 +291,8 @@ def test_describe(self): self.assertEqual("'fo' does not end with 'bo'.", mismatch.describe()) def test_describe_non_ascii_unicode(self): - string = "A\xA7" - suffix = "B\xA7" + string = "A\xa7" + suffix = "B\xa7" mismatch = DoesNotEndWith(string, suffix) self.assertEqual( "{} does not end with {}.".format(text_repr(string), text_repr(suffix)), @@ -300,8 +300,8 @@ def test_describe_non_ascii_unicode(self): ) def test_describe_non_ascii_bytes(self): - string = _b("A\xA7") - suffix = _b("B\xA7") + string = _b("A\xa7") + suffix = _b("B\xa7") mismatch = DoesNotEndWith(string, suffix) self.assertEqual( f"{string!r} does not end with {suffix!r}.", mismatch.describe() @@ -316,12 +316,12 @@ def test_str(self): self.assertEqual("EndsWith('bar')", str(matcher)) def test_str_with_bytes(self): - b = _b("\xA7") + b = _b("\xa7") matcher = EndsWith(b) self.assertEqual(f"EndsWith({b!r})", str(matcher)) def test_str_with_unicode(self): - u = "\xA7" + u = "\xa7" matcher = EndsWith(u) self.assertEqual(f"EndsWith({u!r})", str(matcher)) @@ -404,8 +404,8 @@ class TestMatchesRegex(TestCase, TestMatchersInterface): ("MatchesRegex('a|b')", MatchesRegex("a|b")), ("MatchesRegex('a|b', re.M)", MatchesRegex("a|b", re.M)), ("MatchesRegex('a|b', re.I|re.M)", MatchesRegex("a|b", re.I | re.M)), - ("MatchesRegex({!r})".format(_b("\xA7")), MatchesRegex(_b("\xA7"))), - ("MatchesRegex({!r})".format("\xA7"), MatchesRegex("\xA7")), + ("MatchesRegex({!r})".format(_b("\xa7")), MatchesRegex(_b("\xa7"))), + ("MatchesRegex({!r})".format("\xa7"), MatchesRegex("\xa7")), ] describe_examples = [ @@ -414,9 +414,9 @@ class TestMatchesRegex(TestCase, TestMatchersInterface): ( "{!r} does not match /\\s+\\xa7/".format(_b("c")), _b("c"), - MatchesRegex(_b("\\s+\xA7")), + MatchesRegex(_b("\\s+\xa7")), ), - ("{!r} does not match /\\s+\\xa7/".format("c"), "c", MatchesRegex("\\s+\xA7")), + ("{!r} does not match /\\s+\\xa7/".format("c"), "c", MatchesRegex("\\s+\xa7")), ] diff --git a/testtools/tests/test_compat.py b/testtools/tests/test_compat.py index fc121229..92a4d9a5 100644 --- a/testtools/tests/test_compat.py +++ b/testtools/tests/test_compat.py @@ -111,7 +111,7 @@ class TestTextRepr(testtools.TestCase): ("'", '"\'"', "'''\\\n\\''''"), ("\\", "'\\\\'", "'''\\\n\\\\'''"), # DEL is also unprintable and should be escaped - ("\x7F", "'\\x7f'", "'''\\\n\\x7f'''"), + ("\x7f", "'\\x7f'", "'''\\\n\\x7f'''"), # Character combinations that need double checking ("\r\n", "'\\r\\n'", "'''\\\n\\r\n'''"), ("\"'", "'\"\\''", "'''\\\n\"\\''''"), @@ -127,29 +127,29 @@ class TestTextRepr(testtools.TestCase): # Bytes with the high bit set should always be escaped bytes_examples = ( (_b("\x80"), "'\\x80'", "'''\\\n\\x80'''"), - (_b("\xA0"), "'\\xa0'", "'''\\\n\\xa0'''"), - (_b("\xC0"), "'\\xc0'", "'''\\\n\\xc0'''"), - (_b("\xFF"), "'\\xff'", "'''\\\n\\xff'''"), - (_b("\xC2\xA7"), "'\\xc2\\xa7'", "'''\\\n\\xc2\\xa7'''"), + (_b("\xa0"), "'\\xa0'", "'''\\\n\\xa0'''"), + (_b("\xc0"), "'\\xc0'", "'''\\\n\\xc0'''"), + (_b("\xff"), "'\\xff'", "'''\\\n\\xff'''"), + (_b("\xc2\xa7"), "'\\xc2\\xa7'", "'''\\\n\\xc2\\xa7'''"), ) # Unicode doesn't escape printable characters as per the Python 3 model unicode_examples = ( # C1 codes are unprintable ("\x80", "'\\x80'", "'''\\\n\\x80'''"), - ("\x9F", "'\\x9f'", "'''\\\n\\x9f'''"), + ("\x9f", "'\\x9f'", "'''\\\n\\x9f'''"), # No-break space is unprintable - ("\xA0", "'\\xa0'", "'''\\\n\\xa0'''"), + ("\xa0", "'\\xa0'", "'''\\\n\\xa0'''"), # Letters latin alphabets are printable - ("\xA1", "'\xa1'", "'''\\\n\xa1'''"), - ("\xFF", "'\xff'", "'''\\\n\xff'''"), + ("\xa1", "'\xa1'", "'''\\\n\xa1'''"), + ("\xff", "'\xff'", "'''\\\n\xff'''"), ("\u0100", "'\u0100'", "'''\\\n\u0100'''"), # Line and paragraph seperators are unprintable ("\u2028", "'\\u2028'", "'''\\\n\\u2028'''"), ("\u2029", "'\\u2029'", "'''\\\n\\u2029'''"), # Unpaired surrogates are unprintable - ("\uD800", "'\\ud800'", "'''\\\n\\ud800'''"), - ("\uDFFF", "'\\udfff'", "'''\\\n\\udfff'''"), + ("\ud800", "'\\ud800'", "'''\\\n\\ud800'''"), + ("\udfff", "'\\udfff'", "'''\\\n\\udfff'''"), # Unprintable general categories not fully tested: Cc, Cf, Co, Cn, Zs ) diff --git a/testtools/tests/test_tags.py b/testtools/tests/test_tags.py index e2bc70c0..d1c1b54a 100644 --- a/testtools/tests/test_tags.py +++ b/testtools/tests/test_tags.py @@ -2,7 +2,6 @@ """Test tag support.""" - from testtools import TestCase from testtools.tags import TagContext diff --git a/testtools/tests/test_testresult.py b/testtools/tests/test_testresult.py index 9790ad74..2cf240f3 100644 --- a/testtools/tests/test_testresult.py +++ b/testtools/tests/test_testresult.py @@ -2,7 +2,6 @@ """Test TestResults and related things.""" - import codecs import datetime import doctest @@ -2928,7 +2927,7 @@ def test_control_characters_in_failure_string(self): self._as_output("\a\a\a"), textoutput, ) - self.assertIn(self._as_output("\uFFFD\uFFFD\uFFFD"), textoutput) + self.assertIn(self._as_output("\ufffd\ufffd\ufffd"), textoutput) def _local_os_error_matcher(self): return MatchesAny(Contains("FileExistsError: "), Contains("PermissionError: "))