-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tee should have a public encoding attr #43
Conversation
Not `_encoding`
Please create a new PyPi release after merging this PR. |
If there's a bug, I need to see a full example that reproduces the issue with the current state of |
I don't have a simple example that can be tested easily. You can the CI logs https://dev.azure.com/tue-robotics/tue_robocup/_build/results?buildId=5859&view=logs&j=ce00c4f3-9970-58be-17a6-619446bb3f5a&t=c1c22edd-5a48-59aa-c27e-44463b4e95bc&l=92 Let me know whether this enough for you or not |
I was able to reproduce it in a simple example. Using pynose File structure:
from tests.test_case import _TestDocTests
import unittest
class DocTests(_TestDocTests):
def __init__(self, method_name="test_doctests"):
super().__init__(method_name=method_name)
if __name__ == "__main__":
unittest.main()
import doctest
from pathlib import Path
import importlib
import os
import unittest
class _TestDocTests(unittest.TestCase):
def __init__(self, method_name: str = "test_doctests"):
"""
Constructor
:param method_name: Name of the member variable to run, this should be "test_doctests" and shouldn't
be changed.
"""
assert method_name == "test_doctests", "The method_name should be 'test_doctests'. This is the function which" \
"implements the functionality of this TestCase."
super().__init__(method_name)
def test_doctests(self):
"""
Iterates over all Python files in a path and runs doctest.testmod
"""
path = Path(__file__).parent
for root, dirs, files in os.walk(path):
for filename in files:
if filename.endswith("factorial.py") and "__init__" not in filename:
filepath = os.path.join(root, filename)
module_name = "tests"
module_name = module_name + filepath.split(module_name)[-1]
# module_name = module_name[:-3]
module_name = module_name.replace("/", ".")
module_name = module_name.rstrip(".py")
print(f"{module_name=}")
mod = importlib.import_module(module_name)
print(mod)
doctest.testmod(mod, report=1)
failed_count, attempted_count = doctest.master.summarize(True)
print("Attempted count: {}".format(attempted_count))
self.assertEqual(failed_count, 0, "{} out of {} tests failed".format(failed_count, attempted_count))
"""
This is the "example" module.
The example module supplies one function, factorial(). For example,
>>> factorial(5)
120
"""
def factorial(n):
"""Return the factorial of n, an exact integer >= 0.
>>> [factorial(n) for n in range(6)]
[1, 1, 2, 6, 24, 120]
>>> factorial(30)
265252859812191058636308480000000
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: n must be >= 0
Factorials of floats are OK, but the float must be an exact integer:
>>> factorial(30.1)
Traceback (most recent call last):
...
ValueError: n must be exact integer
>>> factorial(30.0)
265252859812191058636308480000000
It must also not be ridiculously large:
>>> factorial(1e100)
Traceback (most recent call last):
...
OverflowError: n too large
"""
import math
if not n >= 0:
raise ValueError("n must be >= 0")
if math.floor(n) != n:
raise ValueError("n must be exact integer")
if n+1 == n: # catch a value like 1e300
raise OverflowError("n too large")
result = 1
factor = 2
while factor <= n:
result *= factor
factor += 1
return result
if __name__ == "__main__":
import doctest
doctest.testmod() Run It should give you the following error: module_name='tests.lib.factorial'
<module 'tests.lib.factorial' from '/ROOT_DIR/tests/lib/factorial.py'>
E
======================================================================
ERROR: Iterates over all Python files in a path and runs doctest.testmod
----------------------------------------------------------------------
Traceback (most recent call last):
File "/ROOT_DIR/tests/test_case.py", line 38, in test_doctests
doctest.testmod(mod, report=1)
File "/home/USER/.pyenv/versions/3.8.18/lib/python3.8/doctest.py", line 1956, in testmod
runner.run(test)
File "/home/USER/.pyenv/versions/3.8.18/lib/python3.8/doctest.py", line 1452, in run
encoding = save_stdout.encoding
AttributeError: 'Tee' object has no attribute 'encoding'
----------------------------------------------------------------------
Ran 1 test in 0.001s
FAILED (errors=1) |
OK, merged. Will be shipped to PyPI sometime today. |
Shipped in |
As also in the original nose library, the Tee object should have a public
encoding
attribute instead of it being hidden. See https://github.com/nose-devs/nose/blob/7c26ad1e6b7d308cafa328ad34736d34028c122a/nose/plugins/xunit.py#L129As we use nose in combination with doctests, we get an attribute error when doctest tries to get the encoding of what doctest thinks is just a stdout, but because we use nose, it is a Tee object. Which would be fine, if it had the same attributes.
See https://github.com/python/cpython/blob/v3.8.20/Lib/doctest.py#L1452