[issue12657] Cannot override JSON encoding of basic type subclasses

2021-04-01 Thread Samuel Freilich


Samuel Freilich  added the comment:

A fully general solution for this might require a separate way to override the 
behavior for serializing dict keys (since those have to be serialized as 
strings).

--

___
Python tracker 
<https://bugs.python.org/issue12657>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue12657] Cannot override JSON encoding of basic type subclasses

2021-04-01 Thread Samuel Freilich


Samuel Freilich  added the comment:

> A modern solution for this is to define a singledispatch function (with 
> implementations for your custom types) and pass it as the `default` parameter 
> to the dump functions.

Does that work? I thought the default function only got called for 
non-serializable types.

I'm running into the same issue with some code that would like to do round-trip 
serialization of a datastructure (which doesn't need 100% generality of 
supported values but would like to deal with the existing structure of types). 
Dealing with set is easy, for example:

def default(obj):  # pass to default parameter of json.dumps
  if isinstance(obj, frozenset):
return {'_class': 'set', 'items': list(obj)}
  ...

def object_hook(obj):  # pass to object_hook parameter of json.loads
  if obj.get('_class') == 'set':
return set(decoded_dict['items'])
  ...

But you can't do the equivalent thing for tuple, even if you override 
encode/iterencode. It seems like the JSON module is making performance versus 
generality tradeoffs, it doesn't make a fresh call to encode/iterencode for 
every dict key/value for example. Which is fine, but it would be nice if there 
was a mode that allowed getting custom behavior for every type, taking the 
performance cost.

--
nosy: +sfreilich

___
Python tracker 
<https://bugs.python.org/issue12657>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue31466] No easy way to change float formatting when subclassing encoder.JSONEncoder

2021-04-01 Thread Samuel Freilich


Samuel Freilich  added the comment:

I think the less-minor issue, of which this is a small subset, is that 
JSONEncoder doesn't allow changing the behavior for default-serializable types 
at all. That means you can't choose to lose less information in round-trip 
serialization/deserialization, if that's what you want (e.g. there's no way to 
round-trip serialize a tuple with JSONEncoder, though it's trivial to do that 
for a set).

--
nosy: +sfreilich

___
Python tracker 
<https://bugs.python.org/issue31466>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue41114] "TypeError: unhashable type" could often be more clear

2020-10-13 Thread Samuel Freilich


Samuel Freilich  added the comment:

python-ideas thread: 
https://mail.python.org/archives/list/python-id...@python.org/thread/B6OMGYIM47OVGOCZLEY3MEUJDFURJRDV/

The most minimal ideas from that seem to be:

1. Maybe link to the glossary from the error message (if links to documentation 
in error messages are permissible).

2. Add a glossary entry for "unhashable" for the sake of completeness (similar 
to how there are entries for both "immutable" and "mutable").

--

___
Python tracker 
<https://bugs.python.org/issue41114>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue41114] "TypeError: unhashable type" could often be more clear

2020-09-28 Thread Samuel Freilich


Samuel Freilich  added the comment:

> I think it's reasonable to discuss the problem on python-ideas rather than on 
> a bugs issue, when it's not obvious what the right solution is.

I did start a thread there. Don't object to that, if that's a better forum for 
this sort of thing.

--

___
Python tracker 
<https://bugs.python.org/issue41114>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue41114] "TypeError: unhashable type" could often be more clear

2020-09-28 Thread Samuel Freilich


Samuel Freilich  added the comment:

> No minor tweak to the exception message will make this go away.  For 
> understanding to occur, the only way to forward is to learn a bit about 
> hashability.  That is a step that every beginner must take.

This is a derisive and beginner-hostile response that ignores half of what's 
been said by other participants in this thread.

> Also the error message itself is easily Googled

Yeah, the first thing that comes up is ~4k Stack Overflow entries where people 
are really confused by the error message.

--

___
Python tracker 
<https://bugs.python.org/issue41114>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue41114] "TypeError: unhashable type" could often be more clear

2020-09-27 Thread Samuel Freilich


Samuel Freilich  added the comment:

> The user already knows

The example I link to in the initial description appears to be one case where 
the user does not in fact know.

I do think context that this restriction applies to dict key in particular is 
very relevant. The line could use the same type for both the key and the value 
in a dict assignment, for example.

> TypeError: unhashable type: 'dict'.  Consider using an int, str, tuple, or 
> frozenset.

That seems like a pretty reasonable wording, though I think mentioning 
"dictionary key" or "set item" specifically still helps.

It could also link to the documentation directly:
https://docs.python.org/3/glossary.html#term-hashable

Though other error messages don't generally follow that pattern.

> Saying it twice doesn't help.

As the comment you were responding to noted, putting it in the type implies 
there might be additional information in documentation (or at least provides a 
place in documentation to put that information). TypeError is too general to 
say something about that specifically:
https://docs.python.org/3/library/exceptions.html#TypeError

--

___
Python tracker 
<https://bugs.python.org/issue41114>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue41114] "TypeError: unhashable type" could often be more clear

2020-06-25 Thread Samuel Freilich


New submission from Samuel Freilich :

Currently, if you (for example) put a dict as a value in a set or key in a 
dict, you get:

TypeError: unhashable type: 'dict'

I'm pretty sure this wording goes back a long time, but I've noticed that 
Python beginners tend to find this really confusing. It fits into a pattern of 
error messages where you have to explain why the error message is worded the 
way it is after you explain why the error message occurs at all. There are many 
instances of:
https://stackoverflow.com/questions/13264511/typeerror-unhashable-type-dict

It would be clearer if the message was something like:

TypeError: 'dict' can not be used as a set value because it is an unhashable 
type.

(Or "dict key" instead of "set value".)

The exception is raised in PyObject_Hash, so that doesn't have some of the 
context about how/why hash was called. That's called in a lot of places.

Possibly, PyObject_Hash and PyObject_HashNotImplemented could take the format 
string passed to PyErr_Format as an optional second argument, defaulting to the 
current behavior? Then certain callers (in particular, the set and dict 
constructor, set and dict methods that add set values or add/modify dict keys) 
could provide clearer error messages.

--
messages: 372366
nosy: sfreilich
priority: normal
severity: normal
status: open
title: "TypeError: unhashable type" could often be more clear
type: behavior

___
Python tracker 
<https://bugs.python.org/issue41114>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36871] Misleading error from unittest.mock's assert_has_calls

2019-09-24 Thread Samuel Freilich


Change by Samuel Freilich :


--
keywords: +patch
pull_requests: +15942
stage: test needed -> patch review
pull_request: https://github.com/python/cpython/pull/16361

___
Python tracker 
<https://bugs.python.org/issue36871>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36871] Misleading error from unittest.mock's assert_has_calls

2019-09-12 Thread Samuel Freilich


Samuel Freilich  added the comment:

Check out my PR, which solves a much smaller issue: It fixes a bug in the 
exception raising logic in assert_has_calls (and _awaits) which makes 
complicated problems like the one you mention much harder to debug.

Also it has tests!

--

___
Python tracker 
<https://bugs.python.org/issue36871>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36871] Misleading error from unittest.mock's assert_has_calls

2019-09-11 Thread Samuel Freilich


Samuel Freilich  added the comment:

Sure, but the bug in error-handling should still be fixed. Currently, if 
_call_matcher returns an exception, that's ignored by assert_has_calls, and the 
error message generated as a result is extremely misleading!

--

___
Python tracker 
<https://bugs.python.org/issue36871>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36871] Misleading error from unittest.mock's assert_has_calls

2019-09-11 Thread Samuel Freilich


Change by Samuel Freilich :


--
pull_requests: +15630
pull_request: https://github.com/python/cpython/pull/16005

___
Python tracker 
<https://bugs.python.org/issue36871>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36871] Misleading error from unittest.mock's assert_has_calls

2019-09-11 Thread Samuel Freilich


Samuel Freilich  added the comment:

This is still not totally fixed. This solves the underlying error with method 
specs, but not the bug that was causing the error-swallowing in 
assert_has_calls:

https://github.com/python/cpython/blob/ee536b2020b1f0baad1286dbd4345e13870324af/Lib/unittest/mock.py#L2216

expected = [self._call_matcher(c) for c in calls]
cause = expected if isinstance(expected, Exception) else None

isinstance(expected, Exception) is never true, because expected is always a 
list. It should instead be:

cause = next((e for e in expected if isinstance(e, Exception)), None)

--
nosy: +sfreilich

___
Python tracker 
<https://bugs.python.org/issue36871>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36366] Patcher stop method should be idempotent

2019-03-19 Thread Samuel Freilich


New submission from Samuel Freilich :

Currently, it's an error to call the stop() method of a patcher object created 
by mock.patch repeatedly:

>>> patch = mock.patch.object(Foo, 'BAR', 'x')
>>> patch.start()
'x'
>>> patch.stop()
>>> patch.stop()
RuntimeError: stop called on unstarted patcher

This causes unnecessary problems when test classes using mock.patch.stopall for 
cleanup are mixed with those cleaning up patches individually:

class TestA(unittest.TestCase):

  def setUp():
patcher = mock.patch.object(...)
self.mock_a = patcher.start()
self.addCleanup(patcher.stop)

  ...


class TestB(TestA):

  def setUp():
super().setUp()
self.addCleanup(mock.patch.stopall)
self.mock_b = mock.patch.object(...).start()

  ...


This fails because mock.patch.stopall stops the patch set up in TestA.setUp(), 
then that raises an exception when it's stopped again.

But why does patcher.stop() enforce that precondition? Wouldn't it be 
sufficient for it to just enforce the postcondition, that after stop() is 
called the patch is stopped()? That would make it easier to write test code 
which makes use of mock.patch.stopall, which allows the proper cleanup of 
patches to be configured much more concisely.

--
messages: 338371
nosy: sfreilich
priority: normal
severity: normal
status: open
title: Patcher stop method should be idempotent

___
Python tracker 
<https://bugs.python.org/issue36366>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue35711] Print information about an unexpectedly pending error before crashing

2019-01-10 Thread Samuel Freilich


New submission from Samuel Freilich :

_PyObject_FastCallDict and _PyObject_FastCallKeywords assert that there is no 
pending exception before calling functions that might otherwise clobber the 
exception state. However, that doesn't produce very clear output for debugging, 
since the assert failure doesn't say anything about what the pending exception 
actually was. It would be better to print the pending exception first.

--
messages: 333418
nosy: Samuel Freilich
priority: normal
severity: normal
status: open
title: Print information about an unexpectedly pending error before crashing

___
Python tracker 
<https://bugs.python.org/issue35711>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com