tabnanny - Validatore di Indentazione

Scopo: Scorre il codice sorgente di Python alla ricerca di indentazioni sospette

L'uso di una indentazione consistente è importante in un linguaggio come Python dove gli spazi sono significativi. Il modulo tabnanny fornisce un lettore di codice capace di segnalare un uso ambiguo dell'indentazione.

Esecuzione da Riga di Comando

Il modo più semplice di utilizzare tabnanny è di eseguirlo da riga di comando, passando i nomi dei file da verificare. Se si passano nomi di directory, esse sono attraversate ricorsivamente per trovare file con suffisso .py da verificare.

L'esecuzione di tabnanny contro il codice sorgente di PyMOTW-it ha esposto un vecchio modulo con tabulazioni invece che spazi.

$ python3 -m tabnanny .

./fetch_podcasts.py 59 "\tfor enclosure in entry.get('enclosures', []):\n"

La riga 59 di fetch_podcasts.py ha due tabulazioni invece che 8 spazi. Questo non viene evidenziato in un editor di testi, che è stato configurato con le interruzioni di tabulazione ogni 4 spazi, quindi visivamente non vi è alcuna differenza.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# fetch_podcasts.py

from queue import Queue
import threading
import time
import urllib
from urllib.parse import urlparse

import feedparser

# Impostazione di qualche variabile globale
num_fetch_threads = 2
enclosure_queue = Queue()

# Una vera applicazione non utilizzerebbe dati
# scritti direttamente nel codice
feed_urls = [
    'http://talkpython.fm/episodes/rss',
]

def message(s):
    print('{}: {}'.format(threading.current_thread().name, s))

def download_enclosures(q):
    """Questa è la funzione di lavoro del thread.
    Elabora gli elementi nella coda uno dopo l'altro.
    Questi thread di demone girano in un ciclo infinito,
    ed escono solamente quando esce il thread principale
    """

    while True:
        message('Cerco la prossima richiesta')
        url = q.get()
        filename = url.rpartition('/')[-1]
        message('scaricamento {}'.format(filename))
        response = urllib.request.urlopen(url)
        data = response.read()
        # Salva il file scaricato nella directory corrente
        message('scrittura in {}'.format(filename))
        with open(filename, 'wb') as outfile:
            outfile.write(data)
        q.task_done()

# Impostazione di alcuni thread per ottenere le richieste
for i in range(num_fetch_threads):
    worker = threading.Thread(
        target=download_enclosures,
        args=(enclosure_queue,),
        name='worker-{}'.format(i),
    )
    worker.setDaemon(True)
    worker.start()

# Scaricamento del/i feed ed inserimento dell'url da scaricare
# nella coda.
for url in feed_urls:
    response = feedparser.parse(url, agent='fetch_podcasts.py')
    for entry in response['entries'][:5]:
	for enclosure in entry.get('enclosures', []):
	    parsed_url = urlparse(enclosure['url'])
	    message('accodamento {}'.format(
                parsed_url.path.rpartition('/')[-1]))
            enclosure_queue.put(enclosure['url'])

# Ora si attende lo svuotamento della coda, che indica che abbiamo
# elaborato tutti gli scaricamenti.
message('*** Thread principale in attesa')
enclosure_queue.join()
message('*** fatto')

Se si vogliono verificare i file ma non si vogliono vedere i dettagli degli errori, si utilizzi l'opzione -q per sopprimere tutte le informazioni a parte il nome del file.

$ python3 -m tabnanny -q .

./fetch_podcasts.py

Per poter vedere maggiori informazioni sui file esaminati, si usi l'opzione -v.

$ python3 -m tabnanny -v fetch_podcasts.py

'fetch_podcasts.py': *** Line 59: trouble in tab city! ***
offending line: "\tfor enclosure in entry.get('enclosures', []):\n"
indent not greater e.g. at tab sizes 1, 2, 3, 4

Vedere anche:

tabnanny
La documentazione della libreria standard per questo modulo.
tokenize
Scanner lessicale per codice sorgente Python
flake8
Verifica modulare del codice sorgente
pycodestyle
Verifica lo stile guida di Python
pylint
Verifica statica del codice python