Alors comme tu le sais probablement je suis un énorme fan de Rust, donc j’ai tendance à être plutôt d’accord avec toi.
Ton commentaire m’a donné une idée, à partir de python 3.5, il y a les type hints pour définir du typage optionnel: PEP 484 – Type Hints | peps.python.org.
Bref qu’est ce que ça donne si j’ajoute du typage ?
Le code avec du typage (pas partout):
# bug.py
from datetime import datetime, timezone
import unittest
from typing import Dict, List, Any
class Share():
instance_uuid = None
share_id = None
status = None
tag = None
export_location = None
share_proto = None
def map_to_share_object(share: Share,
fields: List[str],
db_share: Dict[str, Any]):
for field in fields:
setattr(share, field, db_share[field])
def main()->None:
NOW = datetime.now(timezone.utc)
share = Share()
fake_db_share = {
'created_at': NOW,
'updated_at': None,
'deleted_at': None,
'deleted': False,
"id": 1,
"instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"share_id": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"status": "attaching",
"tag": "e8debdc0-447a-4376-a10a-4cd9122d7986",
"export_location": "10.0.0.50:/mnt/foo",
"share_proto": "NFS",
},
fake_instance = {
"instance_uuid": "aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa",
"instance_flavor": "tiny"
}
map_to_share_object(share,
[
"instance_uuid",
"share_id",
"status",
"tag",
"export_location",
"share_proto"
],
fake_db_share)
test = unittest.TestCase()
test.assertEqual(share.instance_uuid,
'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa')
test.assertEqual(share.share_id,
'e8debdc0-447a-4376-a10a-4cd9122d7986')
test.assertEqual(share.status,
'attaching')
test.assertEqual(share.tag,
'e8debdc0-447a-4376-a10a-4cd9122d7986')
test.assertEqual(share.export_location,
'10.0.0.50:/mnt/foo')
test.assertEqual(share.share_proto,
'NFS')
if __name__ == '__main__':
main()
Ensuite je lance mypy
pour faire l’analyse statique:
🦉 rribaud ~ workspace bug mypy bug.py
bug.py:54: error: Argument 3 to "map_to_share_object" has incompatible type "Tuple[Dict[str, Union[str, int, bool, datetime, None]]]"; expected "Dict[str, Any]"
Found 1 error in 1 file (checked 1 source file)
AMHA, c’est quand même mieux.
- Déja on trouve le problème pas au runtime. A contrario sans le typage, si le code n’est pas éxécuté, on ne voit pas le problème. (d’ou l’importance encore plus grande des tests et de la couverture)
- Ca donne une information plus précise sur l’origine du problème. On sait que le soucis vient de l’argument 3.
- Ca “autodocumente” le code grace à la signature de la fonction.