Repository: jd-boyd/sexpdata (language: python)

Issue:
Replace nosetests with pytest
nose 1 is discontinued and breaks in 3.10. nose2 is too different.


Discussion / hints:

Fix patch:
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..fed528d
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools"]
+build-backend = "setuptools.build_meta"
diff --git a/tox.ini b/tox.ini
index fb036de..a063320 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,10 +1,9 @@
 [tox]
-envlist = py27, py33, py34, py36
+envlist = py37, py38, py39, py310, py311, pypy3
+isolated_build = True
+
 [testenv]
 deps =
-  nose
   pudb
-  py27: doctest-ignore-unicode
-commands = nosetests {posargs:--with-doctest}
-[testenv:py27]
-commands = nosetests {posargs:--with-doctest --with-doctest-ignore-unicode --doctest-options='+IGNORE_UNICODE'}
+  pytest
+commands = pytest {posargs:--doctest-modules sexpdata.py test_sexpdata.py}


Test patch:
diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml
index fcebd41..d2eaeec 100644
--- a/.github/workflows/tests.yaml
+++ b/.github/workflows/tests.yaml
@@ -9,19 +9,17 @@ jobs:
       fail-fast: false
       matrix:
         python-version:
-          - 3.6
           - 3.7
           - 3.8
           - 3.9
-          - pypy-3.6
-          - pypy-3.7
+          - "3.10"
+          - "3.11"
+          - pypy-3.8
+          - pypy-3.9
         os:
           - ubuntu-latest
           - macos-latest
           - windows-latest
-        exclude:
-          - os: macos-latest
-            python-version: 'pypy-3.6'
     runs-on:  ${{ matrix.os }}
     name: ${{ matrix.os }} @ ${{ matrix.python-version }}
     steps:
@@ -31,6 +29,5 @@ jobs:
         with:
           python-version: ${{ matrix.python-version }}
           architecture: x64
-      - run: python setup.py install
-      - run: pip install nose
-      - run: nosetests --with-doctest
+      - run: pip install . pytest
+      - run: pytest --doctest-modules sexpdata.py test_sexpdata.py
diff --git a/test_sexpdata.py b/test_sexpdata.py
index 481e11f..b936e53 100644
--- a/test_sexpdata.py
+++ b/test_sexpdata.py
@@ -4,16 +4,11 @@
 from sexpdata import (
     PY3,
     ExpectClosingBracket, ExpectNothing, ExpectSExp,
-    parse, tosexp, Symbol, String, Quoted, bracket,
+    parse, tosexp, Symbol, String, Quoted, bracket, Parens,
 )
 import unittest
-from nose.tools import eq_, raises, assert_raises
 
-
-### Test utils
-
-def compare_parsed(sexp, obj):
-    eq_(parse(sexp), obj)
+import pytest
 
 
 ### Test cases
@@ -53,20 +48,14 @@ def compare_parsed(sexp, obj):
 data_identity += map(lambda x: x[1], String._lisp_quoted_specials)
 
 
-def check_identity(obj):
-    eq_(parse(tosexp(obj))[0], obj)
-
-
 def test_identity():
     for data in data_identity:
-        yield (check_identity, data)
+        assert parse(tosexp(data))[0] == data
 
-def check_identity_pretty_print(obj):
-    eq_(parse(tosexp(obj, pretty_print=True))[0], obj)
 
 def test_identity_pretty_print():
     for data in data_identity:
-        yield (check_identity_pretty_print, data)
+        assert parse(tosexp(data, pretty_print=True))[0] == data
 
 
 class BaseTestCase(unittest.TestCase):
@@ -139,63 +128,63 @@ def test_parse_raw_utf8(self):
 
 
 def test_tosexp_str_as():
-    yield (eq_, tosexp('a', str_as='symbol'), 'a')
-    yield (eq_, tosexp(['a'], str_as='symbol'), '(a)')
-    yield (eq_, tosexp('a'), '"a"')
-    yield (eq_, tosexp(['a']), '("a")')
-    yield (eq_, tosexp(Quoted('a')), '\'"a"')
-    yield (eq_, tosexp(Quoted(['a']), str_as='symbol'), '\'(a)')
-    yield (eq_, tosexp([Quoted('a')], str_as='symbol'), '(\'a)')
-    yield (eq_, tosexp(Quoted('a'), str_as='symbol'), '\'a')
-    yield (eq_, tosexp(Quoted(['a'])), '\'("a")')
-    yield (eq_, tosexp([Quoted('a')]), '(\'"a")')
+    assert tosexp('a', str_as='symbol') == 'a'
+    assert tosexp(['a'], str_as='symbol') == '(a)'
+    assert tosexp('a') == '"a"'
+    assert tosexp(['a']) == '("a")'
+    assert tosexp(Quoted('a')) == '\'"a"'
+    assert tosexp(Quoted(['a']), str_as='symbol') == '\'(a)'
+    assert tosexp([Quoted('a')], str_as='symbol') == '(\'a)'
+    assert tosexp(Quoted('a'), str_as='symbol') == '\'a'
+    assert tosexp(Quoted(['a'])) == '\'("a")'
+    assert tosexp([Quoted('a')]) == '(\'"a")'
 
 
 def test_tosexp_tuple_as():
-    yield (eq_, tosexp(('a', 'b')), '("a" "b")')
-    yield (eq_, tosexp(('a', 'b'), tuple_as='array'), '["a" "b"]')
-    yield (eq_, tosexp([('a', 'b')]), '(("a" "b"))')
-    yield (eq_, tosexp([('a', 'b')], tuple_as='array'), '(["a" "b"])')
-    yield (eq_, tosexp(Quoted(('a',))), '\'("a")')
-    yield (eq_, tosexp(Quoted(('a',)), tuple_as='array'), '\'["a"]')
+    assert tosexp(('a', 'b')) == '("a" "b")'
+    assert tosexp(('a', 'b'), tuple_as='array') == '["a" "b"]'
+    assert tosexp([('a', 'b')]) == '(("a" "b"))'
+    assert tosexp([('a', 'b')], tuple_as='array') == '(["a" "b"])'
+    assert tosexp(Quoted(('a',))) == '\'("a")'
+    assert tosexp(Quoted(('a',)), tuple_as='array') == '\'["a"]'
 
 
-@raises(ValueError)
 def test_tosexp_value_errors():
-    tosexp((), tuple_as='')
-    tosexp('', str_as='')
-    tosexp(Parens())
+    with pytest.raises(ValueError):
+        tosexp((), tuple_as='')
+    with pytest.raises(ValueError):
+        tosexp('', str_as='')
+    with pytest.raises(ValueError):
+        tosexp(Parens())
 
 
-@raises(ExpectNothing)
 def test_too_many_brackets():
-    parse("(a b))")
+    with pytest.raises(ExpectNothing):
+        parse("(a b))")
 
 
-@raises(ExpectClosingBracket)
 def test_not_enough_brackets():
-    parse("(a (b)")
+    with pytest.raises(ExpectClosingBracket):
+        parse("(a (b)")
 
 
 def test_no_eol_after_comment():
-    eq_(parse('a ; comment'), [Symbol('a')])
+    assert parse('a ; comment') == [Symbol('a')]
 
 
 def test_issue_4():
-    yield (compare_parsed, "(0 ;; (\n)", [[0]])
-    yield (compare_parsed, "(0;; (\n)", [[0]])
+    assert parse("(0 ;; (\n)") == [[0]]
+    assert parse("(0;; (\n)") == [[0]]
 
 
 def test_issue_18():
     import sexpdata
     sexp = "(foo)'   "
-    with assert_raises(ExpectSExp) as raised:
+    with pytest.raises(ExpectSExp, match='No s-exp is found after an '
+                                         'apostrophe at position 5'):
         sexpdata.parse(sexp)
-    msg = raised.exception.args[0]
-    eq_(msg, 'No s-exp is found after an apostrophe at position 5')
 
     sexp = "'   "
-    with assert_raises(ExpectSExp) as raised:
+    with pytest.raises(ExpectSExp, match='No s-exp is found after an '
+                                         'apostrophe at position 0'):
         sexpdata.parse(sexp)
-    msg = raised.exception.args[0]
-    eq_(msg, 'No s-exp is found after an apostrophe at position 0')