[issue42722] Add --debug command line option to unittest to enable post-mortem debugging
Change by Dominik V. : -- keywords: +patch pull_requests: +22755 stage: -> patch review pull_request: https://github.com/python/cpython/pull/23900 ___ Python tracker <https://bugs.python.org/issue42722> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42722] Add --debug command line option to unittest to enable post-mortem debugging
New submission from Dominik V. : Currently there is no option to use post-mortem debugging via `pdb` on a `unittest` test case which fails due to an exception being leaked. Consider the following example: ``` import unittest def foo(): for x in [1, 2, 'oops', 4]: print(x + 100) class TestFoo(unittest.TestCase): def test_foo(self): self.assertIs(foo(), None) if __name__ == '__main__': unittest.main() ``` If we were calling `foo` directly we could enter post-mortem debugging via `python -m pdb test.py`. However since `foo` is wrapped in a test case, `unittest` eats the exception and thus prevents post-mortem debugging. So I propose adding a command-line option `--debug` to unittest for running test cases in debug mode so that post-mortem debugging can be used. I see that some third-party distributions enable this, but since both `unittest` and `pdb` are part of the standard library, it would be nice if they played well together. Plus the required methods are already in place (`TestCase.debug` and `TestSuite.debug`). There is also a popular StackOverflow question on this topic: https://stackoverflow.com/questions/4398967/python-unit-testing-automatically-running-the-debugger-when-a-test-fails -- messages: 383624 nosy: Dominik V. priority: normal severity: normal status: open title: Add --debug command line option to unittest to enable post-mortem debugging type: enhancement ___ Python tracker <https://bugs.python.org/issue42722> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42597] Improve documentation of locals() w.r.t. "free variables" vs. global variables
New submission from Dominik V. : The documentation of locals() mentions that: > Free variables are returned by locals() when it is called in function blocks > [...] The term "free variable" is defined in the documentation about the execution model (https://docs.python.org/3/reference/executionmodel.html#binding-of-names): > If a variable is used in a code block but not defined there, it is a free > variable. That definition includes global variables (and builtin ones), but these are not returned by locals(). For example compare the following: ``` x = 1 def foo(): # global x x = 1 def bar(): print(locals()) y = x bar() foo() ``` If the `global x` is commented then it prints {'x': 1}, and if it is uncommented it prints {}. The same holds for names of builtins. So the documentation of locals() could mention this in the following way (emphasis added): > Free variables *of enclosing functions* are returned by locals() when it is > called in function blocks [...] - There is also a StackOverflow question, that describes this confusion: https://stackoverflow.com/questions/12919278/how-to-define-free-variable-in-python By the way, would it be helpful to add the term "free variable" to the glossary (https://docs.python.org/3/glossary.html)? -- assignee: docs@python components: Documentation messages: 382721 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Improve documentation of locals() w.r.t. "free variables" vs. global variables type: enhancement versions: Python 3.10 ___ Python tracker <https://bugs.python.org/issue42597> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42345] Equality of typing.Literal depends on the order of arguments
New submission from Dominik V. : [PEP 586](https://www.python.org/dev/peps/pep-0586/#shortening-unions-of-literals) specifies that Literal[v1, v2, v3] is equivalent to Union[Literal[v1], Literal[v2], Literal[v3]] Since the equality of Unions doesn't take into account the order of arguments, Literals parametrized with multiple arguments should not be order dependent either. However they seem to: >>> Literal[1, 2] == Literal[2, 1] False Compare with the equivalent form: >>> Union[Literal[1], Literal[2]] == Union[Literal[2], Literal[1]] True In addition to that, the PEP specifies that nested Literals should be equivalent to the flattened version (https://www.python.org/dev/peps/pep-0586/#legal-parameters-for-literal-at-type-check-time). This section is titled "Legal parameters for Literal at type check time" but since the PEP doesn't specify runtime behavior differently, I think it makes sense to assume it is the same. It seems to be different though: >>> Literal[Literal[1, 2], 3] typing.Literal[typing.Literal[1, 2], 3] >>> Literal[Literal[1, 2], 3] == Literal[1, 2, 3] False Also the flattening follows from the above definition `Literal[v1, v2, v3] == Union[Literal[v1], Literal[v2], Literal[v3]]` and the fact that Unions are flattened. -- messages: 380888 nosy: Dominik V. priority: normal severity: normal status: open title: Equality of typing.Literal depends on the order of arguments type: behavior versions: Python 3.9 ___ Python tracker <https://bugs.python.org/issue42345> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42317] Docs of `typing.get_args`: Mention that due to caching of typing generics the order of arguments for Unions can be different from the one of the returned tuple
Dominik V. added the comment: Thinking more about it, I came to realize that it's not the Union that sits at the root of this behavior, but rather the caching performed by generic types in general. So if we consider ``` L1 = List[Union[int, str]] L2 = List[Union[str, int]] ``` then `get_args(L1)[0] is get_args(L2)[0]` and so `get_args` has no influence on the order of arguments of the Union objects (they are already the same for L1 and L2). So I think it would be more accurate to add the following sentence instead: > If `X` is a generic type, the returned objects `(Y, Z, ...)` might not be > identical to the ones used in the form `X[Y, Z, ...]` due to type caching. Everything else follows from there (including flattening of nested Unions). -- ___ Python tracker <https://bugs.python.org/issue42317> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42317] Docs of `typing.get_args`: Mention that due to caching of typing generics the order of arguments for Unions can be different from the one of the returned tuple
Change by Dominik V. : -- keywords: +patch pull_requests: +22150 stage: needs patch -> patch review pull_request: https://github.com/python/cpython/pull/23254 ___ Python tracker <https://bugs.python.org/issue42317> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue42317] Docs of `typing.get_args`: Mention that due to caching of typing generics the order of arguments for Unions can be different from the one of the returned tuple
New submission from Dominik V. : Due to caching of `__getitem__` for generic types, the order of arguments as returned by `get_args` might be different for Union: ```python >>> from typing import List, Union, get_args >>> get_args(get_args(List[Union[int, str]])[0]) (, ) >>> get_args(get_args(List[Union[str, int]])[0]) (, ) ``` This is because `List[Union[int, str]] is List[Union[str, int]]`. I understand that caching is useful to reduce the memory footprint of type hints, so I suggest to update the documentation of `get_args`. At the moment it reads: > For a typing object of the form X[Y, Z, ...] these functions return X and (Y, > Z, ...). This seems to imply that the returned objects are identical to the ones in the form `X[Y, Z, ...]`. However that's not the case: ```python >>> U1 = Union[int, str] >>> U2 = Union[str, int] >>> get_args(List[U1])[0] is U1 True >>> get_args(List[U2])[0] is U2 False ``` I'm not so much concerned about the identity, but the fact that a subsequent call to `get_args` on the Union returns a different type seems to be relevant. So I propose to add the following sentence to the `get_args` docs: > [...], it gets normalized to the original class. > If `X` is a `Union`, the order of `(Y, Z, ...)` can be different from the one > of the original arguments `[Y, Z, ...]`. Or alternatively: > [...], it gets normalized to the original class. > If `X` is a `Union`, the order of `(Y, Z, ...)` is arbitrary. The second version is shorter but it's not completely accurate (since the order is actually not arbitrary). -- assignee: docs@python components: Documentation messages: 380699 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Docs of `typing.get_args`: Mention that due to caching of typing generics the order of arguments for Unions can be different from the one of the returned tuple type: enhancement versions: Python 3.9 ___ Python tracker <https://bugs.python.org/issue42317> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41496] Create public API for typing._eval_type
Change by Dominik V. : -- keywords: +patch pull_requests: +20898 stage: -> patch review pull_request: https://github.com/python/cpython/pull/21753 ___ Python tracker <https://bugs.python.org/issue41496> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41496] Create public API for typing._eval_type
New submission from Dominik V. : In this [python-ideas thread](https://mail.python.org/archives/list/python-id...@python.org/thread/T6K4DWENPM7LYXSDVYQYDVFEVBMA5K3L/) it was suggested to create a public API for `typing._eval_type` in order to be able to create custom versions of `get_type_hints`. Specifically a version that allows to specify an upper boundary in the MRO when retrieving type hints for a class object. The public API should use `None` as defaults for `globalns` and `localns` and not expose the `recursive_guard` parameter. -- messages: 374933 nosy: Dominik V. priority: normal severity: normal status: open title: Create public API for typing._eval_type type: enhancement versions: Python 3.10 ___ Python tracker <https://bugs.python.org/issue41496> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40344] Programming FAQ about "What is the most efficient way to concatenate many strings together?" -- Improving the example
Dominik V. added the comment: It was not my intention to disturb the traffic on the bug tracker. My apologies if that caused any trouble. I also thought only people subscribed to the indicated topic (e.g. "Documentation") would receive a notification. The docs pages mention that for enhancement proposals one should submit a bug report on the tracker: > If you find a bug in this documentation or would like to propose an > improvement, please submit a bug report on the tracker > (https://docs.python.org/3/bugs.html). I do care about the quality of Python's documentation and I think it could be improved in these cases. Often it is newcomers who consult these pages and they might be irritated by the mentioned parts. I see how it would be distracting to include a more complex real world example, but using an example which performs apparently superfluous steps without any additional comment might seem strange. More experienced users probably won't need such an example at all. In addition it might make people falsely belief that `str.join` expects a list of strings rather than any iterable, and hence the explicit construction of the list. -- ___ Python tracker <https://bugs.python.org/issue40344> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40348] Programming FAQ about "What is delegation?": Fix typos
New submission from Dominik V. : https://docs.python.org/3/faq/programming.html#what-is-delegation The code example uses `self._outfile` with a single leading underscore, however in the subsequent text it is referred to with a double leading underscore: * [...] calling the underlying `self.__outfile.write()` method. * All other methods are delegated to the underlying `self.__outfile` object. These should be fixed to use a single leading underscore as well. -- assignee: docs@python components: Documentation messages: 366896 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "What is delegation?": Fix typos type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40348> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40347] Programming FAQ about "How do you remove duplicates from a list?" -- Improve the examples + Mention possible caveats
New submission from Dominik V. : https://docs.python.org/3/faq/programming.html#how-do-you-remove-duplicates-from-a-list In the beginning it points to the recipes at https://code.activestate.com/recipes/52560/ which does mention various caveats such as > [...] whether [elements are] hashable, and whether they support full > comparisons. It then shows a concrete example implementation which however does require that the elements define a total ordering. The code for the example is pretty long so it might discourage new programmers before they even discover the most likely best solution which comes at the end of the section: list(set(mylist)) This seems by far the most useful solution with evidence from this StackOverflow question: https://stackoverflow.com/questions/7961363/removing-duplicates-in-lists Hence I propose two changes: 1. Include the first sentence of the abstract from the recipes at https://code.activestate.com/recipes/52560/ in the FAQs: "The fastest way to remove duplicates from a sequence depends on some pretty subtle properties of the sequence elements, such as whether they're hashable, and whether they support full comparisons." at the beginning in order to mention possible caveats. 2. Either remove or move the code example relying on `sort` in order to give more visibility to the most likely more relevant solution using `set`. In any case it has the disclaimer about hashability and hence won't trick people into believing it works for all cases. If the `sort` example is not removed, at least it's description should mention that elements must define a total ordering (e.g. if the elements are sets it won't generally work). -- assignee: docs@python components: Documentation messages: 366893 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "How do you remove duplicates from a list?" -- Improve the examples + Mention possible caveats type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40347> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40345] Programming FAQ about "How do I iterate over a sequence in reverse order?" should be more precise about `reversed`
New submission from Dominik V. : https://docs.python.org/3/faq/programming.html#how-do-i-iterate-over-a-sequence-in-reverse-order It contains the following example: for x in reversed(sequence): ... # do something with x ... With the note: > This won’t touch your original sequence, but build a new copy with reversed > order to iterate over. The part about "build a new copy" is not correct in a sense that `reversed` just returns an iterator over the original sequence. This has mainly two consequences: 1. It can't be indexed, i.e. `reversed(sequence)[0]` doesn't work. 2. Changing the original sequence after `r = reversed(sequence)` has been constructed, is reflected in `r` when iterating over it. So the sentence should be changed into something like: > This creates an iterator object that can be used to iterate over the original > sequence in reverse order. Then for the second example about `sequence[::-1]` it would be good to mention the difference to `reversed`, namely that this version *does* create a copy of the original list (in reverse order). It could also be used as an opportunity to show how to reverse a string, since that is a very popular question on StackOverflow. Also the various mentions of Python versions 2.3 and 2.4 seem strange since this is documentation about Python 3 and those version are anyway very old. So they should be left out as well. -- assignee: docs@python components: Documentation messages: 366889 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "How do I iterate over a sequence in reverse order?" should be more precise about `reversed` type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40345> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40344] Programming FAQ about "What is the most efficient way to concatenate many strings together?" -- Improving the example
Dominik V. added the comment: Here's the link to the relevant section: https://docs.python.org/3/faq/programming.html#what-is-the-most-efficient-way-to-concatenate-many-strings-together -- ___ Python tracker <https://bugs.python.org/issue40344> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40344] Programming FAQ about "What is the most efficient way to concatenate many strings together?" -- Improving the example
New submission from Dominik V. : The section mentions the usage of `str.join` and contains the following example: chunks = [] for s in my_strings: chunks.append(s) result = ''.join(chunks) Since `join` accepts any iterable the creation of the `chunks` list in a for loop is superfluous. If people just copy & paste from this FAQ they'll even end up with less performant code. The example could be improved by providing an example list such as: strings = ['spam', 'ham', 'eggs'] meal = ', '.join(strings) Arguably this isn't a particularly long list of strings, so one more example could be added using e.g. `range(100)`: numbers = ','.join(str(x) for x in range(100)) This also emphasizes the fact that `join` takes any iterable rather than just lists. -- assignee: docs@python components: Documentation messages: 366887 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "What is the most efficient way to concatenate many strings together?" -- Improving the example type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40344> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40343] Programming FAQ about "How do I call a method defined in a base class from a derived class that overrides it?" should mention the no-arguments-version of `super`
New submission from Dominik V. : Right now it contains the following example: class Derived(Base): def meth(self): super(Derived, self).meth() `super()` without arguments is beneficial for multiple reasons, so it should be used in the example. Also the paragraph speaks about versions prior 3.0 which seems strange because 1. the page is served at https://docs.python.org/3/faq/programming.html i.e. corresponding to version Python 3 2. Python 2 maintenance has been finally dropped. The provided example is still useful though, for example in multiple inheritance scenarios (though these are very specific and `super()` of course also works if base classes are compatible). So perhaps it's better left out? -- assignee: docs@python components: Documentation messages: 366884 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "How do I call a method defined in a base class from a derived class that overrides it?" should mention the no-arguments-version of `super` type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40343> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40342] Programming FAQ about "How do I apply a method to a sequence of objects?" should include the option of an explicit for-loop
New submission from Dominik V. : Right now the question is simply answered with: > result = [obj.method() for obj in mylist] However this is only appropriate if the result of the method is needed (i.e. if it's some kind of transformation). There are many cases where it's not and the method is meant to update the object in place. Here it's better to use a for loop: for obj in mylist: obj.update() Sometimes people use a one-way list comprehension hack because it saves one line: [obj.update() for obj in mylist] However this is discouraged for multiple reasons (builds a superfluous list, obfuscates the actual intent, ...). So I feel like the Programming FAQ should actively mention this scenario and promote the usage of a for loop here. -- assignee: docs@python components: Documentation messages: 366880 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "How do I apply a method to a sequence of objects?" should include the option of an explicit for-loop type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40342> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40341] Programming FAQ includes actively discouraged solutions; Should those be removed?
New submission from Dominik V. : The Programming FAQ contains multiple solutions (examples) which it describes as "shouldn't be used". The question is why are these included in the first place? Some of them are complicated in a way that a (new) programmer is unlikely to discover them by themselves. Below I include all the relevant parts, since I wasn't sure whether to open a new issue for each them. # [How do I write a function with output parameters (call by reference)?](https://docs.python.org/3/faq/programming.html#how-do-i-write-a-function-with-output-parameters-call-by-reference) Among others it contains these two list items: > 2. By using global variables. This isn’t thread-safe, and is not recommended. > [...] > 5. Or bundle up values in a class instance: [...] There’s almost never a good > reason to get this complicated. Especially number (5) is a pretty obscure way of solving that particular problem (even more so since a perfectly viable solution exists with (1), which is again recommended at the end of the paragraph). This additional recommendation of (1) at the end of the paragraph feels only necessary to draw attention away from the above do-not-use-solutions. Also solutions (3) and (4) are basically equivalent in a sense that they rely on mutable builtin objects. So either they could be merged in one example or the list version could be left out altogether. # [How do I use strings to call functions/methods?](https://docs.python.org/3/faq/programming.html#how-do-i-use-strings-to-call-functions-methods) The last bullet point: > Use locals() or eval() to resolve the function name: [...] Note: Using eval() > is slow and dangerous. If you don’t have absolute control over the contents > of the string, someone could pass a string that resulted in an arbitrary > function being executed. This solution proposes to use `eval` and then actively discourages its use later on. Instead it could mention `globals` as an analogy to `locals` with the example of retrieving a globally defined function in another namespace. # [How can I sort one list by values from another list?](https://docs.python.org/3/faq/programming.html#how-can-i-sort-one-list-by-values-from-another-list) The second part of the paragraph speaks about using a `for` loop with repeated `append` instead of using the previously mentioned list comprehension. It then speaks about the many reasons why the usage of a `for` loop is discouraged here, so it seems strange that it was mentioned in first place. Also, right now, 50% of the whole section are devoted to an analysis about what not to do for the last step which distracts from the actual solution. IMO it is sufficient to just show the list comprehension. -- assignee: docs@python components: Documentation messages: 366878 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ includes actively discouraged solutions; Should those be removed? type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40341> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40340] Programming FAQ about "How do I convert a string to a number?" contains a typo
Dominik V. added the comment: Indeed, thanks for clarifying. It seems I misunderstood the example, and perhaps that calls for a better separation. What about adding > By default, these interpret the number as decimal, so that `int('0144') == > 144` holds true and `int('0x144')` raises ValueError. -- ___ Python tracker <https://bugs.python.org/issue40340> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue40340] Programming FAQ about "How do I convert a string to a number?" contains a typo
New submission from Dominik V. : The paragraph about [How do I convert a string to a number?](https://docs.python.org/3/faq/programming.html#how-do-i-convert-a-string-to-a-number) contains the following sentence: > By default, these interpret the number as decimal, so that `int('0144') == > 144` and `int('0x144')` raises ValueError. The first part however doesn't raise an error. Most likely octal notation was meant, i.e. `int('0o144') == 144`. For consistency with the `int('0x144')` part one could also omit the equality comparison, i.e. just write `int('0o144')`. In order to emphasize that the "and" is not part of the code (though this should be displayed by the browser) once could also write: > [...] so that _both_ `int('0o144')` and `int('0x144')` raise ValueError. (emphasis added) -- assignee: docs@python components: Documentation messages: 366870 nosy: Dominik V., docs@python priority: normal severity: normal status: open title: Programming FAQ about "How do I convert a string to a number?" contains a typo type: enhancement versions: Python 3.8, Python 3.9 ___ Python tracker <https://bugs.python.org/issue40340> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com