bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Opinions on two pylint warnings?


From: Bruno Haible
Subject: Re: Opinions on two pylint warnings?
Date: Thu, 04 Apr 2024 14:48:43 +0200

Hi Collin,

> The first is W0707 [1]. It recommends chaining exceptions. So this:
> 
>     try:  # Try to apply patch
>         sp.check_call(command, shell=True)
>     except sp.CalledProcessError:
>         raise GLError(2, name)
> 
> becomes:
> 
>     try:  # Try to apply patch
>         sp.check_call(command, shell=True)
>     except sp.CalledProcessError as exc:
>         raise GLError(2, name) from exc
> 
> This is used for the exception backtrace messages.

Let's see what the effect is:

===================== foo.py ==================
import subprocess as sp

class GLError(Exception):
   '''foo'''
   def __init__(self, errno: int) -> None:
       pass

try:
    sp.check_call('boom', shell=True)
except sp.CalledProcessError as x:
    raise GLError(2) from x
===============================================

This produces the output:

--------------------------------------------------------------------------------
/bin/sh: 1: boom: not found
Traceback (most recent call last):
  File "/home/bruno/foo.py", line 9, in <module>
    sp.check_call('boom', shell=True)
  File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'boom' returned non-zero exit status 127.

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/home/bruno/foo.py", line 11, in <module>
    raise GLError(2) from x
__main__.GLError: 2
--------------------------------------------------------------------------------

And without the chaining, it is:

--------------------------------------------------------------------------------
/bin/sh: 1: boom: not found
Traceback (most recent call last):
  File "/home/bruno/foo.py", line 9, in <module>
    sp.check_call('boom', shell=True)
  File "/usr/lib/python3.10/subprocess.py", line 369, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'boom' returned non-zero exit status 127.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/bruno/foo.py", line 11, in <module>
    raise GLError(2)
__main__.GLError: 2
--------------------------------------------------------------------------------

The only difference between the two outputs is the message between the two
stack traces. The latter sounds like a program bug; therefore I would say,
let's use the chaining — just in order to clarify that the second exception
is intended.

> The second warning is R1735 [1]. It suggests changing 'dict()' to
> '{}'. I am fine with making that change or silencing the warning.
> 
> I prefer the appearance of '{}', but can understand why some might
> dislike it:
> 
>    Dictionary:
>        var = {} # Empty dictionary.
>        # {0: 'a', 1: 'b', 2: 'c'}
>        var = {i : chr(ord('a') + i) for i in range(3)} 
> 
>    Set:
>        var = set() # We are stuck with this. :(
>        # Might be mistaken for a dictionary at a quick glance?
>        # {1, 2, 3}
>        var = {value for value in [1, 1, 2, 2, 3]}

Oh, indeed there's a fallacy here: {} denotes a dict, not a set!

>>> type({'x','y'})
<class 'set'>
>>> type({'x'})
<class 'set'>
>>> type({})
<class 'dict'>

This is surprising enough that we should add to our coding style:

  - Never use the {} literal, because it denotes a dictionary,
    as opposed to {x}, {x,y}, etc., which denote sets.

Bruno






reply via email to

[Prev in Thread] Current Thread [Next in Thread]