Humanized Opening Hours

Un parser pour les champs opening_hours d'OpenStreetMap

a marqué ce sujet comme résolu.

Bonjour tout le monde ! :)

Je voudrais vous présenter un projet de module Python : Humanized Opening Hours.

Humanized Opening Hours (HOH) est un parser pour les champs opening_hours d’OpenStreetMap, qui permettent de spécifier les horaires d’ouverture d’un lieu. Il fourni alors plusieurs méthodes pour savoir si ce lieu est ouvert à un moment donné, l’heure de sa prochaine ouverture / fermeture, ou encore pour décrire (textuellement) les heures d’ouverture pendant la semaine courante.

Le Github : https://github.com/rezemika/humanized_opening_hours

Installation

HOH est disponible sur pip, mais sous un nom différent1 : pip install osm-humanized-opening-hours.

Il nécessite aussi les modules lark-parser, pytz et babel.

Comment on s’en sert ?

Un petit bout de code vaut mieux qu’une longue digression, donc voici les méthodes les plus utiles de HOH.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import humanized_opening_hours as hoh

field = "Mo-Fr 06:00-21:00; Sa,Su 08:00-12:00"
oh = hoh.HumanizedOpeningHours(field)

# Pour savoir si c'est ouvert actuellement.
oh.is_open()
# True

# Pour savoir quand sera le prochain changement de statut (ouverture / fermeture).
oh.next_change()
# datetime.datetime(2017, 12, 24, 12, 0)

# Pour avoir une description en français des horaires d'ouverture pour la semaine en cours.
print(oh.render(locale_name="fr").plaintext_week_description())
"""
Lundi : 06:00 - 21:00
Mardi : 06:00 - 21:00
Mercredi : 06:00 - 21:00
Jeudi : 06:00 - 21:00
Vendredi : 06:00 - 21:00
Samedi : 08:00 - 12:00
Dimanche : 08:00 - 12:00
"""

Toutes les méthodes et fonctions du module ont des docstrings, vous pouvez donc faire help(hoh.OHParser) pour avoir la documentation des méthodes de HOH, et help(hoh.HOHRenderer) pour avoir celle des méthodes de la classe de rendu des champs. Dans l’exemple ci-dessus, cette classe est obtenue par la méthode render() et renvoie un objet qui fourni des méthodes permettant d’avoir des rendus "lisibles par les humains".

La méthode plaintext_week_description() permet donc d’obtenir une description textuelle des horaires pour la semaine en cours, ou pour n’importe quelle semaine en lui passant un datetime.date (pour utiliser la semaine du jour en question). Pour avoir cette description pour une journée uniquement, utilisez la méthode periods_of_day() qui renvoie un collections.namedtuple. Le nom traduit du jour est disponible via l’attribut name et la description de ses horaires via l’attribut description (qui vaut « closed » ou sa traduction si l’endroit est fermé ce jour là). La méthode humanized_time_before_next_change() renvoie une chaine traduite indiquant le temps restant avant le prochain changement de statut (par exemple, « dans 25 minutes »).

Pourquoi ce projet ?

Au départ, HOH ne devait être qu’une classe utilitaire dans le code de Goose, un projet que je vous avais présenté il y a quelques temps, et qui permet de rechercher des points d’intérêt à proximité. Seulement, cette classe grandissait, et je me suis dit qu’elle pourrait servir à d’autres, car on trouve assez peu de projets Python documentés ou à jour pour parser ces champs (les principaux que j’ai pu trouver sont pyopening_hours et Python-OpeningHours).

HOH en est actuellement à sa version 0.4.2, après plusieurs réécritures jusqu’à obtenir quelque chose de propre et maintenable. Si je le poste ici aujourd’hui, c’est notamment pour avoir vos retours sur son interface pour savoir ce que je devrais améliorer ou modifier avant de viser la 1.0.0, donc n’hésitez pas à donner vos idées et doléances ! :)

TODO-list

Voici la liste des choses actuellement prévues pour les prochaines versions de HOH.

  • Supporter plus de formats de champs.
  • Améliorer la récupération des horaires d’un jour (si l’un(e) d’entre-vous est motivé(e), j’apprécierais particulièrement une relecture extérieure pour ce point).
  • Ajouter plus de tests unitaires.
  • Rendre le parsing plus rapide (0,05 secondes par champ environ pour l’instant).

Merci d’avance pour vos retours et avis ! :)


  1. C’est suite à une erreur de ma part lors d’un premier essai d’envoi sur Pypi. J’avais voulu supprimer le paquet pour "repartir de zéro", mais impossible de réutiliser le même nom. -_-" 

+1 -0

Ça a l’air chouette et bien pensé ta bibliothèque, mais dans le fond c’est assez effrayant qu’une spécification d’heures d’ouvertures soit si complexe.

Question naturelle: c’est quoi ta stratégie de test ? Parce que les tests dans ton dépôt github aujourd’hui ont peut-être l’air un peu légers, en tout cas en comparaison avec le projet Javascript qui a une grosse batterie de tests et qui fait des retours sur les tests sur les données réelles. As-tu essayé de réutiliser leur travail pour tester ta propre bibliothèque ?

Ça a l’air chouette et bien pensé ta bibliothèque, mais dans le fond c’est assez effrayant qu’une spécification d’heures d’ouvertures soit si complexe.

Merci ! :)

Je suis d’accord, j’ai l’impression que ce format a été fait pour être plus facile à écrire qu’à parser.

Question naturelle: c’est quoi ta stratégie de test ? Parce que les tests dans ton dépôt github aujourd’hui ont peut-être l’air un peu légers, en tout cas en comparaison avec le projet Javascript qui a une grosse batterie de tests et qui fait des retours sur les tests sur les données réelles. As-tu essayé de réutiliser leur travail pour tester ta propre bibliothèque ?

gasche

En effet, pour l’instant je me contente majoritairement de vérifier que le parsing d’un champ ne lève pas d’erreur, en supposant alors que toute la procédure consistant à le transformer en arbre syntaxique "transformé" (avec le Transformer de Lark) s’est passée normalement.

Non, je connais très peu Javascript (juste assez pour faire des actions basiques sur une page web), donc je n’ai pas exploré en profondeur cette lib.

+0 -0

Update ! :)

Grâce à la magie de Lark-parser, j’ai pu envoyer un commit qui rend le parsing des champs 35 fois plus rapide (le parsing de 100 champs passe de 2,8 à 0,06 secondes).

Maintenant, avant de passer à la suite (notamment, aux derniers changements de l’API pour rendre l’usage plus simple et intuitif), j’aurais besoin de votre aide. Je cherche en effet une manière propre de récupérer les horaires d’ouverture d’une journée à partir de l’arbre syntaxique généré. Pour l’instant, tout se passe ici, mais je ne suis pas très satisfait de la version actuelle.

Auriez-vous des suggestions ou des idées pour rendre cela plus propre, plus maintenable et plus évolutif ?

Edit : Je viens aussi d’ajouter quelques tests des arbres syntaxiques générés par Lark.

Merci d’avance ! :)

+0 -0

Voilà la version 0.6.0, qui apporte pas mal de fonctionnalités et corrige quelques bugs. Un des apports majeurs est la méthode full_description(), qui permet d’avoir une description complète du champ (et pas seulement pour la semaine en cours, comme avec la méthode plaintext_week_description()). :)

1
2
3
4
5
6
7
8
>>> import humanized_opening_hours as hoh
>>> field = "Mo-Fr 06:00-21:00; Sa,Su 08:00-12:00"
>>> oh = hoh.OHParser(field)
>>> print('\n'.join(oh.render().full_description()))
"""
Monday to Friday: 06:00 to 21:00.
Saturday and Sunday: 08:00 to 12:00.
"""
+0 -0
Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte