# articles

feed_id: http://sametmax.com/?p=16108
title: Python-like n’a aucun intérêt 17
uri: Python-like-n-a-aucun-intérêt-7
url: http://sametmax.com/python-like-na-aucun-interet/
content:
<p>On voit passer des technos ici et là qui annoncent &#8220;un langage qui a un goût de Python&#8221;, &#8220;une syntaxe Python like&#8221;, &#8220;un preprocesseur qui converti un code compatible Python en JS&#8221;, etc.</p>
<p>Ça n&#8217;a aucun intérêt.</p>
<p>Oui, la syntaxe de Python fait parti de ses points forts, d&#8217;une des raisons qu&#8217;on aime le langage. Mais la syntaxe n&#8217;est PAS le langage.</p>
<p>Python, c&#8217;est un standard qui signifie que mon code Python tourne sur CPython, Pypy, IronPython et Jython. Ce n&#8217;est pas qu&#8217;une syntaxe. C&#8217;est aussi l&#8217;accès à une gigantesque <a href="http://sametmax.com/quest-ce-que-la-bibliotheque-standard-python/">stdlib</a>, à des milliers de paquet sur pypi, à de la métaprogrammation, à la capacité de créer des threads, du multiprocessing, des coroutines, d&#8217;accéder au système de fichier, d&#8217;attaquer une base de données, de traiter les dates, etc.</p>
<p>Ce n&#8217;est pas juste la possibilité de faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable <span style="color: #ff7700;font-weight:bold;">if</span> condition<span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Au passage, généralement les Python-like, ne font même pas ça correctement. Oubliant qu&#8217;en python on peut faire aussi :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#93;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: #ff4500;">6</span>:<span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#40;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#41;</span>
next<span style="color: black;">&#40;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#41;</span>
next<span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
<span style="color: black;">&#123;</span>x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#125;</span>
<span style="color: black;">&#123;</span>x: x * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#125;</span>
<span style="color: black;">&#91;</span>x + y <span style="color: #ff7700;font-weight:bold;">for</span> x<span style="color: #66cc66;">,</span> y <span style="color: #ff7700;font-weight:bold;">in</span> iterable<span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span>y * <span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> iterable <span style="color: #ff7700;font-weight:bold;">for</span> y <span style="color: #ff7700;font-weight:bold;">in</span> x<span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Bref, un truc qui fait vaguement comme Python n&#8217;est pas intéressant. Si je veux quelque chose de différent, je vais utiliser un autre langage. Si je veux Python, je vais utiliser Python. Pas un ersatz qui ne me donnera pas un dixième du potentiel d&#8217;un outil que je maîtrise très bien.</p>


feed_id: http://sametmax.com/?p=16116
title: async / await, la feature de dernière minute de Python 3.5 9
uri: async-await-la-feature-de-dernière-minute-de-Python-3-5
url: http://sametmax.com/async-await-la-feature-de-derniere-minute-de-python-3-5/
content:
<p>Ces mots clés vont-ils être introduits pour Python 3.5 alors qu&#8217;elle est déjà en alpha 4, et que la feature freeze est pour la prochaine version ? La release finale est prévue pour le 22 mai, ce qui est à peine un mois, pour une nouveauté <a href="https://www.python.org/dev/peps/pep-0492/#new-coroutine-declaration-syntax">formalisée début avril</a> et toujours en draft.</p>
<p>J&#8217;avoue qu&#8217;à première vue, l&#8217;idée ne m&#8217;a pas enthousiasmé.</p>
<p>D&#8217;abord, parce que ça n&#8217;apporte pas grand chose de nouveau. Les coroutines, ça existe depuis un bail maintenant, et asyncio les exploite avec <code>yield from</code>.</p>
<p>Pour résumer, la proposition est d&#8217;introduire deux mots clés tels que :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> asyncio
&nbsp;
<span style="color: #66cc66;">@</span>asyncio.<span style="color: black;">coroutine</span>
<span style="color: #ff7700;font-weight:bold;">def</span> truc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    bidule<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">yield</span> <span style="color: #ff7700;font-weight:bold;">from</span> machine_asynchrone<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    chose<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Puisse être écrit :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">async <span style="color: #ff7700;font-weight:bold;">def</span> truc<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    bidule<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    await machine_asynchrone<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    chose<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>(Notez que la coloration syntaxique ne les prends pas en compte :))</p>
<p>Le PEP propose également l&#8217;introduction de deux syntaxes pour avoir des context managers et des boucles asynchrones: <code>async with</code> et <code>async for</code></p>
<p>Et ça ne m&#8217;a pas chauffé parce que :</p>
<ul>
<li>Je ne voyais pas l’intérêt d&#8217;ajouter des mots clés pour faire un truc qu&#8217;on peut déjà faire. Le faible nombre de key words dans Python est pour moi une feature.</li>
<li>Il n&#8217;y a rien que ça permette qu&#8217;on ne pouvait pas faire avant.</li>
<li>Ça me parait un peu fait à la dernière minute, introduit comme un voleur avant la release.</li>
<li>C&#8217;est franchement moche le <code>async</code> avec un autre mot clé et ça pête toutes les attentes qu&#8217;on a eu sur la syntaxe du langage jusqu&#8217;ici : maintenant on a des qualificateurs, ce qu&#8217;on avait jamais eu avant. Ca ajouté aux type hintings, qui sont déjà très laids, c&#8217;est charger la mule.</li>
</ul>
<p>Entre temps j&#8217;y ai réfléchi et avec le recul, je commence à voir de sérieuses qualités à cette proposition :</p>
<ul>
<li>On distingue clairement le code qui est pour créer des générateurs, et le code asynchrone. Ce sont des choses qui n&#8217;ont sémantiquement rien à voir, et utiliser <code>yield from</code> pour les deux rendait tout ça bien confus.</li>
<li>C&#8217;est moins à taper : pas besoin d&#8217;importer un décorateur de 3 km et l&#8217;apposer, et quand on a pas mal de point d&#8217;arrêt, <code>await</code> c&#8217;est moins chiant à tapper que <code>yield from</code> et plus joli.</li>
<li>Ca évite pas mal de bug subtiles qui se glissent quand on utilise une coroutine pour la première fois sans comprendre tout le système. Par exemple si on vire tous les <code>yield from</code> d&#8217;une coroutine, c&#8217;est la merde, ce qui n&#8217;est pas le cas pour les <code>await</code>.</li>
<li>Quand on fait une boucle sur un generateur on sait tout de suite si on va avoir un point d&#8217;arrêt ou non.</li>
<li>Les mêmes mots clés sont utilisés dans d&#8217;autre langage, ce qui permet aux migrants de comprendre le principe bien plus vite qu&#8217;avec <code>yield</code> qu&#8217;il faut assimiler, et apprendre à distinguer dans ses deux formes.</li>
</ul>
<p>Bref, <code>async</code> et <code>await</code> sont plus explicites, amènent moins de confusion, évitent des bugs et d&#8217;une manière générale permettent une compréhension plus rapide du code, mais également du concept de l&#8217;asynchrone en général, particulièrement pour les débutants.</p>
<p>Car j&#8217;avais en effet vu pas mal de gens ne rien piger aux coroutines.</p>
<p>Du coup, même si j&#8217;aimerais que le truc ne soit pas baclé et inséré à la va vite avant la bêta, je trouve finalement que c&#8217;est pas mal. La syntaxe n&#8217;est pas fantastique, mais je n&#8217;arrive pas à imaginer mieux (alors que clairement, les <a href="https://www.python.org/dev/peps/pep-0484/">types hinting</a> seraient 100x mieux dans la docstring avec le format existant pour sphynx), donc inutile de critiquer si on apporte pas de solution. </p>


feed_id: http://sametmax.com/?p=16128
title: Point rapide sur les types hints 6
uri: Point-rapide-sur-les-types-hints-5-Recently-updated
url: http://sametmax.com/point-rapide-sur-les-types-hints/
content:
<p>Avec la 3.5 arrive les <a href="https://www.youtube.com/watch?v=2wDvzy6Hgxg">types hints</a>.</p>
<p>Pour remettre ça dans le contexte, Python 3 avait introduit les functions annotations, c&#8217;est à dire la possibilité de rajouter une information aux paramètres et valeur de retour d&#8217;une fonction. Cette information pouvait être n&#8217;importe quel objet Python :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span>a: <span style="color: #483d8b;">&quot;n'importe quel objet&quot;</span><span style="color: #66cc66;">,</span> b: <span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></td></tr></table></div>

<p>Ces annotations ne faisaient absolument rien à part être accessibles :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> add<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span>
<span style="color: #ff4500;">3</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> add.__annotations__
<span style="color: black;">&#123;</span><span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span>: <span style="color: #483d8b;">&quot;n'importe quel objet&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'return'</span>: <span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'ImportError'</span><span style="color: #66cc66;">&gt;</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Le but étant de permettre à la communauté de faire des propositions sur leur utilisation jusqu&#8217;à ce que la préférée soit retenue.</p>
<p>Aucune proposition n&#8217;a néanmoins autant de succès que de permettre optionnellement de déclarer le typage, et c&#8217;est donc ce processus qui est amorcé avec la prochaine version où l&#8217;on pourra faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> add<span style="color: black;">&#40;</span>a: <span style="color: #008000;">int</span><span style="color: #66cc66;">,</span> b: <span style="color: #008000;">int</span><span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">int</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> a + b</pre></td></tr></table></div>

<p>Pour les cas plus complexes, un module contient des interfaces courantes. Par exemple, si votre fonction fait la somme d&#8217;un itérable :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> typing <span style="color: #ff7700;font-weight:bold;">import</span> Iterable
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> total<span style="color: black;">&#40;</span>l: Iterable<span style="color: black;">&#41;</span>:</pre></td></tr></table></div>

<p>Si vous voulez limiter l&#8217;itérable à un itérable d&#8217;entiers :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> total<span style="color: black;">&#40;</span>l: Iterable<span style="color: black;">&#91;</span><span style="color: #008000;">int</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>:</pre></td></tr></table></div>

<p>Pour les fonctions très complexes, ça peut vite devenir très, très moche :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> truc<span style="color: black;">&#40;</span>l: Iterable<span style="color: black;">&#91;</span>Tuple<span style="color: black;">&#40;</span>Any<span style="color: black;">&#40;</span>Bidule<span style="color: #66cc66;">,</span> Machin<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> oui<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span>: <span style="color: #008000;">bool</span><span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span> -<span style="color: #66cc66;">&gt;</span> FuckIt:
    <span style="color: #ff7700;font-weight:bold;">return</span> FuckIt<span style="color: black;">&#40;</span>l<span style="color: #66cc66;">,</span> oui<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Par ailleurs, le module <code>typing</code> va devenir une des rares bonnes raisons d&#8217;utiliser <code>import *</code> :)</p>
<p>La spec prévoit qu&#8217;on puisse mettre ces annotations dans un fichier séparé du code avec juste la signature des fonctions. D&#8217;un côté, ça a le bénéfice de permettre d&#8217;annoter un code inaltérable, ou en Python 2.7. D&#8217;un autre, le DRY va du coup aller se faire foutre et franchement, je code pas en Python pour avoir des headers comme en C.</p>
<p>L&#8217;implémentation originale ne fera strictement rien. Elle est juste là pour voir ce que les outils vont en faire : un IDE pourra facilement trouver une erreur de type, on pourra faire des hooks git qui vérifient qu&#8217;on n&#8217;a pas niqué notre code en balançant un mauvais type et pypy/cython/nuikta/numba vont pouvoir se rouler dans la boue des optimisations.</p>
<p>Cela veut dire que si j&#8217;ignore mon IDE et que je passe des arguments d&#8217;un type qui n&#8217;est pas annoté, Python l&#8217;exécutera quand même. Ouf.</p>
<p>Le bilan ?</p>
<p>Globalement positif.</p>
<p>C&#8217;est vrai que c&#8217;est méga moche. Et les <a href="http://aroberge.blogspot.fr/2015/01/type-hinting-in-python-focus-on.html?m=1">propositions</a> <a href="https://github.com/dobarkod/typedecorator">alternatives</a> ne sont pas mieux.</p>
<p>Je rêve que les annotations dans les docstrings soient utilisées, mais Guido a dit <a href="https://twitter.com/gvanrossum/status/560944233519915008">niet</a> pour des raisons que je trouve faiblement fondées : les dosctrings sont un format libre dur à parser et alors que la syntaxe Python est structurée, avec un bon lexer. L&#8217;argument avancé dans le PEP est <a href="https://www.python.org/dev/peps/pep-0484/#other-backwards-compatible-conventions">carrément faible</a> : les docstrings ça se fold dans tous les éditeurs, c&#8217;est tout l&#8217;avantage.</p>
<p>Perso, je pense que normaliser enfin le format des docstrings ne me parait pas une mauvaise chose. Et puis si on arrive à parser le HTML pourri qu&#8217;on trouve sur le Web, 3 lignes de docstrings, c&#8217;est pas la mer à boire.</p>
<p>Néanmoins c&#8217;est optionnel, souple, et la première implémentation ne se mouille pas trop, ce qui laisse de la marge pour corriger les problèmes qui vont forcément venir.</p>
<p>Le bénéfice potentiel est énorme.</p>
<p>D&#8217;un côté, on aura toujours un langage facile à apprendre et enseigner, le duck typing, l&#8217;exploration de code, le typage dynamique par défaut.</p>
<p>De l&#8217;autre, quand un surcroit de rigueur sera nécessaire, on pourra rajouter un filet de sécurité. Et dans quelques temps, peut-être même gagner sérieusement en perf.</p>
<p>Mais quand même, putain c&#8217;est moche.</p>


feed_id: http://sametmax.com/?p=16141
title: Le débat sur la programmation fonctionnelle en Python 75
uri: Le-débat-sur-la-programmation-fonctionnelle-en-Python-11-Recently
url: http://sametmax.com/le-debat-sur-la-programmation-fonctionnelle-en-python/
content:
<p>L&#8217;écosystème Python est en ébullition depuis la 3.4 et asyncio, tout le monde se sent pousser des ailes de faire évoluer la stack. La 3.5 vient réintroduire le fameux opérateur <code>%</code> pour les bytes, sa disparition ayant fait bien chier tous les développeurs réseaux, on rajoute l&#8217;opérateur <code>@</code> (qui ne fait rien, mais qui servira à numpy pour les opérations sur les matrices), il y a bien entendu le <a href="http://sametmax.com/async-await-la-feature-de-derniere-minute-de-python-3-5/">débat</a> sur <code>async</code>/<code>await</code> et enfin le gros morceau : le <a href="sametmax.com/point-rapide-sur-les-types-hints/">type hinting</a>.</p>
<p>C&#8217;est une période formidable pour la communauté car il rappelle que Python, un langage plus vieux que Java, un langage qui est maintenant considéré comme main stream &#8211; utilisé par des sociétés corporate et l’éducation nationale &#8211; ne restera pas sur ses acquis et va continuer à se réinventer.</p>
<p>Pour cette même raison, il existe un débat parallèle qui a lieu plutôt sur reddit, hackernews, la mailling list de Python-dev et Python-idea ou par PR github interposées sur des projets type <a href="https://github.com/tobgu/pyrsistent">pyrsistent</a>. Il s&#8217;agit de faire de Python un langage fonctionnel.</p>
<h2>La programmation fonctionnelle, c&#8217;est quoi ?</h2>
<p>Ce n&#8217;est pas juste utiliser des fonctions.</p>
<p>Il y a plusieurs caractéristiques à la prog fonctionnelle, mais la plus importante est que tout est immutable (les données ne peuvent être modifiées), et par corollaire, que rien n&#8217;a d&#8217;effet de bord.</p>
<p>Ce qui signifie que dans un langage purement fonctionnel, une structure comme la liste n&#8217;aurait pas de méthode qui ne retourne rien comme <code>append()</code> ou <code>pop()</code>.</p>
<p><code>liste.append(element)</code> serait remplacé par <code>liste + [element]</code>.</p>
<p><code>element = liste.pop()</code> serait remplacé par <code>liste, element = liste[:-1], liste[-1]</code></p>
<p>Vous notez qu&#8217;on ne modifie pas la liste initiale, on recrée de nouvelles structures de données à chaque fois.</p>
<p>Une alternative serait que ces méthodes retournent une nouvelle liste plutôt que <code>None</code>.</p>
<p>Bref, c&#8217;est comme si on avait que des tuples :)</p>
<p>Bien qu&#8217;on puisse créer des formes de programmations orientées objet qui n&#8217;impliquent pas de mutabilité, dans les faits les implémentations sont pour la plupart basées justement sur le fait qu&#8217;on puisse modifier les objets, aussi on oppose souvent FP et OOP.</p>
<p>Une autre caractéristique est qu&#8217;on doit pouvoir remplacer toute expression par son résultat suivant sans changer le sens du programme. C&#8217;est très élégant :</p>
<p><code>[1, 2, 3] + [4]</code> peut être réécrit <code>[1, 2, 3, 4]</code>, et le programme aura toujours le même sens. Il n&#8217;y a pas de notion de référence dont il faut se soucier, seulement les valeurs. Cela élimine naturellement un paquet de bugs et il n&#8217;y a pas de bonne pratique à appliquer ou apprendre sur la modification des données puisque le langage vous force à coder proprement.</p>
<p>En programmation fonctionnelle, la récursion est donc souvent mise en avant. Par exemple, supposons qu&#8217;on calcule la taille d&#8217;une liste ainsi en programmation traditionnelle :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> size<span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>:
    s <span style="color: #66cc66;">=</span> <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> l:
        s +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> s</pre></td></tr></table></div>

<p>Voici une forme possible en programmation fonctionnelle :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> size<span style="color: black;">&#40;</span>l<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> l:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #ff4500;">1</span> + size<span style="color: black;">&#40;</span>l<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>La raison pour cela est qu&#8217;on peut substituer chaque expression à son résultat. Avec <code>l = [1, 2, 3]</code>:</p>
<p><code>size(l)</code> devient <code>size([1, 2, 3])</code>, qui devient <code>1 + size([2, 3])</code> qui devient <code>1 + 1 + size([3])</code> qui devient <code>1 + 1 + 1 + size([])</code> qui devient <code>1 + 1 + 1 + 0</code> qui devient <code>4</code>.</p>
<p>Quelle que soit la forme remplacée, le fonctionnement du programme est rigoureusement identique.</p>
<p>Il devient alors plus facile de prouver qu&#8217;un programme marche, de le tester, et surtout, de travailler de manière concurrente : si rien ne se modifie, nul besoin de lock et de synchronisation car rien n&#8217;est partagé et toute instruction a toujours le même comportement quel que soit le contexte.</p>
<h2>Python possède déjà des features fonctionnelles</h2>
<p>Comme en Python on peut programmer en utilisant plusieurs paradigmes, il n&#8217;y a rien d&#8217;étonnant à ce qu&#8217;on retrouve des amateurs de plusieurs écoles dans les core devs et les outils qui vont avec.</p>
<p>Bien que les listes, les sets, les objets et les dictionnaires soient mutables, les tuples, les chaînes et les entiers ne le sont pas. Par ailleurs, les fonctions sont &#8220;des citoyens de première classe&#8221;, ce qui est considéré comme un pré-requis pour la programmation fonctionnelle. Cette expression signifie qu&#8217;on peut manipuler les fonctions elles-mêmes, les créer dynamiquement, les retourner et les passer en paramètre (c.f: les <a href="sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">décorateurs</a>).</p>
<p>Même si ce n&#8217;est pas explicitement nécessaire pour faire de la programmation fonctionnelle, tout langage fonctionnel sérieux vient avec 5 outils de base :</p>
<ul>
<li><code>map()</code>: appliquer une fonction qui transforme chaque élément d&#8217;un iterable pour en obtenir un nouveau.</li>
<li><code>filter()</code>: appliquer une fonction pour filtrer chaque élément d&#8217;un iterable et en obtenir un nouveau.</li>
<li><code>reduce()</code>: appliquer une fonction aux deux premiers élements d&#8217;un iterable, puis au résultat de cette fonction et à l&#8217;élément suivant, et ainsi de suite, jusqu&#8217;à obtenir un résultat.</li>
<li>Les <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">fonctions anonymes</a>: des fonctions qui peuvent se définir sans bloc ni nom.</li>
<li>La récursion: une fonction peut s&#8217;appeler elle-même.</li>
</ul>
<p>Python possède ces outils : <code>map()</code> et <code>filter()</code> sont des builtins, <code>reduce()</code> peut être trouvé dans le module <code>functools</code> et les fonctions anonymes peuvent être créés avec le mot clés <code>lambda</code>. Et bien sûr, une fonction peut s&#8217;appeler elle-même.</p>
<p>Voyons comment créer une liste de carrés de tous les nombres impairs de 0 à 9 :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">carres <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span>:
        carres.<span style="color: black;">append</span><span style="color: black;">&#40;</span>x * x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>La version fonctionnelle avec <code>map()</code>/<code>filter()</code> et des fonctions anonymes :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">list</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x * x<span style="color: #66cc66;">,</span>  <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> x: x % <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Néanmoins Python va plus loin, puisqu&#8217;il propose les <a href="http://sametmax.com/python-love-les-listes-en-intention-partie/">listes/sets/dictionnaires en intension</a>, qui ne sont ni plus, ni moins que que <code>map()</code>/<code>filter()</code> intégrés sous forme de syntaxe :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: black;">&#91;</span>x * x <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">if</span> x % <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Ce qui est non seulement plus concis mais plus clair et plus performant que les deux versions précédentes.</p>
<p>Donc, malgré des limites que nous verrons ensuite, Python est plutôt bien armé pour la programmation fonctionnelle. La présence des générateurs et tous les outils associés (<code>itertools</code>, <code>functools</code>, <code>yield</code>, <code>yield from</code>) viennent renforcer cet aspect orienté transformation plutôt que modification.</p>
<p>Il est par ailleurs déjà considéré comme une bonne pratique d&#8217;éviter les effets de bord le plus possible, d&#8217;utiliser des générateurs et des intensions. Bref, Python n&#8217;est pas le benêt de la programmation fonctionnelle.</p>
<h2>Les limites de Python et de la programmation fonctionnelle</h2>
<p>Malgré cela, il existe de sérieuses limites pour faire de Python un langage purement fonctionnel.</p>
<p>D&#8217;abord, les listes, les dicos et les sets sont mutables. Ensuite, la récursion est limitée par la taille de la stack (par défaut 1000 récursions), il n&#8217;y a <a href="http://sametmax.com/state-machine-en-python-en-labsence-dalgos-recursifs-beneficiant-de-tail-call-optimisation/">aucune tail call optimisation</a>. Enfin, les lambdas sont bridées à une expression.</p>
<p>Ceci n&#8217;est pas arrivé par accident, mais est le résultat d&#8217;un design du langage imposé par Guido Van Rossum, son créateur et BDFL.</p>
<p>D&#8217;abord, il faut bien se souvenir que raisonner pour modifier une structure de données, c&#8217;est beaucoup plus facile pour la machine ET l&#8217;humain que d&#8217;en recréer une.</p>
<p>Les algos de tris in place sont toujours plus rapides, les transformations in place prennent moins de mémoire, et l&#8217;accumulation est bien plus facile à concevoir, relire et debugger que la récursion.</p>
<p>J&#8217;ai déjà entendu des gens me soutenir que la FP était simple. Ces gens n&#8217;ont soit jamais essayé de former d&#8217;autres personnes à la programmation, soit sont des formateurs de merde. Je pense qu&#8217;au moins ce blog me donne un minimum de crédibilité sur mes qualités de pédagogue et je m&#8217;érige donc en tant que prophète de l&#8217;intelligibilité :</p>
<blockquote><p>
En vérité, je vous le dis, la programmation fonctionnelle, c&#8217;est dur à faire comprendre.
</p></blockquote>
<p>Erlang, Lisp et Haskel ne sont pas user friendly.</p>
<p>Ne me faites pas dire ce que je n&#8217;ai pas dis. Ce sont de beaux langages, des outils performants et utiles, mais Python est 100 fois plus facile à utiliser. Il n&#8217;y a aucune comparaison possible, ce n&#8217;est même pas sur la même échelle sur le graphe.</p>
<p>Ensuite, le monde n&#8217;est pas immutable : les choses ont des états à un instant t. En informatique, une connexion réseaux a un état, un système de fichier a un état, une session a un état, etc. Les langages fonctionnels ont donc recours à tout un tas d&#8217;astuces et d&#8217;enrobages pour les manipuler comme si ce n&#8217;était pas les cas. La fameuse &#8220;simplicité&#8221;, &#8220;élégance&#8221; et &#8220;pureté&#8221; qu&#8217;ils prônent en prend un coup.</p>
<p>Les meilleurs design patterns fonctionnels peuvent devenir un enfer pour travailler avec, les monades étant l&#8217;exemple le plus couramment cité. Déjà que c&#8217;est pas évident de faire passer la OOP, les générateurs, les classes et les décorateurs&#8230; Bonne chance pour les monades, et merci pour le poisson !</p>
<p>La limite de récursion et de la taille des lambdas est également parfaitement volontaire. Comprenez bien : tous les développeurs n&#8217;ont pas (et n&#8217;ont pas à avoir) le même niveau. Mettre un géographe devant une récursion avec injection de dépendance est aussi productif que de demander à un programmeur Web de calculer lui-même sa projection mercator.</p>
<p>Si demain la récursion devient plus facile, les dev chevronnés vont massivement l&#8217;utiliser même quand ce n&#8217;est pas indispensables : donnez un jouet à un geek, et il va s&#8217;en servir. Mais <strong>la lisibilité est primordiale, c&#8217;est une feature de Python</strong>. Les codes deviendront alors soudainement significativement plus durs à lire et à débugger, pour un gain minime. En effet, la récursion ne m&#8217;a JAMAIS manqué en Python. Les développeurs ne sont pas raisonnables, ils ne vont jamais se dire, je vais m&#8217;assurer que ce code sera facile à lire pour un débutant ou moi sans café, ils vont utiliser tous les outils à leur disposition. Guido a donc volontairement limité les outils à ce qui garde un code facile à appréhender.</p>
<p>C&#8217;est ce qui a fait le succès de Python jusqu&#8217;à présent. C&#8217;est un langage facile à prendre en main, et productif. Lire le code d&#8217;un autre est simple.</p>
<p>Lire le code Lisp d&#8217;un autre n&#8217;est PAS simple.</p>
<p>Une stack trace d&#8217;une erreur en pleine récursion est pleinement inutile.</p>
<p>Le callback hell de Javascript plein de fonctions anonymes en cascade est dégueulasse.</p>
<p>Vous allez me répondre : &#8220;les gens n&#8217;ont qu&#8217;a programmer proprement&#8221; où &#8220;il y a des outils pour ça&#8221;</p>
<p>Outre le fait que pouvoir coder en Python avec juste notepad et la console est une des ses meilleures features, c&#8217;est ignorer la nature humaine.</p>
<p>On pourrait penser que quelque chose d&#8217;aussi simple qu&#8217;une indentation propre et un espacement consistant est la base.</p>
<p>Mais non.</p>
<p>Jetez un œil à n&#8217;importe quel programme JS ou PHP de petite ou moyenne taille, et vous trouverez invariablement des blocs de traviole, des variables globales, des espaces qui dégueulent à droite et à gauche et des saloperies en tout genre.</p>
<p>Python force l&#8217;indentation. Python a un PEP8.</p>
<p>J&#8217;adore ça.</p>
<p>Ca amène les porcs à coder plus proprement.</p>
<p>C&#8217;est pareil pour les lambdas et la récursion. On force la main aux gens déraisonnables pour qu&#8217;ils ne fassent pas de connerie. Désolé, je n&#8217;ai pas confiance dans les barbus pour créer des choses user friendly. Et moi, j&#8217;aime ça, le code accessible. Fuck la pureté.</p>
<p>Si vous voulez des trucs tarabiscotés, Lisp le fera très bien.</p>
<p>Mais ce n&#8217;est pas Lisp qui a autant de succès, c&#8217;est Python. Et vous savez pourquoi ?</p>
<p>Parce qu&#8217;il est productif, facile, lisible, et avec une énorme communauté pleine de diversité car il est accessible à tout ce monde.</p>
<p>Bref, vous l&#8217;avez compris, je suis contre faire de Python un langage purement fonctionnel si c&#8217;est au prix de tout cela.</p>
<p>Maintenant, il existera peut être des moyens techniques pour rendre des implémentations d&#8217;outils fonctionnels aussi performants et lisibles que leurs versions non fonctionnelles.</p>
<p>Ca a été le cas avec les intensions : de longues chaines de <code>map()</code> et <code>filter()</code> illisibles deviennent claires avec une belle intension. Et c&#8217;est clairement un gain par rapport au <code>for</code> + <code>append()</code> traditionnel. Mais pour les cas moins simple, on a toujours la possibilité d&#8217;utiliser cette méthode, qui est facile à lire, à comprendre et à débugger.</p>
<p>Je gage qu&#8217;un compromis intelligent, voire carrément malin, puisse être trouvé en la matière.</p>
<p>Mais s&#8217;il vous plait, ne cassez pas Python juste pour avoir un nouveau jouet, vous scierez la branche sur laquelle nous sommes tous assis en train de boire l&#8217;apéro en rigolant.</p>
<p>C&#8217;est un reproche qui a été fait au type hinting : si on offre cette possibilité, elle sera utilisée, et tout code avec ces annotations est significativement plus moche. Si demain la majorité des projets en font un pré-requis, beurk.</p>
<p>Je ne pense pas que ça arrivera car c&#8217;est un sacré effort supplémentaire de les écrire. Donc on le fera uniquement si ça vaut le coup : par exemple un gros projet ou une lib avec une bonne base d&#8217;utilisateur.</p>
<p>Ce n&#8217;est pas le cas pour la programmation fonctionnelle : son coût d&#8217;écriture est beaucoup plus bas que celui de la relecture. On paie plus tard. Et ça les gens ne savent pas gérer. L&#8217;humain est naze pour investir dans le futur, c&#8217;est pour ça que nous consommons les ressources de notre planète comme des goinfres, qu&#8217;on pollue à foison et qu&#8217;on laisse des dirigeants voter des lois liberticides.</p>
<h2>Bonnes pratiques</h2>
<p>Bien que je suis clairement en faveur de mettre un frein à l&#8217;enthousiasme des programmeurs FP tant qu&#8217;un terrain d&#8217;entente intelligent ne sera pas trouvé, ça ne veut pas dire qu&#8217;on ne peut pas bénéficier de leurs propositions.</p>
<p>En effet, sachez que vous serez un meilleur programmeur, et que votre programme gagnera en qualité, si vous appliquez quelques principes de programmation fonctionnelle et utilisez les outils déjà existant en Python pour en tirer parti.</p>
<p>Le tout est de ne pas en abuser, et surtout, de ne pas s&#8217;interdire de pondre un code bête et simple quand c&#8217;est plus rapide ou plus clair.</p>
<p>D&#8217;abord, limiter les effets de bord est toujours une bonne chose.</p>
<p>Si vous vous trouvez à modifier une structure de données dans une fonction alors qu&#8217;elle l&#8217;a reçue en paramètre, réfléchissez à deux fois. Est-ce vraiment nécessaire ? Ne pouvez-vous pas faire autrement. A part pour quelques cas très précis (tri sur place, passes multiples, cache, etc), il rare d&#8217;avoir à le faire.</p>
<p>Utilisez les intensions et les générateurs. Utilisez <code>itertools</code>. Utilisez <code>functools</code>. Ces outils demandent un peu d&#8217;apprentissage, mais ils sont formidables : plus performants, plus expressifs, plus lisibles.</p>
<p>Il vous faudra un peu de pratique pour trouver un bon équilibre. Arrive un point où on les utilise partout, ce qui rend le debuggage plus difficile. Passé ce stade, revenez en arrière, calmez-vous, respirez, retourner à l&#8217;impératif, ce n&#8217;est pas non plus retourner au visual basic.</p>
<p>Quand vous faites de la programmation concurrente, voyez si vous ne pouvez pas isoler vos états derrière des services, et faites communiquer les services entre eux via des messages immutables. Votre application sera plus claire, plus stable.</p>
<p>D&#8217;une manière générale, il est bon de diviser son code en petites unités, fonctionnelles justement, qui se passent des valeurs les unes aux autres.</p>
<p>Mais au final, n&#8217;oubliez pas la définition d&#8217;un bon code :</p>
<ul>
<li>Ca marche.</li>
<li>Ca continue de marcher.</li>
<li>On comprend pourquoi ça marche.</li>
</ul>
<p>Le reste n&#8217;est que drosophilie sodomite.</p>


feed_id: http://sametmax.com/?p=16157
title: Est-ce que cet outil existe en Python ? 12
uri: Est-ce-que-cet-outil-existe-en-Python-3-Recently-updated
url: http://sametmax.com/est-ce-que-cet-outil-existe-en-python/
content:
<p>Le test unitaire le plus simple, c&#8217;est de vérifier que son API publique n&#8217;a pas changé.</p>
<p>Ça veut dire :</p>
<ul>
<li>vérifier que les modules ont bien les mêmes définitions (un nom qui était importable n&#8217;a pas disparu).</li>
<li>vérifier que les fonctions et méthodes ont bien la même signature (les arguments avec le même nom n&#8217;ont pas changé de place, et les keywords arguments n&#8217;ont pas changé de nom).</li>
<li>vérifier que les classes ont le même nom, les mêmes méthodes publiques avec les mêmes signatures et les mêmes attributs.</li>
</ul>
<p>Ce sont des tests super cons qui demandent d&#8217;écrire du code du genre :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Foo:
    bar <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> stuff<span style="color: #66cc66;">=</span><span style="color: #008000;">False</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">stuff</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> thing<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;doh&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># et dans les tests</span>
<span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>Foo<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'bar'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>Foo<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'thing'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #008000;">self</span>.<span style="color: black;">assertTrue</span><span style="color: black;">&#40;</span><span style="color: #008000;">hasattr</span><span style="color: black;">&#40;</span>Foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'stuff'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Et personne ne le fait, car déjà les tests c&#8217;est relou, mais écrire des tautologies à la main, c&#8217;est au dela du tolérable.</p>
<p>Pourtant, ce genre de tests m&#8217;aurait déjà sauvé les gosses plusieurs fois. Une faute de frappe qui se glisse, un attribut qu&#8217;on rend privé, un méthode qu&#8217;on déplace et on pense avoir tout refactoré, un pote qui change un truc qu&#8217;on utilisait, etc.</p>
<p>Je me demandais donc si il existait un truc qui permette de faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">self</span>.<span style="color: black;">assertStablePublicAPI</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;package.module&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># scanne tout le module et tous les objets</span>
<span style="color: #008000;">self</span>.<span style="color: black;">assertStablePublicAPI</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;package.module:Class&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># check juste la classe</span>
<span style="color: #008000;">self</span>.<span style="color: black;">assertStablePublicAPI</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;package.module:func&quot;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># check juste la function</span></pre></td></tr></table></div>

<p>Le but étant que quand on lance les test, ça check si ça rencontre un nouvel objet/attribut/param et sauvegarde tout un dans un JSON. Aux prochains tests, si on a modifier l&#8217;API publique, le test foire jusqu&#8217;à ce qu&#8217;on modifie explicitement le fichier JSON.</p>
<p>On doit bien entendu pouvoir régler le truc pour ignorer ou ajouter explicitement des choses à checker, par exemple par défaut ça ignore tous les machins avec des underscores dans le nom.</p>
<p>J&#8217;ai cherché sur le net, mais j&#8217;arrive pas à trouver ça. Des pistes ?</p>


feed_id: http://sametmax.com/?p=16187
title: Quels exercices pour débutants en Python ? 40
uri: Quels-exercices-pour-débutants-en-Python
url: http://sametmax.com/quels-exercices-pour-debutants-en-python/
content:
<p>Quand quelqu&#8217;un commence à programmer avec Python, il faut lui apprendre les bases : les conditions, les boucles, les listes, les dicos, les fichiers, les fonctions, les classes et tout le bordel.</p>
<p>Pour que ça rentre, et pour identifier les points à consolider, les exercices sont indispensables.</p>
<p>Malheureusement un bon exercice est très dur à construire :</p>
<ul>
<li>Il faut qu&#8217;il soit suffisamment intéressant pour garder l&#8217;élève en éveil. Découvrir quelque chose, faire un truc qui paraisse un peu utile, etc.</li>
<li>Mais il ne faut pas mélanger trop de notions nouvelles à la fois (et donc on est limité par ce que l&#8217;élève sait).</li>
<li>Si possible, il est bon d&#8217;éviter de se répéter. Or quand on travaille sur des notions connexes (ex: liste et boucle for) ou qu&#8217;on fait un autre exo sur le même thème, c&#8217;est chaud.</li>
</ul>
<p>Il y a des grands classiques : </p>
<ul>
<li>Le jeu &#8220;deviner un nombre&#8221;</li>
<li>Le master mind</li>
<li>La todo list</li>
<li>Calculer le nombre de fois qu&#8217;apparait chaque mot dans dans un texte.</li>
<li>Parcourir tout un tas de fichiers et en trouver un avec une caractéristique particulière.</li>
<li>Déplacer ses fichiers récursivement pour les organiser selon une hiérarchie nom/dossier.</li>
<li>Lire une page web et en extraire une partie.</li>
<li>Parcourir son historique Web Chrome/Firefox et trouver les 5 sites les plus visités.</li>
</ul>
<p>Certains ne sont plus possibles : parcourir l&#8217;API tweeter par exemple est devenu beaucoup trop compliqué alors qu&#8217;avant c&#8217;était un truc super fun à faire faire.</p>
<p>D&#8217;autres sont vachement plus faciles : s&#8217;envoyer un sms d&#8217;alerte si il va pleuvoir aujourd&#8217;hui est un jeu d&#8217;enfant si on est chez free qui a une URL pour ça.</p>
<p>Est-ce que vous avez des exos sympas à proposer ? Je cherche l&#8217;inspiration.</p>
<p>Si vous postez un exo, merci d&#8217;y joindre les notions testées et les pré-requis ainsi que, si nécessaire, le public visé.</p>


feed_id: http://sametmax.com/?p=16175
title: Pourquoi obliger le SSL par défaut est une grosse connerie 36 Recently updated !
uri: Pourquoi-obliger-le-SSL-par-défaut-est-une-grosse-connerie-19-Rece
url: http://sametmax.com/pourquoi-obliger-le-ssl-par-defaut-est-une-grosse-connerie/
content:
<p>Chrome et Mozilla <a href="https://blog.mozilla.org/security/2015/04/30/deprecating-non-secure-http/">parlent</a> de limiter les fonctionnalités de leurs navigateurs sur les sites qui n&#8217;utilisent pas SSL.</p>
<p>Sur le papier, c&#8217;est pavé de bonnes intentions : forcer les auteurs de sites à chiffrer la communication entre le serveur et le client. Plus de sécurité pour les utilisateurs, tant pis pour les dev paresseux, pas vrai ?</p>
<p><strong>Sauf que HTTPS fonctionne sur le principe d&#8217;autorités centrales</strong>. Vous devez obtenir un certificat auprès d&#8217;une autorité de confiance, sans quoi le navigateur va afficher ça :<br />
<div id="attachment_16176" style="width: 700px" class="wp-caption aligncenter"><a href="media/a4d75434.firefoxCertError.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2015/05/firefoxCertError.jpg" class="grouped_elements" rel="tc-fancybox-group16175"><img src="media/a4d75434.firefoxCertError.jpg" data-original-source="http://sametmax.com/wp-content/uploads/2015/05/firefoxCertError.jpg" alt="This connection is untrusted" width="690" height="431" class="size-full wp-image-16176" /></a><p class="wp-caption-text">Michou ne va pas lire ce texte, encore moins chercher et trouver comment accéder au site. Elle va courir. Un virus !</p></div></p>
<p>Les moteurs de recherche vont vous plomber, l&#8217;utilisateur va fuir, bref, votre site est mort.</p>
<p>Et c&#8217;est la que ça devient fun, car les autorités centrales sont des organismes privés, et il n&#8217;y en a pas beaucoup. Ils ne sont pas tenus de vous filer un certificat, et peuvent le retirer à tout moment. </p>
<p>En clair, <strong>forcer SSL partout, c&#8217;est donner la main à quelques grosses boites pour décider qui a le droit d&#8217;être sur le Web ou pas.</strong> Vous voulez faire un truc qui ne leur plait pas ? Attention, montrer un tableau classique avec des nichons ne plait pas à Apple, faire un noeud Tor ne plait pas à Amazon, les bitcoins ne plaisent pas à Paypal et être gay ne plait pas à plein de gouvernements.</p>
<p>Toutes ces entités travaillent main dans la main avec les autorités de certification, et avoir Mozilla en <a href="https://letsencrypt.org/">proposer</a> une n&#8217;y changera rien. Si vous faites un truc que ces gens ne veulent pas, vous effacer du Web sera aussi facile que de faire pression pour révoquer votre certificat.</p>
<p>Sans jugement. Sans procès. Sans recours possible.</p>
<p>Le Web deviendra un app store.</p>
<p>EDIT : </p>
<p>Je rajoute mon commentaire sur let&#8217;s encrypt ici sinon je sens que tout le monde va radoter</p>
<blockquote><p>L’article a un lien qui pointe vers let’s encrypt. Ca ne change rien : c’est centralisé, privé, et subira des pressions comme tous les autres. J’aime Mozilla, j’ai confiance en eux, mais ils n’ont aucun moyen de garantir la neutralité de let’s encrypt, ne serait que par rapport aux gouvernements.</p>
<p>Et puis quoi ? A la fin tous les sites “border line” seront chez eux ? Comme ça bam, un bon single point of failure à attaquer pour tout faire tomber d’un coup ?</p>
<p>FBI. FBI. FBI.</p></blockquote>


feed_id: http://sametmax.com/?p=16231
title: Python 3 est fait pour les nouveaux venus 19
uri: Python-3-est-fait-pour-les-nouveaux-venus-12-Recently-updated
url: http://sametmax.com/python-3-est-fait-pour-les-nouveaux-venus/
content:
<p>&#8220;Je n&#8217;ai pas vraiment de raison de migrer vers Python 3&#8243; est la cause numéro 1 de la lente migration de Python 2 vers 3. <a href="http://astrofrog.github.io/blog/2015/05/09/2015-survey-results/">16% utilisent Python 3 comme VM principale</a>, contre 81% pour 2.7 (on notera la part ridicule des autres versions, que vous pouvez donc ignorer dans le support de vos libs). Le report de la dépréciation de Python 2 de 2015 à 2020 a donc tout son sens : la communauté a pris son temps car le jeu n&#8217;en valait pas la chandelle.</p>
<p>Mais on y arrive. La plupart des libs importantes <a href="http://python3wos.appspot.com/">sont portées</a>, les hostings supportent beaucoup mieux Python 3, même le portage de twisted <a href="https://twistedmatrix.com/trac/milestone/Python-3.x">a repris</a>, <a href="http://twistedmatrix.com/pipermail/twisted-python/2015-May/029481.html">grace à Crossbar d&#8217;ailleurs</a> :) Perso je commence toujours mes nouveaux projets en Python 3.</p>
<p>On peut le dire maintenant, tout le monde a eu un peu peur. D&#8217;ailleurs <a href="https://www.youtube.com/watch?feature=player_detailpage&#038;v=VhCsOwzRgyc#t=472">Guido n&#8217;est pas prêt de recommencer</a>. Après PHP 6 et Perl 6 qu&#8217;on attend toujours, des ralages dans tous les sens, des version 3.0, 3.1 et 3.2 vraiment à chier, après le retrait de <code>%</code> pour les bytes et l&#8217;appel pour une 2.8, on s&#8217;est tous demandé si ça allait pas foirer. </p>
<p>Maintenant, je suis certain que non. On a passé cette étape, ça a pris du temps, ça a fait mal au cul, mais pendant que Node <a href="https://twitter.com/sam_et_max/status/595495925541404672">se divise en 3 versions</a> alors qu&#8217;il existe depuis à peine 6 ans, Python fête ses 20 ans avec une seule transition difficile, qui s&#8217;est révélée gagnante.</p>
<p>Mais gagnante pour qui ?</p>
<p>C&#8217;est vrai qu&#8217;il y a de bonnes features qui ne sont qu&#8217;en version 3 : <a href="https://docs.python.org/3/library/asyncio.html">asyncio</a>, <a href="https://docs.python.org/3/library/pathlib.html">pathlib</a>, <a href="https://docs.python.org/3/library/statistics.html">statistics</a>, <a href="https://docs.python.org/3/library/ipaddress.html">ipaddress</a>, <a href="https://docs.python.org/3/library/enum.html">enums</a>, <a href="https://docs.python.org/dev/library/lzma.html">lzma</a>, <a href="http://stackoverflow.com/questions/24752395/python-raise-from-form-usage">raise from</a>, <a href="https://www.python.org/dev/peps/pep-0380/">yield from</a>, <a href="https://docs.python.org/3/library/functools.html#functools.singledispatch">singledispatch</a>, <a href="https://docs.python.org/2/library/multiprocessing.html">multiprocessing.Pool.map</a>, <a href="https://www.python.org/dev/peps/pep-0465/">@</a>, <a href="http://sametmax.com/async-await-la-feature-de-derniere-minute-de-python-3-5/">await/async</a>, les <a href="http://sametmax.com/point-rapide-sur-les-types-hints/">type hints</a>, le <a href="http://stackoverflow.com/questions/1261875/python-nonlocal-statement">support avancé des closures</a> et <a href="http://www.reddit.com/r/Python/comments/2x8d64/pep_448_additional_unpacking_generalizations/">l&#8217;unpacking étendu</a>. Mais d&#8217;abord, certaines arrivent pour la 3.5, ensuite, les autres n&#8217;ont visiblement pas motivé les vieux de la vieille à faire le pas pendant 5 ans. </p>
<p>Pourquoi ? Parce que Python 3 n&#8217;a pas été créé pour eux. Il a été créé pour les nouveaux arrivants dans le langage.</p>
<p>Ayant un peu d&#8217;expérience avec le fait d&#8217;enseigner Python, je peux vous dire que faire passer Python 2 et Python 3, c&#8217;est le jour et la nuit :</p>
<ul>
<li>Le texte marche automatiquement la plupart du temps : on a des objets unicodes partout, utf8 est par défaut, <code>os.truc</code> retourne de l&#8217;unicode, <code>open</code> a un paramètre <code>encoding</code> et mettre &#8220;é&#8221; dans un <code>print</code> ou un commentaire marche out of the box. Ca change la vie.</li>
<li>Le corolaire est qu&#8217;il y a plein de truc en moins à expliquer. <code>u</code>, <code>from __future__</code>, <code># coding</code> mais aussi <code>object</code> et mon favori : <code>super()</code> et non <code>super(ClassName, self)</code>. Franchement même moi ça me perturbe de taper ça.</li>
<li><code>print()</code> n&#8217;est pas un cas particulier : écrire sur <code>stderr</code>, éviter un saut de ligne et séparer des entrées sont juste des paramètres de fonctions et non des <code>&gt;&gt;</code> et <code>,</code>.</li>
<li>Les noms des modules de la stdlib sont cohérents. On peut les deviner, les découvrir et chercher de la doc plus facilement.</li>
<li>La hiérarchie des exceptions est beaucoup plus claire. <code>IOError/OSError</code> ont des enfants qui évitent l&#8217;obscure usage de <code>errno</code>.</li>
<li>Par ailleurs plein de messages d&#8217;erreurs sont plus explicites.</li>
<li>Et des nouveaux messages d&#8217;erreur font leur apparition. On ne peut plus faire <code>True = reponse</code> ou <code>2 > "1"</code>. Cette dernière, TOUT LE MONDE me l&#8217;a faite.</li>
<li>Les pyc sont groupés dans un dossier. Tellement plus clair.</li>
<li>Le shell Python a l&#8217;autocompletion activée. </li>
<li><code>/</code> est moins surprenant. Encore un truc de moins à expliquer.</li>
<li>&#8220;There is one way to do it&#8221;. Plus de <code>range</code> vs <code>xrange</code>, <code>__str__</code> vs <code>__unicode__</code>, <code>str()</code> vs <code>bytes</code> vs <code>unicode</code>, <code>int()</code> vs <code>long()</code>, <code>dict.items</code> vs <code>iteritems</code> vs <code>viewitems</code>, <code>input()</code> vs <code>raw_input().</code>&#8230; Est-ce que vous voyez la somme de choses en moins à apprendre ? C&#8217;est colossale. Et plein de sources d&#8217;erreurs en moins. Par exemple, <code>input()</code> en Python 2 déclenche <code>NameError</code> quand on saisie des lettres. C&#8217;est super marrant, je vous raconte pas.</li>
<li>Les imports sont toujours absolus. Combien de fois j&#8217;ai du dire &#8220;alors, tu as appelé ton module test.py, et ça peut pas marcher parce que&#8230;&#8221;.</li>
<li>Ne pas avoir à dire &#8220;nan, tu peux pas utiliser <code>return</code> si tu utilises <code>yield</code> parce que&#8230; heu&#8230; c&#8217;est comme ça&#8221;.</li>
<li>Et tous ces bugs qui arrivent parce que quelque part, l&#8217;apprenant a utilisé une old style class dans la hierarchie et on passe 20 minutes à essayer comprendre un comportement aberrant pendant que le reste de la classe est sur facebook.</li>
<li> Les variables ont une portée limitée dans les compréhensions :

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">5</span><span style="color: black;">&#93;</span>:
    squared <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span>x**<span style="color: #ff4500;">2</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Affiche 1, 3, 5 en Python 3, 4 4 4 en Python 2. Certes, j&#8217;essaye d&#8217;apprendre à mes élèves à faire gaffe aux noms de variables, mais bon, y en a toujours un qui chie dans la colle, faut pas se leurrer.
</li>
</ul>
<p>Nous, utilisateurs chevronnés de la 2.7, ne nous rendons pas compte de la somme de connaissance que nous avons accumulé au fil des années pour contourner ces problèmes. Les nouveaux, même autodidactes, vont aller beaucoup plus vite.</p>
<p>Python 3 fait très bien son boulot : garder Python sa place de meilleur langage pour l&#8217;apprentissage. Ca tombe bien, parce qu&#8217;un fois appris, il sert aussi à plein de choses professionnellement, et pas juste du dev Web (ruby), du sysadmin (perl) ou des maths (R).</p>
<p>Et du coup la migration a pris du temps.</p>
<p>Depuis la 3.4, tout s&#8217;accélère. L&#8217;investissement est en train de payer.</p>
<p>Perso, quand je dois écrire du Python 2 maintenant, ça me fait râler :)</p>


feed_id: http://sametmax.com/?p=16221
title: Je n’expliquerai plus les CBV 17
uri: Je-n-expliquerai-plus-les-CBV-12-Recently-updated
url: http://sametmax.com/je-nexpliquerai-plus-les-cbv/
content:
<p>Les <a href="http://sametmax.com/des-vues-normales-aux-vues-generiques-django/">Class Based Views</a> sont des vues génériques réutilisables qui permettent de faire automatiquement des tâches courantes dans Django comme :</p>
<ul>
<li>Récupérer et afficher une ou plusieurs entrées en base de données.</li>
<li>Afficher et valider un formulaire.</li>
<li>Faire un mix des deux pour modifier des entrées en base.</li>
</ul>
<p><a href="http://sametmax.com/des-annees-plus-tards-je-naime-toujours-pas-les-cbv/">Je ne les ai jamais aimées</a>. Avant, les vues génériques étaient sous forme de fonction, simples, pratiques, c&#8217;était parfait. Et ça a été retiré du framework pour des versions OO sous prétexte que c&#8217;était plus flexible.</p>
<p>Maintenant, ce sont ces gros tas immondes, avec un ordre d&#8217;appel de méthodes complexes, des mixins dans tous les sens et une chaine d&#8217;héritage velue. </p>
<p>Je pense que c&#8217;est une bonne occasion pour rappeler que la POO n&#8217;est pas faite pour être utilisée partout, tout le temps. Aucun putain de paradigme de programmation n&#8217;est fait pour être utilisé partout, tout le temps. C&#8217;est pour ça qu&#8217;il y en a plusieurs.</p>
<p>Dans notre cas des CBV, la conséquence est que c&#8217;est <a href="http://sametmax.com/explication-de-code-des-mixins-et-des-decorateurs-de-methode-pour-django/">un enfer</a> pour expliquer tout usage qui ne soit pas un hello world, ce que la doc se garde bien de faire.</p>
<p>Après il y a toujours un malin pour dire &#8220;mais si tu vois tu fais ça, et ça, ça prend 5 lignes, c&#8217;est pas si dur&#8221;. Ouai, maintenant va expliquer ça à un stagiaire, et donne lui un exercice avec une form view qui doit modifier un objet, le lier à un user seulement si il a la permission de le faire. Juste pour voir en combien de temps il trouve. Je vais en WE à Barcelone en attendant. Je prévoie une extension à Rome pour quand il devra relire son code le trimestre prochain.</p>
<p>Et si encore c&#8217;était pour un gain de productivité évident, je fermerais les yeux. Mais c&#8217;est pas le cas. Même moi qui sait utiliser ces&#8230; ces choses&#8230; je dois regarder dans la doc à chaque fois que j&#8217;en utilise une. Et ensuite quand je relis mon code quelques mois plus tard, je chope de pattes d&#8217;oies aux coins des yeux.</p>
<blockquote><p>If you have to refer to the documentation every time you use a module, find (or build) a new module.</p></blockquote>
<p>Dixit Kenneth Reitz, le mec qui a pondu <a href="https://github.com/kennethreitz/requests">requests</a>. Donc on va user something else que les CBV, si vous le voulez bien.</p>
<p>Un lecteur m&#8217;a (encore) pointé du doigt qu&#8217;un schéma du MRO et de l&#8217;ordre d&#8217;appel des méthodes serait utile. Vous vous rendez compte du truc ? On peut comprendre l&#8217;ORM sans schéma alors que c&#8217;est une machine de guerre, et il faut une carte pour comprendre comment faire un listing un peu custo avec une CBV ? J&#8217;ai évalué la somme de travail pour faire ledit schéma, et elle est énorme : trop de classes, trop de méthodes, trop de subtilités.</p>
<p>Bref, je jette le tablier, fuck les CBV. Je ne les inclurai plus dans mes formations, mes tutos, mes aides sur les forums, etc.</p>


feed_id: http://sametmax.com/?p=16208
title: Zerobin passe à Python 3 16
uri: Zerobin-passe-à-Python-3-14-Recently-updated
url: http://sametmax.com/zerobin-passe-a-python-3/
content:
<p>Ça faisait longtemps que je n&#8217;avais pas touché <a href="https://github.com/sametmax/0bin">0bin</a>, le pastebin chiffré côté client écrit en Python.</p>
<p>Le support de Python 2 devait s&#8217;arrêter en mai 2015, soit ce mois-ci. Cela a été repoussé à 2020, mais pour marquer le coup symboliquement j&#8217;ai porté notre brave bestiole qui supporte maintenant la 2.7 et la 3.4.</p>
<p>Comme je n&#8217;ai jamais pris le temps de faire des tests unitaires sur ce projet, il est possible que j&#8217;ai cassé des trucs. J&#8217;ai testé manuellement, mais bon, on ne sait jamais, je vous avertis avant du danger :)</p>
<p>Le portage a pris une après-midi.</p>
<p>Même si ce n&#8217;est pas l&#8217;affaire de deux minutes, ce n&#8217;est pas non plus la montagne qu&#8217;on s&#8217;en fait. C&#8217;est du boulot, chiant et ingrat (surtout pour supporter 2.x ET 3.x avec une seule base de code), mais pas un travail de titan.</p>
<p>Et en prime, ça me permet de faire un peu reparler du projet qui n&#8217;avait plus eu de mise à jour depuis un bail.</p>
<p>Il mérite d&#8217;ailleurs encore pas mal d&#8217;amour :</p>
<ul>
<li>Y a des issues qui sont toujours en attente sur github (certaines datent d&#8217;un an). Et c&#8217;est parce que je suis une merde procrastinatrice, il faut bien l&#8217;avouer.</li>
<li>Quelques features comme la suppression de l&#8217;histo ou d&#8217;un paste en particulier seraient les bienvenues.</li>
<li>Ca mériterait d&#8217;être porté à Angular. La lasagna jquery, c&#8217;est pas glop.</li>
<li>Un client Python serait pas de refus, et donc une API, et donc une clé API.</li>
<li>Une admin pour ses propres pastes avec URL jetable serait idéale. Mais faudrait changer le format de fichier des pastes, et donc versionner le format, et prévoir la migration des anciens.</li>
<li>Une admin pour les DMCA s&#8217;est faite sentir pas mal de fois.</li>
<li>Un script pour delete un paste en Python aussi.</li>
<li>Et pourquoi pas un packaging sous forme de .deb ou .rpm ?</li>
<li>Le support des bases de données n&#8217;a jamais été implémenté, c&#8217;est triste.</li>
<li>On avait parlé d&#8217;en faire une version avec auto réplication sur ses amis pour éviter la censure.</li>
<li>Et de faire un chat chiffré en dessous.</li>
<li>Et un éditeur de paste collaboratif. Mais faudrait porter zerobin vers crossbar.io.</li>
</ul>
<p>Bref, ce &#8220;petit&#8221; projet a de beaux jours devant lui. Sauf que pour l&#8217;instant, y a une seule limace qui code dessus.</p>
<p>P.S : j&#8217;ai aussi réparé le &#8220;Mail this&#8221;, qui n&#8217;utilise plus l&#8217;URL raccourcie. En effet cette dernière n&#8217;est pas dispo dès qu&#8217;on dépasse le rate de l&#8217;API google, ce qui arrive tous les jours maintenant. La rançon du succès je suppose.</p>


feed_id: http://sametmax.com/?p=16198
title: Pendant ce temps, à Vera Cruz 8
uri: Pendant-ce-temps-à-Vera-Cruz-8-Recently-updated
url: http://sametmax.com/pendant-ce-temps-a-vera-cruz/
content:
<p>Pour une fois, ce n&#8217;est pas un article payé par Tavendo, mais bien un truc que je ponds par enthousiasme :)</p>
<p>Pendant qu&#8217;on en parle pas, la stack WAMP continue d&#8217;évoluer, des mises à jours significatives ayant été apportées à Crossbar.io, ainsi qu&#8217;aux libs Python et JS d&#8217;autobahn. Parmi les plus intéressantes :</p>
<ul>
<li>Le code passe de la licence Apache 2 à la licence MIT, augmentant la compatibilité avec un tas d&#8217;autres licences.</li>
<li>On peut faire un SUB avec un joker, et donc lier un seul callback à plusieurs événements.</li>
<li>On peut faire un register avec un joker également.</li>
<li>On peut choisir la stratégie à appliquer si plusieurs registers sont faits sur le même nom.</li>
<li>Une meta API permet d&#8217;être prévenu quand un client fait quelque chose ou de demander l&#8217;état des nœuds en cours.</li>
</ul>
<p>Inutile de dire que c&#8217;est trop cool.</p>
<p>Pour profiter de tout ça, il suffit de faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">pip <span style="color: #c20cb9; font-weight: bold;">install</span> crossbar autobahn <span style="color: #660033;">--upgrade</span></pre></td></tr></table></div>

<p>Et de télécharger la nouvelle version de la <a href="https://autobahn.s3.amazonaws.com/autobahnjs/latest/autobahn.min.jgz">dernière version</a> de la lib JS.</p>
<h2>Licence MIT</h2>
<p>Auparavant le travail de Tavendo était essentiellement sous Licence Apache. Une licence libre, certes, mais qui pouvait poser problème quand on mélangeait tout ça avec d&#8217;autres licences (par exemple, elle n&#8217;est pas compatible avec la GPL2). Avec la version 0.10, le code est maintenant sous licence MIT, beaucoup plus permissive.</p>
<h2>Joker pour les subs</h2>
<p>Supposez que vous faites un système de jeu d&#8217;échec donc chaque coup déclenche un événement &#8220;chess.game.[id_de_partie]&#8221;. C&#8217;est pratique, car seuls les clients intéressés à cette partie vont recevoir les événements. Mais si votre serveur doit enregistrer un log de tous les coups d&#8217;une partie, il faut que chaque client envoie AUSSI les coups au serveur explicitement.</p>
<p>C&#8217;était en tout cas vrai avant cette mise à jour, puisque maintenant on peut spécifier <a href="http://crossbar.io/docs/Pattern-Based-Subscriptions/">des jokers</a> dans les noms des topics au moment de l&#8217;abonnement.</p>
<p>Essentiellement il y a deux modes.</p>
<p>Le mode &#8220;prefix&#8221;, qui match tous les events qui commencent par ce nom :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">session.<span style="color: #660066;">subscribe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;debut.du.nom.du.topic&quot;</span><span style="color: #339933;">,</span> callback<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> match<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;prefix&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
# matchera debut.<span style="color: #660066;">du</span>.<span style="color: #660066;">nom</span>.<span style="color: #660066;">du</span>.<span style="color: #660066;">topic</span>.<span style="color: #660066;">genial</span> et debut.<span style="color: #660066;">du</span>.<span style="color: #660066;">nom</span>.<span style="color: #660066;">du</span>.<span style="color: #660066;">topic</span>.<span style="color: #660066;">trop</span>.<span style="color: #660066;">cool</span></pre></td></tr></table></div>

<p>Et le mode &#8220;wildcard&#8221; qui permet, un peu comme les glob Unix (mais on utilise &#8220;..&#8221; au lieu de &#8220;*&#8221;&#8221;), de faire un texte à trou :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">session.<span style="color: #660066;">subscribe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;nom.du.topic..general&quot;</span><span style="color: #339933;">,</span> callback<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> match<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;wildcard&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
# matchera <span style="color: #3366CC;">&quot;nom.du.topic.moins.general&quot;</span> et <span style="color: #3366CC;">&quot;nom.du.topic.oui.mon.general&quot;</span></pre></td></tr></table></div>

<p>Tous les callbacks qui matchent un topic seront appelés.</p>
<h2>Plusieurs clients pour la même procédure</h2>
<p>On peut utiliser le même principe que pour les sub avec joker, mais pour les procédures.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">session.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;debut.du.nom.de.la.procedure&quot;</span><span style="color: #339933;">,</span> callback<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> match<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;prefix&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>    
session.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;nom.de.la.procedure..generale&quot;</span><span style="color: #339933;">,</span> callback<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> match<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;wildcard&quot;</span> <span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>La différence avec le subscribe, c&#8217;est que seule UNE procédure est appelée. Dans les cas simples, un match exact prend le dessus sur un prefix (et le plus long prefix gagne toujours), qui prend le dessus sur un wildcard. Crossbar n&#8217;implemente pas encore de résolution pour deux wildcards en conflits, et je ne sais pas ce qu&#8217;il fait dans ce cas.</p>
<p>Il est aussi possible de <a href="http://crossbar.io/docs/Shared-Registrations/">de définir des règles</a> d&#8217;appels en faisant :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;">session.<span style="color: #660066;">register</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;nom.de.la.procedure..generale&quot;</span><span style="color: #339933;">,</span> procedure1<span style="color: #339933;">,</span> <span style="color: #009900;">&#123;</span> invoke<span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;regle&quot;</span><span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></td></tr></table></div>

<p>La règle peut être :</p>
<ul>
<li><strong>roundrobin</strong>: on prend la liste de clients, on regarde le dernier appelé, et on utilise le suivant.</li>
<li><strong>random</strong>: on prend un client au hasard.</li>
<li><strong>last</strong>: on prend le dernier client ajouté de la liste.</li>
<li><strong>first</strong>: on prend premier client ajouté à la liste.</li>
</ul>
<p>&#8220;roundrobin&#8221; et &#8220;random&#8221; sont pratiques pour faire du load balancing.</p>
<p>&#8220;last&#8221; et &#8220;first&#8221; sont pratique pour les mises à jour d&#8217;un client sans arrêter le serveur. En gros on rajoute un client, on attend un peu, &#8220;last&#8221; route tout sur le dernier client, donc le nouveau client prend les requêtes, et on peut arrêter le vieux clients sans souci. </p>
<h2>Meta RPC</h2>
<p>Crossbar met automatiquement à notre disposition des procédures distantes toutes faites qui donnent des informations sur l&#8217;état des clients et du routeur. Voici les RPC que vous pouvez maintenant faire :</p>
<ul>
<li><strong>wamp.session.list</strong>: lister les sessions des clients connectés au routeur.</li>
<li><strong>wamp.session.get</strong>: obtenir les infos d&#8217;un session pour un ID en particulier.</li>
<li><strong>wamp.session.count</strong>: obtenir le nombre de client connectés.</li>
<li><strong>wamp.registration.lookup</strong>: absolument aucune idée.</li>
<li><strong>wamp.registration.get</strong>: obtenir des infos sur une procédure distante enregistrée.</li>
<li><strong>wamp.registration.list_callees</strong>: lister les clients ayant enregistré pour une procédure avec ce nom.</li>
<li><strong>wamp.registration.count_callees</strong>: compter les clients ayant enregistré une procédure avec ce nom.</li>
<li><strong>wamp.registration.list</strong>: lister toutes les procédures distantes disponibles.</li>
<li><strong>wamp.registration.remove_callee</strong>: virer un client de la liste de des clients enregistrés pour cet procédure.</li>
<li><strong>wamp.subscription.lookup</strong>: toujours aucune idée.</li>
<li><strong>wamp.subscription.get</strong>: récupérer des infos sur l&#8217;abonnement avec cet ID.</li>
<li><strong>wamp.subscription.list_subscribers</strong>: lister les clients qui sont abonnés à ce sujet.</li>
<li><strong>wamp.subscription.count_subscribers</strong>: compter les clients abonnés à ce sujet.</li>
<li><strong>wamp.subscription.match</strong>: aucune idée.</li>
<li><strong>wamp.subscription.list</strong>: lister tous les sujets d&#8217;abonnement disponibles.</li>
<li><strong>wamp.subscription.remove_subscriber</strong>: </li>
<p> virer un client de la liste des abonnés à ce sujet.</ul>
<p>En gros, si vous voulez faire une admin qui vous permet de killer certains client ou rechercher si des events existent, vous utilisez ça.</p>
<h2>Meta SUB</h2>
<p>De même, le routeur envoie maintenant des publications sur des sujets concernant le cycle son cycle de vie et celui des clients. On peut donc s&#8217;abonner à ces meta topic pour réagir à l&#8217;activité de son système :</p>
<ul>
<li><strong>wamp.session.on_join</strong> : un client s&#8217;est connecté au routeur.</li>
<li><strong>wamp.session.on_leave</strong> : un client s&#8217;est déconnecté du routeur.</li>
<li><strong>wamp.subscription.on_create</strong> : un nouveau topic existe.</li>
<li><strong>wamp.subscription.on_subscribe</strong> : un client s&#8217;est abonné à un topic.</li>
<li><strong>wamp.subscription.on_unsubscribe</strong> : un client s&#8217;est désabonné à un topic.</li>
<li><strong>wamp.subscription.on_delete</strong> : un topic est retiré de la liste des topics disponibles.</li>
<li><strong>wamp.registration.on_create</strong> : une procédure distante porte ce nom pour la première fois.</li>
<li><strong>wamp.registration.on_register</strong> : un client propose ajoute un callable pour ce nom de procédure distante..</li>
<li><strong>wamp.registration.on_unregister</strong> : un client retire son callable pour ce nom de procédure distante. </li>
<li><strong>wamp.registration.on_delete</strong> : le nom de cette procédure n&#8217;a plus aucun callable lié.</li>
<li><strong>wamp.schema.on_define</strong> : aucune idée.</li>
<li><strong>wamp.schema.on_undefine</strong> : kamolox. </li>
</ul>
<p>Ce genre de truc est idéal pour faire un petit outil de monitoring pour son archi et voir ce qui se passe en temps réel.</p>
<h2>Le HTTP bridge est complet</h2>
<p>Le <a href="http://crossbar.io/docs/HTTP-Bridge-Services/">bridge HTTP</a> propose maintenant PUB/SUB, et tout RPC. On peut donc maintenant utiliser crossbar depuis n&#8217;importe quel app qui peut faire du HTTP : flask, pyramid, ruby on rails, du PHP pur, wget en ligne de commande et tout le bordel. C&#8217;est plus verbeux, mais ça dépanne bien.</p>


feed_id: http://sametmax.com/?p=16249
title: Le don du mois : Vasalgel 2
uri: Le-don-du-mois-Vasalgel
url: http://sametmax.com/le-don-du-mois-vasalgel/
content:
<p>Il n&#8217;y a pas de date pour le don du mois, ça part quand ça me prend.</p>
<p>Aujourd&#8217;hui l&#8217;inspiration s&#8217;est présentée sous la forme d&#8217;une newsletter que je reçois régulièrement à propos de couilles de babouins. Si, si.</p>
<p>Souvenez-vous, <a href="http://sametmax.com/la-quete-de-la-contraception-masculine/">je suis l&#8217;avancée du projet RISUG</a>, un contraceptif masculin semi-permanent et non hormonal.</p>
<p>Le concept est indien, mais la <a href="https://www.parsemusfoundation.org/vasalgel-home/">Parmesus Foundation essaye d&#8217;importer le procédé</a> aux USA. Ca veut dire une batterie de tests à faire, l&#8217;approbation auprès des autorités, etc.</p>
<p>La fondation se présente avec ce but :</p>
<blockquote><p>Advance innovative medical research and develop low-cost solutions that are neglected by the pharmaceutical industry.</p></blockquote>
<p>C&#8217;est peut être du bullshit (&#8220;écrivez à l&#8217;arc&#8221; :)), et franchement difficile de m&#8217;assurer que mon argent ne finira pas dans les poches d&#8217;un business angel peu scrupuleux.</p>
<p>Mais personnellement, je suis prêt à payer très cher pour éviter toute forme de contraception contraignante tout en ayant la certitude de ne pas avoir d&#8217;enfants.</p>
<p>Du coup, je soutiens l&#8217;initiative, qui par ailleurs <a href="https://parsemusfoundation.secure.nonprofitsoapbox.com/donate">accepte les bitcoins</a>. 0.25BTC partent donc dans leur poche, et je croise les doigts. Un jour peut être, je pourrai faire un saut à JFK pour faire brider mes nageurs.</p>


feed_id: http://sametmax.com/?p=16275
title: Pourquoi il est difficile de “juste ajouter un nouveau mot clé” 11
uri: Pourquoi-il-est-difficile-de-juste-ajouter-un-nouveau-mot-clé
url: http://sametmax.com/pourquoi-il-est-difficile-de-juste-ajouter-un-nouveau-mot-cle/
content:
<p>Avec les types hints, beaucoup ont suggéré l&#8217;ajout de nouveaux mots clés pour déclarer les types des paramètres et des variables. Guido a refusé, au moins pour les paramètres des fonctions, et s&#8217;en tient aux annotations.</p>
<p>Mais pourquoi être si têtu ? Après tout, c&#8217;est forward compatible, n&#8217;est-ce pas ?</p>
<p>Faux.</p>
<p>Quand on rajoute un mot clé, on ne peut plus l&#8217;utiliser comme nom de variable, et donc tout code qui utilise une variable qui porte ce nom va planter quand il passera à cette version de Python.</p>
<p>Inutile de dire qu&#8217;un mot clé doit être court et explicite, et que tous les mots courts et explicites sont utilisés comme noms de variables quelque part.</p>
<p>C&#8217;est pour cette raison que l&#8217;ajout de <code>async</code>/<code>await</code> a lancé toute une discussion sur la manière de changer la grammaire.</p>
<p>Et vous savez ce qui a été décidé ? </p>
<p>De ne PAS interdire de faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">async <span style="color: #66cc66;">=</span> await <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
async <span style="color: #ff7700;font-weight:bold;">def</span> foo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    await bar
<span style="color: #808080; font-style: italic;"># pas de SyntaxError</span></pre></td></tr></table></div>

<p>En clair, le parseur va détecter des cas particuliers pour ces instructions dans lesquelles il les identifie comme mot clés, et autoriser quand même leur usage comme variable dans tous les autres cas.</p>
<p>C&#8217;est un compromis pour garder la compatibilité ascendante, mais un compromis qui non seulement introduit un cas particulier dans le code du parseur (beurk), mais en plus permet d&#8217;écrire un code qui avant n&#8217;était pas permis, rendant le langage un peu moins cohérent. Un changement que maintenant on va se trainer pour les releases à venir, qui ouvre un précédent pour les futures débats, qui peut potentiellement s&#8217;accumuler avec d&#8217;autres changement futurs&#8230;</p>
<p>Faire évoluer un langage qui a 20 ans et dont il y a des millions de lignes de code partout, c&#8217;est dur. Chaque petite modification peut entrainer des conséquences importantes, et tout juste milieu renferme des craquelures d&#8217;inélégance.</p>
<p>C&#8217;est aussi pour ça qu&#8217;il est si plaisant d&#8217;inventer son langage, son framework, son outil pour faire x mieux que le status quo y. Il est parfait. Il est tout frais. Personne ne l&#8217;utilise. Il n&#8217;a encore eu aucune cicatrice.</p>
<p>A l&#8217;inverse, garder le cap malgré les remous, maintenir une diète saine et un équilibre mais accepter les saloperies qui passent de temps en temps, ça c&#8217;est difficile. Je suis épaté que Python soit resté si propre avec tout ce qui lui est arrivé au fil des années, et c&#8217;est grâce Guido qui a su dire NON à tout un tas de petits détails qui ne paraissaient pas importants, mais qui cumulés sur 2 décennies auraient transformé le langage en créature fantasque.</p>
<p>Pourvu qu&#8217;ça dure.</p>


feed_id: http://sametmax.com/?p=16268
title: Un ptit post pour remercier tous les contributeurs 32
uri: Un-ptit-post-pour-remercier-tous-les-contributeurs-8-Recently-updat
url: http://sametmax.com/un-grand-merci/
content:
<p>Après ces quelques années de blogging je voulais remercier, et je pense pouvoir parler aussi au nom de Sam,  tous ceux qui ont participé à la joie et la bonne humeur de ce blog.</p>
<p>Mais aussi à l&#8217;évolution d&#8217;IndexError où nous pouvons voir chaque jour avec un très grand plaisir des contributeurs aider sans critiquer ou juger, apporter des réponses ou donner des pistes sans rien demander en échange.</p>
<p>Merci à vous tous de donner de votre (précieux) temps pour aider votre &#8220;prochain&#8221; programmeur. La vitesse des réponses sur IndexError est tout juste hallucinante malgré la &#8220;petite&#8221; communauté.</p>
<p>De plus les commentaires sur le Blog sont toujours courtois et intéressants.</p>
<p>Je remercie en particulier pour IndexError, pour le Blog ça serait trop long à lister (mais j&#8217;en oublie certainement):</p>
<p>Foxmask, boblinux, jc, cOda, doublenain, furankun, Hawke et bien d&#8217;autres&#8230;</p>
<p>Aller je vais aux putes, ce post m&#8217;a épuisé.</p>
<p>Passez un bon Noël!</p>


feed_id: http://sametmax.com/?p=16319
title: Hasta la vista ! 4
uri: Hasta-la-vista-2
url: http://sametmax.com/hasta-la-vista/
content:
<p>Je me barre pour environ 2 semaines, et ne pondrai pas d&#8217;article pendant cette période.</p>
<p>Mettez ce temps à profit pour travailler votre lancer de nain.</p>


feed_id: http://sametmax.com/?p=16281
title: Un gros guide bien gras sur les tests unitaires en Python, partie 5 7
uri: Un-gros-guide-bien-gras-sur-les-tests-unitaires-en-Python-partie-5-5
url: http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-5/
content:
<p>Vous avez <a href="http://sametmax.com/un-gros-guide-bien-gras-sur-les-tests-unitaires-en-python-partie-4/">vu</a> les modules pour faire les tests, mais dès que vous allez vouloir faire des tests sérieux, vous allez vous heurter à la dure réalité.</p>
<p>La réalité est que pour tester, il vous faut la réalité.</p>
<p>Par exemple, si vous tapez dans une base de données, il vous faut une base de données opérationnelle. Pour tester un téléchargement, il vous faut une connexion internet. Pour tester si votre API fonctionne, il faut lancer un serveur Web.</p>
<p>Autre chose, si votre code appelle un autre code, comment vous assurer que cet appel a bien eu lieu ? Il faudrait aussi un logger pour tous les appels, et si le code n&#8217;est pas le vôtre, c&#8217;est encore plus chiant.</p>
<p>Comme nous savons que les informaticiens sont des grosses larves, il y a forcément une solution, au moins partielle, à ces problèmes. En l’occurrence, on va jouer au docteur, à la dinette, aux cowboys et aux indiens.</p>
<p>Bref, on va jouer à faire semblant.</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/vjncyiuwwXQ?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<h2>Les objets mocks</h2>
<p>Un objet mock, c&#8217;est un objet basé sur le <a href="http://sametmax.com/usages-et-dangers-du-null-object-pattern-en-python/">null object pattern</a> qui sert à faire semblant. Quand on l&#8217;instancie avec n&#8217;importe quoi, ça marche, quand on appelle n&#8217;importe quelle méthode, ça marche et ça renvoie un mock.</p>
<p>Bien entendu, comme les besoins des tests sont un peu plus raffinés que ça, mock fait plus que du null object pattern, et permet :</p>
<ul>
<li>De configurer son API.</li>
<li>De configurer ses sides effects.</li>
<li>De configurer sa valeur de retour.</li>
<li>De monkey patcher un autre objet.</li>
<li>D&#8217;enregistrer tous les appels qu&#8217;on lui fait.</li>
</ul>
<p>Alors évidement, comme ça, je me doute bien que la puissance de l&#8217;outil ne vous frappe pas en face comme le nez au milieu de l&#8217;eureka dans un couloir.</p>
<p>C&#8217;est pour ça qu&#8217;on va passer aux exemples concrets. D&#8217;abord, assurez-vous de pouvoir faire <code>import unittest.mock</code>, qui est dispo depuis Python 3.3. Si ce n&#8217;est pas le cas, <a href="http://sametmax.com/votre-python-aime-les-pip/">l&#8217;installer</a> avec <code>pip install mock</code> vous permettra de l&#8217;importer sous la forme <code>import mock</code>. Le reste, c&#8217;est pareil.</p>
<h2>On dirait que moi je t&#8217;attaque et toi tu meurs pas</h2>
<p>Un objet mock est un <a href="http://sametmax.com/les-trucmuchables-en-python/">callable</a>, c&#8217;est-à-dire qu&#8217;il peut être appelé comme une fonction ou une classe, et il retourne toujours un objet mock :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">unittest</span>.<span style="color: black;">mock</span> <span style="color: #ff7700;font-weight:bold;">import</span> MagicMock <span style="color: #808080; font-style: italic;"># ou from mock import MagicMock</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>mock<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302100559296'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302101821704'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock<span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #008000;">Exception</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302101821704'</span><span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>On peut appeler n&#8217;importe quoi sur son objet mock, et ça retourne toujours un objet mock :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">foo</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock.foo()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302101723960'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">nimporte</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">nawak</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">je</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">te</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #dc143c;">dis</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock.nimporte().nawak().je().te().dis()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302101825744'</span><span style="color: #66cc66;">&gt;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock + mock - <span style="color: #ff4500;">10000</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock.__add__().__sub__()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302134081520'</span><span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>Quand retourner un objet mock n&#8217;est pas possible, l&#8217;objet essaye d&#8217;avoir le comportement qui fera planter le moins possible :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>mock<span style="color: black;">&#41;</span>
<span style="color: #ff4500;">1</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: black;">&#91;</span>m <span style="color: #ff7700;font-weight:bold;">for</span> m <span style="color: #ff7700;font-weight:bold;">in</span> mock<span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<h2>On dirait que le bâton, là, c&#8217;est un sabre laser</h2>
<p>Parfois, néanmoins, il est utile de vouloir avoir un comportement spécifique. Il se trouve que les méthodes des objets mocks peuvent être des objets mocks. Mock, mock, mock !!!!!</p>
<p>Et les objets mocks peuvent être configurés pour avoir un effet de bord ou une valeur de retour :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">mock.<span style="color: black;">you</span> <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span>side_effect<span style="color: #66cc66;">=</span><span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'mofo !'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># un callable marche aussi</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">you</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-21-a7e6455585e9&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    mock.<span style="color: black;">you</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python3.4/unittest/mock.py&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">885</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #0000cd;">__call__</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> _mock_self._mock_call<span style="color: black;">&#40;</span>*args<span style="color: #66cc66;">,</span> **kwargs<span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python3.4/unittest/mock.py&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">941</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> _mock_call
    <span style="color: #ff7700;font-weight:bold;">raise</span> effect
<span style="color: #008000;">ValueError</span>: mofo <span style="color: #66cc66;">!</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">mock</span> <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span>return_value<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;moooooooooock&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">mock</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'moooooooooock'</span></pre></td></tr></table></div>

<p>Cela vous permet d&#8217;utiliser les objets mocks comme des remplacements pour des objets réels dans vos tests mais chiants à instancier comme une event loop, un serveur, une connexion à une base de données&#8230; Ca permet aussi de remplacer des appels très longs par des trucs instantanés.</p>
<p>Mais la partie vraiment fun, c&#8217;est qu&#8217;on peut associer des vrais objets avec des objets mocks :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">class</span> VraiObjetSerieuxEtTout:
...     <span style="color: #ff7700;font-weight:bold;">def</span> faire_un_truc_super_serieux<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
...         <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;... and don't call me Shirley&quot;</span>
...     <span style="color: #ff7700;font-weight:bold;">def</span> faire_un_autre_truc_serieux<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
...         <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">&quot;why so serious ?&quot;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius <span style="color: #66cc66;">=</span> VraiObjetSerieuxEtTout<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_truc_super_serieux</span> <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># It's a kinda magic, magic !</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_autre_truc_serieux</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'why so serious ?'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_truc_super_serieux</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ieux'</span><span style="color: black;">&#41;</span>.<span style="color: black;">delamort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">3</span>:<span style="color: #ff4500;">14</span><span style="color: black;">&#93;</span> + <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&lt;</span>MagicMock name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'mock().delamort().__getitem__().__add__()'</span> <span style="color: #008000;">id</span><span style="color: #66cc66;">=</span><span style="color: #483d8b;">'140302103288296'</span><span style="color: #66cc66;">&gt;</span></pre></td></tr></table></div>

<p>Et là ça devient super sympa : vous pouvez utilisez vos vrais objets, et pour certains appels, juste vous faciliter la vie pour les tests.</p>
<h2>On dirait qu&#8217;on compte le nombre de balles que tu as tirées</h2>
<p>Puisque les objets mocks sont un peu les <a href="http://sametmax.com/merci-de-respecter-les-salopes">grosses salopes</a> de la programmation et acceptent tout ce qui vient (oups, je viens de tuer l’ambiance métaphore enfantine là), il peut être nécessaire de vérifier ce qui s&#8217;est passé. Or il se trouve qu&#8217;ils intègrent un historique des appels :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_truc_super_serieux</span>.<span style="color: black;">mock_calls</span>
<span style="color: black;">&#91;</span>call<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ieux'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 call<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">delamort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 call<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">delamort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: #008000;">slice</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">14</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span>
 call<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">delamort</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__getitem__</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__add__</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p> Et comme vérifier qu&#8217;un appel a bien eu lieu est une tâche courante, <a href="https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.assert_called_with">des méthodes</a> pour les tests unitaires ont été intégrées :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_truc_super_serieux</span>.<span style="color: black;">assert_called_with</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ieux'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> sirius.<span style="color: black;">faire_un_truc_super_serieux</span>.<span style="color: black;">assert_called_with</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'not_ieux'</span><span style="color: black;">&#41;</span>
Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>:
  File <span style="color: #483d8b;">&quot;&lt;ipython-input-56-e8c4890f08d9&gt;&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span>
    sirius.<span style="color: black;">faire_un_truc_super_serieux</span>.<span style="color: black;">assert_called_with</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'not_ieux'</span><span style="color: black;">&#41;</span>
  File <span style="color: #483d8b;">&quot;/usr/lib/python3.4/unittest/mock.py&quot;</span><span style="color: #66cc66;">,</span> line <span style="color: #ff4500;">760</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">in</span> assert_called_with
    <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">AssertionError</span><span style="color: black;">&#40;</span>_error_message<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">from</span> cause
<span style="color: #008000;">AssertionError</span>: Expected call: mock<span style="color: black;">&#40;</span><span style="color: #483d8b;">'not_ieux'</span><span style="color: black;">&#41;</span>
Actual call: mock<span style="color: black;">&#40;</span><span style="color: #483d8b;">'ieux'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>On dirait que tu vas mettre ces porte-jartelles et&#8230;</h2>
<p>Pour finir, le module <code>mock</code> vient avec <code>patch()</code>, qui sert à, surprise, patcher les objets, et propose des <a href="http://sametmax.com/les-context-managers-et-le-mot-cle-with-en-python/">context managers</a> et des <a href="http://sametmax.com/comprendre-les-decorateurs-python-pas-a-pas-partie-1/">décorateurs</a> pour se faciliter la vie.</p>
<p>Par exemple, détourner <code>open()</code> temporairement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">unittest</span>.<span style="color: black;">mock</span> <span style="color: #ff7700;font-weight:bold;">import</span> patch
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">with</span> patch<span style="color: black;">&#40;</span><span style="color: #483d8b;">'__main__.open'</span><span style="color: #66cc66;">,</span> mock_open<span style="color: black;">&#40;</span>read_data<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'wololo'</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> create<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> mock:
...     <span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'zefile'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> h:
...         <span style="color: black;">result</span> <span style="color: #66cc66;">=</span> h.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> mock.<span style="color: black;">assert_called_once_with</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'zefile'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">assert</span> result <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'wololo'</span></pre></td></tr></table></div>

<p>Ou alors avoir une partie d&#8217;un module qui soit un mock pour tout un appel de fonction :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">@</span>patch<span style="color: black;">&#40;</span><span style="color: #483d8b;">'os.listdir'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> ah<span style="color: black;">&#40;</span>mock<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">listdir</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'.'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># l'objet mock initial est aussi passé en param automatiquement</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>mock<span style="color: black;">&#41;</span>
ah<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;">## &lt;MagicMock name='listdir()' id='140302096346864'&gt;</span>
<span style="color: #808080; font-style: italic;">## &lt;MagicMock name='listdir' id='140302101454688'&gt;</span></pre></td></tr></table></div>

<p>Le module mock est vraiment très complet, avec des outils pour checker les signatures, passer <code>isinstance()</code>, overrider le contenu d&#8217;un dico, et tout un tas de cas particuliers et corner cases. Donc <a href="https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch">lisez la doc</a> si vous rencontrez un blocage avant de paniquer.</p>
<h2>Dis, comment on fait les bébés</h2>
<p>Exemple prit d&#8217;une base de code IRL, avec une fonction pytest qui teste un objet <code>response</code> représentant une réponse HTTP. Si on appelle <code>write()</code> sur cet objet sous-jacent elle doit faire des appels à deux méthodes privées et une méthode d&#8217;un objet Twisted.</p>
<p>Problème, ces méthodes :</p>
<ul>
<li>Supposent qu&#8217;une event loop est lancée.</li>
<li>Ecrivent sur le réseau.</li>
<li>Sont potentiellement appelées de manière asynchrone, en dehors de notre contrôle.</li>
<li>Ont des side effects donc on veut être certains qu&#8217;elles sont appelées, et avec les bons paramètres.</li>
</ul>
<p>Du coup, on les remplace par des objets mocks, et yala :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> test_write<span style="color: black;">&#40;</span>response<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">assert</span> response.<span style="color: black;">write</span> <span style="color: #66cc66;">!=</span> response._req.<span style="color: black;">write</span>
    response._disable_rendering <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'_disable_rendering'</span><span style="color: black;">&#41;</span>
    response._set_twisted_headers <span style="color: #66cc66;">=</span> MagicMock<span style="color: black;">&#40;</span>name<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'_set_twisted_headers'</span><span style="color: black;">&#41;</span>
    response.<span style="color: black;">write</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span>
    response._set_twisted_headers.<span style="color: black;">assert_called_once_with</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    response._disable_rendering.<span style="color: black;">assert_called_once_with</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">assert</span> response.<span style="color: black;">write</span> <span style="color: #66cc66;">==</span> response._req.<span style="color: black;">write</span>
    response._req.<span style="color: black;">write</span>.<span style="color: black;">assert_called_once_with</span><span style="color: black;">&#40;</span>b<span style="color: #483d8b;">'test'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<h2>Et pourquoi ? Et pourquoi ? Et pourquoi ?</h2>
<p>Prochaines étapes, savoir quand tester, et quoi tester, mais aussi comment rendre un code plus testable. Probablement la partie qui sera la plus difficile à écrire pour moi, car c&#8217;est assez subjectif. On parlera sans doute du code coverage, et je gage que je vais devoir créer un petit projet bidon pour tester tout ça, du genre un minifieur d&#8217;URL ou autre. Faudra voir l&#8217;inspiration.</p>


feed_id: http://sametmax.com/?p=16349
title: La branlette fait faire des économies 26
uri: La-branlette-fait-faire-des-économies-9-Recently-updated
url: http://sametmax.com/la-branlette-fait-faire-des-economies/
content:
<p>Vous connaissez cette sagesse populaire qui incite à ne jamais faire les courses le ventre vide ?</p>
<p>J&#8217;aimerais ajouter une règle d&#8217;hygiène de vie qu&#8217;il vaudrait enseigner dès le collège à tous les mâles en devenir : branlez-vous avant l&#8217;action.</p>
<p>Par action je n&#8217;entends pas la session de pirouette basque avec la voisine, bien que selon la situation ça puisse être une bonne stratégie.</p>
<p>Non, je parles de remplir un objectif qui demande un minimum de prise de décision suivi d&#8217;une action ou d&#8217;une interaction sociale majeure.</p>
<p>Dans Le Loup de Wall Street, qui n&#8217;est pas un monument du cinéma mais reste un divertissement scorcesien décent, un personnage secondaire résume bien le principe :</p>
<p><span class='embed-youtube' style='text-align:center; display: block;'><iframe class='youtube-player' type='text/html' width='1170' height='689' src='http://www.youtube.com/embed/aSn1g-6h1OQ?version=3&#038;rel=1&#038;fs=1&#038;showsearch=0&#038;showinfo=1&#038;iv_load_policy=1&#038;wmode=transparent' frameborder='0' allowfullscreen='true'></iframe></span></p>
<p>Et la raison est que, en plus de faire diminuer les tensions, se palucher un coup améliore sérieusement la capacité de choix, en retirant temporairement du diagramme décisionnel de votre tête tout un tas de losanges jaunes, biologiques et psychologiques.</p>
<p>Évidement, certains pourraient répliquer qu&#8217;il faudrait mieux avoir du self control, du recul et la capacité à gérer les situations en dehors de sa zone de confort.</p>
<p>A cela je répliquerais que oui, mais en attendant que chacun fasse murir le Clint Eastwood qui est en lui, un paquet de kleenex propose un bon rapport qualité/prix.</p>
<p>Avant un entretien de job, branlez-vous.</p>
<p>Avant de faire un gros achat, branlez-vous.</p>
<p>Avant d&#8217;aller dans une intense réunion, branlez-vous.</p>
<p>Avant de faire une code review, branlez-vous.</p>
<p>Avant de valider une mise en prod, branlez-vous.</p>
<p>Le seul cas où je ne recommande pas de se masturber, c&#8217;est pour la drague, contrairement à ce qu&#8217;on dit dans Marie à tout prix :</p>
<blockquote><p>You choke the chicken before any big date, don&#8217;t you? Tell me you spank the monkey before any big date. Oh my God, he doesn&#8217;t flog the dolphin before a big date. Are you crazy? That&#8217;s like going out there with a loaded gun! Of course that&#8217;s why you&#8217;re nervous. Oh my dear friend, please sit, please. Look, um, after you&#8217;ve had sex with a girl, and you&#8217;re lying in bed with her, are you nervous? No, you&#8217;re not, why? </p></blockquote>
<p>Parce que conserver une érection en suspens, ça garde motivé pour tendre vers son but, si je puis dire.</p>
<p>Pour le reste, dans le doute, branlez-vous.</p>
<p>Il en restera toujours quelque chose, n&#8217;est-pas ?</p>


feed_id: http://sametmax.com/?p=16360
title: Le don du mois 8
uri: Le-don-du-mois-4
url: http://sametmax.com/le-don-du-mois/
content:
<p>J&#8217;utilise Ubuntu au quotidien, et j&#8217;ai déjà donné au projet, mais les dernières décisions prises par l&#8217;équipe de la distrib ne me paraissent pas toujours judicieuses.</p>
<p>Aussi, afin de contribuer à Ubuntu, mais aussi à de nombreux autres projets, le don du mois sera pour le projet <a href="https://www.debian.org/">Debian</a>, qui est à la racine de nombreuses distribs, dont Ubuntu. Les bénéfices se feront donc en cascade.</p>
<p>L&#8217;équipe de Debian a su garder un cap en terme de qualité et de stabilité au cours des longues années de son existence, et sur un projet libre de cette taille, c&#8217;est un exploit. </p>
<p><a href="https://www.debian.org/donations.fr.html">$50 partent donc pour eux.</a> Avec <a href="http://linuxfr.org/users/elessar/journaux/debian-adopte-systemd-comme-init-par-defaut">l&#8217;adoption de systemd par défaut</a>, ils vont avoir besoin de ressources pour réaménager la caverne à trolls.</p>


feed_id: http://sametmax.com/?p=16365
title: Oh le beau scam ! 6
uri: Oh-le-beau-scam-4
url: http://sametmax.com/oh-le-beau-scam/
content:
<p>J&#8217;ai reçu ce mail ce matin :</p>
<blockquote><p>Attention: Important Notice , DOMAIN SERVICE NOTICE<br />
Domain Name: SITEDESAM.COM</p>
<p>Complete and return by fax to:<br />
1-206-278-9897</p>
<p>ATT: SAM<br />
ADMINISTRATIVE CONTACT<br />
&#8211;<br />
5686876587@CONTACT.GANDI.NET<br />
GANDI 63-65 BOULEVARD MASSENA &#8211; &#8211; (GANDI) PARIS &#8211; &#8211; &#8211; (GANDI) 75013<br />
(GANDI) FR<br />
WWW.SITEDESAM.COM<br />
Please ensure that your contact information is correct or make the necessary changes above </p>
<p>Requested Reply Before<br />
JUNE 08,2015</p>
<p>PART I: REVIEW SOLICITATION</p>
<p>Attn: SAM<br />
As a courtesy to domain name holders, we are sending you this notification for your business Domain name search engine registration. This letter is to inform you that it&#8217;s time to send in your registration and save.</p>
<p>Failure to complete your Domain name search engine registration by the expiration date may result in cancellation of this offer making it difficult for your customers to locate you on the web.</p>
<p>Privatization allows the consumer a choice when registering. Search engine subscription includes domain name search engine submission. You are under no obligation to pay the amounts stated below unless you accept this offer. Do not discard, this notice is not an invoice it is a courtesy reminder to register your domain name search engine listing so your customers can locate you on the web.</p>
<p>This Notice for: WWW.SITEDESAM.COM will expire on JUNE 08,2015 Act today!</p>
<p>Select Term: </p>
<p>[ ] 1 year   06/08/2015 &#8211; 06/08/2016 $75.00<br />
[ ] 2 year   06/08/2015 &#8211; 06/08/2017 $119.00<br />
[ ] 5 year   06/08/2015 &#8211; 06/08/2020 $199.05<br />
[ ] 10 year -Most Recommended- 06/08/2015 &#8211; 06/08/2025 $295.00<br />
[ ] Lifetime (NEW!) Limited time offer &#8211; Best value! Lifetime $499.00  </p>
<p>Today&#8217;s Date: _____________________ Signature: _____________________ </p>
<p>Payment by Credit Card<br />
Select the term above, then return by fax: 1-206-278-9897</p>
<p>SITEDESAM.COM</p>
<p>&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-</p>
<p>By accepting this offer, you agree not to hold DS liable for any part. Note that THIS IS NOT A BILL. This is a solicitation. You are under no obligation to pay the amounts stated unless you accept this offer. The information in this letter contains confidential and/or legally privileged information from the notification processing department of the DS 3501 Jack Northrop Ave. Suite #F9238 Hawthorne, CA 90250 USA, This information is intended only for the use of the individual(s) named above. There is no pre-existing relationship between DS and the domain mentioned above. This notice is not in any part associated with a continuation of services for domain registration. Search engine submission is an optional service that you can use as a part of your website optimization and alone may not increase the traffic to your site. If you do not wish to receive further updates from DS reply with Remove to unsubscribe. If you are not the intended recipient, you are hereby notified that disclosur<br />
 e, copying, distribution or the taking of any action in reliance on the contents for this letter is strictly prohibited.</p></blockquote>
<p> Le mail est très bien fait, car en le scannant j&#8217;ai vu le nom de mon site, le mail de mon registrat, et le mot &#8220;expire&#8221; dedans en plus d&#8217;un formulaire à retourner par fax :). Le langage utilisé est particulièrement vicieux et bien composé, et il m&#8217;a donc forcé à le lire plus lentement pour bien comprendre qu&#8217;il s&#8217;agissait d&#8217;une grosse arnaque.</p>
<p> C&#8217;est comme ces lettres qu&#8217;on reçoit après la création d&#8217;une entreprise pour s&#8217;enregistrer auprès d&#8217;annuaires qui portent des noms qui font très sérieux comme &#8220;Enregistrement des membres des chambres commerciales&#8221;. </p>
<p> J&#8217;imagine bien le gars qui a 30000 problèmes à résoudre, la tête dans le guidon et qui fait sans chercher à comprendre. Ca doit rapporter une fortune;</p>


feed_id: http://sametmax.com/?p=16371
title: Templates de projet avec cookiecutter 8
uri: Templates-de-projet-avec-cookiecutter
url: http://sametmax.com/templates-de-projet-avec-cookiecutter/
content:
<p>Beaucoup de frameworks viennent avec des templates de projets maintenant. Django vient avec <code>django-admin startproject --template</code>, tandis que crossbar vient avec <code>crossbar init --template</code>. L&#8217;idée d&#8217;avoir de templates pour ses projets n&#8217;a rien de nouveau, d&#8217;ailleurs la plupart des OS modernes ont au moins ça intégré pour des fichiers. Ainsi Ubuntu à un dossière &#8220;Modèles&#8221;, et tout ce qu&#8217;il y a dedans peut être dupliqué ailleurs via un clic droit dans Nautilus.</p>
<p>Néanmoins la meilleure solution à ce jour vient de Audrey Roy, qui est avant tout connue pour avoir co-écrit le livre Two scoops of Django, et qui a aussi pondu <a href="http://cookiecutter.readthedocs.org/en/latest/readme.html">cookiecutter</a>.</p>
<p>L&#8217;outil est très simple. D&#8217;abord un <a href="http://sametmax.com/votre-python-aime-les-pip/">pip</a> pour l&#8217;installer :</p>
<p><code>pip install cookiecutter</code></p>
<p>Notez que bien que le projet soit en Python, les templates peuvent être en n&#8217;importe quel langage, cookiecutter s&#8217;en branle. Lui, il va juste copier le contenu du template dans un dossier, et remplacer les variables notées <code>{{}}</code> dedans.</p>
<p>Pour commencer, on créé un dossier nommé <code>{{cookiecutter.repo_name}}</code> qui va contenir le template de son projet. Oui, le nom du dossier est <code>{{cookiecutter.repo_name}}</code>. En effet les noms de dossiers et fichiers sont aussi templatisables, et passés à la moulinette de <a href="https://en.wikipedia.org/wiki/Jinja_%28template_engine%29">jinja2</a>.</p>
<p>Dans ce dossier, on peut mettre tous les fichiers qu&#8217;on veut, avec des noms normaux, ou avec des variables. Le contenu des fichiers peut, bien entendu, contenir aussi des variables. Les variables sont toujours de la forme <code>{{cookiecutter.nom_de_variable}}</code>.</p>
<p>Ensuite, à côté de notre dossier nommé <code>{{cookiecutter.repo_name}}</code> (le dossier du template), on peut créer un fichier <code>cookiecutter.json</code> qui va contenir les valeurs par défaut de nos variables :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="javascript" style="font-family:monospace;"><span style="color: #009900;">&#123;</span>
    <span style="color: #3366CC;">&quot;repo_name&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;nouveau_projet&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;version&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;0.1.0&quot;</span><span style="color: #339933;">,</span>
    <span style="color: #3366CC;">&quot;autre_variable&quot;</span><span style="color: #339933;">:</span> <span style="color: #3366CC;">&quot;Bidule&quot;</span>
<span style="color: #009900;">&#125;</span></pre></td></tr></table></div>

<p>Enfin pour récolter les fruits de son labeur, on lance <code>cookiecutter /chemin/vers/template</code> et l&#8217;outil va vous poser tout un tas de question pour remplir les variables, puis va générer le nouveau projet dans le dossier courant.</p>
<p>Cookiecutter accepte aussi des urls de repo git et mercurial comme source de template, et l&#8217;auteur de l&#8217;outil fournit un <a href="https://github.com/audreyr/cookiecutter-pypackage">template de projet Python</a> très complet par ce biais. </p>
<p>On va l&#8217;utiliser comme exemple.</p>
<p>Voici son contenu :</p>
<pre>├── cookiecutter.json <= valeur par défaut des variables
├── {{cookiecutter.repo_name}} <= template du projet
│   ├── AUTHORS.rst
│   ├── CONTRIBUTING.rst
│   ├── {{cookiecutter.repo_name}}
│   │   ├── {{cookiecutter.repo_name}}.py
│   │   └── __init__.py
│   ├── docs
│   │   ├── authors.rst
│   │   ├── conf.py
│   │   ├── contributing.rst
│   │   ├── history.rst
│   │   ├── index.rst
│   │   ├── installation.rst
│   │   ├── make.bat
│   │   ├── Makefile
│   │   ├── readme.rst
│   │   └── usage.rst
│   ├── HISTORY.rst
│   ├── LICENSE
│   ├── Makefile
│   ├── MANIFEST.in
│   ├── README.rst
│   ├── requirements.txt
│   ├── setup.cfg
│   ├── setup.py
│   ├── tests
│   │   ├── __init__.py
│   │   └── test_{{cookiecutter.repo_name}}.py
│   └── tox.ini
└── README.rst</pre>
<p>Certains usages de variables sont assez évident, comme par exemple le fichier __init__:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
__author__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'{{ cookiecutter.full_name }}'</span>
__email__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'{{ cookiecutter.email }}'</span>
__version__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'{{ cookiecutter.version }}'</span></pre></td></tr></table></div>

<p>D'autres sont assez malines et inattendues comme le fichier de test :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
test_{{ cookiecutter.repo_name }}
----------------------------------
Tests for `{{ cookiecutter.repo_name }}` module.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> cookiecutter.<span style="color: black;">repo_name</span> <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> cookiecutter.<span style="color: black;">repo_name</span> <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Test<span style="color: black;">&#123;</span><span style="color: black;">&#123;</span> cookiecutter.<span style="color: black;">repo_name</span>|capitalize <span style="color: black;">&#125;</span><span style="color: black;">&#125;</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_something<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> tearDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">unittest</span>.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On note l'usage du filtre jinja <code>capitalize</code>. Tous les outils de jinja sont à disposition, ce serait con de s'en priver.</p>
<p>Pour utiliser le template on fait <code>$ cookiecutter https://github.com/audreyr/cookiecutter-pypackage.git</code>, ce qui nous donne :</p>
<pre>
Clonage dans 'cookiecutter-pypackage'...
remote: Counting objects: 505, done.
remote: Total 505 (delta 0), reused 0 (delta 0), pack-reused 505
Réception d'objets: 100% (505/505), 77.89 KiB | 0 bytes/s, done.
Résolution des deltas: 100% (265/265), done.
Vérification de la connectivité... fait.
full_name (default is "Audrey Roy")? Sam
email (default is "audreyr@gmail.com")? lesametlemax@gmail.com
github_username (default is "audreyr")? sam
project_name (default is "Python Boilerplate")? essai
repo_name (default is "boilerplate")? essai
project_short_description (default is "Python Boilerplate contains all the boilerplate you need to create a Python package.")? C'est un essai j'ai dis
release_date (default is "2015-01-11")? 
year (default is "2015")? 
version (default is "0.1.0")? </pre>
<p>Notez les valeurs par défaut du fichier JSON, qui sont celles de l'auteur.</p>
<p>Le résultat généré :</p>
<pre>
├── essai
│   ├── AUTHORS.rst
│   ├── CONTRIBUTING.rst
│   ├── docs
│   │   ├── authors.rst
│   │   ├── conf.py
│   │   ├── contributing.rst
│   │   ├── history.rst
│   │   ├── index.rst
│   │   ├── installation.rst
│   │   ├── make.bat
│   │   ├── Makefile
│   │   ├── readme.rst
│   │   └── usage.rst
│   ├── essai
│   │   ├── essai.py
│   │   └── __init__.py
│   ├── HISTORY.rst
│   ├── LICENSE
│   ├── Makefile
│   ├── MANIFEST.in
│   ├── README.rst
│   ├── requirements.txt
│   ├── setup.cfg
│   ├── setup.py
│   ├── tests
│   │   ├── __init__.py
│   │   └── test_essai.py
│   └── tox.ini
└── README.rst</pre>
<p>Le fichier __init__ est devenu :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
__author__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'Sam'</span>
__email__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'lesametlemax@gmail.com'</span>
__version__ <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'0.1.0'</span></pre></td></tr></table></div>

<p>Et le fichier de test :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #483d8b;">&quot;&quot;&quot;
test_essai
----------------------------------
&nbsp;
Tests for `essai` module.
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">unittest</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> essai <span style="color: #ff7700;font-weight:bold;">import</span> essai
&nbsp;
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> TestEssai<span style="color: black;">&#40;</span><span style="color: #dc143c;">unittest</span>.<span style="color: black;">TestCase</span><span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> setUp<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> test_something<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> tearDown<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'__main__'</span>:
    <span style="color: #dc143c;">unittest</span>.<span style="color: black;">main</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>L'outil accepte <a href="http://cookiecutter.readthedocs.org/en/latest/advanced_usage.html">un beau degré de customisation</a>, avec un fichier de configuration général au niveau de l'utilisateur (et donc des valeurs par défaut par utilisateur), une API programmable en Python, des hooks pre et post generation (qui permettent d'injecter des variables dynamiquement comme par exemple un uuid ou un timestamp).</p>
<p>Donc si vous recréez souvent les mêmes layout de projet encore et encore, pensez à cookiecutter.</p>
<p>Mais surtout, surtout, si vous codez votre propre framework, ne faites pas comme Django, utilisez l'API de cookiecutter au lieu de réinventer la roue.</p>


feed_id: http://sametmax.com/?p=16379
title: Le problème avec les plans de cours 5
uri: Le-problème-avec-les-plans-de-cours-1-Recently-updated
url: http://sametmax.com/le-probleme-avec-les-plans-de-cours/
content:
<p>Quand je suis sollicité pour une formation, l&#8217;organisme demandeur requiert souvent un plan de cours.</p>
<p>Je le fournis toujours, et la première chose que je fais en commençant la formation, c&#8217;est de le mettre à la poubelle.</p>
<p>Pourquoi ?</p>
<p>D&#8217;une part, j&#8217;essaye toujours de contacter les participants avant, afin d&#8217;analyser leurs besoins réels. Pas ceux imaginés par l&#8217;organisme de formation, les RH, le training manager, le chef d&#8217;équipe ou leur fanstasme sur ce qu&#8217;ils doivent faire.</p>
<p>Non, je demande ce qu&#8217;ils font au quotidien, leurs missions, leurs postes, leurs tâches, leurs envies, leurs styles, leurs objectifs et projets. J&#8217;en déduis des notions clés, et je leur propose. Ils me corrigent, et on arrive à quelque chose d&#8217;utile.</p>
<p>Mais même ainsi, si je me limitais à organiser ces notions en un document avec des grands titres qui regroupent tout ça par thème ou pas unité de temps, puis ordonnés sous forme de liste, je ne remplirai pas ce contrat le jour J.</p>
<p>En effet, un plan de cours est linéaire, tandis que l&#8217;enseignement ne l&#8217;est pas.</p>
<p>Prenez par exemple les chaînes de caractères. On pourrait se dire que c&#8217;est la base, on en parle au début et c&#8217;est bon.</p>
<p>Pas du tout.</p>
<p>Voici toutes les notions liées aux chaînes de caractères en Python qu&#8217;on peut aborder dans une formation pour débutants :</p>
<ul>
<li>print</li>
<li>donnée vs représentation</li>
<li>formatage</li>
<li>concaténation</li>
<li>transformation</li>
<li>recherche</li>
<li>immutabilité</li>
<li>itérabilité</li>
<li>indexabilité</li>
<li>hashabilité</li>
<li>préfixes et caractères d’échappement</li>
<li>bytes vs string</li>
<li>charset</li>
<li>python 2 vs python 3</li>
<li>docstrings</li>
</ul>
<p>Et là je ne parle même pas de la notion du sens du texte. Je ne parle pas des fichiers. Je ne parle pas d&#8217;extraction complexe avec des regex. Je ne parle pas de l&#8217;utilisation du texte dans un protocole de communication ou un outil de sérialisation. Je ne parle pas de format de contenu comme sphinx ou les doctests. Je parle bien juste de la structure de données, le truc le plus basique du langage, une des notions les plus primitives qui sert de socle à toutes les autres.</p>
<p>Bien entendu tous ces aspects ne sont pas utiles tout de suite, et on les introduit au fur et à mesure de la formation. Contextuellement.</p>
<p>Toutes les notions sont comme ça. Les centaines nécessaires à l&#8217;apprentissage du langage ont de multiples facettes, qui ne sont pas présentables en bloc.</p>
<p>On ne les enseigne pas pour en faire le tour, on en prend un petit bout, on le mélange avec le reste, comme on prendrait des fils qu&#8217;on croiserait alors pour tisser un vêtement.</p>
<p>Un plan qui dirait: on voit les strings ici, et c&#8217;est finit, ne ferait que mentir. Mais un plan qui dirait la vérité ferait 10 pages de listing alambiqué rempli de concepts qui s&#8217;entrecroisent sans même donner leurs interactions pourtant indispensables. Dans tous les cas, rien de pertinent.</p>
<p>Pourquoi je l&#8217;écris alors ?</p>
<p>Essentiellement pour deux raisons :</p>
<p>D&#8217;abord une raison administrative. Beaucoup de dossiers requièrent un plan, afin de démontrer que le prestataire sait de quoi il parle. Mais surtout, les commerciaux ont besoin d&#8217;un plan pour avoir quelque chose de concret sur lequel s&#8217;appuyer pour faire leur vente.</p>
<p>La seconde raison est pour que les gens qui vont à la formation, sachent à quelle sauce qu&#8217;ils vont être mangés. C&#8217;est vrai, le plan ne reflète en aucun cas la réalité de la formation, mais il va donner une idée de ce qu&#8217;on va aborder. On peut ainsi faire ses choix, demander des amendements, s&#8217;y préparer, etc.</p>
<p>Aussi, quand vous faites un cours, ne rejetez pas l&#8217;importance de faire un plan. Mais libérez-vous en dès que vous faites le premier pas dans la salle de cours. Il est des contrats qu&#8217;il faut savoir briser.</p>


feed_id: http://sametmax.com/?p=16389
title: La mort du tuto angular 27
uri: La-mort-du-tuto-angular-4
url: http://sametmax.com/la-mort-du-tuto-angular/
content:
<p><a href="http://sametmax.com/je-me-te-tate-a-arreter-le-tuto-angular/">J&#8217;avais demandé</a> si il y avait encore des gens intéressés par le <a href="http://sametmax.com/angularjs-pour-les-utilisateurs-de-jquery-partie-2/">tuto angularjs</a> que j&#8217;avais commencé. En effet les ressources sur Angular sont généralement de mauvaise qualité, et la réponse avait été un gros OUI.</p>
<p>Je m&#8217;étais donc mis en tête de continuer. Malgré <a href="https://www.youtube.com/watch?v=KJ_xAwSeFR8">la mort annoncée du framework</a>. Malgré <a href="http://www.i-programmer.info/news/167-javascript/7932-angularjs-20-is-radically-different-.html">une V2 qui va tout casser</a>.</p>
<p>Voyez-vous, j&#8217;aime Angular. Bien que je pense que pour des grosses apps une approche comme ReactJS + BackboneJS est plus saine, pour une petit app rapide ou du prototypage c&#8217;est très productif et pratique.</p>
<p>En plus, je n&#8217;aime vraiment pas manquer à mes engagements, et en presque 3 ans de ce blog, je les ai tenu. J&#8217;ai toujours publié les articles promis. Toujours répondu aux mails. Parfois avec des mois de retard, certes, mais je n&#8217;ai signé aucun contrat moral sur les deadlines :)</p>
<p>Je vais néanmoins faire une exception ici et envoyer le tuto Angular au cimetière. Toute mes excuses à ceux qui l&#8217;attendaient.</p>
<p>Bien sûr il y a le fait que j&#8217;ai beaucoup de travail. Cependant si c&#8217;était la cause principale je n&#8217;écrirais plus ici car ça me demande des heures et des heures chaque semaine.</p>
<p>C&#8217;est surtout qu&#8217;il se trouve que j&#8217;avorte régulièrement des tentatives de retravailler dessus. C&#8217;est un signe de manque de motivation certain, et je viens d&#8217;en comprendre aujourd&#8217;hui la raison : c&#8217;est du Javascript.</p>
<p>Jusqu&#8217;ici le blog s&#8217;était autorisé régulièrement des sorties de la ligne éditoriale, mais un tel travail, un guide complet sur Angular, enterine le JS comme un sujet majeur du site.</p>
<p>Or ce n&#8217;est pas le cas.</p>
<p><a href="http://sametmax.com/un-gros-troll-de-plus-sur-javacscript/">Je n&#8217;aime pas Javascript.</a></p>
<p>Du coup non seulement me motiver à faire le dossier me demande une énorme énergie (qui pour le moment se transforme en procrastination coupable), mais en prime je me dis que c&#8217;est dépenser des ressources pour faire le taff d&#8217;une communauté qu&#8217;au final je ne supporte que par obligation professionnelle.</p>
<p>Le résultat est donc que bien que je vais continuer à parler de JS et à coder en JS (programmation Web oblige), je ne vais pas lui accorder autant de place sur S&#038;M ou dans mes heures de loisir.</p>
<p>Je remercie ceux qui prennent le temps de le faire, après tout je profite de leur travail. De mon côté, je vais me concentrer sur les domaines qui me sont plus chers, et parler d&#8217;autre chose uniquement de manière ponctuelle. L&#8217;investissement me parait plus judicieux.</p>


feed_id: http://sametmax.com/?p=16396
title: IndexErrorCoders, le compte github de la communauté d’IndexError 24
uri: IndexErrorCoders-le-compte-github-de-la-communauté-d-IndexError-16
url: http://sametmax.com/indexerrorcoders-le-compte-github-de-la-communaute-dindexerror/
content:
<p>C&#8217;est pas moi, j&#8217;ai rien fais !</p>
<p>J&#8217;ai reçu une notif m&#8217;invitant à participer à <a href="https://github.com/indexerrorcoders">ce groupe de travail</a>, et en regardant de plus près, j&#8217;ai vu qu&#8217;il s&#8217;appelait IndexErrorCoders.</p>
<p>Après investigation, il est né <a href="http://indexerror.net/1957/design-patterns-votre-caisse-%C3%A0-outils?show=2051#c2051">d&#8217;une question sur IndexError</a> qui, commentaire après commentaire, à abouti à la création d&#8217;un <a href="https://github.com/indexerrorcoders/python-patterns">repo git dédié aux design patterns Python.</a></p>
<p>C&#8217;est toujours sympas de voir les trucs qui se forment autour de notre petite communauté, on a l&#8217;impression de vivre dans une coloc avec tout le monde :)</p>
<p>Bonne chance au projet.</p>


feed_id: http://sametmax.com/?p=16407
title: Nouveau fichier de start up Python 9
uri: Nouveau-fichier-de-start-up-Python-Recently-updated
url: http://sametmax.com/nouveau-fichier-de-start-up-python/
content:
<p>Régulièrement je passe un coup de dépoussiérage sur mes outils, et aujourd&#8217;hui c&#8217;est le tour du script de start up.</p>
<p>Pour ceux qui ne se souviennent pas, on peut utiliser la variable d&#8217;environnement <a href="http://sametmax.com/variables-denvironnement-utilisees-par-python/">PYTHONSTARTUP</a> pour choisir un script de démarrage pour le shell.</p>
<p>Ca attend un chemin absolu vers un fichier Python, et donc sous Mac et Linux, on met dans son <code>.bashrc</code> ou équivalent :</p>
<p><code>export PYTHONSTARTUP=/chemin/vers/son/script.py</code></p>
<p>Sous Windows, on ouvre une console et on fait :</p>
<p><code>SETX PYTHONSTARTUP c:\chemin\vers\son\script.py</code></p>
<p>Et dedans on peut mettre tout le code Python qu&#8217;on veut, ça sera lancé automatiquement quand on démarre le shell, mais PAS quand on lance un script Python.</p>
<p>Le script est exécuté dans l&#8217;espace de nom du shell, donc tous les imports du script sont mis à la disposition du shell. Du coup, pour moi il contient :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># -*- coding: utf-8 -*-</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># faut que ça marche pareil en P2 et P3</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">__future__</span> <span style="color: #ff7700;font-weight:bold;">import</span> unicode_literals<span style="color: #66cc66;">,</span> print_function<span style="color: #66cc66;">,</span> absolute_import
&nbsp;
<span style="color: #808080; font-style: italic;"># Les imports des modules de la libs standars que j'utilise le plus</span>
<span style="color: #808080; font-style: italic;"># car à force çe me gave de les réimporter moi-même à chaque session</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> json
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">csv</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span>
<span style="color: #ff7700;font-weight:bold;">import</span> hashlib
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">tempfile</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">random</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">shelve</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">atexit</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">subprocess</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">glob</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">glob</span>
<span style="color: #ff7700;font-weight:bold;">from</span> uuid <span style="color: #ff7700;font-weight:bold;">import</span> uuid4
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">pprint</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">pprint</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># on shadow le open() builtin histoire d'avoir toujours le</span>
<span style="color: #808080; font-style: italic;"># paramètre encoding</span>
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">codecs</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #008000;">open</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">itertools</span> <span style="color: #ff7700;font-weight:bold;">import</span> *
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> *
<span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">datetime</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span><span style="color: #66cc66;">,</span> timedelta
&nbsp;
<span style="color: #808080; font-style: italic;"># imports d'outils tierces parties que j'utilise souvent mais qui pourraient ne</span>
<span style="color: #808080; font-style: italic;"># pas être installés</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> arrow
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> requests
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">from</span> path <span style="color: #ff7700;font-weight:bold;">import</span> path
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">from</span> minibelt <span style="color: #ff7700;font-weight:bold;">import</span> *
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># activation d'autocompletion si ce n'est pas déjà le cas, notamment sous</span>
<span style="color: #808080; font-style: italic;"># des vieux shell Python ordinnaire</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">rlcompleter</span>
    <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">readline</span>
    <span style="color: #dc143c;">readline</span>.<span style="color: black;">parse_and_bind</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;tab: complete&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">ImportError</span>:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># si on est dans un virtual env</span>
env <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">environ</span>.<span style="color: black;">get</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'VIRTUAL_ENV'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">if</span> env:
&nbsp;
    <span style="color: #808080; font-style: italic;"># afficher le nom de l'env dans le prompt (marche pas dans ipython qui</span>
    <span style="color: #808080; font-style: italic;"># a sa propre config pour ça)</span>
    env_name <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>env<span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">sys</span>.<span style="color: black;">ps1</span> <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">'(%s) %s '</span> % <span style="color: black;">&#40;</span>env_name<span style="color: #66cc66;">,</span> <span style="color: #008000;">getattr</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'ps1'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'&gt;&gt;&gt;'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># affichage une fois des modules installés avec pip pour qu'on sache</span>
    <span style="color: #808080; font-style: italic;"># ce qu'on a a dispo dans cet env</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>Virtualenv '{}' contains:<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span>.<span style="color: black;">format</span><span style="color: black;">&#40;</span>env_name<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #dc143c;">cmd</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">subprocess</span>.<span style="color: black;">check_output</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span>env + <span style="color: #483d8b;">&quot;/bin/pip&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;freeze&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>
                                  stderr<span style="color: #66cc66;">=</span><span style="color: #dc143c;">subprocess</span>.<span style="color: black;">STDOUT</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">try</span>:
        <span style="color: #dc143c;">cmd</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">cmd</span>.<span style="color: black;">decode</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'utf8'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">except</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
    <span style="color: #dc143c;">cmd</span> <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">cmd</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
    p <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">'(^.*<span style="color: #000099; font-weight: bold;">\:</span><span style="color: #000099; font-weight: bold;">\s</span>)|((#|@).*$)|(==.*$)'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;'&quot;</span> + <span style="color: #483d8b;">&quot;', '&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">sorted</span><span style="color: black;">&#40;</span><span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">basename</span><span style="color: black;">&#40;</span>p.<span style="color: black;">sub</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span><span style="color: #66cc66;">,</span> f<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> f <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">cmd</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;'<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
&nbsp;
<span style="color: #808080; font-style: italic;"># alias pour printer rapidement</span>
p <span style="color: #66cc66;">=</span> <span style="color: #ff7700;font-weight:bold;">print</span>
pp <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">pprint</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># avoir toujours un dossier temporaire près à l'usage</span>
TEMP_DIR <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">tempfile</span>.<span style="color: black;">gettempdir</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'pythontemp'</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #dc143c;">os</span>.<span style="color: black;">makedirs</span><span style="color: black;">&#40;</span>TEMP_DIR<span style="color: black;">&#41;</span>
    TEMP_DIR <span style="color: #66cc66;">=</span> path<span style="color: black;">&#40;</span>TEMP_DIR<span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># si possible un objet path</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">Exception</span> <span style="color: #ff7700;font-weight:bold;">as</span> e:
    <span style="color: #ff7700;font-weight:bold;">pass</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># avoir un dico persistant pour garder des objets entre deux sessions. Pratique quand</span>
<span style="color: #808080; font-style: italic;"># on a un gros array numpy qu'on n'a pas envie de se faire chier à se recréer</span>
<span style="color: #ff7700;font-weight:bold;">class</span> Store<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> filename<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'DICT'</span><span style="color: #66cc66;">,</span> <span style="color: #dc143c;">shelve</span>.<span style="color: black;">DbfilenameShelf</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># cleaning the dict on the way out</span>
        <span style="color: #dc143c;">atexit</span>.<span style="color: black;">register</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>._clean<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> name<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> name <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;DICT&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'_clean'</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">try</span>:
                <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">DICT</span><span style="color: black;">&#91;</span>name<span style="color: black;">&#93;</span>
            <span style="color: #ff7700;font-weight:bold;">except</span>:
                <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">None</span>
        <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">object</span>.<span style="color: #0000cd;">__getattribute__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> name<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__setattr__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> name<span style="color: #66cc66;">,</span> value<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">if</span> name <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;DICT&quot;</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'_clean'</span><span style="color: black;">&#41;</span>:
            <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">ValueError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;'%s' is a reserved name for this store&quot;</span> % name<span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DICT</span><span style="color: black;">&#91;</span>name<span style="color: black;">&#93;</span> <span style="color: #66cc66;">=</span> value
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> _clean<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">DICT</span>.<span style="color: black;">sync</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">DICT</span>.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Ainsi on peut faire store.foo = 'bar' et récupérer store.foo à la session</span>
<span style="color: #808080; font-style: italic;"># suivante. Moi je store tout dans un truc temporaire mais si vous voulez</span>
<span style="color: #808080; font-style: italic;"># garder la persistance entre deux reboots, il suffit de choisir un autre</span>
<span style="color: #808080; font-style: italic;"># dossier. </span>
python_version <span style="color: #66cc66;">=</span> <span style="color: #483d8b;">&quot;py%s&quot;</span> % <span style="color: #dc143c;">sys</span>.<span style="color: black;">version_info</span>.<span style="color: black;">major</span>
store <span style="color: #66cc66;">=</span> Store<span style="color: black;">&#40;</span><span style="color: #dc143c;">os</span>.<span style="color: black;">path</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>TEMP_DIR<span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'store.%s.db'</span><span style="color: black;">&#41;</span> % python_version<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Il est un peu relou puisqu&#8217;il faut qu&#8217;il marche pour P2 et P3&#8230;</p>
<p>Je me demande si je devrais pas faire un repo pour ce genre de truc.</p>


feed_id: http://sametmax.com/?p=16433
title: Pourquoi les nouveaux programmeurs ne lisent plus le code source des autres 80
uri: Pourquoi-les-nouveaux-programmeurs-ne-lisent-plus-le-code-source-des-a
url: http://sametmax.com/pourquoi-les-nouveaux-programmeurs-ne-lisent-plus-le-code-source-des-autres/
content:
<p>Dans un <a href="https://rhettinger.wordpress.com/2011/01/28/open-your-source-more/#comment-569">ancien post</a> sur son blog, Raymond Hettinger s&#8217;attristait de voir les devs lire de moins en moins le code source. Bien qu&#8217;il datait de plus de 4 ans, je n&#8217;ai pas pu m&#8217;empêcher de répondre. Puis je me suis dis que la traduction aurait tout à fait sa place ici.</p>
<p>La cause de ce phénomène est très culturel. J&#8217;enseigne à mes étudiants que si ils veulent en savoir plus sur le fonctionnement d&#8217;un bout de code d&#8217;un module, ils peuvent juste faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> module
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>module.__file__<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Puis ouvrir le fichier dont ils obtiennent ainsi le chemin dans leur éditeur préféré. Cela marche en tout cas pour tous les modules en pur Python.</p>
<p>En fait, si vous utilisez ipython, vous pouvez même faire :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">!</span>votreediteur module.__file__<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Et ça l&#8217;ouvrira directement. Par exemple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">!</span>subl module.__file__<span style="color: black;">&#91;</span>:-<span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Malgré cette information, ils ne le font jamais.</p>
<p>En partie parce qu&#8217;ils ont peur.</p>
<p>En partie parce que plus personne n&#8217;enseigne cet état d&#8217;esprit à l&#8217;université ou dans les tutos.</p>
<p>Mais essentiellement parce que toute autre méthode est plus productive, donc ils sont formés à utiliser à peu près tout sauf regarder le code source.</p>
<p>Chercher sur Google, demander sur un site d&#8217;aide, sur IRC, une mailling list, à un collègue, brute forcer tous les snippets qui traînent en les copiant/collant à la chaîne, et même, Dieu nous garde, lire la doc. Tout cela est plus facile et rapide que de lire le code source, parce lire les sources part du principe qu&#8217;on comprend comment tout marche. </p>
<p>Il y a aussi le fait que lire le code source il y a 30 ans était compétitif avec les autres options de consultation, tandis qu&#8217;aujourd&#8217;hui de nombreux devs ont 4 ordis chez eux avec un accès haut débit à la connaissance du monde entier. </p>
<p>Et bien sûr, ils se sont habitués à la vitesse. Et plus que ça, leurs enseignants/boss s&#8217;y sont habitués, et leur comportement communique implicitement cette attente, ce qui amène à ne pas lire les sources.</p>
<p>Cela m&#8217;a pris 5 ans de programmation pro avant de commencer à regarder les sources par moi-même de manière régulière. J&#8217;y ai été forcé, ayant beaucoup travaillé en Afrique et en Asie où avoir l&#8217;info hors ligne est un avantage.</p>
<p>Malgré cela, je ne le fais que pour le code Python, car mes talents en C sont faibles et je n&#8217;ai jamais pris le temps de télécharger les fichiers C. Je sais pertinemment que la programmation C est un atout important à avoir. Je souhaite l&#8217;apprendre. Et Rust, et Erlang, et Haskell, et l&#8217;espagnol et m&#8217;améliorer dans le gestion des CSS, l&#8217;administration système, la sécurité des systèmes, et essayer Riak, et OpenStack&#8230; Bien entendu, ça c&#8217;est juste la partie technique, j&#8217;ai une vie très pleine à côté. </p>
<p>Car voilà la seconde partie de la vérité : l&#8217;époque où on pouvait maitriser tout le champ de connaissance en informatique est révolue.</p>
<p>Je passe une HEURE, tous les jours, juste pour me mettre à jour dans mon ridicule petit champ d&#8217;expertise, et je n&#8217;ai même pas le temps de tout lire, encore moins de pratiquer. C&#8217;est 300 heures par an juste pour garder la tête hors de l&#8217;eau.</p>
<p>Maintenant, imaginez les débutants. Ils débarquent dans ce monde avec tellement de langages, de libs, de frameworks, d&#8217;outils, de technos ! Tellement de couches et de niveaux d&#8217;indirection ! Ils vont essayer d&#8217;obtenir la réponse aussi facilement qu&#8217;ils le peuvent, parce que la somme de connaissances accumulées qui permettent de lire les sources (ce n&#8217;est pas un acte simple, c&#8217;est une illusion qui bercent ceux qui sont devenus assez bons pour le faire sans effort), cette montagne, nous avons eu beaucoup plus de temps pour l&#8217;escalader qu&#8217;ils en ont. Et malgré cela, ils ont plus de choses que nous à apprendre.</p>
<p>Or le temps ne s&#8217;arrête pas pour autant, et l&#8217;expérience du marché se transforme. Les clients s&#8217;attendent aujourd&#8217;hui à des expériences logicielles bien plus complexes: designs léchés, animations, vitesse, connectivité, synchronisation, notification en temps réel, interconnexion de services, Web APIS, recherche intelligente, présentation contextuelle et personnalisée de l&#8217;information, traitement de médias riche&#8230; Et ça c&#8217;est juste pour des produits app/Web, car chaque marché a vu les attentes grandir.</p>
<p>Donc on attend d&#8217;eux qu&#8217;ils livrent tout ça, car les concurrents le font. Mais sans les y former, et si possible sans les payer trop cher. Et ASAP, évidement.</p>
<p>Les gens que je forme vont chercher un moyen d&#8217;obtenir le résultat dont ils ont besoin aussi vite que possible, avec aussi peu d&#8217;effort que possible.</p>
<p>C&#8217;est triste, mais je comprends parfaitement.</p>


feed_id: http://sametmax.com/?p=16427
title: Une boucle while de moins 5
uri: Une-boucle-while-de-moins-5-Recently-updated
url: http://sametmax.com/une-boucle-while-de-moins/
content:
<p>Si vous devez retenir un truc de la partie Python de ce blog, c&#8217;est qu&#8217;en Python, l&#8217;itération est tout.</p>
<p>Du coup, on utilise pas beaucoup <code>while</code>, à part dans quelques cas particuliers.</p>
<p>Le cas d&#8217;école, c&#8217;est la lecture d&#8217;un fichier octet par octet.</p>
<p>Imaginez, vous créez un petit array de float écrits en 64 bits :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> numpy <span style="color: #ff7700;font-weight:bold;">as</span> np
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a <span style="color: #66cc66;">=</span> np.<span style="color: black;">sin</span><span style="color: black;">&#40;</span>np.<span style="color: black;">linspace</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">2.0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3.0</span><span style="color: #66cc66;">,</span> num<span style="color: #66cc66;">=</span><span style="color: #ff4500;">100</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> a.<span style="color: black;">dtype</span>
dtype<span style="color: black;">&#40;</span><span style="color: #483d8b;">'float64'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Vous sauvegardez tout ça dans un fichier :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a.<span style="color: black;">tofile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/data'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Si vous voulez lire le fichier <strong>hors de numpy</strong>, il faut le charger float par float, donc le lire 64 bits par 64 bits soit par groupes de 8 octets.</p>
<p>La méthode canonique :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/data'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        nombre <span style="color: #66cc66;">=</span> f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> nombre:
            <span style="color: #ff7700;font-weight:bold;">break</span>
        <span style="color: #808080; font-style: italic;"># faire un truc avec le nombre</span></pre></td></tr></table></div>

<p>Mais il existe une autre manière de faire cela, moins connue : utiliser <code>iter()</code>.</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/data'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
    <span style="color: #ff7700;font-weight:bold;">for</span> nombre <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">iter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span>: f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> b<span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span>:
        <span style="color: #808080; font-style: italic;"># faire un truc avec nombre</span></pre></td></tr></table></div>

<p>Cela marche car <code>iter()</code>, parmi ses nombreuses fonctionnalités, accepte un <a href="http://sametmax.com/les-trucmuchables-en-python/">callable</a> en paramètre (ici notre <a href="http://sametmax.com/fonctions-anonymes-en-python-ou-lambda/">lambda</a>), et va l&#8217;appeler jusqu&#8217;à ce que celui-ci retourne une valeur dite &#8220;sentinelle&#8221; (ici notre second paramètre).</p>


feed_id: http://sametmax.com/?p=16463
title: Liste des cours et tutos mise à jour 14
uri: Liste-des-cours-et-tutos-mise-à-jour-11-Recently-updated
url: http://sametmax.com/liste-des-cours-et-tutos-mise-a-jour/
content:
<p>Les <a href="http://sametmax.com/cours-et-tutos/">listes des cours et tutos</a> du blog a été mise à jour.</p>
<p>Bon, là, je dois avouer que je suis super fier. On a l&#8217;équivalent de plusieurs bouquins maintenant en magasin, et si je crève demain au moins j&#8217;aurais laissé un chouette boulot derrière.</p>


feed_id: http://sametmax.com/?p=16503
title: Lire un format binaire en Python avec struct 22
uri: Lire-un-format-binaire-en-Python-avec-struct-6-Recently-updated
url: http://sametmax.com/lire-un-format-binaire-en-python-avec-struct/
content:
<p>Une suite de valeurs ne veut rien dire en soi, et même le sacro-saint binaire supposé être le socle de toute l&#8217;informatique n&#8217;a aucun sens si on ne connaît pas le format utilisé pour ce qu&#8217;il doit représenter.</p>
<p>Toujours la même opposition entre données et représentation.</p>
<p>Par exemple, le binaire peut représenter <a href="http://sametmax.com/la-fin-du-mystere-du-binaire-nananere/">un chiffre en base 2</a> ou <a href="http://sametmax.com/lencoding-en-python-une-bonne-fois-pour-toute/">un texte encodé</a>.</p>
<p>Pour autant, cela ne veut pas dire qu&#8217;il n&#8217;existe pas des formats prépondérant. En informatique, beaucoup de données binaires sont organisées pour correspondre aux structures de données du langage C, ces dernières étant une implémentation du standard <a href="https://fr.wikipedia.org/wiki/IEEE_754">IEEE 754</a> (en effet les strings sont des arrays d&#8217;int en C, donc le texte et les nombres sont des suites de chiffres).</p>
<p>Par exemple, si vous créez un array numpy contenant des nombres de 0 à 1000 stockés en int32 et sauvegardez son contenu dans un fichier :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> numpy
<span style="color: #66cc66;">&gt;&gt;&gt;</span> numpy.<span style="color: black;">arange</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1000</span><span style="color: #66cc66;">,</span> dtype<span style="color: #66cc66;">=</span>np.<span style="color: black;">int32</span><span style="color: black;">&#41;</span>.<span style="color: black;">tofile</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/tmp/data'</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le fichier va ici contenir une suite de 1 et de 0 représentant 1000 entiers, chacun comme un paquet de 4 octets organisés selon la sémantique que comprend le langage C.</p>
<p>Pour avoir une idée de l&#8217;organisation du contenu, on peut prendre un éditeur hexa qui vous affichera :</p>
<pre>0000 0000 0100 0000 0200 0000 0300 0000 0400 0000 0500 0000 0600 0000 0700 0000 0800 0000 0900 0000 0a00 0000 0b00 0000 0c00 0000 0d00 0000 0e00 0000 0f00 0000 1000 0000 1100 0000 1200 0000 1300 0000</pre>
<p>Ça se lit ainsi :</p>
<pre>
0000 0000 => 0
0100 0000 => 1
0200 0000 => 2
0300 0000 => 3
0400 0000 => 4
0500 0000 => 5
0600 0000 => 6
0700 0000 => 7
0800 0000 => 8
0900 0000 => 9
0a00 0000 => 10
0b00 0000 => 11
0c00 0000 => 12
0d00 0000 => 13
0e00 0000 => 14
0f00 0000 => 15
1000 0000 => 16
1100 0000 => 17
1200 0000 => 18
1300 0000 => 19
...</pre>
<p>Numpy étant codé en C, cela semble plutôt logique qu&#8217;il dump tout ça dans ce format.</p>
<p>Mais c&#8217;est une représentation tellement courante que de nombreux formats standards l&#8217;utilisent. Par exemple, les archives et les images stockent souvent leurs données ainsi.</p>
<p>Prenez le format d&#8217;image PNG, la <a href="https://tools.ietf.org/html/rfc2083">RFC indique</a> que la taille de l&#8217;image est stockée dans le fichier sous la forme de deux entiers représentés par 4 octets chacun, ordonnés en <a href="https://fr.wikipedia.org/wiki/Endianness">big-endian</a>, entre l&#8217;octet 16 et l&#8217;octet 24.</p>
<p>On peut donc récupérer ces informations en lisant son fichier image :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">with</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'image.png'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'rb'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">as</span> f:
    taille <span style="color: #66cc66;">=</span> f.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">24</span><span style="color: black;">&#41;</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">16</span>:<span style="color: #ff4500;">24</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Le problème étant : comment lire cette info ? C&#8217;est un blob binaire qui ne veut rien dire pour Python :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>taille<span style="color: black;">&#41;</span>
b<span style="color: #483d8b;">'<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>07<span style="color: #000099; font-weight: bold;">\x</span>80<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>00<span style="color: #000099; font-weight: bold;">\x</span>048'</span></pre></td></tr></table></div>

<p>Le module <a href="https://docs.python.org/3.4/library/struct.html">struct</a> est fait pour ça, on lui passe une donnée au format structure C, et il la convertit en type Python. Cela marche <del datetime="2015-06-26T06:29:30+00:00">ansi</del>, pardon, ainsi :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'motif_du_format_a_convertir'</span><span style="color: #66cc66;">,</span> donnee<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le format à convertir est une chaîne de caractères qui contient des symboles décrivant la structure de la donnée qu&#8217;on souhaite récupérer. Little-endian ou big-endian ? String, Int, Bool ?</p>
<p>Pour la taille de la photo, on sait qu&#8217;il y a deux entiers, non signés (une taille ne va pas être négative), en big-endian. D&#8217;après la doc de <code>struct</code>, on peut lui désigner un entier non signé avec &#8216;I&#8217;, et il faut les qualifier avec &#8216;>&#8217; pour l&#8217;ordre big-endian. Du coup:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">taille <span style="color: #66cc66;">=</span> <span style="color: #dc143c;">struct</span>.<span style="color: black;">unpack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&gt;II'</span><span style="color: #66cc66;">,</span> taille<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>taille<span style="color: black;">&#41;</span>
<span style="color: black;">&#40;</span><span style="color: #ff4500;">1920</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">1080</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Il se trouve que mon image de test est un screenshot et que mon écran a une résolution de 1920&#215;1080 :)</p>
<p>On peut faire l&#8217;opération inverse avec <code>struct.pack</code>, et bien entendu manipuler des formats plus complexes : il suffit de changer le motif qui représente le format à convertir.</p>


feed_id: http://sametmax.com/?p=16421
title: Quelques astuces à propos de and et or 19
uri: Quelques-astuces-à-propos-de-and-et-or-17-Recently-updated
url: http://sametmax.com/quelques-astuces-a-propos-de-and-et-or/
content:
<p>Dans beaucoup de langages populaires, <code>and</code> et <code>or</code> sont écrits <code>&#038;&#038;</code> et <code>||</code>. Ces symboles existent en Python, mais ils sont là pour appliquer des opérations binaires :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">0b010</span> &amp; <span style="color: #ff4500;">0b111</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0b10'</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> bin<span style="color: black;">&#40;</span><span style="color: #ff4500;">0b010</span> | <span style="color: #ff4500;">0b111</span><span style="color: black;">&#41;</span>
<span style="color: #483d8b;">'0b111'</span></pre></td></tr></table></div>

<p>Ce n&#8217;est néanmoins pas la seule bizarrerie de Python dans le domaine.</p>
<h2>Shortcuts</h2>
<p>Les opérateurs <code>and</code> et <code>or</code> court-circuitent les conditions dès que possible, c&#8217;est à dire qu&#8217;ils retournent la valeur au plus tôt, même si ça signifie ne pas exécuter tout le code.</p>
<p>Par exemple, prenons deux fonctions:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Yeah !'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">True</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Errrr...'</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Si je fais un <code>or</code> dessus, ça va me retourner <code>True</code>, et afficher deux messages :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Errrr...
<span style="color: black;">Yeah</span> <span style="color: #66cc66;">!</span>
<span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Mais si j&#8217;INVERSE les deux fonctions, alors je n&#8217;aurais qu&#8217;un seul message qui va s&#8217;afficher :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Yeah <span style="color: #66cc66;">!</span>
<span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>La raison est que <code>or</code> sait qu&#8217;il peut retourner <code>True</code> dès qu&#8217;il obtient au moins une valeur <code>True</code>. <code>vrai()</code> retourne <code>True</code>, donc <code>or</code> sait que tout la condition sera forcément vraie, et il n&#8217;exécute pas le code du reste de la condition. Ainsi, <code>faux()</code> n&#8217;est jamais appelée.</p>
<p><code>and</code> fait pareil :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Yeah <span style="color: #66cc66;">!</span>
Errrr...
<span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Et à l&#8217;envers :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">and</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Errrr...
<span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Car dans le second cas, <code>and</code> sait qu&#8217;il doit avoir toutes les valeurs à <code>True</code> pour renvoyer <code>True</code>. Comme il reçoit <code>False</code> dès le premier test, il ne va pas plus loin, et <code>vrai()</code> n&#8217;est jamais appelée.</p>
<p>Le but de cette fonctionnalité est d&#8217;autoriser le développeur à mettre les fonctions qui sont les plus gourmandes en ressource tout à droite de la condition, ainsi elle ne seront pas toujours appelées, ce qui améliore les perfs.</p>
<p>Si vous avez besoin que les fonctions soient toujours appelées car elles ont des effets de bord (c&#8217;est mal, boooouh !), il suffit de mettre leurs résultats dans des variables :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> a <span style="color: #66cc66;">=</span> vrai<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Yeah <span style="color: #66cc66;">!</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b <span style="color: #66cc66;">=</span> faux<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
Errrr...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> b <span style="color: #ff7700;font-weight:bold;">and</span> a
<span style="color: #008000;">False</span></pre></td></tr></table></div>

<h2>Pas de bool</h2>
<p>La plupart des opérateurs utilisés pour faire des tests retournent des booléans :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">2</span>
<span style="color: #008000;">False</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #483d8b;">&quot;chat&quot;</span>
<span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Mais <code>and</code> et <code>or</code> ne retournent pas des booléans. Dès qu&#8217;ils sont certains du résultats de la condition, ils retournent la valeurs qu&#8217;ils ont sous la main.</p>
<p>Cela est du au fait qu&#8217;en Python, tout a une valeur <code>True</code> ou <code>False</code> dans un contexte booléen. Pour faire simple, n&#8217;importe quel objet mis dans une condition vaut soit <code>True</code>, soit <code>False</code>.</p>
<p>Par exemple, une liste vide vaut <code>False</code> dans une condition, une liste non vide vaut <code>True</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> couleurs <span style="color: #66cc66;">=</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">if</span> couleurs:
   ...:     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;J'ai une couleur !&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> couleurs.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'rouge'</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">if</span> couleurs:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;J'ai une couleur !&quot;</span><span style="color: black;">&#41;</span>
J<span style="color: #483d8b;">'ai une couleur !</span></pre></td></tr></table></div>

<p>On peut le vérifier facilement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'rouge'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Il est facile de se souvenir de ce qui est faux ou vrai en Python. <code>False</code>, <code>None</code>, <code>0</code> et tout ce qui est vide est faux :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #008000;">False</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">0</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;&quot;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
   ...:     <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
   ...:     
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'bool'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'NoneType'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'list'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'set'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'dict'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'tuple'</span><span style="color: #66cc66;">&gt;,</span> <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>Tout le reste est vrai :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">for</span> x <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#40;</span><span style="color: #008000;">Ellipsis</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">True</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">432</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">&quot;foo&quot;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">&quot;bar&quot;</span><span style="color: black;">&#93;</span><span style="color: #66cc66;">,</span>  <span style="color: #008000;">set</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;ba&quot;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: black;">&#123;</span><span style="color: #483d8b;">&quot;pa&quot;</span>: <span style="color: #483d8b;">&quot;pa&quot;</span><span style="color: black;">&#125;</span><span style="color: #66cc66;">,</span> 
              <span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;doh&quot;</span><span style="color: #66cc66;">,</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff7700;font-weight:bold;">lambda</span> : <span style="color: #008000;">None</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">len</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #008000;">type</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span>x<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'ellipsis'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'bool'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'int'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'str'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'list'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'set'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'dict'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'tuple'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'function'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&lt;</span><span style="color: #ff7700;font-weight:bold;">class</span> <span style="color: #483d8b;">'builtin_function_or_method'</span><span style="color: #66cc66;">&gt;</span> <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Du coup, <code>and</code> et <code>or</code> vont vérifier la valeur de chaque objet de la condition, et retourner le premier à partir duquel ils sont certains du résultat de la condition entière.</p>
<p>Par exemple, si je fais :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">True</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">True</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">False</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">False</span>
    <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p><code>and</code> n&#8217;est certain que la condition est fausse qu&#8217;au moment où on attend le premier <code>False</code>. C&#8217;est donc ce <code>False</code> qu&#8217;il retourne.</p>
<p>Cela est beaucoup plus clair quand on le fait avec des objets plus complexes :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
    <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Puisque :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'a'</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p><code>and</code> n&#8217;est certain du résultat de la condition qu&#8217;en arrivant sur <code>[]</code>, qu&#8217;il retourne. </p>
<p>Si tous les éléments sont vrais, il va donc prendre le dernier :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;a&quot;</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff4500;">1</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">True</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span>
    <span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #ff4500;">3</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>C&#8217;est la même chose pour <code>or</code> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;&quot;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">None</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">False</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff4500;">0</span>
    <span style="color: #ff4500;">0</span></pre></td></tr></table></div>

<p>Là, <code>or</code> ne peut pas savoir si la condition est fausse avant d&#8217;arriver au tout dernier élément, qu&#8217;il retourne.</p>
<p>Mais si je glisse un truc vrai dans le lot :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #483d8b;">&quot;&quot;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #008000;">False</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #ff4500;">0</span>
    <span style="color: black;">&#123;</span><span style="color: #ff4500;">1</span>: <span style="color: #ff4500;">2</span><span style="color: black;">&#125;</span></pre></td></tr></table></div>

<p>Comme il n&#8217;a besoin que d&#8217;un élément vrai pour que toute la condition soit vraie, dès qu&#8217;il en rencontre un, il le retourne.</p>
<h2>Il n&#8217;y a pas de XOR</h2>
<p>Le &#8220;ou&#8221; exclusif, opération qui retourne vrai seulement si un élément est vrai mais pas l&#8217;autre, n&#8217;existe pas sous la forme d&#8217;un opérateur en Python. Évidement on peut l&#8217;émuler manuellement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> xor<span style="color: black;">&#40;</span>a<span style="color: #66cc66;">,</span> b<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#40;</span>a <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #ff7700;font-weight:bold;">not</span> b<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">not</span> a <span style="color: #ff7700;font-weight:bold;">and</span> b<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Mais une astuce de sioux permet un résultat plus court avec une syntaxe un poil plus proche des langages qui possèdent cet opérateur :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #008000;">bool</span><span style="color: black;">&#40;</span>a<span style="color: black;">&#41;</span> ^ <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span>b<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Exemple :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> ^ <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'pomme'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> ^ <span style="color: #008000;">bool</span><span style="color: black;">&#40;</span><span style="color: black;">&#91;</span><span style="color: #483d8b;">'banane'</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #008000;">False</span></pre></td></tr></table></div>

<p>^ est en effet l&#8217;opérateur XOR pour les opérations binaires. La partie marrante, c&#8217;est qu&#8217;en Python :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">True</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">1</span>
    <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">False</span> <span style="color: #66cc66;">==</span> <span style="color: #ff4500;">0</span>
    <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>Et comme :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span> ^ <span style="color: #ff4500;">1</span>
    <span style="color: #ff4500;">0</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff4500;">1</span> ^ <span style="color: #ff4500;">0</span>
    <span style="color: #ff4500;">1</span></pre></td></tr></table></div>

<p>Alors:</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">True</span> ^ <span style="color: #008000;">True</span>
    <span style="color: #008000;">False</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #008000;">True</span> ^ <span style="color: #008000;">False</span>
    <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>On obtient le résultat voulu. </p>
<p>Oui, c&#8217;est un peu tordu, je vous l&#8217;accorde.</p>


feed_id: http://sametmax.com/?p=16529
title: Compter et grouper : encore plus fainéant 5
uri: Compter-et-grouper-encore-plus-fainéant-4-Recently-updated
url: http://sametmax.com/compter-et-grouper-encore-plus-faineant/
content:
<p>Après avoir bien galéré à créer un compteur à la main avec un dico, <a href="http://sametmax.com/aller-plus-loin-avec-les-hash-maps-en-python/">vous avez découvert</a> les joies des méthodes <code>dict.get</code> et <code>dict.setdefault</code>. Puis évidemment quelqu&#8217;un vous a pointé vers <code>collections.defaultdict</code>, et enfin, vous avez fini par découvrir <code>collections.Counter</code>. Joie.</p>
<p>Le parcours est à peu près toujours le même quand on veut grouper ou compter des valeurs en Python.</p>
<p>Malgré cela, je vois encore des gens qui sous utilisent ces collections. Par exemple, <code>Counter</code> peut compter automatiquement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> Counter
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Counter<span style="color: black;">&#40;</span><span style="color: #483d8b;">'jfsqmfjdklmqfjsdqklmfjdsqhfdqsjkhfdshjkl'</span><span style="color: black;">&#41;</span>
    Counter<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'j'</span>: <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'f'</span>: <span style="color: #ff4500;">6</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'q'</span>: <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'s'</span>: <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span>: <span style="color: #ff4500;">5</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'k'</span>: <span style="color: #ff4500;">4</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'l'</span>: <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'m'</span>: <span style="color: #ff4500;">3</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'h'</span>: <span style="color: #ff4500;">3</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Mais ce que ne réalisent pas beaucoup de développeurs, c&#8217;est que cet objet accepte n&#8217;importe quel itérable en paramètre. Nous sommes en Python, et rededjiou, je me tue à répéter que l&#8217;itération est la philosophie centrale du langage.</p>
<p>Donc le compteur peut prendre une expression génératrice en paramètre.</p>
<p>Par exemple, si vous voulez compter un truc un peu plus complexe que des éléments, comme mettons, le ratio de lignes commentées dans un fichier, vous n&#8217;avez pas besoin de faire ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">count <span style="color: #66cc66;">=</span> Counter<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'ascii'</span><span style="color: black;">&#41;</span>:
        count<span style="color: black;">&#91;</span>line.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'#'</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span> +<span style="color: #66cc66;">=</span> <span style="color: #ff4500;">1</span>
 <span style="color: #808080; font-style: italic;"># out : Counter({True: 10, False: 3})</span></pre></td></tr></table></div>

<p>Ceci marchera parfaitement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">count <span style="color: #66cc66;">=</span> Counter<span style="color: black;">&#40;</span>line.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'#'</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc/fstab'</span><span style="color: #66cc66;">,</span> encoding<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'ascii'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># out : Counter({True: 10, False: 3})</span></pre></td></tr></table></div>

<p>Vous pouvez également utiliser des générateurs plus complexes. Combien de fichiers par types d&#8217;extensions ?</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">os</span>
<span style="color: #ff7700;font-weight:bold;">import</span> pathlib
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_extensions<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> dirpath<span style="color: #66cc66;">,</span> dirnames<span style="color: #66cc66;">,</span> files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> files:
            ext <span style="color: #66cc66;">=</span> pathlib.<span style="color: black;">Path</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>.<span style="color: black;">suffix</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> ext: <span style="color: #808080; font-style: italic;"># on ignore les fichiers sans extension</span>
                <span style="color: #ff7700;font-weight:bold;">yield</span> ext
&nbsp;
&nbsp;
Counter<span style="color: black;">&#40;</span>get_extensions<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>.<span style="color: black;">most_common</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">9</span><span style="color: black;">&#41;</span>
 <span style="color: #808080; font-style: italic;"># Out : </span>
 <span style="color: #808080; font-style: italic;"># ('.conf', 632),</span>
 <span style="color: #808080; font-style: italic;"># ('.0', 348),</span>
 <span style="color: #808080; font-style: italic;"># ('.gz', 323),</span>
 <span style="color: #808080; font-style: italic;"># ('.jhansonxi', 207),</span>
 <span style="color: #808080; font-style: italic;"># ('.pem', 177),</span>
 <span style="color: #808080; font-style: italic;"># ('.load', 127),</span>
 <span style="color: #808080; font-style: italic;"># ('.ttb', 86),</span>
 <span style="color: #808080; font-style: italic;"># ('.ktb', 80),</span>
 <span style="color: #808080; font-style: italic;"># ('.kti', 55)]</span></pre></td></tr></table></div>

<p>Notez que le <code>Counter</code> peut faire plus que compter. Ici il nous donne les 9 plus grandes valeurs du classement, mais en prime, il peut aussi nous faire des opérations ensemblistes :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> c <span style="color: #66cc66;">=</span> Counter<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;aabbbbbbbbbbbbcccc&quot;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c &amp; Counter<span style="color: black;">&#40;</span><span style="color: #483d8b;">'aaaaaaaaaaaaaaabbcddddddd'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># valeurs min</span>
    Counter<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">2</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span>: <span style="color: #ff4500;">1</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> c | Counter<span style="color: black;">&#40;</span><span style="color: #483d8b;">'aaaaaaaaaaaaaaabbcddddddd'</span><span style="color: black;">&#41;</span> <span style="color: #808080; font-style: italic;"># valeurs max</span>
    Counter<span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'a'</span>: <span style="color: #ff4500;">15</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'b'</span>: <span style="color: #ff4500;">12</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'d'</span>: <span style="color: #ff4500;">7</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'c'</span>: <span style="color: #ff4500;">4</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Le compteur fournit par Python est donc naturellement très, très puissant.</p>
<p>Une autre chose qui est rarement faite : sous-classer ces types.</p>
<p>Par exemple, si vous avez souvent des opérations où il faut grouper des valeurs :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">collections</span> <span style="color: #ff7700;font-weight:bold;">import</span> defaultdict
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> Grouper<span style="color: black;">&#40;</span>defaultdict<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> iterable<span style="color: black;">&#41;</span>:
        <span style="color: #008000;">super</span><span style="color: black;">&#40;</span>Grouper<span style="color: #66cc66;">,</span> <span style="color: #008000;">self</span><span style="color: black;">&#41;</span>.<span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">list</span><span style="color: black;">&#41;</span>
        <span style="color: #008000;">self</span>.<span style="color: black;">update</span><span style="color: black;">&#40;</span>iterable<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> update<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> iterable<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">try</span>:
            iterable <span style="color: #66cc66;">=</span> iterable.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">AttributeError</span>:
            iterable <span style="color: #66cc66;">=</span> iterable
        <span style="color: #ff7700;font-weight:bold;">for</span> k<span style="color: #66cc66;">,</span> v <span style="color: #ff7700;font-weight:bold;">in</span> iterable:
            <span style="color: #008000;">self</span><span style="color: black;">&#91;</span>k<span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>v<span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On prend un default dict, on lui dit qu&#8217;un update ajoute les éléments à la liste en valeur plutôt que de la remplacer, et zou, vous avez un dictionnaire qui va grouper toutes les valeurs automatiquement.</p>
<p>Liste des fichiers par extensions ? Fastoche !</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> get_extensions<span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">for</span> dirpath<span style="color: #66cc66;">,</span> dirnames<span style="color: #66cc66;">,</span> files <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #dc143c;">os</span>.<span style="color: black;">walk</span><span style="color: black;">&#40;</span>path<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">for</span> name <span style="color: #ff7700;font-weight:bold;">in</span> files:
            ext <span style="color: #66cc66;">=</span> pathlib.<span style="color: black;">Path</span><span style="color: black;">&#40;</span>name<span style="color: black;">&#41;</span>.<span style="color: black;">suffix</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> ext: 
                <span style="color: #ff7700;font-weight:bold;">yield</span> ext<span style="color: #66cc66;">,</span> name <span style="color: #808080; font-style: italic;"># on rajoute le name ici</span>
&nbsp;
<span style="color: #66cc66;">&gt;&gt;&gt;</span>files <span style="color: #66cc66;">=</span> Grouper<span style="color: black;">&#40;</span>get_extensions<span style="color: black;">&#40;</span><span style="color: #483d8b;">'/etc'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> files<span style="color: black;">&#91;</span><span style="color: #483d8b;">'.tti'</span><span style="color: black;">&#93;</span>
<span style="color: black;">&#91;</span><span style="color: #483d8b;">'en-na-ascii.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'numbers-french.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'devanagari.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'letters-cyrillic.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'punctuation-basic.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'malayalam.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'ascii-basic.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'spaces.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'letters-latin.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'letters-latin-dot8.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'en-chess.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'numbers-dot8.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'punctuation-tibetan.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'boxes.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'gujarati.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'numbers-nemeth.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'punctuation-alternate.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'common.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'blocks.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'gurmukhi.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'kannada.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'telugu.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'tamil.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'numbers-dot6.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'de-chess.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'control-latin.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'letters-tibetan.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'oriya.tti'</span><span style="color: #66cc66;">,</span>
 <span style="color: #483d8b;">'bengali.tti'</span><span style="color: black;">&#93;</span></pre></td></tr></table></div>

<p>Bref, compter et grouper sont des opérations si communes : ne vous faites par chier à refaire tout ça à la main.</p>


feed_id: http://sametmax.com/?p=16562
title: Le don du mois : sublime text 13
uri: Le-don-du-mois-sublime-text-4-Recently-updated
url: http://sametmax.com/le-don-du-mois-sublime-text/
content:
<p>Se faire plaisir et faire plaisir aux autres n&#8217;est pas incompatible.</p>
<p>Par exemple, quand Sublime Text est sorti j&#8217;ai pris un an avant d&#8217;acheter la licence. Là, j&#8217;ai sublime text 3 depuis à peu près la même période sur mon ordi, et je vais me payer la licence.</p>
<p>Pour moi, c&#8217;est une forme de don. En effet, l&#8217;auteur permet d&#8217;utiliser 100% de son logiciel pour toujours, et sans rien raquer. La seule chose, c&#8217;est que toutes les X sauvegardes, une pop up apparaît pour vous demander si vous voulez l&#8217;acheter. Vous pouvez ne jamais le faire. Beaucoup ne le font jamais.</p>
<p>Aujourd&#8217;hui, je vais faire sauter la pop up, et je remercie l&#8217;auteur pour me fournir un joujou que j&#8217;adore.</p>
<p>N&#8217;oubliez pas, si vous utilisez un IDE commercial (PyCharm, Komodo, etc), acheter la licence vous apporte des choses à vous, mais aussi, est un bon moyen de témoigner votre reconnaissance aux auteurs. Après tout, vous gagnez votre vie en partie grace à eux.</p>
<p>Si votre éditeur est gratuit, voire libre (je pense aux trolls de VI et Emacs qui frétillent dans les commentaires), pensez à faire un don à ces projets. Le fait qu&#8217;ils soient bien établis ne veut pas dire qu&#8217;il n&#8217;en ont pas besoin, bien au contraire.</p>
<p>Sublime n&#8217;est pas donné, et <a href="https://www.sublimetext.com/buy">je paie de ma poche 70$</a>, avec plaisir néanmoins, car cet outil les vaut largement.</p>
<p>Bref, la morale de ce mois, c&#8217;est que les donations ne sont pas uniquement pour les groupes à but non lucratif. Vous pouvez donnez à des boîtes, des administrations, des clodos dans la rue. Vous pouvez racheter un livre que vous avez déjà lu, offrir un morceau que vous avez déjà écouté. Le don n&#8217;a pas de forme propre, la seule condition étant l&#8217;intention.</p>


feed_id: http://sametmax.com/?p=16556
title: A propos des attributs préfixés de deux underscores 2
uri: A-propos-des-attributs-préfixés-de-deux-underscores-2-Recently-up
url: http://sametmax.com/a-propos-des-attributs-prefixes-de-deux-underscores/
content:
<p>En Python, <a href="http://sametmax.com/le-guide-ultime-et-definitif-sur-la-programmation-orientee-objet-en-python-a-lusage-des-debutants-qui-sont-rassures-par-les-textes-detailles-qui-prennent-le-temps-de-tout-expliquer-partie-3/"> il n&#8217;y a pas d&#8217;attributs privés au sens propre</a>, uniquement une convention disant que tout ce qu&#8217;on préfixe d&#8217;un underscore ne fait pas partie de l&#8217;API publique.</p>
<p>Cette convention est tellement bien établie que les outils de génération de documentation et de complétion de code la prennent souvent en compte.</p>
<p>Ca fait partie de la philosophie du langage : tout est ouvert. Guido <a href="https://www.artima.com/weblogs/viewpost.jsp?thread=211430">parle même d&#8217;open kimono</a>, le petit coquin.</p>
<p>Pourtant il existe une fonctionnalité qui semble rendre un attribut privé, qui est d&#8217;utiliser un préfix de DEUX underscores :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> Yo<span style="color: black;">&#40;</span><span style="color: #008000;">object</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        <span style="color: #008000;">self</span>.__bitch <span style="color: #66cc66;">=</span> <span style="color: #008000;">True</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> Yo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.__bitch
---------------------------------------------------------------------------
<span style="color: #008000;">AttributeError</span>                            Traceback <span style="color: black;">&#40;</span>most recent call last<span style="color: black;">&#41;</span>
<span style="color: #66cc66;">&lt;</span>ipython-input-<span style="color: #ff4500;">5</span>-225402ba2794<span style="color: #66cc66;">&gt;</span> <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #66cc66;">&lt;</span>module<span style="color: #66cc66;">&gt;</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
----<span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span> Yo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.__bitch
&nbsp;
<span style="color: #008000;">AttributeError</span>: <span style="color: #483d8b;">'Yo'</span> <span style="color: #008000;">object</span> has no attribute <span style="color: #483d8b;">'__bitch'</span></pre></td></tr></table></div>

<p>En fait, l&#8217;attribut n&#8217;a pas été rendu privé, mais son mécanisme de résolution de nom a été changé :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> Yo<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>._Yo__bitch
    <span style="color: #008000;">True</span></pre></td></tr></table></div>

<p>C&#8217;est ce qu&#8217;on appelle le <a href="https://en.wikipedia.org/wiki/Name_mangling">name mangling</a>, et cette obscure fonctionnalité a été utilisée pour s&#8217;assurer qu&#8217;un attribut ne sera pas écrasé par erreur par une classe enfant.</p>
<p>L&#8217;attribut n&#8217;est pas privé, il est juste accessible autrement, c&#8217;est tout.</p>


feed_id: http://sametmax.com/?p=16572
title: Subreddit Sam et Max 9
uri: Subreddit-Sam-et-Max-3-Recently-updated
url: http://sametmax.com/subreddit-sam-et-max/
content:
<p>Il manque un forum pour le blog, et une zone de discussion meta pour IndexError, un vecteur alternatif de propagation d&#8217;info à twitter&#8230;</p>
<p>On a tenté discourse, trop chiant.</p>
<p>Un vieux forum en PHP, meh.</p>
<p>Coder le truc nous même, trop long.</p>
<p>Ce n&#8217;est pas de l&#8217;info critique, on a pas besoin d&#8217;avoir la main dessus, et si demain on nous ferme on peut vivre avec.</p>
<p>On s&#8217;est chauffé à récupérer le code de reddit : python, libre, forum simple. Mais pourquoi se faire chier ? On a juste ouvert un <a href="https://www.reddit.com/r/sametmax/">subreddit Sam et Max</a>.</p>
<p>C&#8217;est un complément au chan IRC (freenode.net#sametmax) pour discuter d&#8217;un peu tout en rapport avec le blog. J&#8217;y posterai aussi la plupart des liens que je poste sur twitter, car je sais que plein de gens n&#8217;aiment pas twitter.</p>
<p>Tout comme le blog et le compte twitter, ce sera NSFW. Souvenez-vous, les seuls trucs SFW qu&#8217;on a pour le moment sont <a href="http://0bin.net">0bin.net</a> et <a href="http://indexerror.net/">IndexError.net</a>.</p>
<p>Pas encore de politique de modération précise ou de ligne éditoriale, donc on va affiner au fur et à mesure. Évitez évidemment de poster :</p>
<ul>
<li>Pubs</li>
<li>Propagande pédo nazi terroriste d&#8217;appel à la haine zoophile</li>
</ul>
<p>Oui vous pouvez poster des annonces de job. Oui vous pouvez poster un article cool sur une techno JS sympa. Le reddit est plus souple, si c&#8217;est pas du Python, c&#8217;est pas grave : y a un système de vote qui tuera votre post si tout le monde s&#8217;en branle.</p>
<p>Tous les contributeurs les plus actifs du blog, de IE et les modos officiels peuvent d&#8217;office demander les droits modo. Il suffit de faire la demande en commentaire dans la version reddit de ce post.</p>


feed_id: http://sametmax.com/?p=16587
title: Bougez avec la poste… 13
uri: Bougez-avec-la-poste-8
url: http://sametmax.com/bougez-avec-la-poste/
content:
<p>On a décidé de commander quelques trucs pour bidouiller un raspberry PI sur un site américain.</p>
<p>Grâce au Tracking chez UPS on peut savoir où se balade notre colis.<br />
C&#8217;est assez cocasse&#8230;</p>
<p>Apparement le colis est arrivé dans notre ville mais a du repartir à Paris pour enfin revenir demain ou&#8230;</p>
<p>Heureusement que c&#8217;est pas un bon Maroilles bien vieux.</p>
<p><img src="media/628d3b24.laposte.png" data-original-source="http://sametmax.com/wp-content/uploads/2015/07/laposte.png" alt="laposte" width="1368" height="1530" class="aligncenter size-full wp-image-16588" /></p>


feed_id: http://sametmax.com/?p=16581
title: Tester Python 3.5 beta 14
uri: Tester-Python-3-5-beta-5-Recently-updated
url: http://sametmax.com/tester-python-3-5-beta/
content:
<p><a href="https://www.reddit.com/r/sametmax/comments/3cfr83/whats_new_in_python_35_python_350b2_documentation/">Python 3.5 est en phase beta</a>, et c&#8217;est une release très (mais alors très très très) attendue.</p>
<p>Si vous ne voulez pas attendre et tester le bouzin de suite, il est facile de setup la bestiole sous linux :</p>
<ul>
<li>Installer un compilateur et les headers de Python;</li>
<li>Télécharger les sources;</li>
<li>Décompresser tout ça;</li>
<li>Compiler;</li>
<li>Installer.</li>
</ul>
<p>Un exemple possible :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #dc143c;">cd</span> /tmp
sudo apt-get install python-dev gcc <span style="color: #808080; font-style: italic;"># ou yum install python-devel gcc</span>
wget https://www.<span style="color: black;">python</span>.<span style="color: black;">org</span>/ftp/python/3.5.0/Python-3.5.0b3.<span style="color: black;">tgz</span>
tar -xvf Python-3.5.0b3.<span style="color: black;">tgz</span>
<span style="color: #dc143c;">cd</span> Python-3.5.0b3
./configure
make
sudo make altinstall</pre></td></tr></table></div>

<p>Ne faites surtout PAS <code>sudo make install</code>, qui écraserait votre python principal.</p>
<p>Ensuite on lance :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="bash" style="font-family:monospace;">$ python3.5
$ python3.5
Python 3.5.0b3 <span style="color: #7a0874; font-weight: bold;">&#40;</span>default, Jul  <span style="color: #000000;">5</span> <span style="color: #000000;">2015</span>, <span style="color: #000000;">23</span>:<span style="color: #000000;">52</span>:07<span style="color: #7a0874; font-weight: bold;">&#41;</span> 
<span style="color: #7a0874; font-weight: bold;">&#91;</span>GCC 4.8.4<span style="color: #7a0874; font-weight: bold;">&#93;</span> on linux
Type <span style="color: #ff0000;">&quot;help&quot;</span>, <span style="color: #ff0000;">&quot;copyright&quot;</span>, <span style="color: #ff0000;">&quot;credits&quot;</span> or <span style="color: #ff0000;">&quot;license&quot;</span> <span style="color: #000000; font-weight: bold;">for</span> <span style="color: #c20cb9; font-weight: bold;">more</span> information.
Traceback <span style="color: #7a0874; font-weight: bold;">&#40;</span>most recent call <span style="color: #c20cb9; font-weight: bold;">last</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>:
  File <span style="color: #ff0000;">&quot;/home/sam/Scripts/pythonstartup.py&quot;</span>, line <span style="color: #000000;">119</span>, <span style="color: #000000; font-weight: bold;">in</span> 
    store = Store<span style="color: #7a0874; font-weight: bold;">&#40;</span>os.path.join<span style="color: #7a0874; font-weight: bold;">&#40;</span>TEMP_DIR, <span style="color: #ff0000;">'store.%s.db'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span> <span style="color: #000000; font-weight: bold;">%</span> python_version<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  File <span style="color: #ff0000;">&quot;/home/sam/Scripts/pythonstartup.py&quot;</span>, line <span style="color: #000000;">93</span>, <span style="color: #000000; font-weight: bold;">in</span> __init__
    object.__setattr__<span style="color: #7a0874; font-weight: bold;">&#40;</span>self, <span style="color: #ff0000;">'DICT'</span>, shelve.DbfilenameShelf<span style="color: #7a0874; font-weight: bold;">&#40;</span>filename<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
  File <span style="color: #ff0000;">&quot;/usr/local/lib/python3.5/shelve.py&quot;</span>, line <span style="color: #000000;">227</span>, <span style="color: #000000; font-weight: bold;">in</span> __init__
    Shelf.__init__<span style="color: #7a0874; font-weight: bold;">&#40;</span>self, dbm.open<span style="color: #7a0874; font-weight: bold;">&#40;</span>filename, flag<span style="color: #7a0874; font-weight: bold;">&#41;</span>, protocol, writeback<span style="color: #7a0874; font-weight: bold;">&#41;</span>
  File <span style="color: #ff0000;">&quot;/usr/local/lib/python3.5/dbm/__init__.py&quot;</span>, line <span style="color: #000000;">91</span>, <span style="color: #000000; font-weight: bold;">in</span> open
    <span style="color: #ff0000;">&quot;available&quot;</span>.format<span style="color: #7a0874; font-weight: bold;">&#40;</span>result<span style="color: #7a0874; font-weight: bold;">&#41;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
dbm.error: db <span style="color: #7a0874; font-weight: bold;">type</span> is dbm.gnu, but the module is not available
<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt; import types
<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt; print<span style="color: #7a0874; font-weight: bold;">&#40;</span><span style="color: #ff0000;">':)'</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
:<span style="color: #7a0874; font-weight: bold;">&#41;</span>
<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt;<span style="color: #000000; font-weight: bold;">&amp;</span>gt;</pre></td></tr></table></div>

<p>En dehors du vomi d&#8217;intro, tout marche chez moi.</p>


feed_id: http://sametmax.com/?p=16600
title: Today is a glorious day 15
uri: Today-is-a-glorious-day-4-Recently-updated
url: http://sametmax.com/today-is-a-glorious-day/
content:
<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> crossbar
<span style="color: #66cc66;">&gt;&gt;&gt;</span> crossbar.__version__
<span style="color: #483d8b;">'0.10.4'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> twisted
<span style="color: #66cc66;">&gt;&gt;&gt;</span> twisted.__version__
<span style="color: #483d8b;">'15.2.1'</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Wait for it...'</span><span style="color: black;">&#41;</span>
Wait <span style="color: #ff7700;font-weight:bold;">for</span> it...
<span style="color: #66cc66;">&gt;&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">version</span>
<span style="color: #483d8b;">'3.4.0 (default, Apr 11 2014, 13:05:11) <span style="color: #000099; font-weight: bold;">\n</span>[GCC 4.8.2]'</span></pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=16607
title: Réagir à un changement sur un fichier avec watchdog 14
uri: Réagir-à-un-changement-sur-un-fichier-avec-watchdog-5
url: http://sametmax.com/reagir-a-un-changement-sur-un-fichier-avec-watchdog/
content:
<p>Il y a des tas de choses qu&#8217;on peut vouloir faire au moment où un fichier change :</p>
<ul>
<li>Faire un backup;</li>
<li>Lancer les tests unittaires;</li>
<li>Démarrer un build;</li>
<li>Recharger un contenu;</li>
<li>Envoyer un email;</li>
<li>Afficher une notification;</li>
<li>Mettre à jour un listing.</li>
</ul>
<p>Et ce n&#8217;est même pas dur à faire en Python grace à la lib <a href="https://pypi.python.org/pypi/watchdog">watchdog</a> :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;">pip install watchdog</pre></td></tr></table></div>

<p>D&#8217;abord, on créer un handler, une classe qui va contenir le code à lancer quand il arrive quelque chose à nos fichiers :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> watchdog.<span style="color: black;">events</span> <span style="color: #ff7700;font-weight:bold;">import</span> FileSystemEventHandler
&nbsp;
<span style="color: #ff7700;font-weight:bold;">class</span> MonHandler<span style="color: black;">&#40;</span>FileSystemEventHandler<span style="color: black;">&#41;</span>:
&nbsp;
    <span style="color: #808080; font-style: italic;"># cette méthode sera appelée à chaque fois qu'un fichier</span>
    <span style="color: #808080; font-style: italic;"># est modifié</span>
    <span style="color: #ff7700;font-weight:bold;">def</span> on_modified<span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: #66cc66;">,</span> event<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;Ah, le fichier %s a été modifé&quot;</span> % event.<span style="color: black;">src_path</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># On peut aussi implémenter les méthodes suivantes :</span>
    <span style="color: #808080; font-style: italic;"># - on_any_event(self, event)</span>
    <span style="color: #808080; font-style: italic;"># - on_moved(self, event)</span>
    <span style="color: #808080; font-style: italic;"># - on_created(self, event)</span>
    <span style="color: #808080; font-style: italic;"># - on_deleted(self, event)</span>
    <span style="color: #808080; font-style: italic;"># - on_modified(self, event)</span></pre></td></tr></table></div>

<p>Ensuite on créé un observer, qui va lancer un thread dans lequel il va&#8230; observer :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> watchdog.<span style="color: black;">observers</span> <span style="color: #ff7700;font-weight:bold;">import</span> Observer
&nbsp;
observer <span style="color: #66cc66;">=</span> Observer<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># Surveiller récursivement tous les événements du dossier /tmp</span>
<span style="color: #808080; font-style: italic;"># et appeler les méthodes de MonHandler quand quelque chose</span>
<span style="color: #808080; font-style: italic;"># se produit</span>
observer.<span style="color: black;">schedule</span><span style="color: black;">&#40;</span>MonHandler<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: #66cc66;">,</span> path<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'/tmp'</span><span style="color: #66cc66;">,</span> recursive<span style="color: #66cc66;">=</span><span style="color: #008000;">True</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>On démarre tout ça :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span>
observer.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># L'observer travaille dans un thread séparé donc on fait une </span>
<span style="color: #808080; font-style: italic;"># boucle infinie pour maintenir le thread principal</span>
<span style="color: #808080; font-style: italic;"># actif dans cette démo mais dans un vrai programme,</span>
<span style="color: #808080; font-style: italic;"># vous mettez votre taff ici.</span>
<span style="color: #ff7700;font-weight:bold;">try</span>:
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #008000;">True</span>:
        <span style="color: #dc143c;">time</span>.<span style="color: black;">sleep</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">except</span> <span style="color: #008000;">KeyboardInterrupt</span>:
    <span style="color: #808080; font-style: italic;"># Ctrl + C arrête tout</span>
    observer.<span style="color: black;">stop</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #808080; font-style: italic;"># on attend que tous les threads se terminent proprement</span>
observer.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>Pour les ones shot, watchdog vient avec la commande <code>watchmedo</code>  qui permet de lancer un commande shell en cas d&#8217;événement :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;"># lancer 'echo lefichier' pour chaque fichier python ou texte modifié de mon dossier utilisateur </span>
watchmedo shell-command --patterns<span style="color: #66cc66;">=</span><span style="color: #483d8b;">&quot;*.py;*.txt&quot;</span> --recursive --command<span style="color: #66cc66;">=</span><span style="color: #483d8b;">'echo &quot;${watch_src_path}&quot;'</span> /home/sam</pre></td></tr></table></div>

<p>Personnellement j&#8217;aime le lundi.</p>
<hr />
<p><a href="https://github.com/sametmax/codes-des-articles/blob/master/2015/juillet/watch_file.py">Télécharger le code de l&#8217;article</a></p>


feed_id: http://sametmax.com/?p=16615
title: The User is dead 9
uri: The-User-is-dead-Recently-updated
url: http://sametmax.com/the-user-is-dead/
content:
<p>L&#8217;authentification de mémé (enfin, mémé&#8230;) n&#8217;a plus de sens, et pourtant, on continue de la montrer en exemple dans tous les tutos :</p>
<ul>
<li>Un compte utilisateur.</li>
<li>Un email.</li>
<li>Un mot de passe.</li>
</ul>
<p>Boom, on vérifie le mot de passe (avec un peu de chance sur une version sainement hachée), on identifie l&#8217;utilisateur, et c&#8217;est plié.</p>
<p>C&#8217;est simple, c&#8217;est beau, ça marche.</p>
<p>Mais ça ne représente pas du tout la réalité.</p>
<p>Une des plus grosses erreurs de design de frameworks comme Django est justement la classe <code>User</code>.</p>
<p>En soit, la classe <code>User</code> n&#8217;est pas un problème, mais son omniprésence dans toutes les couches du framework et sa promotion au rang d&#8217;unité de référence dans les apps tierces parties ont gardé la vision de l&#8217;authentification très monolithique.</p>
<p>C&#8217;est que le Web n&#8217;a plus du tout la forme qu&#8217;il avait il y a 10 ans, et aujourd&#8217;hui, vous pouvez vous connecter via un service (facebook, twitter, github&#8230;), utiliser une authentification à double facteur (sms, email, yubikey&#8230;) ou avoir un compte unique qui unifie plusieurs fournisseurs (ah, le fameux compte Google qui fait gmail, youtube, calendar, play, saucisseland&#8230;).</p>
<p>Les gens ont plusieurs identités, plusieurs comptes, plusieurs modes d&#8217;authentification, plusieurs points d&#8217;entrées. Ce modèle ne marche plus :</p>
<pre>USER <-- Profile </pre>
<p>Si vous créez un service aujourd'hui et que vous souhaitez prendre en compte cette réalité, le schéma en base de données va plutôt ressembler à un truc du genre :</p>
<pre>                      +-------+
                      |Session|
                      +----+--+
                           |
                           |
                           |
                           |
+-----------+         +----v---+         +--------+
|  Identity | <-------+ Account| <-------+Profile |
+-----------+         +--------+         +--------+
                 +------^   ^--------+
                 |                   |
                 |                   |
                 |                   |
                 |                   |
         +-------+-----+      +------+----+
         | Credential  |      |  Service  |
         +-------------+      +-----------+
</pre>
<p>Et encore, je n'ai pas mis les permissions, les devices, les comptes multi-utilisateurs, la vérification des comptes (lien email, sms, etc), les niveaux d'offre commerciale... Ca rend le truc vraiment compliqué.</p>
<p>Ce qui est important ici, c'est que la notion de compte devient centrale, mais que seule l'identité est unique. Une identité peut avoir plusieurs comptes. Et un compte peut être chez votre service ou un service externe. Et l'authentification peut très bien avoir lieu ailleurs : ldap, OAuth, Mozilla Personna, Open ID...</p>
<p>Si votre utilisateur a un compte chez Facebook et un compte chez vous, les deux sont des comptes, avec leurs profils, reliés à la même identité, servant à vous donner des informations, permettant de se loguer... Et vous devez garder une trace de tout ça. Le fait que l'API d'un service tape sur votre serveur et l'autre non n'a en fait aucune importance pour l'utilisateur, qui utilise tout ça comme un gros blob comme si internet était un tout.</p>
<p>La nouvelle génération ne fait pas la différence avec un site Web et un app, ne sait pas ce qu'est une URL ou un cookie et ne veut pas rentrer trop de mots de passe, mais veut par contre utiliser 5000 services.</p>
<p>Ainsi on voit que les archis basées sur des microservices (hello crossbar :)) commencent à avoir la côte, faisant abstraction de la notion de "ceci est mon app, ceci est ton app" dans la structure de son projet. Bien entendu, la distinction est importante d'un point de vue humain, mais du point de vue du workflow d'authentification, non.</p>
<p>Par contre, forcément, ça fait beaucoup plus qu'une table <code>User</code> et une table <code>Profile</code> en base de données, et c'est pourquoi toutes les apps pluggables des frameworks actuellement ont leurs propres structures bizarres, incompatibles et torturées pour faire tenir toute cette logique. Parce qu'on code sur des frameworks qui vivent encore dans les années 2000, qui passent à votre vue un objet <code>User</code> en paramètre avec ses attributs <code>username</code> et <code>email</code>.</p>
<p>Mais ce que vous avez en face de vous, ce n'est pas un utilisateur.</p>
<p>C'est une session d'utilisation.</p>
<p>D'un service (le votre). Liée à un compte. Qui peut-être (surement) possède un profil avec un username.</p>
<p>Cette session s'est initiée par une authentification avec une méthode parmi 100 auprès d'un service également, lié à un compte, avec un profil. Peut-être le même service que celui qui est utilisé, peut-être pas.</p>
<p>Et cette authentification a pu être demandée par un utilisateur, ou encore un autre service, ou un logiciel client complètement automatiquement. Souvenez-vous : la session n'a peut-être aucun humain derrière.</p>
<p>Ce qui est en face de vous n'est pas un utilisateur. L'utilisateur est mort il y a des années.</p>


feed_id: http://sametmax.com/?p=16625
title: Toutes les lettres UTF8 4
uri: Toutes-les-lettres-UTF8-Recently-updated
url: http://sametmax.com/toutes-les-lettres-utf8/
content:
<p>Pour l&#8217;ascii, on a <code>string.ascii_letters</code>, mais rien de tel pour un autre charset.</p>
<p>Voici comment obtenir une string qui contient toutes les lettres en UTF8 :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> <span style="color: #dc143c;">unicodedata</span> <span style="color: #ff7700;font-weight:bold;">import</span> category
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_all_unicode_letters<span style="color: black;">&#40;</span>categs<span style="color: #66cc66;">=</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'Lu'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Ll'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Lt'</span><span style="color: #66cc66;">,</span> <span style="color: #483d8b;">'Lm'</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>:
    <span style="color: #808080; font-style: italic;"># Categores unicode dans lesquelles récupérer les lettres</span>
    <span style="color: #808080; font-style: italic;"># On peut virer 'Lt', 'Lm' si on veut garder des lettres plus</span>
    <span style="color: #808080; font-style: italic;"># proches de notre alphabet</span>
    categs <span style="color: #66cc66;">=</span> <span style="color: #008000;">set</span><span style="color: black;">&#40;</span>categs<span style="color: black;">&#41;</span> 
    <span style="color: #808080; font-style: italic;"># on prend tous les symboles utf8</span>
    all_unicode <span style="color: #66cc66;">=</span> <span style="color: black;">&#40;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">65536</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># on garde ceux qui sont dans une categorie 'lettre'</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>c <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> all_unicode <span style="color: #ff7700;font-weight:bold;">if</span> category<span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">in</span> categs<span style="color: black;">&#41;</span>
&nbsp;
letters <span style="color: #66cc66;">=</span> get_all_unicode_letters<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>C&#8217;est quand même bien foutu pour ça unicode : <a href="http://www.fileformat.info/info/unicode/category/index.htm">tout est catégorisé</a> avec les trucs en majuscule, les modifieurs, les nombres, les espaces et tout le bordel.</p>
<p>Par exemple vous voulez voir tous les symboles monétaires :</p>

<div class="wp_syntax"><table><tr><td class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> pognon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    all_unicode <span style="color: #66cc66;">=</span>  <span style="color: black;">&#40;</span><span style="color: #008000;">chr</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">65536</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>c <span style="color: #ff7700;font-weight:bold;">for</span> c <span style="color: #ff7700;font-weight:bold;">in</span> all_unicode <span style="color: #ff7700;font-weight:bold;">if</span> category<span style="color: black;">&#40;</span>c<span style="color: black;">&#41;</span> <span style="color: #66cc66;">==</span> <span style="color: #483d8b;">'Sc'</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span><span style="color: black;">&#40;</span>pognon<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
$¢£¤¥֏؋৲৳৻૱௹฿៛₠₡₢₣₤₥₦₧₨₩₪₫€₭₮₯₰₱₲₳₴₵₶₷₸₹₺꠸﷼﹩＄￠￡￥￦</pre></td></tr></table></div>


feed_id: http://sametmax.com/?p=16632
title: On avait un de nos sites qui ramait, quand soudain… 17
uri: On-avait-un-de-nos-sites-qui-ramait-quand-soudain-7
url: http://sametmax.com/on-avait-un-de-nos-sites-qui-ramait-quand-soudain/
content:
<blockquote><p>- Allez, Max, fais moi un copier/coller !<br />
&#8211; Non.<br />
&#8211; Alleeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeez. C&#8217;est drôle !<br />
&#8211; Putain tu fais chier.</p></blockquote>
<pre>
SELECT * FROM "video" INNER JOIN "video_sites" ON ("video"."id" = "video_sites"."video_id") WHERE ("video_sites"."site_id" = 1 AND "video"."status" = 'online' AND NOT ("video"."id" IN (SELECT * FROM "video" U0 WHERE U0."id" IN (68, 98, 102, 103, 109, 121, 128, 129, 131, 132, 133, 230, 231, 232, 235, 236, 238, 240, 241, 242, 243, 245, 247, 248, 249, 251, 252, 253, 255, 256, 257, 259, 261, 262, 264, 266, 267, 270, 271, 272, 273, 275, 277, 279, 281, 282, 283, 284, 285, 286, 287, 288, 289, 291, 292, 293, 294, 295, 296, 297, 299, 300, 301, 302, 303, 304, 305, 307, 309, 311, 314, 315, 317, 318, 319, 320, 322, 324, 325, 327, 329, 330, 331, 333, 334, 336, 337, 338, 339, 340, 342, 344, 345, 346, 347, 348, 350, 352, 353, 354, 355, 356, 359, 360, 361, 368, 369, 371, 372, 374, 377, 378, 380, 382, 385, 386, 387, 388, 389, 390, 393, 394, 395, 399, 401, 402, 404, 405, 407, 409, 410, 411, 412, 413, 414, 415, 416, 418, 557, 561, 589, 596, 599, 600, 602, 606, 611, 612, 620, 622, 623, 626, 629, 636, 642, 645, 646, 656, 663, 677, 679, 682, 685, 691, 692, 695, 699, 719, 762, 865, 1059, 1066, 1068, 1069, 1072, 1075, 1085, 1088, 1090, 1092, 1093, 1094, 1096, 1100, 1101, 1102, 1103, 1138, 1148, 1163, 1172, 1194, 1197, 1204, 1211, 1216, 1218, 1230, 1243, 1297, 1326, 1333, 1334, 1347, 1351, 1377, 1383, 1386, 1448, 1454, 1476, 1503, 1546, 1574, 1599, 1612, 1616, 1620, 1629, 1648, 1660, 1666, 1679, 1705, 1729, 1731, 1739, 1766, 1802, 1855, 1861, 1891, 1970, 2064, 2077, 2108, 2143, 2268, 2275, 2289, 2342, 2365, 2402, 2408, 2422, 2504, 2523, 2537, 2621, 2684, 2707, 2711, 2737, 2819, 2898, 2925, 3323, 3334, 3356, 3370, 3424, 3438, 3480, 3488, 3506, 4311, 4547, 4733, 4779, 4840, 4853, 4871, 4890, 4930, 4940, 5107, 5178, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196, 5197, 5198, 5199, 5200, 5201, 5202, 5203, 5204, 6427, 6428, 6445, 6447, 6449, 6489, 6494, 6495, 6515, 6551, 6552, 6572, 6586, 6599, 6682, 6916, 6924, 6927, 6950, 6957, 6963, 6968, 6975, 6981, 7094, 7251, 7257, 7272, 7434, 7496, 7507, 7511, 7536, 7660, 7666, 7720, 7764, 7846, 7852, 7861, 7864, 7925, 7936, 7962, 7984, 7994, 8032, 8102, 8110, 8122, 8126, 8166, 8277, 8278, 8281, 8300, 8341, 8351, 8374, 8407, 8497, 8515, 8544, 8559, 8583, 8593, 8604, 8614, 8650, 8702, 8733, 8772, 8852, 8865, 8873, 8883, 8894, 8912, 8987, 8999, 9011, 9061, 9068, 9100, 9108, 9120, 9213, 9259, 9419, 9430, 9441, 9545, 9583, 9641, 9656, 9668, 9672, 9711, 9726, 9807, 9814, 9819, 9833, 9847, 9904, 9963, 10000, 10002, 10006, 10041, 10106, 10119, 10169, 10202, 10232, 10249, 10277, 10279, 10327, 10357, 10449, 10528, 10550, 10603, 10639, 10670, 10728, 10779, 10780, 10783, 10817, 10910, 11130, 11150, 11169, 11182, 11223, 11231, 11293, 11298, 11299, 11349, 11353, 11356, 11361, 11368, 11374, 11378, 11383, 11392, 11394, 11396, 11401, 11405, 11413, 11414, 11418, 11424, 11430, 11431, 11442, 11444, 11497, 11498, 11526, 11561, 11591, 11592, 11593, 11801, 11802, 12312, 12351, 12352, 12353, 12414, 12415, 12416, 12417, 12418, 12419, 12420, 12421, 12422, 12423, 12424, 12425, 12426, 12427, 12542, 12543, 12544, 12619, 12620, 12621, 12764, 12765, 12903, 12904, 12905, 12954, 12955, 12956, 13016, 13017, 13018, 13019, 13020, 13021, 13022, 13023, 13024, 13025, 13026, 13027, 13223, 13224, 13225, 13374, 13375, 13376, 13514, 13515, 13516, 13562, 13624, 13625, 13626, 13627, 13628, 13629, 13630, 13631, 13632, 13633, 13634, 13635, 13636, 13637, 13638, 13821, 13822, 13950, 13951, 13952, 14074, 14075, 14076, 14120, 14121, 14172, 14173, 14174, 14175, 14176, 14177, 14178, 14179, 14402, 14403, 14404, 14460, 14461, 14748, 14749, 14750, 14853, 14854, 14855, 14857, 14858, 14920, 14921, 14922, 14923, 14924, 14925, 14926, 14927, 14928, 14929, 14931, 14932, 14933, 14934, 15159, 15160, 15161, 15378, 15379, 15380, 15443, 15444, 15528, 15529, 15530, 15710, 15711, 15712, 15803, 15805, 15806, 15807, 15808, 15857, 15858, 15859, 15860, 15861, 15862, 15863, 15864, 15865, 15866, 15867, 15868, 15869, 15870, 15871, 15872, 16084, 16085, 16086, 16288, 16289, 16290, 16350, 16351, 16352, 16432, 16433, 16434, 16599, 16600, 16601, 16694, 16695, 16696, 16697, 16698, 16746, 16747, 16748, 16749, 16750, 16751, 16752, 16753, 16908, 16983, 16984, 16985, 17173, 17174, 17175, 17243, 17244, 17245, 17317, 17318, 17319, 17441, 17442, 17553, 17554, 17555, 17638, 17639, 17640, 17687, 17688, 17689, 17690, 17691, 17692, 17693, 17694, 17695, 17911, 17912, 17913, 18099, 18223, 18224, 18225, 18425, 18426, 18427, 18517, 18518, 18519, 18574, 18575, 18576, 18577, 18578, 18579, 18580, 18581, 18775, 18776, 18982, 18983, 18984, 18988, 18989, 18990, 19116, 19117, 19190, 19191, 19192, 19220, 19221, 19222, 19358, 19359, 19360, 19505, 19506, 19507, 19508, 19509, 19510, 19511, 19512, 19708, 19709, 19887, 19888, 19889, 19893, 19894, 19895, 20070, 20071, 20072, 20096, 20097, 20098, 20200, 20201, 20202, 20275, 20276, 20277, 20278, 20279, 20280, 20281, 20282, 20283, 20488, 20489, 20490, 20542, 20543, 20660, 20661, 20662, 20663, 20664, 20665, 20666, 20865, 20866, 20867, 21181, 21182, 21183, 21208, 21209, 21210, 21349, 21350, 21351, 21425, 21464, 21465, 21466, 21467, 21468, 21469, 21470, 21471, 21472, 21473, 21633, 21634, 21635, 21869, 21870, 21871, 21875, 21876, 21877, 22002, 22003, 22004, 22029, 22030, 22031, 22132, 22133, 22134, 22313, 22314, 22315, 22319, 22320, 22321, 22356, 22451, 22452, 22453, 22474, 22475, 22476, 22562, 22563, 22564, 22594, 22595, 22596, 22689, 22690, 22691, 22692, 22693, 22694, 22695, 22696, 22697, 22755, 22756, 22757, 22829, 22830, 22846, 22979, 22980, 22981, 22982, 23089, 23090, 23091, 23094, 23095, 23096, 23097, 23098, 23119, 23120, 23121, 23122, 23123, 23128, 23129, 23130, 23144, 23145, 23158, 23159, 23312, 23313, 23343, 23367, 23368, 23448, 23462, 23463, 23464, 23532, 23533, 23534, 23535, 23653, 23654, 23656, 23657, 23723, 23724, 23725, 23737, 23738, 23803, 23881, 23882, 23883, 23884, 24002, 24003, 24004, 24010, 24011, 24012, 24029, 24031, 24040, 24127, 24128, 24244, 24245, 24269, 24276, 24290, 24334, 24338, 24339, 24378, 24387, 24393, 24402, 24595, 24596, 24597, 24611, 24612, 24622, 24623, 24624, 24640, 24641, 24642, 24643, 24657, 24658, 24686, 24788, 24831, 24832, 24914, 24915, 24965, 24988, 24989, 24992, 25003, 25004, 25005, 25112, 25113, 25127, 25233, 25234, 25330, 25331, 25332, 25368, 25390, 25409, 25417, 25419, 25444, 25445, 25637, 25638, 25639, 25654, 25670, 25671, 25672, 25686, 25687, 25688, 25695, 25696, 25837, 25915, 25937, 25938, 25948, 25949, 25962, 25993, 25994, 26049, 26051, 26052, 26053, 26061, 26095, 26096, 26097, 26230, 26231, 26334, 26347, 26350, 26351, 26457, 26510, 26512, 26519, 26520, 26740, 26742, 26758, 26759, 26780, 26800, 26801, 26803, 26832, 26833, 27031, 27034, 27035, 27064, 27065, 27066, 27082, 27175, 27293, 27294, 27317, 27318, 27405, 27418, 27420, 27456, 27508, 27509, 27510, 27511, 27654, 27660, 27672, 27686, 27775, 27852, 27853, 27854, 27862, 27880, 28082, 28092, 28093, 28107, 28219, 28270, 28276, 28277, 28278, 28284, 28366, 28374, 28375, 28376, 28381, 28478, 28479, 28484, 28489, 28600, 28601, 28602, 28606, 28607, 28608, 28693, 28718, 28719, 28894, 28895, 28896, 28899, 28901, 28916, 28917, 28931, 29102, 29115, 29129, 29130, 29131, 29147, 29150, 29304, 29305, 29311, 29312, 29316, 29317, 29318, 29435, 29450, 29451, 29463, 29473, 29474, 29530, 29602, 29603, 29616, 29617, 29628, 29629, 29736, 29761, 29762, 29763, 29777, 29778, 29795, 29797, 29902, 29903, 29908, 29967, 29976, 30094, 30110, 30112, 30136, 30137, 30258, 30261, 30277, 30278, 30279, 30362, 30398, 30400, 30401, 30418, 30419, 30459, 30562, 30563, 30635, 30690, 30703, 30823, 30824, 30843, 30844, 30967, 30968, 30976, 30977, 31071, 31083, 31084, 31087, 31098, 31099, 31211, 31212, 31213, 31221, 31345, 31346, 31369, 31420, 31423, 31424, 31474, 31475, 31476, 31477, 31493, 31494, 31596, 31597, 31598, 31609, 31610, 31625, 31741, 31742, 31743, 31760, 31870, 31871, 31881, 31909, 31965, 31990, 32001, 32003, 32009, 32010, 32113, 32122, 32123, 32147, 32234, 32236, 32237, 32238, 32244, 32245, 32306, 32344, 32577, 32676, 32690, 32696, 32716, 32717, 32768, 32771, 32776, 32837, 32838, 32962, 33090, 33193, 33299, 33300, 33303, 33304, 33686, 33705, 33784, 33867, 34027, 34333, 34437, 34460, 34507, 34757, 34845, 34868, 34946, 34947, 34967, 35106, 35136, 35240, 35241, 35321, 35413, 35414, 35537, 35538, 35616, 35707, 36023, 36028, 36058, 36059, 36298, 36299, 36524, 36636, 36659, 36720, 36890, 36891, 36939, 36966, 37021, 37022, 37041, 37042, 37043, 37044, 37047, 37048, 37066, 37101, 37102, 37124, 37125, 37161, 37176, 37177, 37255, 37298, 37315, 37370, 37416, 37417, 37432, 37504, 37554, 37571, 37624, 37639, 37655, 37656, 37704, 37706, 37736, 37737, 37787, 37788, 37818, 38398, 38399, 38430, 38431, 38524, 38590, 38639, 38858, 38859, 39141, 39228, 39314, 39387, 39509, 39729, 40240, 40253, 40298, 40299, 40369, 40370, 40371, 40372, 40426, 40427, 40428, 40429, 40837, 40882, 40889, 40890, 40926, 40928, 40929, 40965, 40966, 40970, 41007, 41015, 41016, 41067, 41068, 41077, 41078, 41110, 41114, 41115, 41161, 41162, 41171, 41172, 41200, 41201, 41210, 41211, 41240, 41241, 41247, 41248, 41276, 41277, 41285, 41329, 41330, 41339, 41340, 41369, 41370, 41408, 41409, 41438, 41608, 41609, 41708, 41790, 41791, 41871, 41908, 41940, 42011, 42110, 42143, 42145, 42184, 42275, 42278, 42389, 42460, 42733, 42747, 42919, 43146, 43173, 43176, 43382, 43798, 43801, 43802, 43804, 43811, 43982, 43990, 44020, 44022, 44025, 44243, 44257, 44590, 44629, 44639, 44653, 44654, 44660, 44669, 44671, 44672, 44673, 44674, 44676, 44995, 44999, 45002, 45003, 45008, 45010, 45014, 45016, 45018, 45019, 45020, 45100, 45104, 45106, 45119, 45142, 45143, 45262, 45391, 45392, 45393, 45394, 45396, 45397, 45399, 45400, 45401, 45533, 45684, 45716, 45870, 45983, 45989, 45998, 46002, 46012, 46013, 46016, 46017, 46019, 46020, 46077, 46162, 46359, 46365, 46424, 46432, 46433, 46437, 46441, 46442, 46443, 46446, 46537, 46538, 46540, 46542, 46552, 46579, 46580, 46581, 46583, 46584, 46780, 46895, 46897, 46899, 46902, 46905, 46906, 46908, 46909, 46912, 47103, 47263, 47311, 47347, 47477, 47539, 47547, 47568, 47573, 47586, 47587, 47589, 47593, 47595, 47917, 47963, 47965, 47968, 47969, 47972, 47973, 47974, 47976, 48029, 48030, 48031, 48032, 48036, 48054, 48057, 48158, 48164, 48261, 48263, 48265, 48267, 48268, 48269, 48270, 48272, 48274, 48417, 48523, 48546, 48580, 48696, 48724, 48731, 48746, 48750, 48760, 48762, 48763, 48765, 48768, 48770, 48862, 49019, 49062, 49064, 49066, 49067, 49069, 49070, 49072, 49074, 49135, 49137, 49138, 49139, 49141, 49151, 49177, 49178, 49179, 49180, 49287, 49351, 49353, 49354, 49356, 49358, 49360, 49362, 49364, 49365, 49565, 49598, 49706, 49748, 49755, 49775, 49780, 49791, 49793, 49795, 49798, 49799, 49801, 49814, 49815, 49831, 49871, 50105, 50156, 50158, 50162, 50164, 50168, 50169, 50171, 50175, 50228, 50231, 50272, 50340, 50350, 50356, 50444, 50446, 50447, 50449, 50451, 50453, 50455, 50457, 50464, 50583, 50618, 50644, 50689, 50899, 50905, 50921, 50924, 50930, 50932, 50933, 50934, 50935, 50937, 50951, 50952, 51009, 51092, 51176, 51237, 51239, 51240, 51242, 51243, 51244, 51245, 51246, 51286, 51287, 51288, 51289, 51294, 51323, 51325, 51326, 51327, 51328, 51330, 51377, 51428, 51429, 51431, 51432, 51434, 51435, 51436, 51567, 51649, 51659, 51666, 51677, 51687, 51871, 51928, 52186, 52196, 52219, 52223, 52231, 52233, 52234, 52235, 52237, 52269, 52271, 52290, 52341, 52347, 52462, 52598, 52623, 52640, 52650, 52722, 52725, 52734, 52737, 52738, 52742, 52745, 52748, 52750, 52753, 52754, 52760, 52763, 52764, 52767, 52769, 52770, 52773, 52884, 52889, 52891, 52893, 52908, 52914, 52919, 52923, 52932, 52938, 52952, 52969, 52998, 53097, 53108, 53185, 53188, 53189, 53191, 53193, 53195, 53196, 53197, 53198, 53252, 53343, 53354, 53367, 53426, 53475, 53478, 53481, 53483, 53486, 53489, 53491, 53492, 53576, 53661, 53706, 53739, 53970, 54023, 54044, 54209, 54212, 54263, 54273, 54288, 54320, 54332, 54345, 54347, 54349, 54351, 54353, 54355, 54479, 54481, 54513, 54586, 54647, 54767, 54816, 54885, 54889, 54891, 54893, 54894, 54897, 54898, 55009, 55015, 55016, 55018, 55020, 55028, 55106, 55129, 55131, 55136, 55141, 55142, 55148, 55153, 55161, 55191, 55255, 55271, 55276, 55280, 55285, 55301, 55317, 55318, 55319, 55320, 55322, 55323, 55324, 55325, 55327, 55394, 55411, 55534, 55540, 55602, 55733, 55735, 55736, 55738, 55740, 55742, 55744, 55746, 55747, 55817, 55846, 55916, 56005, 56090, 56125, 56178, 56225, 56253, 56264, 56303, 56309, 56334, 56409, 56414, 56505, 56708, 56723, 56789, 56792, 56808, 56819, 56823, 56825, 56826, 56828, 56838, 56855, 56858, 56861, 56865, 56867, 56871, 56873, 56875, 56930, 56931, 56932, 56934, 56936, 56944, 56977, 57032, 57082, 57083, 57084, 57085, 57086, 57087, 57089, 57090, 57091, 57186, 57189, 57190, 57252, 57323, 57558, 57650, 57656, 57686, 57696, 57720, 57722, 57725, 57727, 57730, 57732, 57736, 57738, 57739, 57740, 57742, 57743, 57744, 57747, 57749, 57796, 57797, 57809, 57846, 57848, 57851, 57853, 57865, 57879, 57889, 57982, 58102, 58223, 58234, 58292, 58523, 58531, 58556, 58559, 58566, 58567, 58568, 58569, 58570, 58571, 58599, 58601, 58639, 58747, 58760, 59017, 59153, 59154, 59155, 59156, 59157, 59158, 59179, 59180, 59181, 59182, 59183, 59225, 59226, 59227, 59228, 59229, 59230, 59281, 59282, 59283, 59378, 59389, 59423, 59451, 59476, 59477, 59502, 59510, 59547, 59558, 59559, 59562, 59580, 59588, 59649, 59697, 59756, 59766, 59769, 59770, 59792, 59793, 59906, 59944, 59976, 59977, 60011, 60058, 60059, 60085, 60086, 60087, 60088, 60091, 60112, 60117, 60120, 60152, 60198, 60212, 60213, 60252, 60258, 60310, 60318, 60319, 60327, 60334, 60410, 60468, 60470, 60471, 60475, 60476, 60496, 60586, 60599, 60634, 60674, 60717, 60728, 60760, 60789, 60793, 60815, 60816, 60840, 60843, 60844, 60855, 60860, 60861, 60872, 60888, 60899, 60908, 60909, 60912, 60917, 60929, 60933, 60934, 60948, 60963, 60964, 60971, 60978, 60992, 60996, 60999, 61001, 61007, 61043, 61047, 61062, 61089, 61090, 61106, 61109, 61112, 61113, 61125, 61132, 61135, 61146, 61152, 61156, 61160, 61178, 61182, 61190, 61198, 61201, 61204, 61216, 61222, 61223, 61241, 61259, 61270, 61309, 61322, 61323, 61324, 61327, 61339, 61354, 61358, 61371, 61379, 61381, 61407, 61442, 61445, 61449, 61451, 61453, 61456, 61482, 61488, 61495, 61499, 61500, 61510, 61515, 61549, 61551, 61564, 61590, 61607, 61613, 61622, 61632, 61633, 61635, 61658, 61663, 61664, 61689, 61709, 61727, 61730, 61735, 61737, 61741, 61744, 61752, 61753, 61769, 61794, 61819, 61829, 61837, 61839, 61844, 61847, 61865, 61866, 61872, 61875, 61877, 61880, 61885, 61887, 61889, 61901, 61908, 61929, 61935, 61941, 61943, 61950, 61954, 61969, 61983, 62006, 62007, 62028, 62029, 62034, 62047, 62054, 62063, 62080, 62088, 62089, 62093, 62094, 62111, 62125, 62144, 62154, 62155, 62178, 62188, 62196, 62198, 62207, 62210, 62233, 62248, 62254, 62267, 62283, 62292, 62305, 62309, 62316, 62317, 62320, 62324, 62345, 62361, 62362, 62366, 62367, 62371, 62382, 62390, 62391, 62392, 62406, 62427, 62447, 62457, 62460, 62463, 62465, 62476, 62513, 62522, 62527, 62537, 62539, 62548, 62552, 62555, 62561, 62563, 62574, 62576, 62580, 62599, 62628, 62636, 62639, 62644, 62650, 62655, 62665, 62672, 62687, 62697, 62701, 62704, 62705, 62706, 62714, 62722, 62732, 62749, 62778, 62780, 62800, 62808, 62816, 62825, 62835, 62837, 62854, 62864, 62865, 62874, 62876, 62910, 62929, 62932, 62935, 62983, 62986, 63001, 63017, 63018, 63019, 63030, 63032, 63034, 63054, 63077, 63104, 63126, 63158, 63162, 63167, 63169, 63208, 63258, 63265, 63290, 63315, 63327, 63361, 63390, 63393, 63396, 63420, 63459, 63465, 63477, 63516, 63564, 63571, 63575, 63591, 63598, 63634, 63659, 63673, 63682, 63697, 63708, 63735, 63741, 63742, 63789, 63805, 63807, 63834, 63853, 63858, 63872, 63881, 63906, 63936, 63941, 63962, 63982, 63993, 64018, 64021, 64039, 64041, 64060, 64080, 64090, 64095, 64106, 64115, 64129, 64155, 64157, 64160, 64163, 64188, 64196, 64236, 64244, 64250, 64256, 64286, 64324, 64373, 64385, 64403, 64420, 64426, 64432, 64443, 64520, 64528, 64530, 64541, 64547, 64550, 64561, 64587, 64612, 64631, 64650, 64663, 64723, 64728, 64822, 64894, 64901, 64923, 64935, 64950, 64956, 65004, 65041, 65085, 65109, 65121, 65152, 65153, 65162, 65212, 65231, 65274, 65286, 65292, 65307, 65308, 65369, 65377, 65402, 65404, 65407, 65423, 65446, 65459, 65474, 65475, 65485, 65491, 65493, 65542, 65577, 65604, 65615, 65616, 65638, 65652, 65659, 65668, 65684, 65693, 65694, 65720, 65732, 65737, 65766, 65798, 65814, 65821, 65822, 65826, 65851, 65865, 65891, 65903, 65904, 65910, 65911, 65921, 65924, 65934, 65951, 65952, 65974, 65982, 66001, 66041, 66053, 66068, 66070, 66103, 66107, 66129, 66130, 66144, 66147, 66150, 66153, 66156, 66158, 66193, 66195, 66212, 66233, 66265, 66313, 66318, 66329, 66347, 66348, 66349, 66357, 66360, 66363, 66387, 66413, 66418, 66462, 66463, 66469, 66479, 66483, 66511, 66513, 66563, 66572, 66583, 66592, 66597, 66603, 66617, 66648, 66659, 66663, 66666, 66693, 66723, 66736, 66742, 66751, 66845, 66856, 66869, 66872, 66885, 66919, 66969, 67066, 67068, 67095, 67129, 67145, 67191, 67237, 67270, 67313, 67436, 67453, 67470, 67471, 67522, 67525, 67557, 67565, 67572, 67593, 67633, 67634, 67713, 67747, 67758, 67813, 67884, 67890, 67927, 67934, 67937, 67985, 68008, 68016, 68493, 68499, 68513, 70289, 70310, 70326, 70437, 70456, 70466, 70473, 70667, 70683, 70780, 70789, 70790, 70799, 70805, 70876, 70895, 70938, 70964, 70965, 71032, 71044, 71047, 71073, 71077, 71078, 71134, 71157, 71163, 71167, 71181, 71194, 71225, 71233, 71248, 71250, 71254, 71304, 71313, 71319, 71321, 71328, 71408, 71439, 71446, 71567, 71583, 71594, 71605, 71610, 71692, 71698, 71719, 71823, 71871, 71872, 71885, 71936, 71942, 71945, 71969, 71982, 72049, 72056, 72072, 72149, 72161, 72192, 72195, 72206, 72219, 72232, 72234, 72264, 72298, 72321, 72323, 72391, 72396, 72401, 72515, 72516, 72520, 72526, 72546, 72622, 72646, 72662, 72663, 72675, 72677, 72732, 72746, 72798, 72872, 73000, 73026, 73064, 73069, 73098, 73102, 73117, 73130, 73149, 73239, 73292, 73326, 73364, 73452, 73610, 73622, 73645, 73660, 73685, 73788, 73849, 73851, 73868, 73904, 73991, 74070, 74085, 74181, 74184, 74210, 74227, 74284, 74296, 74308, 74314, 74322, 74326, 74336, 74384, 74404, 74459, 74469, 74525, 74580, 74681, 74691, 74746, 74749, 74778, 74784, 74930, 74984, 74994, 75027, 75125, 75130, 75163, 75184, 75185, 75202, 75206, 75234, 75238, 75258, 75297, 75312, 75326, 75423, 75436, 75446, 75480, 75481, 75489, 75512, 75513, 75534, 75561, 75568, 75574, 75576, 75583, 75595, 75616, 75623, 75659, 75674, 75688, 75714, 75751, 75776, 75785, 75818, 75832, 75902, 75940, 76057, 76073, 76075, 76229, 76245, 76298, 76355, 76357, 76365, 76407, 76415, 76416, 76430, 76463, 76561, 76674, 76722, 76812, 76821, 76831, 76842, 76884, 77028, 77038, 77103, 77180, 77247, 77432, 77475, 77482, 77738, 77785, 78079, 78130, 78201, 78232, 78262, 78344, 78361, 78404, 78606, 78704, 78832, 78844, 78868, 79035, 79153, 79155, 79227, 79373, 79521, 79813, 79868, 79972, 80170, 80182, 80216, 80272, 80329, 80338, 80362, 80393, 80509, 80812, 80853, 80868, 80950, 80971, 80988, 81049, 81065, 81169, 81176, 81230, 81621, 81624, 81776, 81861, 81900, 81981, 82006, 82040, 82059, 82072, 82082, 82617, 82699, 82891, 82903, 83000, 83008, 83174, 83678, 83883, 83999, 84258, 84349, 84485, 84526, 84531, 84578, 84689, 84722, 84780, 84847, 84912, 84921, 84974, 85013, 85021, 85050, 85100, 85113, 85126, 85138, 85216, 85227, 85238, 85314, 85353, 85402, 85448, 85460, 85484, 85506, 85518, 85572, 85586, 85756, 85836, 85861, 85862, 85874, 85913, 85914, 85949, 85965, 86141, 86160, 86173, 86229, 86258, 86312, 86347, 86510, 86568, 86593, 86628, 86668, 89064, 89867, 90071, 91804, 91815, 92168, 92451, 92729, 92744, 92757, 92884, 93174, 93611, 93787, 95556, 95636, 95884, 95910, 95930, 96008, 96107, 96417, 96559, 96672, 96778, 96868, 97409, 97529, 97585, 97640, 97881, 97960, 98042, 98127, 98129, 98173, 98213, 98239, 98283, 98349, 98396, 98447, 98533, 100414, 102705, 103970, 103976, 103977, 103979, 103980, 103999, 104000, 104013, 104017, 104022, 104023, 104026, 104034, 104040, 104045, 104047, 104081, 104083, 104105, 104107, 104109, 104120, 104123, 104136, 104149, 104153, 104154, 104162, 104163, 104169, 104191, 104203, 104209, 104212, 104215, 104220, 104224, 104236, 104247, 104249, 104279, 104304, 104308, 104309, 104312, 104316, 104318, 104320, 104326, 104329, 104331, 104335, 104342, 104347, 104348, 104365, 104374, 104381, 104386, 104395, 104411, 104421, 104436, 104442, 104453, 104455, 104476, 104478, 104495, 104500, 104506, 104520, 104894, 104947, 105170, 105189, 105246, 105307, 105366, 105368, 105468, 105508, 105509, 105569, 105620, 105630, 105638, 105650, 105701, 105714, 105726, 105732, 105736, 105762, 105769, 105795, 105815, 105832, 105861, 106174, 106382, 106409, 106637, 106797, 106926, 107066, 107280, 107297, 107321, 107512, 107562, 107663, 107689, 107764, 107799, 107842, 107845, 107887, 107888, 108033, 108168, 108444, 108483, 108547, 108794, 109573, 109658, 109936, 110228, 110231, 110236, 110247, 110328, 110386, 110477, 110554, 110698, 111065, 111204, 111232, 111320, 111335, 111344, 111352, 111530, 111531, 111534, 111546, 111599, 111771, 111965, 112002, 112057, 112149, 112608, 112614, 112735, 112748, 113010, 113019, 113028, 113192, 113289, 113383, 113386, 113620, 113637, 113802, 113865, 113967, 113990, 114046, 114107, 114129, 114156, 114169, 114214, 114223, 114253, 114287, 114375, 114523, 114930, 114988, 115115, 115143, 115272, 115430, 115431, 115743, 115851, 115913, 115921, 115926, 116031, 116043, 116055, 116740, 116756, 116955, 117028, 117032, 117041, 117061, 117102, 117239, 117359, 117390, 117420, 117604, 117709, 117847, 118061, 118292, 118294, 118310, 118328, 118425, 118480, 118482, 118581, 118611, 118766, 118811, 118907, 119025, 119054, 119082, 119150, 119172, 119208, 119251, 119371, 119378, 119501, 119604, 119729, 119735, 119823, 119859, 119889, 119934, 120057, 120063, 120098, 120114, 120187, 120210, 120316, 120402, 120425, 120433, 120439, 120534, 120573, 120598, 120608, 120622, 120660, 120688, 120789, 120937, 121009, 121456, 121657, 122345, 122369, 122375, 122924, 123038, 123596, 123745, 124085, 124398, 124446, 124454, 124512, 124818, 124865, 124950, 124962, 124994, 125018, 125028, 125057, 125111, 125210, 125261, 125301, 125304, 125547, 125673, 125714, 125730, 125764, 125783, 125864, 125880, 125979, 126023, 126093, 126174, 126227, 126228, 126229, 126375, 126644, 126687, 126695, 126701, 126715, 126722, 126744, 126799, 126976, 126988, 127020, 127075, 127091, 127215, 127274, 127314, 127385, 127485, 127593, 127604, 127757, 127825, 127910, 128022, 128050, 128118, 128200, 128279, 128293, 128316, 128441, 128559, 128572, 128597, 128689, 128693, 128702, 128734, 128917, 128966, 128990, 129312, 129452, 129716, 129720, 129750, 129826, 129901, 129976, 130061, 130070, 130072, 130116, 130234, 130303, 130374, 130516, 130599, 130682, 130686, 130796, 130840, 130876, 130956, 130958, 130984, 131058, 131062, 131217, 131227, 131243, 131290, 131322, 131349, 131422, 131438, 131516, 131850, 131853, 131890, 132216, 132254, 132272, 132345, 132396, 132420, 132459, 132475, 132592, 132661, 132757, 132863, 132867, 132906, 132991, 133014, 133041, 133049, 133131, 133167, 133239, 133400, 133602, 133649, 133682, 133698, 133866, 133888, 133889, 133939, 134035, 134158, 134159, 134164, 134260, 134372, 134383, 134458, 134460, 134657, 134670, 134695, 134851, 135015, 135047, 135062, 135396, 135433, 135605, 135696, 135782, 135816, 135820, 135940, 135948, 135993, 136161, 136181, 136258, 136259, 136458, 136485, 136543, 136683, 136824, 136968, 137025, 137037, 137070, 137077, 137139, 137190, 137191, 137305, 137424, 137434, 137823, 138036, 138128, 138130, 138137, 138150, 138163, 138207, 138280, 138299, 138307, 138442, 138479, 138497, 138511, 138937, 139033, 139121, 139184, 139274, 139302, 139424, 139638, 139939, 140026, 140099, 140246, 140301, 140407, 140440, 140764, 140832, 140946, 141023, 141056, 141098, 141203, 141275, 141280, 141290, 141510, 141522, 141525, 141602, 141647, 141774, 141778, 141847, 141871, 141926, 141945, 142041, 142608, 142759, 142888, 142926, 142995, 143123, 143177, 143260, 143277, 143357, 143425, 143439, 143482, 143816, 143871, 144082, 144096, 144105, 144106, 144107, 144171, 144189, 144261, 144325, 144413, 144503, 144555, 144556, 144705, 144788, 144875, 144944, 145092, 145330, 145365, 145535, 145545, 145673, 145820, 145826, 145875, 145909, 146098, 146186, 146220, 146287, 146494, 146572, 146653, 146663, 146710, 146736, 146752, 146790, 146800, 146923, 146957, 147070, 147136, 147262, 147277, 147444, 147495, 147519, 147907, 147935, 147951, 147996, 148114, 148159, 148247, 148264, 148356, 148361, 148370, 148404, 148406, 148423, 148446, 148664, 148681, 148713, 148744, 148830, 149036, 149074, 149100, 149201, 149366, 149421, 149532, 149580, 149596, 149791, 149804, 149807, 149841, 149847, 150247, 150281, 150342, 150362, 150504, 150640, 150688, 150830, 150866, 151007, 151020, 151062, 151201, 152137, 153140, 153306, 153617, 153941, 154687, 154690, 155005, 155258, 155440, 155532, 155950, 156341, 156454, 156580, 156683, 156725, 156734, 157027, 157145, 157227, 157385, 157394, 157409, 157502, 157545, 157663, 157697, 157804, 157962, 157987, 158101, 158108, 158164, 158368, 158411, 158573, 158625, 158710, 158719, 158820, 158872, 158934, 159033, 159037, 159102, 159193, 159336, 159353, 159403, 159572, 159667, 159868, 159950, 160112, 160143, 160287, 160546, 160681, 160909, 161133, 161240, 161260, 161270, 161293, 161301, 161326, 161352, 161474, 161495, 161533, 161605, 161744, 162103, 162108, 162220, 162327, 162345, 162398, 162515, 162776, 162857, 162913, 163103, 163160, 163226, 163271, 163463, 163487, 163524, 163593, 163619, 163766, 163821, 163869, 163927, 163928, 164007, 164061, 164138, 164207, 164222, 164352, 164419, 164458, 164482, 164543, 164555, 164562, 164577, 164679, 164689, 164782, 164800, 164893, 164987, 165054, 165088, 165207, 165218, 165230, 165326, 165576, 165577, 165591, 165674, 165878, 165898, 165989, 166620, 166810, 166978, 167059, 167088, 167245, 167265, 167277, 167331, 167477, 167493, 167765, 167837, 167936, 168043, 168077, 168117, 168121, 168126, 168135, 168143, 168145, 168150, 168160, 168165, 168178, 168184, 168187, 168192, 168306, 168450, 168482, 168490, 168495, 168523, 168570, 168576, 168583, 168588, 168589, 168611, 168624, 168642, 168657, 168660, 168667, 168692, 168693, 168695, 168696, 168704, 168709, 168732, 168734, 168737, 168741, 168752, 168754, 168772, 168783, 168791, 168796, 168797, 168811, 168813, 168816, 168863, 168869, 168875, 168882, 168885, 168898, 168901, 168913, 168938, 168945, 168957, 168964, 168971, 168992, 169017, 169022, 169031, 169061, 169064, 169069, 169073, 169077, 169090, 169092, 169093, 169105, 169116, 169124, 169139, 169149, 169160, 169163, 169174, 169184, 169186, 169187, 169194, 169197, 169205, 169217, 169236, 169241, 169242, 169269, 169275, 169277, 169278, 169279, 169282, 169287, 169288, 169303, 169323, 169339, 169342, 169357, 169369, 169380, 169409, 169422, 169708, 169954, 170004, 170005, 170007, 170012, 170036, 170052, 170054, 170059, 170062, 170064, 170068, 170102, 170115, 170139, 170145, 170146, 170147, 170152, 170164, 170187, 170198, 170204, 170205, 170211, 170214, 170215, 170224, 170226, 170256, 170261, 170278, 170297, 170304, 170306, 170320, 170332, 170338, 170362, 170365, 170367, 170368, 170372, 170384, 170457, 170465, 170468, 170473, 170477, 170481, 170482, 170500, 170530, 170538, 170546, 170561, 170569, 170579, 170581, 170596, 170606, 170614, 170644, 170653, 170654, 170656, 170658, 170716, 170720, 170723, 170724, 170736, 170739, 170742, 170746, 170749, 170790, 170833, 170907, 170916, 170924, 170929, 170936, 170944, 170974, 170990, 171012, 171014, 171017, 171044, 171052, 171083, 171149, 171157, 171160, 171199, 171210, 171243, 171270, 171271, 171295, 171332, 171348, 171368, 171370, 171378, 171390, 171393, 171431, 171477, 171558, 171561, 171568, 171593, 171600, 171604, 171606, 171634, 171683, 171689, 171694, 171729, 171739, 171741, 171768, 171791, 171801, 171856, 171871, 171892, 171899, 171927, 171950, 172022, 172039, 172149, 172178, 172214, 172246, 172265, 172278, 172315, 172320, 172329, 172343, 172347, 172354, 172357, 172361, 172364, 172377, 172382, 172411, 172435, 172450, 172474, 172484, 172485, 172520, 172545, 172552, 172598, 172600, 172602, 172607, 172659, 172669, 172671, 172688, 172756, 172773, 172779, 172804, 172829, 172837, 172859, 172881, 172905, 172923, 172965, 172971, 172979, 172986, 172992, 172994, 173053, 173063, 173070, 173081, 173096, 173108, 173111, 173156, 173190, 173206, 173253, 173282, 173305, 173318, 173321, 173331, 173370, 173395, 173431, 173439, 173500, 173566, 173599, 173648, 173676, 173693, 173695, 173707, 173750, 173763, 173793, 173883, 173956, 173971, 173979, 173996, 174046, 174086, 174121, 174123, 174144, 174163, 174182, 174186, 174234, 174279, 174293, 174305, 174336, 174356, 174371, 174441, 174444, 174468, 174469, 174476, 174489, 174541, 174556, 174869, 174937, 175016, 175174, 175433, 175678, 176111, 176300, 176975, 177139, 177212, 177217, 177221, 177235, 177265, 177322, 177340, 177350, 177380, 177399, 177405, 177478, 177479, 177481, 177493, 177552, 177600, 177611, 177621, 177629, 177634, 177648, 177655, 177658, 177664, 177680, 177697, 177708, 177732, 177738, 177780, 177802, 177837, 177846, 177859, 177868, 177902, 177907, 177910, 177911, 177912, 177938, 177940, 177951, 177952, 177954, 177980, 177988, 178032, 178036, 178060, 178074, 178075, 178087, 178109, 178124, 178143, 178166, 178172, 178178, 178186, 178196, 178199, 178203, 178267, 178303, 178330, 178362, 178372, 178375, 178401, 178431, 178433, 178439, 178453, 178462, 178470, 178472, 178476, 178488, 178503, 178519, 178523, 178546, 178555, 178580, 178643, 178664, 178668, 178672, 178673, 178686, 178687, 178700, 178709, 178722, 178740, 178766, 178803, 178811, 178812, 178814, 178825, 178829, 178859, 178891, 178893, 178903, 178909, 179024, 179314, 179441, 179606, 179615, 179653, 179669, 179694, 179702, 179727, 179740, 179754, 179756, 179770, 179777, 179789, 179791, 179808, 179814, 179817, 179822, 179824, 179835, 179847, 179863, 179896, 179898, 179925, 179972, 180012, 180056, 180078, 180106, 180113, 180114, 180141, 180149, 180165, 180174, 180192, 180196, 180204, 180206, 180208, 180213, 180235, 180251, 180301, 180313, 180350, 180363, 180373, 180401, 180435, 180450, 180454, 180502, 180736, 181559, 181864, 182263, 182378, 182435, 182572, 182635, 182655, 182716, 182897, 183033, 183179, 183251, 183299, 183416, 183443, 183533, 183557, 183572, 183633, 183682, 183784, 183885, 183947, 183949, 183974, 184038, 184132, 184180, 184182, 184218, 184475, 184542, 184633, 184638, 184787, 184812, 184895, 184930, 184985, 185028, 185089, 185090, 185290, 185302, 185448, 186626, 186653, 186660, 187791, 187794, 187864, 188325, 188497, 188893, 189201, 189445, 189986, 190073, 190270, 190543, 190679, 190845, 191082, 191401, 191459, 191528, 191681, 192266, 193204, 193472, 193619, 194609, 194847, 195957, 197151, 197272, 198097, 198367, 199470, 199937, 200738, 201048, 202131, 203893, 203967, 205356, 206762, 208212, 208346, 208936, 211614, 212541, 212821, 213734, 214042, 214167, 214842, 216067, 216551, 217754, 220539, 222852, 224160, 225556, 226041, 226897, 226920, 228889, 229843, 233607, 233808, 239094, 239668, 240425, 243318, 243934, 244185, 245220, 246518, 249764, 253113, 253260, 255043, 256633, 257846, 257913, 259344, 260665, 267201, 269298, 270421, 270884, 271321, 271851, 274534, 274615, 279346, 281007, 282230, 282298, 284060, 284159, 284257, 285443, 285698, 285894, 286592, 286924, 287013, 289741, 290536, 291972, 292517, 294197, 296347, 297204, 297810, 299480, 299706, 299888, 299930, 300259, 300436, 300586, 300985, 301289, 301290, 301465, 301503, 301659, 301702, 302091, 302797, 302976, 303050, 303248, 303447, 303451, 303573, 304226, 304295, 305150, 305336, 305404, 305782, 305970, 306005, 306012, 306061, 306185, 306258, 306655, 307174, 307262, 307267, 307661, 307854, 308067, 308478, 308617, 309199, 309407, 309729, 310451, 310496, 310950, 310956, 310994, 311449, 311629, 311690, 311769, 311770, 311920, 311923, 311930, 311976, 311980, 312066, 312067, 312068, 312072, 312211, 312237, 312301, 312330, 312367, 312386, 312393, 312507, 312513, 312525, 312527, 312529, 312531, 312564, 312665, 312671, 312676, 312677, 312823, 312824, 312831, 312834, 312864, 312874, 312887, 312973, 312980, 312981, 312982, 313032, 313046, 313086, 313089, 313130, 313204, 313210, 313246, 313267, 313268, 313269, 313277, 313278, 313279, 313291, 313310, 313311, 313376, 313379, 313391, 313545, 313579, 313630, 313640, 313698, 313726, 313877, 314076, 314129, 314170, 314255, 314428, 314454, 314610, 314615, 314643, 314788, 314879, 314889, 314928, 314969, 314976, 315000, 315037, 315055, 315072, 315152, 315205, 315215, 315230, 315235, 315259, 315274, 315300, 315303, 315316, 315360, 315410, 315429, 315521, 315576, 315741, 315746, 315846, 315884, 315911, 315913, 315975, 316008, 316089, 316167, 316202, 316214, 316289, 316294, 316378, 316438, 316504, 316626, 316670, 316695, 316853, 316881, 316884, 316905, 317012, 317030, 317049, 317249, 317274, 317451, 317587, 317689, 317765, 317784, 317935, 318096, 318199, 318223, 318305, 318593, 318837, 318922, 318972, 319399, 319422, 319576, 319670, 319737, 319832, 319858, 319966, 320013, 320078, 320522, 320601, 320719, 320740, 320749, 320938, 320951, 320952, 320959, 321015, 321132, 321416, 321445, 321448, 321760, 321795, 321856, 322038, 322089, 322150, 322158, 322170, 322211, 322340, 322534, 322549, 322557, 322567, 322583, 322613, 322645, 322652, 322706, 322709, 322853, 322898, 322957, 323032, 323038, 323075, 323132, 323231, 323249, 323291, 323477, 323515, 323574, 323648, 323752, 323767, 323808, 323819, 323823, 323844, 323888, 323941, 323946, 323954, 323958, 324003, 324016, 324045, 324050, 324075, 324094, 324105, 324108, 324114, 324120, 324131, 324136, 324144, 324169, 324174, 324180, 324188, 324191, 324202, 324227, 324241, 324255, 324259, 324260, 324299, 324340, 324369, 324385, 324437, 324455, 324469, 324475, 324525, 324555, 324564, 324584, 324585, 324594, 324603, 324606, 324608, 324609, 324618, 324622, 324623, 324627, 324628, 324632, 324644, 324647, 324651, 324653, 324662, 324669, 324670, 324674, 324676, 324680, 324681, 324687, 324691, 324696, 324701, 324702, 324705, 324710, 324715, 324723, 324731, 324732, 324734, 324739, 324740, 324744, 324747, 324751, 324757, 324760, 324762, 324771, 324772, 324774, 324776, 324781, 324788, 324795, 324796, 324800, 324802, 324806, 324811, 324816, 324819, 324823, 324829, 324839, 324841, 324845, 324853, 324858, 324864, 324867, 324869, 324871, 324876, 324879, 324892, 324895, 324898, 324902, 324908, 324914, 324920, 324927, 324930, 324931, 324936, 324940, 324942, 324944, 324945, 324948, 324960, 324963, 324968, 324973, 324979, 324986, 324989, 324991, 324994, 324999, 325004, 325025, 325027, 325029, 325031, 325035, 325041, 325047, 325053, 325059, 325061, 325078, 325081, 325088, 325089, 325103, 325107, 325114, 325117, 325122, 325135, 325137, 325142, 325144, 325149, 325170, 325176, 325178, 325182, 325184, 325186, 325202, 325206, 325210, 325214, 325222, 325227, 325228, 325232, 325237, 325242, 325248, 325251, 325258, 325262, 325265, 325269, 325277, 325280, 325281, 325291, 325300, 325301, 325305, 325307, 325311, 325318, 325322, 325326, 325327, 325336, 325338, 325347, 325350, 325351, 325358, 325360, 325361, 325362, 325369, 325377, 325382, 325386, 325397, 325400, 325403, 325412, 325423, 325434, 325437, 325450, 325452, 325457, 325458, 325459, 325466, 325469, 325472, 325476, 325481, 325484, 325495, 325498, 325503, 325511, 325515, 325518, 325528, 325535, 325544, 325551, 325564, 325566, 325570, 325572, 325575, 325577, 325590, 325597, 325602, 325604, 325606, 325608, 325626, 325630, 325631, 325633, 325636, 325653, 325656, 325667, 325668, 325675, 325684, 325689, 325700, 325706, 325708, 325714, 325719, 325721, 325722, 325726, 325727, 325737, 325742, 325747, 325750, 325754, 325765, 325771, 325776, 325780, 325786, 325792, 325793, 325794, 325803, 325809, 325824, 325840, 325846, 325847, 325872, 325877, 325881, 325894, 325912, 325913, 325920, 325931, 325940, 325949, 325955, 325981, 325983, 326006, 326011, 326016, 326028, 326039, 326044, 326049, 326058, 326062, 326085, 326092, 326094, 326104, 326113, 326119, 326133, 326134, 326142, 326156, 326160, 326164, 326171, 326172, 326180, 326183, 326196, 326199, 326223, 326228, 326230, 326239, 326256, 326257, 326263, 326286, 326293, 326308, 326319, 326336, 326350, 326352, 326357, 326363, 326395, 326410, 326424, 326431, 326434, 326444, 326451, 326452, 326456, 326463, 326465, 326472, 326476, 326481, 326486, 326494, 326497, 326501, 326502, 326507, 326520, 326546, 326550, 326559, 326560, 326567, 326571, 326588, 326607, 326612, 326621, 326632, 326633, 326643, 326649, 326656, 326666, 326672, 326678, 326681, 326686, 326691, 326694, 326705, 326710, 326713, 326730, 326732, 326753, 326756, 326765, 326783, 326784, 326791, 326795, 326801, 326804, 326810, 326825, 326829, 326846, 326856, 326863, 326871, 326883, 326885, 326888, 326891, 326902, 326905, 326911, 326921, 326950, 326968, 326972, 326977, 326985, 326986, 326995, 326999, 327002, 327014, 327023, 327034, 327036, 327039, 327044, 327045, 327048, 327055, 327064, 327071, 327080, 327093, 327099, 327110, 327114, 327121, 327123, 327132, 327134, 327140, 327144, 327148, 327149, 327157, 327165, 327169, 327177, 327188, 327195, 327197, 327199, 327200, 327216, 327219, 327237, 327241, 327243, 327245, 327251, 327259, 327261, 327265, 327269, 327270, 327276, 327298, 327307, 327308, 327316, 327339, 327340, 327343, 327344, 327345, 327351, 327352, 327355, 327359, 327374, 327375, 327377, 327382, 327383, 327395, 327421, 327422, 327431, 327437, 327447, 327451, 327454, 327475, 327482, 327486, 327487, 327492, 327504, 327510, 327515, 327518, 327524, 327525, 327526, 327533, 327536, 327539, 327547, 327548, 327553, 327570, 327577, 327589, 327593, 327597, 327606, 327609, 327613, 327615, 327616, 327620, 327639, 327647, 327648, 327650, 327656, 327662, 327669, 327684, 327692, 327712, 327715, 327731, 327736, 327738, 327744, 327753, 327761, 327766, 327773, 327780, 327785, 327789, 327792, 327805, 327810, 327816, 327832, 327833, 327835, 327838, 327842, 327845, 327864, 327869, 327873, 327879, 327889, 327897, 327911, 327917, 327932, 327936, 327942, 327948, 327962, 327965, 327967, 327969, 327971, 327978, 327983, 327987, 327998, 328009, 328014, 328021, 328029, 328030, 328036, 328037, 328044, 328049, 328054, 328062, 328064, 328067, 328070, 328071, 328081, 328083, 328091, 328096, 328103, 328108, 328113, 328123, 328128, 328135, 328143, 328145, 328151, 328166, 328172, 328174, 328179, 328199, 328208, 328215, 328219, 328225, 328227, 328241, 328243, 328249, 328254, 328259, 328261, 328265, 328271, 328275, 328282, 328287, 328288, 328293, 328297, 328303, 328307, 328309, 328312, 328313, 328317, 328323, 328337, 328338, 328348, 328352, 328357, 328368, 328374, 328384, 328385, 328386, 328393, 328400, 328403, 328404, 328410, 328413, 328414, 328446, 328450, 328454, 328463, 328469, 328488, 328495, 328498, 328513, 328523, 328526, 328545, 328558, 328560, 328575, 328581, 328582, 328592, 328599, 328601, 328620, 328633, 328639, 328651, 328652, 328655, 328656, 328663, 328666, 328677, 328681, 328686, 328693, 328695, 328699, 328705, 328717, 328722, 328726, 328727, 328730, 328734, 328737, 328741, 328743, 328751, 328758, 328766, 328771, 328781, 328785, 328789, 328797, 328803, 328815, 328828, 328831, 328835, 328839, 328848, 328851, 328862, 328865, 328871, 328872, 328875, 328878, 328882, 328884, 328888, 328897, 328903, 328915, 328927, 328944, 328945, 328947, 328951, 328961, 328966, 328973, 328984, 328997, 328999, 329005, 329010, 329017, 329020, 329027, 329029, 329055, 329059, 329063, 329076, 329078, 329082, 329084, 329086, 329089, 329104, 329105, 329121, 329125, 329126, 329133, 329137, 329144, 329151, 329155, 329156, 329159, 329166, 329189, 329190, 329193, 329203, 329211, 329215, 329217, 329221, 329232, 329234, 329235, 329240, 329247, 329248, 329252, 329258, 329260, 329266, 329271, 329279, 329281, 329283, 329290, 329291, 329296, 329300, 329304, 329317, 329331, 329339, 329343, 329344, 329345, 329361, 329374, 329375, 329389, 329391, 329393, 329401, 329406, 329415, 329417, 329421, 329444, 329446, 329471, 329474, 329481, 329492, 329510, 329516, 329518, 329520, 329523, 329526, 329534, 329537, 329548, 329552, 329555, 329568, 329571, 329575, 329590, 329595, 329602, 329609, 329611, 329618, 329631, 329637, 329654, 329663, 329674, 329684, 329692, 329696, 329705, 329716, 329720, 329730, 329739, 329750, 329763, 329764, 329771, 329779, 329782, 329789, 329806, 329812, 329816, 329824, 329830, 329833, 329840, 329848, 329850, 329855, 329862, 329873, 329878, 329887, 329890, 329895, 329902, 329904, 329906, 329918, 329940, 329942, 329950, 329952, 329966, 329977, 329979, 329981, 329982, 329987, 329989, 329993, 329996, 330000, 330003, 330004, 330010, 330016, 330035, 330036, 330040, 330043, 330047, 330050, 330053, 330056, 330074, 330094, 330105, 330112, 330114, 330121, 330124, 330127, 330136, 330142, 330154, 330159, 330162, 330166, 330174, 330175, 330183, 330194, 330203, 330214, 330219, 330228, 330231, 330242, 330248, 330250, 330252, 330292, 330295, 330300, 330306, 330309, 330314, 330335, 330342, 330346, 330353, 330362, 330369, 330376, 330383, 330387, 330392, 330399, 330407, 330408, 330415, 330422, 330425, 330430, 330436, 330444, 330458, 330459, 330461, 330478, 330482, 330484, 330496, 330501, 330503, 330512, 330520, 330525, 330531, 330532, 330534, 330544, 330561, 330567, 330569, 330573, 330579, 330583, 330587, 330596, 330626, 330636, 330640, 330666, 330677, 330678, 330686, 330687, 330697, 330702, 330706, 330711, 330713, 330722, 330731, 330735, 330743, 330755, 330767, 330775, 330780, 330785, 330789, 330792, 330801, 330807, 330816, 330820, 330826, 330831, 330845, 330846, 330854, 330870, 330881, 330882, 330889, 330904, 330912, 330919, 330925, 330926, 330938, 330941, 330948, 330959, 330962, 330970, 330972, 330973, 330979, 330990, 330993, 330998, 331000, 331002, 331006, 331012, 331014, 331017, 331021, 331027, 331029, 331032, 331041, 331044, 331047, 331054, 331059, 331085, 331092, 331097, 331104, 331109, 331110, 331120, 331121, 331135, 331137, 331143, 331144, 331149, 331152, 331172, 331197, 331199, 331207, 331208, 331213, 331220, 331223, 331252, 331261, 331266, 331297, 331302, 331318, 331322, 331333, 331340, 331344, 331347, 331351, 331358, 331366, 331371, 331372, 331374, 331382, 331394, 331398, 331406, 331416, 331424, 331431, 331432, 331445, 331456, 331461, 331468, 331475, 331481, 331488, 331498, 331504, 331506, 331507, 331514, 331516, 331527, 331529, 331533, 331536, 331539, 331542, 331553, 331556, 331557, 331561, 331567, 331569, 331573, 331580, 331590, 331597, 331601, 331604, 331611, 331619, 331626, 331638, 331646, 331650, 331654, 331674, 331685, 331693, 331696, 331702, 331705, 331711, 331721, 331734, 331748, 331750, 331778, 331782, 331788, 331793, 331826, 331833, 331838, 331841, 331852, 331862, 331867, 331872, 331884, 331886, 331889, 331899, 331909, 331913, 331917, 331922, 331926, 331935, 331940, 331952, 331956, 331967, 331970, 331974, 331979, 331986, 331988, 331991, 331993, 332003, 332005, 332007, 332012, 332015, 332017, 332023, 332028, 332036, 332041, 332046, 332057, 332065, 332067, 332075, 332077, 332079, 332081, 332083, 332085, 332088, 332096, 332100, 332124, 332136, 332154, 332157, 332161, 332164, 332171, 332181, 332184, 332189, 332196, 332204, 332208, 332215, 332229, 332233, 332234, 332243, 332248, 332253, 332254, 332255, 332265, 332266, 332268, 332276, 332284, 332288, 332291, 332295, 332302, 332308, 332315, 332320, 332331, 332350, 332356, 332359, 332364, 332366, 332369, 332373, 332388, 332390, 332393, 332398, 332404, 332411, 332435, 332437, 332448, 332453, 332455, 332464, 332474, 332487, 332492, 332494, 332502, 332506, 332521, 332530, 332536, 332548, 332551, 332556, 332562, 332575, 332580, 332585, 332598, 332615, 332622, 332624, 332627, 332630, 332655, 332668, 332677, 332690, 332693, 332700, 332723, 332733, 332740, 332745, 332751, 332755, 332761, 332764, 332768, 332776, 332790, 332800, 332809, 332824, 332827, 332832, 332837, 332845, 332855, 332859, 332868, 332872, 332874, 332878, 332879, 332882, 332885, 332895, 332899, 332902, 332912, 332913, 332918, 332920, 332924, 332929, 332941, 332949, 332955, 332991, 333000, 333007, 333016, 333019, 333026, 333031, 333040, 333059, 333061, 333065, 333068, 333077, 333084, 333091, 333094, 333095, 333099, 333107, 333114, 333117, 333127, 333132, 333135, 333138, 333142, 333149, 333153, 333164, 333170, 333174, 333187, 333192, 333193, 333199, 333206, 333210, 333211, 333215, 333231, 333233, 333244, 333259, 333260, 333266, 333269, 333273, 333283, 333287, 333296, 333297, 333304, 333307, 333314, 333318, 333320, 333330, 333333, 333335, 333341, 333353, 333360, 333363, 333379, 333390, 333391, 333394, 333405, 333408, 333412, 333416, 333427, 333434, 333449, 333455, 333457, 333468, 333473, 333475, 333479, 333482, 333483, 333487, 333494, 333500, 333506, 333518, 333521, 333530, 333537, 333541, 333544, 333545, 333548, 333565, 333588, 333592, 333595, 333598, 333600, 333606, 333608, 333609, 333614, 333626, 333635, 333636, 333644, 333646, 333651, 333655, 333674, 333675, 333679, 333691, 333695, 333699, 333708, 333716, 333717, 333721, 333728, 333733, 333740, 333742, 333743, 333745, 333752, 333754, 333755, 333758, 333760, 333761, 333765, 333784, 333789, 333793, 333795, 333797, 333803, 333807, 333808, 333812, 333814, 333822, 333825, 333827, 333836, 333838, 333842, 333852, 333859, 333868, 333870, 333874, 333877, 333881, 333883, 333886, 333890, 333896, 333909, 333912, 333920, 333987, 333995, 334180, 334236, 334277, 334328, 334365, 334406, 334419, 334491, 334575, 334630, 334678, 334680, 334695, 334754, 334808, 334812, 334826, 334970, 335011, 335014, 335042, 335090, 335125, 335171, 335198, 335212, 335303, 335393, 335449, 335464, 335565, 335579, 335604, 335647, 335656, 335725, 335727, 335767, 335774, 335801, 335809, 335856, 335893, 335941, 335985, 336005, 336046, 336135, 336328, 336368, 336395, 336434, 336479, 336620, 336702, 336715, 336808, 336852, 337014, 337077, 337254, 337265, 337315, 337348, 337458, 337483, 337661, 337686, 337690, 337706, 337711, 337718, 337767, 337803, 337817, 337919, 337950, 338009, 338010, 338167, 338263, 338364, 338387, 338401, 338534, 338602, 338618, 338714, 338744, 338786, 338931, 338946, 338956, 339020, 339040, 339092, 339132, 339252, 339298, 339350, 339410, 339487, 339529, 339531, 339574, 339584, 339751, 339800, 339809, 339836, 339887, 339938, 339958, 340032, 340047, 340062, 340133, 340274, 340315, 340359, 340362, 340466, 340481, 340560, 340574, 340589, 340599, 340602, 340648, 340698, 340783, 340792, 340874, 340888, 340895, 340942, 340996, 341068, 341110, 341139, 341154, 341256, 341273, 341292, 341296, 341417, 341489, 341530, 341579, 341618, 341706, 341837, 341913, 341921, 341990, 342118, 342126, 342161, 342163, 342319, 342324, 342334, 342338, 342497, 342602, 342676, 342719, 342854, 342855, 342942, 343048, 343100, 343107, 343113, 343265, 343285, 343345, 343415, 343478, 343551, 343563, 343587, 345460, 345613, 345614, 345619, 345747, 345776, 345818, 345948, 345997, 346056, 346102, 346310, 346316, 346439, 346480, 346499, 346530, 346531, 346669, 346710, 346831, 346838, 346866, 346876, 346943, 347004, 347006, 347009, 347011, 347016, 347020, 347027, 347029, 347035, 347040, 347045, 347050, 347055, 347063, 347069, 347077, 347083, 347087, 347090, 347094, 347108, 347122, 347128, 347133, 347140, 347154, 347160, 347167, 347174, 347181, 347187, 347197, 347198, 347202, 347204, 347214, 347216, 347225, 347239, 347242, 347248, 347250, 347254, 347268, 347278, 347281, 347284, 347285, 347290, 347302, 347320, 347328, 347337, 347338, 347344, 347348, 347354, 347360, 347367, 347370, 347374, 347382, 347386, 347391, 347400, 347416, 347419, 347423, 347435, 347439, 347446, 347457, 347464, 347470, 347478, 347481, 347486, 347495, 347498, 347501, 347507, 347510, 347512, 347519, 347520, 347523, 347535, 347541, 347550, 347554, 347560, 347564, 347572, 347581, 347585, 347590, 347595, 347602, 347616, 347622, 347631, 347636, 347640, 347663, 347672, 347675, 347683, 347687, 347692, 347693, 347697, 347703, 347706, 347713, 347724, 347735, 347737, 347740, 347748, 347750, 347754, 347759, 347767, 347776, 347782, 347792, 347801, 347803, 347810, 347822, 347826, 347830, 347836, 347841, 347847, 347857, 347864, 347871, 347875, 347887, 347909, 347914, 347920, 347922, 347927, 347929, 347931, 347933, 347940, 347941, 347945, 347947, 347949, 347954, 347961, 347967, 347969, 347972, 347981, 347982, 347987, 347995, 348002, 348004, 348012, 348016, 348030, 348035, 348042, 348050, 348054, 348065, 348066, 348073, 348075, 348091, 348096, 348098, 348106, 348107, 348138, 348157, 348161, 348165, 348171, 348181, 348189, 348190, 348193, 348195, 348199, 348203, 348210, 348211, 348220, 348228, 348234, 348237, 348239, 348247, 348257, 348258, 348262, 348267, 348272, 348276, 348282, 348288, 348290, 348305, 348310, 348312, 348324, 348338, 348342, 348345, 348352, 348358, 348363, 348368, 348381, 348390, 348397, 348417, 348430, 348442, 348446, 348450, 348453, 348468, 348473, 348477, 348489, 348490, 348494, 348500, 348515, 348516, 348522, 348527, 348538, 348541, 348546, 348551, 348552, 348558, 348560, 348561, 348574, 348580, 348586, 348587, 348589, 348593, 348595, 348597, 348605, 348606, 348611, 348613, 348617, 348621, 348626, 348630, 348639, 348642, 348645, 348648, 348657, 348660, 348665, 348678, 348681, 348690, 348692, 348696, 348699, 348703, 348705, 348707, 348717, 348722, 348723, 348731, 348734, 348736, 348739, 348741, 348744, 348748, 348749, 348752, 348755, 348757, 348767, 348769, 348779, 348783, 348790, 348793, 348795, 348798, 348806, 348807, 348813, 348818, 348824, 348828, 348829, 348834, 348843, 348847, 348849, 348851, 348858, 348861, 348864, 348869, 348874, 348875, 348876, 348881, 348883, 348884, 348886, 348887, 348894, 348897, 348902, 348905, 348908, 348915, 348919, 348921, 348922, 348926, 348929, 348931, 348944, 348946, 348947, 348951, 348952, 348953, 348957, 348961, 348963, 348970, 348974, 348976, 348979, 348980, 348982, 348985, 348987, 348993, 348995, 348998, 349001, 349002, 349006, 349011, 349016, 349019, 349022, 349026, 349029, 349033, 349035, 349039, 349047, 349048, 349055, 349058, 349062, 349064, 349070, 349073, 349075, 349078, 349082, 349084, 349087, 349090, 349092, 349097, 349098, 349105, 349106, 349111, 349114, 349120, 349128, 349134, 349139, 349146, 349150, 349153, 349160, 349161, 349164, 349167, 349169, 349172, 349179, 349181, 349183, 349186, 349189, 349196, 349198, 349199, 349200, 349207, 349217, 349220, 349222, 349224, 349236, 349237, 349242, 349251, 349252, 349254, 349256, 349257, 349259, 349261, 349264, 349270, 349276, 349282, 349286, 349290, 349295, 349302, 349304, 349306, 349307, 349309, 349310, 349320, 349324, 349325, 349335, 349339, 349342, 349346, 349347, 349350, 349351, 349354, 349361, 349363, 349364, 349366, 349369, 349372, 349376, 349381, 349384, 349386, 349392, 349394, 349397, 349399, 349401, 349405, 349406, 349409, 349410, 349411, 349414, 349416, 349418, 349420, 349424, 349432, 349434, 349436, 349440, 349441, 349444, 349449, 349451, 349453, 349455, 349456, 349458, 349461, 349463, 349468, 349470, 349472, 349473, 349474, 349476, 349477, 349479, 349485, 349489, 349491, 349493, 349494, 349496, 349499, 349501, 349502, 349504, 349511, 349513, 349520, 349522, 349530, 349533, 349537, 349541, 349542, 349544, 349547, 349549, 349553, 349556, 349559, 349570, 349571, 349573, 349575, 349578, 349590, 349604, 349606, 349609, 349612, 349624, 349625, 349628, 349635, 349637, 349639, 349641, 349647, 349649, 349650, 349652, 349655, 349661, 349663, 349675, 349678, 349680, 349682, 349684, 349693, 349696, 349698, 349702, 349704, 349707, 349709, 349711, 349713, 349715, 349719, 349726, 349729, 349732, 349734, 349745, 349746, 349750, 349752, 349753, 349756, 349759, 349769, 349772, 349775, 349776, 349778, 349782, 349784, 349787, 349789, 349790, 349791, 349795, 349798, 349800, 349805, 349807, 349813, 349814, 349819, 349821, 349822, 349823, 349825, 349831, 349835, 349836, 349838, 349846, 349847, 349849, 349853, 349864, 349870, 349876, 349878, 349880, 349892, 349898, 349901, 349907, 349909, 349910, 349926, 349931, 349933, 349942, 349946, 349948, 349955, 349957, 349959, 349962, 349973, 349975, 349977, 349983, 349984, 349985, 349991, 349999, 350001, 350006, 350007, 350010, 350012, 350014, 350017, 350020, 350025, 350028, 350030, 350032, 350034, 350038, 350040, 350046, 350047, 350049, 350051, 350055, 350057, 350059, 350060, 350065, 350068, 350069, 350070, 350072, 350074, 350078, 350080, 350081, 350083, 350085, 350086, 350089, 350091, 350096, 350099, 350102, 350105, 350106, 350110, 350111, 350113, 350116, 350118, 350120, 350123, 350126, 350127, 350133, 350137, 350139, 350141, 350142, 350145, 350152, 350153, 350157, 350160, 350161, 350163, 350169, 350171, 350174, 350187, 350191, 350193, 350197, 350199, 350204, 350206, 350207, 350209, 350210, 350212, 350218, 350219, 350221, 350223, 350225, 350234, 350235, 350240, 350246, 350247, 350249, 350251, 350262, 350265, 350266, 350269, 350279, 350280, 350284, 350287, 350288, 350291, 350299, 350300, 350303, 350304, 350311, 350314, 350316, 350319, 350320, 350326, 350329, 350334, 350341, 350345, 350349, 350353, 350358, 350363, 350365, 350367, 350368, 350372, 350373, 350375, 350377, 350378, 350383, 350388, 350393, 350396, 350402, 350404, 350406, 350412, 350414, 350416, 350421, 350423, 350426, 350429, 350430, 350436, 350438, 350439, 350442, 350444, 350448, 350450, 350453, 350454, 350458, 350461, 350464, 350472, 350476, 350480, 350481, 350487, 350489, 350491, 350493, 350495, 350504, 350506, 350508, 350509, 350511, 350513, 350514, 350521, 350524, 350527, 350536, 350538, 350539, 350543, 350545, 350549, 350552, 350554, 350557, 350569, 350570, 350571, 350575, 350585, 350590, 350591, 350599, 350600, 350603, 350613, 350616, 350619, 350621, 350626, 350627, 350629, 350631, 350637, 350648, 350650, 350665, 350669, 350671, 350806, 350807, 350810, 350811, 350812, 350815, 350817, 350818, 350819, 350827, 350831, 350833, 350834, 350838, 350839, 350843, 350846, 350853, 350857, 350858, 350861, 350862, 350867, 350870, 350873, 350888, 350892, 350895, 350897, 350899, 350908, 350910, 350912, 350913, 350917, 350924, 350926, 350930, 350931, 350934, 350936, 350940, 350944, 350947, 350948, 350952, 350955, 350958, 350960, 350961, 350966, 350968, 350972, 350976, 350982, 350991, 351006, 351012, 351023, 351039, 351051, 351054, 351058, 351071, 351079, 351085, 351088, 351091, 351106, 351110, 351150, 351155, 351161, 351192, 351194, 351205, 351220, 351224, 351230, 351231, 351240, 351251, 351257, 351271, 351272, 351280, 351291, 351292, 351305, 351318, 351338, 351341, 351357, 351359, 351369, 351374, 351381, 351383, 351384, 351390, 351398, 351403, 351406, 351409, 351414, 351431, 351448, 351485, 351537, 351553, 351564, 351588, 351593, 351610, 351611, 351612, 351624, 351640, 351645, 351673, 351679, 351717, 351759, 351784, 351785, 351812, 351817, 351835, 351846, 351865, 351890, 351907, 351912, 351919, 351928, 351936, 351964, 351965, 351995, 352007, 352022, 352028, 352031, 352034, 352037, 352050, 352057, 352080, 352104, 352108, 352125, 352132, 352140, 352143, 352160, 352169, 352172, 352189, 352219, 352227, 352237, 352248, 352252, 352260, 352263, 352265, 352278, 352317, 352327, 352334, 352346, 352354, 352376, 352382, 352390, 352392, 352411, 352421, 352440, 352460, 352483, 352490, 352508, 352528, 352548, 352553, 352574, 352576, 352600, 352631, 352640, 352662, 352676, 352688, 352700, 352704, 352707, 352719, 352729, 352748, 352751, 352766, 352771, 352783, 352796, 352821, 352829, 352850, 352852, 352861, 352883, 352884, 352896, 352905, 352948, 352959, 352973, 352974, 352988, 353009, 353016, 353034, 353065, 353079, 353085, 353098, 353107, 353114, 353132, 353135, 353141, 353145, 353167, 353190, 353204, 353229, 353248, 353258, 353261, 353269, 353283, 353285, 353312, 353316, 353329, 353344, 353345, 353349, 353363, 353366, 353377, 353382, 353401, 353422, 353438, 353441, 353467, 353485, 353494, 353501, 353515, 353529, 353536, 353564, 353566, 353575, 353584, 353588, 353599, 353602, 353613, 353634, 353649, 353665, 353677, 353686, 353691, 353705, 353714, 353726, 353737, 353758, 353776, 353790, 353800, 353805, 353825, 353839, 353850, 353870, 353876, 353880, 353909, 353916, 353922, 353931, 353941, 353966, 353987, 353989, 354001, 354010, 354021, 354031, 354038, 354069, 354089, 354094, 354099, 354112, 354119, 354125, 354133, 354147, 354148, 354157, 354159, 354170, 354183, 354188, 354203, 354207, 354209, 354219, 354239, 354242, 354251, 354264, 354277, 354288, 354346, 354363, 354371, 354377, 354392, 354397, 354412, 354418, 354432, 354439, 354442, 354448, 354478, 354492, 354498, 354510, 354513, 354531, 354551, 354562, 354582, 354588, 354601, 354613, 354639, 354647, 354658, 354663, 354670, 354682, 354695, 354703, 354709, 354731, 354734, 354759, 354810, 354828, 354835, 354842, 354845, 354860, 354871, 354873, 354884, 354889, 354898, 354906, 354924, 354927, 354943, 354954, 354958, 354972, 354990, 355007, 355015, 355022, 355023, 355032, 355065, 355071, 355088, 355095, 355096, 355105, 355106, 355112, 355124, 355144, 355152, 355163, 355168, 355178, 355188, 355197, 355206, 355210, 355215, 355219, 355238, 355258, 355268, 355274, 355291, 355306, 355318, 355328, 355334, 355349, 355358, 355367, 355383, 355384, 355389, 355397, 355406, 355409, 355412, 355415, 355417, 355420, 355423, 355430, 355439, 355455, 355459, 355464, 355472, 355482, 355484, 355486, 355492, 355497, 355512, 355514, 355527, 355537, 355545, 355557, 355561, 355573, 355576, 355580, 355581, 355589, 355600, 355602, 355610, 355613, 355622, 355629, 355650, 355656, 355658, 355670, 355684, 355689, 355694, 355729, 355732, 355734, 355735, 355749, 355754, 355766, 355771, 355785, 355802, 355812, 355819, 355825, 355828, 355835, 355840, 355853, 355858, 355883, 355899, 355908, 355918, 355919, 355925, 355934, 355948, 355961, 355966, 355993, 355997, 356018, 356026, 356032, 356050, 356091, 356117, 356136, 356151, 356158, 356170, 356174, 356191, 356198, 356211, 356257, 356264, 356270, 356272, 356286, 356317, 356321, 356326, 356333, 356346, 356355, 356356, 356361, 356374, 356377, 356383, 356391, 356414, 356425, 356444, 356456, 356461, 356472, 356477, 356478, 356489, 356494, 356503, 356534, 356540, 356584, 356606, 356607, 356628, 356634, 356657, 356666, 356669, 356682, 356684, 356696, 356712, 356727, 356730, 356739, 356745, 356750, 356763, 356768, 356787, 356796, 356805, 356845, 356849, 356859, 356877, 356883, 356890, 356900, 356916, 356919, 356930, 356945, 356976, 356978, 357003, 357008, 357038, 357042, 357045, 357060, 357074, 357079, 357086, 357096, 357098, 357114, 357117, 357118, 357127, 357136, 357152, 357173, 357182, 357191, 357198, 357199, 357207, 357215, 357228, 357235, 357246, 357247, 357251, 357272, 357286, 357287, 357300, 357313, 357318, 357327, 357331, 357335, 357344, 357348, 357350, 357353, 357364, 357377, 357402, 357405, 357412, 357413, 357424, 357428, 357436, 357449, 357458, 357467, 357475, 357485, 357494, 357496, 357504, 357513, 357522, 357523, 357531, 357542, 357544, 357560, 357576, 357579, 357588, 357606, 357610, 357625, 357637, 357643, 357651, 357656, 357665, 357680, 357694, 357707, 357715, 357721, 357723, 357746, 357757, 357758, 357777, 357779, 357781, 357794, 357798, 357807, 357813, 357815, 357831, 357842, 357857, 357859, 357873, 357886, 357898, 357904, 357912, 357920, 357937, 357951, 357955, 357965, 357974, 357988, 357997, 357999, 358007, 358021, 358032, 358039, 358041, 358060, 358075, 358097, 358111, 358113, 358136, 358144, 358148, 358171, 358189, 358201, 358210, 358217, 358218, 358222, 358238, 358241, 358249, 358253, 358264, 358266, 358274, 358292, 358295, 358303, 358311, 358314, 358347, 358349, 358357, 358360, 358372, 358380, 358397, 358404, 358410, 358418, 358434, 358438, 358447, 358463, 358480, 358492, 358499, 358507, 358514, 358521, 358534, 358558, 358562, 358567, 358570, 358575, 358585, 358599, 358605, 358611, 358616, 358626, 358639, 358651, 358677, 358688, 358696, 358703, 358715, 358717, 358733, 358740, 358748, 358753, 358757, 358768, 358772, 358787, 358790, 358800, 358814, 358819, 358825, 358829, 358830, 358834, 358838, 358856, 358866, 358869, 358882, 358886, 358900, 358903, 358918, 358922, 358925, 358936, 358937, 358941, 358943, 358955, 358963, 358977, 358981, 358986, 358992, 358999, 359001, 359010, 359022, 359034, 359035, 359048, 359050, 359052, 359066, 359068, 359073, 359097, 359099, 359103, 359118, 359121, 359130, 359132, 359144, 359155, 359158, 359163, 359171, 359183, 359193, 359203, 359206, 359209, 359218, 359222, 359227, 359228, 359232, 359236, 359241, 359244, 359257, 359266, 359271, 359277, 359279, 359286, 359296, 359307, 359310, 359318, 359326, 359328, 359337, 359338, 359344, 359350, 359356, 359361, 359366, 359374, 359375, 359378, 359388, 359395, 359404, 359405, 359411, 359419, 359423, 359424, 359431, 359436, 359446, 359456, 359465, 359466, 359472, 359476, 359487, 359492, 359499, 359512, 359517, 359535, 359543, 359544, 359549, 359561, 359572, 359584, 359590, 359597, 359603, 359622, 359625, 359628, 359641, 359644, 359652, 359663, 359664, 359674, 359689, 359696, 359705, 359708, 359720, 359723, 359730, 359738, 359749, 359757, 359763, 359776, 359802, 359829, 359834, 359838, 359844, 359854, 359864, 359869, 359873, 359875, 359883, 359896, 359898, 359908, 359911, 359917, 359925, 359930, 359937, 359947, 359954, 359955, 359973, 359978, 359981, 359985, 359990, 360006, 360017, 360025, 360028, 360039, 360044, 360047, 360049, 360056, 360069, 360073, 360084, 360088, 360098, 360103, 360106, 360110, 360135, 360145, 360150, 360153, 360159, 360164, 360177, 360178, 360182, 360187, 360192, 360195, 360208, 360212, 360213, 360222, 360224, 360230, 360234, 360264, 360267, 360273, 360277, 360284, 360287, 360288, 360293, 360301, 360325, 360335, 360338, 360342, 360345, 360357, 360362, 360372, 360383, 360403, 360424, 360433, 360441, 360468, 360472, 360480, 360483, 360496, 360504, 360511, 360516, 360535, 360543, 360555, 360560, 360570, 360573, 360578, 360581, 360583, 360590, 360597, 360603, 360614, 360620, 360624, 360630, 360634, 360635, 360642, 360650, 360653, 360654, 360667, 360673, 360689, 360711, 360712, 360718, 360723, 360724, 360739, 360759, 360767, 360780, 360782, 360795, 360802, 360815, 360827, 360843, 360855, 360860, 360863, 360873, 360892, 360897, 360909, 360923, 360939, 360940, 360945, 360963, 360975, 360988, 361009, 361012, 361025, 361029, 361042, 361046, 361057, 361075, 361083, 361088, 361096, 361099, 361109, 361120, 361133, 361154, 361168, 361193, 361205, 361223, 361254, 361257, 361263, 361282, 361292, 361302, 361312, 361323, 361324, 361343, 361354, 361356, 361365, 361369, 361383, 361386, 361398, 361427, 361431, 361436, 361469, 361478, 361482, 361490, 361510, 361519, 361536, 361560, 361572, 361587, 361602, 361613, 361617, 361627, 361633, 361646, 361655, 361657, 361676, 361685, 361687, 361711, 361712, 361723, 361747, 361760, 361765, 361776, 361787, 361790, 361801, 361814, 361861, 361870, 361889, 361902, 361909, 361913, 361923, 361936, 361958, 361973, 361974, 362006, 362048, 362071, 362077, 362098, 362106, 362113, 362125, 362133, 362141, 362153, 362157, 362173, 362183, 362200, 362212, 362214, 362226, 362235, 362245, 362268, 362285, 362309, 362318, 362325, 362338, 362348, 362349, 362393, 362401, 362415, 362425, 362433, 362442, 362449, 362454, 362477, 362494, 362495, 362512, 362533, 362539, 362542, 362552, 362558, 362574, 362582, 362593, 362606, 362623, 362631, 362639, 362643, 362679, 362680, 362691, 362708, 362712, 362717, 362723, 362725, 362746, 362758, 362775, 362785, 362787, 362793, 362808, 362823, 362828, 362844, 362855, 362873, 362903, 362905, 362921, 362925, 362941, 362942, 362957, 362977, 362994, 363007, 363010, 363018, 363027, 363028, 363039, 363050, 363060, 363066, 363076, 363089, 363090, 363098, 363101, 363132, 363137, 363148, 363158, 363173, 363181, 363187, 363196, 363227, 363238, 363239, 363242, 363251, 363257, 363261, 363274, 363286, 363306, 363326, 363365, 363378, 363388, 363390, 363402, 363444, 363464, 363468, 363480, 363485, 363495, 363509, 363512, 363522, 363529, 363538, 363550, 363557, 363569, 363581, 363582, 363586, 363590, 363605, 363608, 363621, 363647, 363649, 363654, 363669, 363673, 363696, 363703, 363727, 363742, 363754, 363757, 363763, 363767, 363785, 363800, 363833, 363839, 363846, 363852, 363853, 363861, 363904, 363913, 363916, 363925, 363934, 363936, 363943, 363949, 363954, 363978, 363988, 363991, 363998, 364018, 364022, 364025, 364038, 364039, 364046, 364063, 364081, 364082, 364104, 364107, 364126, 364147, 364155, 364168, 364221, 364226, 364241, 364249, 364254, 364260, 364270, 364271, 364281, 364291, 364298, 364309, 364310, 364347, 364354, 364372, 364389, 364399, 364414, 364433, 364442, 364451, 364461, 364462, 364471, 364483, 364490, 364499, 364512, 364531, 364539, 364569, 364584, 364594, 364606, 364631, 364632, 364638, 364643, 364680, 364700, 364716, 364752, 364755, 364791, 364799, 364806, 364812, 364846, 364852, 364860, 364864, 364882, 364913, 364947, 364983, 364999, 365027, 365058, 365087, 365101, 365108, 365115, 365121, 365143, 365171, 365174, 365188, 365195, 365216, 365232, 365238, 365244, 365260, 365265, 365275, 365295, 365321, 365324, 365334, 365345, 365356, 365366, 365384, 365391, 365394, 365402, 365405, 365409, 365433, 365445, 365456, 365467, 365474, 365524, 365545, 365554, 365562, 365566, 365572, 365583, 365590, 365595, 365600, 365604, 365618, 365623, 365631, 365650, 365669, 365679, 365707, 365708, 365715, 365738, 365763, 365784, 365796, 365802, 365806, 365827, 365840, 365906, 365933, 365948, 365967, 365981, 366010, 366022, 366036, 366059, 366070, 366077, 366080, 366099, 366104, 366118, 366129, 366139, 366170, 366184, 366192, 366230, 366250, 366258, 366259, 366267, 366273, 366285, 366292, 366294, 366322, 366341, 366344, 366365, 366393, 366412, 366418, 366422, 366436, 366474, 366484, 366495, 366501, 366521, 366523, 366545, 366558, 366589, 366606, 366621, 366630, 366640, 366661, 366672, 366685, 366686, 366704, 366717, 366719, 366720, 366730, 366733, 366746, 366748, 366755, 366759, 366767, 366778, 366798, 366818, 366820, 366828, 366841, 366856, 366868, 366879, 366884, 366898, 366915, 366922, 366925, 366943, 366944, 366961, 366978, 366983, 366995, 367010, 367018, 367047, 367067, 367079, 367084, 367085, 367091, 367105, 367113, 367167, 367186, 367192, 367205, 367211, 367217, 367231, 367238, 367248, 367263, 367282, 367312, 367323, 367325, 367342, 367351, 367362, 367388, 367429, 367438, 367453, 367462, 367471, 367488, 367489, 367501, 367517, 367522, 367537, 367558, 367565, 367569, 367582, 367592, 367632, 367645, 367656, 367666, 367674, 367690, 367699, 367706, 367729, 367737, 367738, 367748, 367753, 367763, 367765, 367773, 367784, 367808, 367838, 367855, 367863, 367873, 367879, 367909, 367916, 367922, 367932, 367945, 367946, 367954, 367964, 367965, 367976, 367999, 368001, 368041, 368051, 368061, 368071, 368085, 368097, 368113, 368117, 368131, 368152, 368156, 368170, 368171, 368172, 368181, 368192, 368207, 368214, 368218, 368228, 368233, 368256, 368273, 368294, 368299, 368308, 368335, 368345, 368353, 368361, 368378, 368384, 368390, 368399, 368412, 368416, 368421, 368430, 368437, 368450, 368455, 368469, 368472, 368485, 368488, 368495, 368508, 368534, 368542, 368549, 368558, 368583, 368597, 368613, 368655, 368675, 368686, 368692, 368721, 368722, 368739, 368743, 368765, 368793, 368794, 368808, 368811, 368823, 368825, 368837, 368854, 368874, 368875, 368884, 368889, 368902, 368906, 368912, 368921, 368927, 368933, 368946, 368948, 368954, 369015, 369022, 369036, 369060, 369122, 369127, 369136, 369180, 369207, 369215, 369245, 369255, 369268, 369274, 369279, 369287, 369298, 369302, 369317, 369326, 369330, 369334, 369369, 369374, 369390, 369400, 369407, 369430, 369448, 369451, 369477, 369484, 369490, 369491, 369503, 369505, 369518, 369526, 369530, 369552, 369556, 369560, 369581, 369591, 369608, 369645, 369651, 369670, 369676, 369678, 369683, 369694, 369705, 369716, 369731, 369742, 369752, 369764, 369778, 369797, 369798, 369813, 369819, 369838, 369843, 369858, 369860, 369862, 369877, 369878, 369887, 369892, 369904, 369906, 369914, 369932, 369939, 369946, 369948, 369955, 369960, 369971, 369972, 370004, 370006, 370014, 370016, 370020, 370023, 370043, 370051, 370074, 370083, 370088, 370096, 370120, 370131, 370141, 370145, 370147, 370169, 370178, 370179, 370182, 370187, 370189, 370216, 370223, 370228, 370241, 370251, 370277, 370287, 370307, 370328, 370334, 370339, 370345, 370347, 370373, 370383, 370399, 370420, 370428, 370445, 370473, 370484, 370489, 370499, 370511, 370522, 370533, 370536, 370539, 370544, 370554, 370589, 370603, 370614, 370617, 370649, 370657, 370663, 370679, 370694, 370701, 370710, 370734, 370741, 370747, 370751, 370770, 370779, 370791, 370809, 370815, 370843, 370872, 370878, 370880, 370894, 370914, 370940, 370941, 370953, 370955, 370970, 370972, 370983, 370989, 371006, 371012, 371033, 371037, 371041, 371050, 371065, 371066, 371076, 371081, 371089, 371093, 371113, 371118, 371124, 371136, 371155, 371161, 371173, 371175, 371186, 371187, 371197, 371201, 371219, 371230, 371237, 371250, 371253, 371267, 371286, 371304, 371309, 371312, 371342, 371343, 371347, 371371, 371372, 371379, 371388, 371397, 371403, 371411, 371430, 371458, 371483, 371500, 371504, 371511, 371512, 371530, 371536, 371547, 371551, 371560, 371572, 371585, 371599, 371610, 371617, 371619, 371635, 371652, 371659, 371661, 371666, 371671, 371684, 371691, 371706, 371724, 371726, 371737, 371748, 371765, 371777, 371802, 371805, 371828, 371832, 371838, 371856, 371857, 371861, 371877, 371890, 371901, 371914, 371920, 371936, 371957, 371973, 371974, 371975, 371991, 371997, 372001, 372010, 372017, 372024, 372059, 372073, 372076, 372087, 372095, 372125, 372129, 372131, 372132, 372140, 372150, 372159, 372167, 372174, 372182, 372189, 372197, 372207, 372225, 372233, 372243, 372252, 372253, 372263, 372268, 372275, 372278, 372294, 372308, 372311, 372324, 372329, 372341, 372347, 372397, 372409, 372419, 372420, 372432, 372457, 372464, 372476, 372477, 372490, 372498, 372512, 372533, 372536, 372548, 372560, 372567, 372570, 372578, 372583, 372595, 372605, 372618, 372622, 372631, 372646, 372651, 372657, 372665, 372677, 372691, 372713, 372727, 372744, 372749, 372802, 372806, 372822, 372831, 372839, 372843, 372848, 372865, 372867, 372934, 372946, 372968, 372972, 372988, 372997, 373015, 373035, 373069, 373078, 373083, 373090, 373096, 373103, 373115, 373125, 373138, 373146, 373149, 373164, 373165, 373170, 373184, 373206, 373216, 373218, 373230, 373236, 373246, 373249, 373258, 373261, 373276, 373293, 373298, 373313, 373322, 373328, 373333, 373344, 373346, 373356, 373367, 373368, 373382, 373384, 373389, 373394, 373414, 373428, 373431, 373438, 373450, 373458, 373485, 373509, 373510, 373523, 373527, 373530, 373544, 373556, 373567, 373596, 373597, 373603, 373610, 373624, 373647, 373655, 373659, 373667, 373671, 373704, 373726, 373751, 373756, 373767, 373777, 373785, 373788, 373791, 373800, 373807, 373810, 373820, 373837, 373846, 373853, 373858, 373870, 373871, 373881, 373894, 373904, 373907, 373910, 373927, 373934, 373937, 373941, 373953, 373968, 374025, 374028, 374043, 374051, 374053, 374072, 374094, 374098, 374102, 374115, 374127, 374149, 374164, 374167, 374175, 374191, 374204, 374214, 374219, 374228, 374235, 374251, 374274, 374276, 374279, 374290, 374297, 374306, 374309, 374318, 374329, 374338, 374355, 374357, 374367, 374376, 374384, 374402, 374403, 374420, 374437, 374438, 374447, 374450, 374459, 374470, 374474, 374479, 374484, 374495, 374513, 374527, 374543, 374562, 374568, 374574, 374581, 374587, 374593, 374605, 374632, 374642, 374644, 374650, 374659, 374667, 374678, 374692, 374695, 374720, 374730, 374748, 374762, 374764, 374768, 374779, 374784, 374813, 374814, 374832, 374839, 374844, 374859, 374873, 374879, 374890, 374901, 374925, 374941, 374945, 374960, 374963, 374979, 374986, 374994, 374998, 375004, 375022, 375029, 375034, 375041, 375043, 375056, 375067, 375116, 375127, 375133, 375154, 375179, 375193, 375212, 375219, 375224, 375233, 375235, 375241, 375247, 375259, 375262, 375270, 375273, 375289, 375311, 375348, 375353, 375365, 375376, 375381, 375383, 375394, 375413, 375426, 375446, 375455, 375474, 375477, 375501, 375508, 375522, 375523, 375530, 375538, 375546, 375551, 375556, 375564, 375588, 375596, 375599, 375605, 375609, 375617, 375621, 375634, 375638, 375660, 375670, 375695, 375718, 375733, 375737, 375741, 375756, 375765, 375784, 375786, 375795, 375797, 375802, 375811, 375817, 375824, 375825, 375832, 375848, 375852, 375858, 375870, 375878, 375881, 375896, 375910, 375915, 375924, 375932, 375937, 375970, 375974, 375980, 375984, 375990, 375998, 376001, 376007, 376028, 376034, 376038, 376057, 376077, 376088, 376095, 376118, 376129, 376161, 376175, 376179, 376182, 376186, 376203, 376206, 376233, 376250, 376254, 376260, 376278, 376282, 376286, 376289, 376295, 376302, 376334, 376339, 376344, 376360, 376378, 376386, 376406, 376408, 376418, 376420, 376460, 376465, 376479, 376496, 376506, 376522, 376529, 376534, 376535, 376550, 376562, 376568, 376571, 376591, 376620, 376626, 376634, 376647, 376652, 376668, 376679, 376681, 376738, 376745, 376757, 376759, 376779, 376796, 376805, 376808, 376814, 376825, 376852, 376876, 376880, 376894, 376910, 376929, 376934, 376936, 376954, 376955, 376976, 376985, 376991, 377010, 377036, 377040, 377049, 377061, 377070, 377084, 377108, 377150, 377167, 377195, 377211, 377221, 377229, 377244, 377245, 377248, 377249, 377258, 377277, 377298, 377309, 377315, 377325, 377335, 377357, 377371, 377373, 377378, 377394, 377424, 377436, 377453, 377459, 377460, 377480, 377496, 377504, 377507, 377524, 377548, 377559, 377568, 377569, 377587, 377593, 377594, 377598, 377601, 377602, 377606, 377609, 377628, 377637, 377646, 377649, 377662, 377674, 377681, 377701, 377716, 377726, 377733, 377743, 377763, 377788, 377805, 377812, 377822, 377835, 377844, 377852, 377853, 377854, 377859, 377865, 377880, 377896, 377903, 377908, 377920, 377946, 377949, 377951, 377967, 377969, 377976, 378006, 378010, 378019, 378022, 378026, 378041, 378052, 378055, 378067, 378079, 378091, 378092, 378104, 378119, 378123, 378135, 378152, 378178, 378198, 378199, 378217, 378222, 378236, 378266, 378267, 378278, 378279, 378304, 378308, 378339, 378344, 378345, 378369, 378374, 378384, 378386, 378394, 378400, 378417, 378423, 378430, 378431, 378440, 378465, 378467, 378486, 378505, 378512, 378524, 378525, 378543, 378546, 378563, 378565, 378571, 378583, 378584, 378585, 378591, 378594, 378604, 378607, 378622, 378627, 378630, 378647, 378661, 378669, 378674, 378686, 378701, 378714, 378716, 378722, 378729, 378736, 378739, 378747, 378762, 378787, 378800, 378801, 378816, 378823, 378833, 378883, 378893, 378898, 378921, 378926, 378951, 378969, 378970, 378972, 378983, 378991, 378999, 379018, 379026, 379031, 379045, 379048, 379064, 379068, 379089, 379097, 379116, 379123, 379133, 379142, 379149, 379151, 379172, 379183, 379185, 379200, 379203, 379226, 379252, 379260, 379269, 379279, 379286, 379298, 379306, 379315, 379328, 379336, 379342, 379351, 379356, 379361, 379365, 379370, 379371, 379384, 379389, 379395, 379413, 379437, 379440, 379441, 379470, 379476, 379500, 379510, 379514, 379524, 379531, 379548, 379556, 379574, 379581, 379586, 379602, 379615, 379616, 379621, 379626, 379632, 379633, 379651, 379663, 379679, 379685, 379726, 379732, 379736, 379739, 379745, 379748, 379787, 379801, 379831, 379832, 379850, 379857, 379864, 379907, 379914, 379931, 379934, 379935, 379942, 379949, 379952, 379960, 379968, 379972, 379987, 380000, 380017, 380024, 380031, 380037, 380038, 380047, 380049, 380060, 380065, 380072, 380099, 380106, 380118, 380129, 380135, 380138, 380149, 380156, 380159, 380172, 380184, 380204, 380214, 380221, 380225, 380238, 380256, 380257, 380281, 380294, 380297, 380305, 380310, 380328, 380331, 380353, 380365, 380367, 380368, 380394, 380414, 380426, 380433, 380439, 380454, 380458, 380487, 380489, 380493, 380513, 380515, 380524, 380541, 380551, 380586, 380628, 380629, 380643, 380656, 380663, 380704, 380707, 380726, 380728, 380744, 380746, 380753, 380759, 380765, 380785, 380807, 380825, 380827, 380835, 380842, 380860, 380869, 380879, 380888, 380896, 380911, 380922, 380923, 380942, 380971, 380974, 380981, 380983, 381014, 381025, 381032, 381042, 381047, 381058, 381089, 381108, 381110, 381116, 381123, 381129, 381137, 381154, 381160, 381168, 381197, 381199, 381217, 381254, 381260, 381270, 381274, 381296, 381304, 381307, 381317, 381336, 381342, 381352, 381366, 381379, 381395, 381399, 381401, 381414, 381422, 381432, 381436, 381458, 381459, 381464, 381475, 381476, 381477, 381482, 381495, 381509, 381531, 381532, 381538, 381562, 381566, 381579, 381587, 381608, 381626, 381642, 381657, 381669, 381693, 381700, 381726, 381734, 381747, 381757, 381765, 381800, 381824, 381835, 381846, 381853, 381861, 381863, 381869, 381874, 381882, 381883, 381892, 381893, 381900, 381908, 381912, 381920, 381923, 381927, 381943, 381951, 381973, 381985, 381988, 381995, 381997, 382016, 382040, 382046, 382053, 382088, 382092, 382113, 382128, 382134, 382143, 382151, 382162, 382165, 382172, 382182, 382201, 382222, 382223, 382246, 382255, 382273, 382281, 382288, 382307, 382334, 382346, 382352, 382362, 382373, 382383, 382384, 382415, 382423, 382425, 382447, 382450, 382458, 382469, 382487, 382493, 382494, 382503, 382512, 382517, 382536, 382562, 382565, 382571, 382580, 382607, 382623, 382639, 382665, 382668, 382681, 382689, 382695, 382709, 382718, 382727, 382747, 382750, 382795, 382802, 382817, 382824, 382834, 382837, 382853, 382856, 382875, 382879, 382901, 382906, 382911, 382914, 382938, 382939, 382956, 382970, 382989, 383001, 383023, 383037, 383102, 383104, 383108, 383115, 383123, 383125, 383134, 383146, 383147, 383168, 383177, 383195, 383228, 383241, 383248, 383255, 383257, 383265, 383293, 383296, 383302, 383307, 383310, 383334, 383340, 383359, 383360, 383373, 383384, 383385, 383390, 383398, 383441, 383451, 383465, 383467, 383469, 383493, 383497, 383603, 383605, 383627, 383643, 383645, 383683, 383696, 383702, 383706, 383733, 383738, 383746, 383772, 383788, 383793, 383803, 383822, 383839, 383849, 383885, 383894, 383900, 383922, 383939, 383956, 383992, 384000, 384034, 384048, 384078, 384085, 384101, 384109, 384127, 384131, 384155, 384198, 384233, 384243, 384247, 384264, 384277, 384291, 384359, 384360, 384377, 384397, 384416, 384424, 384449, 384459, 384462, 384467, 384484, 384495, 384514, 384515, 384524, 384551, 384552, 384624, 384635, 384662, 384712, 384731, 384743, 384749, 384783, 384820, 384835, 384852, 384859, 384883, 384910, 384932, 384996, 385007, 385027, 385028, 385042, 385053, 385060, 385062, 385071, 385093, 385127, 385138, 385150, 385167, 385223, 385225, 385260, 385266, 385285, 385299, 385311, 385319, 385330, 385349, 385364, 385382, 385391, 385418, 385432, 385433, 385450, 385456, 385479, 385484, 385488, 385490, 385495, 385497, 385505, 385516, 385527, 385535, 385543, 385556, 385557, 385559, 385570, 385576, 385599, 385609, 385612, 385621, 385624, 385635, 385640, 385644, 385647, 385662, 385674, 385676, 385706, 385707, 385719, 385737, 385753, 385756, 385763, 385766, 385768, 385773, 385784, 385788, 385796, 385810, 385812, 385832, 385845, 385846, 385869, 385873, 385884, 385889, 385901, 385917, 385931, 385941, 385950, 385982, 385990, 385996, 386010, 386041, 386047, 386057, 386058, 386081, 386103, 386118, 386124, 386130, 386135, 386139, 386147, 386160, 386182, 386187, 386193, 386209, 386240, 386258, 386276, 386277, 386292, 386310, 386318, 386328, 386333, 386355, 386363, 386366, 386385, 386400, 386408, 386422, 386435, 386454, 386465, 386474, 386477, 386483, 386494, 386506, 386517, 386529, 386538, 386546, 386554, 386565, 386598, 386610, 386624, 386631, 386635, 386639, 386647, 386656, 386661, 386668, 386680, 386683, 386697, 386717, 386719, 386724, 386729, 386740, 386747, 386750, 386770, 386771, 386776, 386782, 386788, 386791, 386798, 386806, 386820, 386829, 386845, 386846, 386864, 386865, 386869, 386877, 386879, 386885, 386900, 386903, 386910, 386919, 386948, 386952, 386960, 386970, 386981, 386992, 387005, 387018, 387041, 387044, 387060, 387072, 387079, 387114, 387130, 387136, 387150, 387155, 387156, 387162, 387181, 387193, 387205, 387214, 387220, 387224, 387228, 387244, 387250, 387260, 387265, 387296, 387305, 387311, 387317, 387333, 387338, 387345, 387352, 387363, 387368, 387380, 387381, 387396, 387404, 387414, 387427, 387444, 387451, 387476, 387477, 387483, 387490, 387499, 387501, 387502, 387513, 387522, 387530, 387533, 387543, 387557, 387562, 387566, 387573, 387596, 387643, 387662, 387667, 387673, 387693, 387718, 387738, 387755, 387767, 387768, 387784, 387791, 387816, 387828, 387832, 387842, 387851, 387889, 387896, 387912, 387916, 387920, 387926, 387935, 387936, 387958, 387971, 387982, 387985, 388002, 388015, 388039, 388051, 388089, 388099, 388105, 388107, 388112, 388117, 388128, 388140, 388150, 388155, 388159, 388165, 388174, 388195, 388204, 388212, 388218, 388220, 388224, 388226, 388236, 388244, 388263, 388267, 388297, 388301, 388319, 388325, 388347, 388371, 388405, 388470, 388495, 388501, 388509, 388513, 388524, 388527, 388535, 388557, 388561, 388575, 388577, 388588, 388604, 388609, 388611, 388631, 388635, 388641, 388660, 388669, 388677, 388680, 388691, 388697, 388700, 388710, 388717, 388732, 388756, 388759, 388771, 388803, 388815, 388822, 388823, 388827, 388841, 388851, 388853, 388860, 388861, 388877, 388885, 388891, 388901, 388913, 388922, 388928, 388939, 388971, 388979, 388986, 388988, 389006, 389019, 389035, 389038, 389052, 389064, 389096, 389106, 389127, 389132, 389145, 389150, 389160, 389164, 389165, 389174, 389179, 389188, 389209, 389233, 389256, 389266, 389274, 389276, 389283, 389302, 389321, 389325, 389351, 389371, 389385, 389413, 389417, 389427, 389430, 389437, 389444, 389453, 389465, 389468, 389472, 389477, 389490, 389492, 389502, 389515, 389521, 389534, 389535, 389552, 389558, 389570, 389572, 389580, 389590, 389597, 389603, 389619, 389621, 389631, 389634, 389638, 389645, 389648, 389655, 389656, 389665, 389666, 389668, 389673, 389688, 389693, 389708, 389717, 389719, 389729, 389750, 389760, 389771, 389782, 389785, 389786, 389793, 389813, 389822, 389827, 389833, 389837, 389884, 389921, 389930, 389938, 389974, 389976, 389990, 390005, 390032, 390035, 390049, 390055, 390084, 390103, 390111, 390113, 390119, 390175, 390202, 390207, 390235, 390282, 390310, 390312, 390352, 390362, 390368, 390378, 390386, 390411, 390416, 390442, 390451, 390474, 390483, 390496, 390516, 390543, 390544, 390548, 390554, 390559, 390568, 390569, 390576, 390593, 390613, 390636, 390640, 390648, 390656, 390665, 390681, 390696, 390712, 390743, 390761, 390770, 390772, 390800, 390804, 390821, 390830, 390835, 390840, 390853, 390861, 390896, 390900, 390905, 390909, 390937, 390942, 390943, 390958, 390966, 390979, 390993, 391024, 391035, 391044, 391077, 391094, 391098, 391121, 391154, 391168, 391231, 391246, 391255, 391260, 391272, 391275, 391282, 391301, 391311, 391318, 391343, 391348, 391359, 391394, 391398, 391414, 391468, 391503, 391572, 391580, 391583, 391605, 391627, 391651, 391678, 391721, 391746, 391749, 391758, 391772, 391781, 391794, 391827, 391834, 391843, 391878, 391879, 391882, 391898, 391900, 391907, 391921, 391928, 391948, 391958, 391980, 392005, 392024, 392035, 392056, 392063, 392105, 392124, 392142, 392157, 392176, 392178, 392183, 392195, 392202, 392207, 392212, 392216, 392238, 392261, 392268, 392274, 392281, 392295, 392300, 392304, 392320, 392351, 392365, 392371, 392381, 392393, 392395, 392405, 392421, 392453, 392467, 392477, 392515, 392519, 392539, 392554, 392559, 392604, 392605, 392621, 392624, 392655, 392674, 392680, 392694, 392706, 392726, 392736, 392747, 392758, 392760, 392770, 392775, 392788, 392813, 392823, 392849, 392858, 392879, 392881, 392886, 392909, 392927, 392946, 392951, 392958, 392977, 392984, 392998, 393012, 393027, 393031, 393046, 393047, 393058, 393067, 393076, 393085, 393094, 393107, 393132, 393135, 393152, 393168, 393170, 393183, 393186, 393213, 393218, 393231, 393234, 393244, 393264, 393268, 393293, 393294, 393353, 393357, 393362, 393363, 393374, 393377, 393391, 393399, 393422, 393454, 393456, 393468, 393477, 393486, 393510, 393525, 393528, 393541, 393558, 393564, 393592, 393611, 393632, 393643, 393650, 393653, 393673, 393680, 393697, 393706, 393712, 393720, 393738, 393745, 393752, 393767, 393810, 393813, 393833, 393857, 393880, 393885, 393896, 393903, 393911, 393922, 393923, 393945, 393948, 393963, 393974, 393983, 393991, 394026, 394039, 394051, 394064, 394073, 394101, 394109, 394130, 394144, 394171, 394178, 394195, 394204, 394218, 394259, 394283, 394298, 394309, 394322, 394362, 394395, 394399, 394418, 394424, 394440, 394463, 394472, 394478, 394488, 394496, 394497, 394515, 394517, 394529, 394532, 394539, 394556, 394560, 394568, 394595, 394598, 394604, 394606, 394637, 394642, 394654, 394665, 394668, 394673, 394693, 394695, 394705, 394717, 394721, 394731, 394733, 394745, 394752, 394764, 394789, 394802, 394842, 394881, 394901, 394902, 394903, 394914, 394918, 394928, 394940, 394945, 394950, 394956, 394974, 394977, 394978, 394991, 395017, 395022, 395024, 395035, 395038, 395046, 395053, 395061, 395073, 395075, 395103, 395114, 395116, 395131, 395147, 395157, 395177, 395180, 395196, 395208, 395224, 395225, 395251, 395263, 395289, 395322, 395329, 395336, 395352, 395363, 395367, 395380, 395382, 395418, 395428, 395432, 395438, 395462, 395467, 395472, 395479, 395507, 395522, 395524, 395535, 395541, 395552, 395561, 395581, 395597, 395613, 395620, 395634, 395660, 395681, 395683, 395695, 395704, 395707, 395769, 395772, 395803, 395849, 395859, 395865, 395872, 395884, 395892, 395908, 395912, 395917, 395923, 395956, 395957, 395966, 395972, 395978, 395989, 396001, 396014, 396017, 396020, 396026, 396035, 396043, 396055, 396060, 396071, 396087, 396090, 396108, 396112, 396116, 396126, 396145, 396147, 396169, 396180, 396183, 396199, 396209, 396232, 396291, 396325, 396326, 396327, 396336, 396352, 396357, 396370, 396372, 396394, 396416, 396420, 396426, 396436, 396449, 396456, 396462, 396466, 396470, 396480, 396489, 396508, 396514, 396530, 396541, 396553, 396561, 396564, 396572, 396637, 396640, 396647, 396650, 396656, 396670, 396690, 396700, 396722, 396795, 396798, 396808, 396838, 396841, 396885, 396893, 396901, 396913, 396917, 396934, 396940, 396944, 396959, 396963, 396972, 396973, 396986, 396990, 396996, 397003, 397016, 397032, 397055, 397064, 397083, 397091, 397092, 397124, 397135, 397139, 397154, 397167, 397170, 397186, 397189, 397204, 397226, 397250, 397261, 397270, 397282, 397294, 397318, 397327, 397342, 397346, 397375, 397382, 397384, 397385, 397389, 397393, 397397, 397443, 397464, 397472, 397496, 397510, 397512, 397524, 397534, 397586, 397611, 397613, 397631, 397663, 397683, 397687, 397718, 397719, 397737, 397745, 397747, 397768, 397785, 397791, 397795, 397798, 397800, 397809, 397832, 397858, 397860, 397866, 397892, 397893, 397923, 397977, 397978, 397999, 398020, 398036, 398037, 398052, 398053, 398081, 398092, 398097, 398099, 398125, 398143, 398175, 398180, 398189, 398191, 398194, 398195, 398232, 398255, 398273, 398284, 398297, 398311, 398324, 398329, 398340, 398358, 398370, 398381, 398385, 398390, 398392, 398397, 398399, 398415, 398460, 398468, 398486, 398488, 398497, 398500, 398512, 398526, 398541, 398544, 398549, 398572, 398585, 398602, 398605, 398645, 398647, 398651, 398668, 398684, 398687, 398703, 398734, 398755, 398756, 398774, 398789, 398811, 398833, 398838, 398868, 398871, 398872, 398887, 398897, 398919, 398930, 398954, 398970, 398972, 398975, 398982, 398983, 398992, 399005, 399011, 399024, 399029, 399037, 399049, 399050, 399065, 399066, 399091, 399103, 399125, 399134, 399158, 399185, 399189, 399190, 399199, 399222, 399226, 399252, 399258, 399270, 399304, 399307, 399313, 399328, 399335, 399340, 399364, 399369, 399372, 399385, 399388, 399393, 399455, 399459, 399478, 399481, 399482, 399490, 399507, 399524, 399535, 399546, 399547, 399562, 399572, 399573, 399577, 399591, 399598, 399608, 399617, 399627, 399634, 399654, 399660, 399679, 399680, 399703, 399708, 399710, 399719, 399727, 399740, 399742, 399747, 399761, 399764, 399775, 399792, 399799, 399812, 399818, 399826, 399838, 399844, 399875, 399885, 399907, 399911, 399918, 399929, 399949, 399957, 399963, 399966, 399979, 399988, 399993, 399998, 400003, 400017, 400019, 400027, 400043, 400052, 400071, 400095, 400099, 400116, 400127, 400136, 400150, 400156, 400158, 400160, 400164, 400191, 400194, 400200, 400205, 400212, 400224, 400226, 400242, 400249, 400254, 400262, 400269, 400295, 400322, 400335, 400351, 400368, 400377, 400386, 400389, 400396, 400398, 400407, 400422, 400436, 400454, 400458, 400461, 400482, 400483, 400485, 400506, 400521, 400542, 400549, 400574, 400586, 400595, 400599, 400603, 400606, 400631, 400632, 400636, 400639, 400673, 400685, 400693, 400717, 400729, 400745, 400753, 400765, 400775, 400796, 400820, 400824, 400838, 400840, 400845, 400854, 400858, 400874, 400876, 400883, 400887, 400898, 400903, 400911, 400919, 400933, 400938, 400951, 400952, 400958, 400969, 400976, 400992, 400998, 401002, 401007, 401014, 401031, 401041, 401049, 401050, 401072, 401077, 401083, 401085, 401114, 401136, 401137, 401173, 401183, 401186, 401191, 401197, 401200, 401208, 401223, 401245, 401267, 401330, 401351, 401354, 401359, 401361, 401362, 401393, 401399, 401421, 401441, 401448, 401453, 401469, 401481, 401501, 401503, 401511, 401527, 401542, 401554, 401559, 401561, 401581, 401583, 401605, 401615, 401618, 401627, 401642, 401645, 401654, 401670, 401672, 401676, 401684, 401702, 401708, 401711, 401718, 401729, 401739, 401750, 401773, 401790, 401792, 401804, 401807, 401855, 401857, 401873, 401900, 401911, 401921, 401923, 401943, 401962, 401966, 401968, 401971, 401979, 401990, 402016, 402038, 402042, 402065, 402067, 402084, 402100, 402107, 402114, 402118, 402122, 402127, 402143, 402159, 402162, 402163, 402167, 402194, 402195, 402198, 402213, 402215, 402233, 402239, 402251, 402253, 402263, 402296, 402315, 402324, 402329, 402334, 402354, 402357, 402371, 402396, 402407, 402425, 402433, 402448, 402453, 402494, 402507, 402515, 402518, 402524, 402538, 402549, 402563, 402565, 402582, 402599, 402610, 402617, 402651, 402662, 402669, 402672, 402689, 402705, 402711, 402713, 402723, 402730, 402739, 402740, 402755, 402759, 402760, 402764, 402778, 402789, 402793, 402809, 402810, 402818, 402833, 402843, 402857, 402874, 402881, 402888, 402899, 402907, 402917, 402943, 402954, 402964, 402969, 402972, 402976, 402986, 403009, 403013, 403024, 403036, 403045, 403056, 403065, 403069, 403076, 403093, 403105, 403107, 403150, 403162, 403165, 403203, 403208, 403209, 403222, 403226, 403231, 403270, 403285, 403287, 403342, 403343, 403349, 403357, 403375, 403394, 403404, 403410, 403413, 403415, 403427, 403466, 403469, 403483, 403487, 403497, 403506, 403510, 403518, 403522, 403526, 403545, 403557, 403564, 403568, 403583, 403611, 403617, 403620, 403632, 403643, 403644, 403654, 403660, 403671, 403691, 403697, 403703, 403705, 403710, 403739, 403746, 403756, 403833, 403839, 403852, 403868, 403872, 403875, 403884, 403911, 403931, 403935, 403951, 403953, 403955, 403960, 403966, 403971, 403978, 403993, 404004, 404008, 404027, 404030, 404036, 404041, 404049, 404062, 404079, 404089, 404119, 404127, 404163, 404166, 404180, 404204, 404209, 404219, 404228, 404247, 404250, 404260, 404262, 404264, 404275, 404276, 404296, 404298, 404300, 404316, 404329, 404336, 404348, 404351, 404380, 404382, 404384, 404391, 404395, 404410, 404416, 404433, 404435, 404436, 404440, 404453, 404454, 404470, 404480, 404482, 404487, 404488, 404492, 404494, 404500, 404501, 404506, 404528, 404535, 404556, 404565, 404583, 404607, 404618, 404624, 404636, 404650, 404669, 404673, 404685, 404694, 404702, 404711, 404720, 404730, 404739, 404743, 404746, 404748, 404752, 404774, 404790, 404791, 404794, 404811, 404820, 404829, 404831, 404834, 404841, 404854, 404857, 404860, 404874, 404882, 404884, 404894, 404895, 404899, 404915, 404923, 404926, 404939, 404947, 404952, 404976, 404983, 404987, 404996, 404997, 405016, 405031, 405032, 405038, 405043, 405047, 405050, 405055, 405058, 405069, 405080, 405083, 405093, 405094, 405098, 405115, 405124, 405146, 405147, 405151, 405156, 405170, 405185, 405189, 405213, 405260, 405261, 405267, 405277, 405286, 405294, 405315, 405336, 405359, 405378, 405392, 405395, 405400, 405403, 405406, 405418, 405422, 405429, 405432, 405440, 405442, 405450, 405472, 405488, 405492, 405500, 405507, 405519, 405520, 405523, 405526, 405527, 405539, 405548, 405557, 405566, 405577, 405586, 405587, 405618, 405621, 405635, 405640, 405650, 405653, 405658, 405663, 405673, 405676, 405692, 405694, 405697, 405702, 405706, 405727, 405736, 405744, 405751, 405772, 405779, 405793, 405800, 405804, 405814, 405831, 405843, 405846, 405863, 405870, 405884, 405895, 405900, 405911, 405913, 405916, 405930, 405943, 405961, 405979, 405987, 405994, 406014, 406045, 406062, 406068, 406082, 406090, 406095, 406096, 406109, 406127, 406129, 406144, 406148, 406157, 406193, 406195, 406200, 406213, 406226, 406232, 406246, 406248, 406250, 406257, 406268, 406271, 406276, 406280, 406297, 406302, 406307, 406321, 406326, 406337, 406343, 406346, 406359, 406388, 406400, 406409, 406410, 406425, 406435, 406440, 406443, 406446, 406456, 406476, 406481, 406493, 406502, 406514, 406521, 406531, 406540, 406545, 406546, 406608, 406614, 406639, 406657, 406671, 406681, 406701, 406712, 406714, 406717, 406736, 406744, 406763, 406778, 406790, 406796, 406823, 406826, 406828, 406853, 406883, 406887, 406895, 406896, 406898, 406917, 406929, 406930, 406943, 406958, 406970, 406973, 406984, 406986, 407000, 407001, 407019, 407022, 407025, 407030, 407035, 407048, 407057, 407065, 407072, 407074, 407077, 407078, 407091, 407116, 407118, 407122, 407163, 407164, 407165, 407174, 407179, 407198, 407201, 407215, 407216, 407218, 407243, 407244, 407259, 407322, 407347, 407354, 407358, 407411, 407412, 407419, 407422, 407426, 407434, 407438, 407445, 407450, 407464, 407466, 407476, 407478, 407511, 407527, 407547, 407557, 407565, 407583, 407584, 407589, 407605, 407608, 407622, 407630, 407635, 407663, 407687, 407691, 407693, 407702, 407705, 407710, 407713, 407716, 407721, 407761, 407770, 407781, 407797, 407803, 407809, 407813, 407815, 407824, 407830, 407848, 407853, 407860, 407865, 407873, 407891, 407892, 407901, 407906, 407932, 407945, 407947, 407958, 407967, 407970, 407971, 407972, 407974, 407978, 407989, 407991, 407995, 407997, 408007, 408018, 408021, 408031, 408041, 408052, 408061, 408063, 408070, 408073, 408084, 408088, 408100, 408103, 408105, 408115, 408130, 408136, 408140, 408181, 408189, 408190, 408196, 408207, 408214, 408227, 408231, 408242, 408253, 408254, 408260, 408274, 408284, 408300, 408314, 408324, 408331, 408347, 408354, 408355, 408378, 408399, 408406, 408409, 408418, 408425, 408426, 408435, 408439, 408452, 408465, 408492, 408493, 408497, 408503, 408508, 408513, 408547, 408550, 408557, 408559, 408578, 408597, 408610, 408639, 408644, 408654, 408661, 408665, 408679, 408680, 408699, 408726, 408735, 408749, 408781, 408790, 408793, 408812, 408815, 408835, 408840, 408842, 408850, 408880, 408892, 408901, 408918, 408922, 408953, 408961, 408988, 409007, 409008, 409033, 409035, 409036, 409061, 409089, 409091, 409097, 409105, 409114, 409115, 409121, 409126, 409135, 409144, 409161, 409182, 409186, 409190, 409198, 409201, 409204, 409216, 409222, 409233, 409241, 409244, 409246, 409252, 409255, 409264, 409270, 409283, 409289, 409290, 409291, 409304, 409330, 409334, 409336, 409345, 409355, 409358, 409377, 409387, 409404, 409414, 409425, 409439, 409443, 409449, 409455, 409460, 409461, 409474, 409477, 409486, 409489, 409495, 409496, 409506, 409524, 409538, 409539, 409547, 409552, 409553, 409565, 409578, 409588, 409592, 409595, 409598, 409622, 409635, 409696, 409704, 409717, 409718, 409760, 409771, 409777, 409785, 409795, 409810, 409811, 409814, 409821, 409827, 409850, 409864, 409870, 409877, 409881, 409892, 409894, 409909, 409920, 409931, 409934, 409940, 409945, 409948, 409950, 409969, 409980, 410005, 410009, 410020, 410036, 410039, 410045, 410082, 410094, 410118, 410150, 410160, 410175, 410190, 410217, 410222, 410232, 410248, 410267, 410282, 410301, 410302, 410303, 410349, 410352, 410359, 410369, 410370, 410378, 410386, 410391, 410402, 410405, 410417, 410423, 410425, 410426, 410448, 410457, 410467, 410476, 410483, 410493, 410498, 410519, 410527, 410541, 410553, 410556, 410560, 410572, 410574, 410591, 410596, 410612, 410615, 410625, 410627, 410628, 410632, 410647, 410648, 410665, 410670, 410676, 410680, 410681, 410701, 410702, 410704, 410718, 410727, 410740, 410742, 410743, 410746, 410754, 410759, 410768, 410774, 410775, 410783, 410792, 410798, 410804, 410806, 410810, 410834, 410844, 410860, 410867, 410869, 410871, 410885, 410895, 410913, 410919, 410928, 410944, 410964, 410979, 411000, 411003, 411024, 411025, 411028, 411035, 411064, 411069, 411086, 411099, 411120, 411124, 411137, 411145, 411154, 411164, 411167, 411173, 411190, 411195, 411201, 411214, 411218, 411226, 411232, 411242, 411251, 411253, 411286, 411298, 411319, 411322, 411335, 411368, 411388, 411390, 411395, 411398, 411399, 411404, 411405, 411410, 411442, 411488, 411511, 411521, 411523, 411530, 411535, 411539, 411540, 411548, 411558, 411561, 411565, 411580, 411582, 411591, 411603, 411607, 411609, 411620, 411621, 411625, 411635, 411649, 411660, 411698, 411702, 411709, 411710, 411718, 411726, 411730, 411745, 411748, 411760, 411761, 411765, 411771, 411784, 411789, 411800, 411808, 411813, 411818, 411823, 411830, 411835, 411839, 411848, 411856, 411873, 411881, 411889, 411898, 411910, 411918, 411919, 411948, 411950, 411966, 411989, 412023, 412024, 412043, 412053, 412055, 412065, 412070, 412073, 412077, 412102, 412118, 412126, 412127, 412168, 412174, 412188, 412196, 412197, 412206, 412220, 412233, 412250, 412257, 412270, 412285, 412300, 412311, 412313, 412321, 412327, 412334, 412341, 412351, 412354, 412355, 412365, 412371, 412372, 412377, 412380, 412381, 412403, 412431, 412446, 412459, 412472, 412475, 412482, 412491, 412493, 412514, 412549, 412553, 412558, 412570, 412585, 412591, 412597, 412600, 412602, 412621, 412631, 412640, 412650, 412651, 412655, 412685, 412689, 412703, 412709, 412715, 412728, 412730, 412732, 412748, 412751, 412789, 412797, 412809, 412815, 412841, 412848, 412865, 412867, 412875, 412878, 412891, 412904, 412912, 412926, 412943, 412945, 412951, 412958, 412967, 412971, 412979, 412982, 413019, 413026, 413027, 413030, 413051, 413057, 413061, 413070, 413081, 413092, 413097, 413112, 413120, 413121, 413127, 413145, 413158, 413165, 413169, 413179, 413190, 413195, 413204, 413210, 413222, 413226, 413229, 413231, 413243, 413244, 413253, 413259, 413274, 413277, 413280, 413287, 413290, 413297, 413299, 413303, 413327, 413339, 413340, 413343, 413354, 413359, 413378, 413418, 413426, 413435, 413454, 413464, 413471, 413521, 413553, 413564, 413573, 413589, 413598, 413605, 413611, 413615, 413625, 413633, 413642, 413649, 413652, 413668, 413671, 413677, 413682, 413683, 413687, 413691, 413698, 413708, 413728, 413731, 413750, 413754, 413755, 413764, 413782, 413789, 413805, 413820, 413836, 413842, 413856, 413866, 413870, 413891, 413908, 413915, 413952, 413962, 413966, 413975, 413976, 413994, 414011, 414025, 414028, 414037, 414040, 414047, 414048, 414061, 414062, 414065, 414072, 414082, 414092, 414093, 414101, 414104, 414119, 414127, 414128, 414137, 414141, 414146, 414158, 414168, 414176, 414181, 414192, 414194, 414195, 414205, 414209, 414212, 414218, 414223, 414230, 414237, 414243, 414247, 414254, 414258, 414263, 414267, 414282, 414286, 414289, 414291, 414296, 414302, 414304, 414320, 414322, 414325, 414328, 414329, 414334, 414335, 414353, 414355, 414371, 414375, 414379, 414383, 414387, 414398, 414424, 414430, 414446, 414466, 414469, 414473, 414483, 414514, 414520, 414542, 414546, 414551, 414562, 414568, 414578, 414585, 414589, 414602, 414606, 414616, 414622, 414643, 414655, 414665, 414670, 414681, 414684, 414688, 414690, 414710, 414715, 414719, 414723, 414737, 414751, 414758, 414773, 414802, 414810, 414811, 414812, 414824, 414827, 414831, 414837, 414843, 414847, 414872, 414875, 414878, 414910, 414914, 414917, 414941, 414946, 414962, 414966, 414969, 414989, 414990, 415013, 415019, 415021, 415025, 415035, 415042, 415045, 415052, 415053, 415058, 415059, 415063, 415069, 415127, 415164, 415175, 415180, 415187, 415196, 415209, 415210, 415262, 415296, 415307, 415325, 415343, 415348, 415356, 415358, 415370, 415373, 415402, 415404, 415419, 415428, 415439, 415465, 415502, 415508, 415512, 415517, 415539, 415549, 415556, 415564, 415568, 415584, 415595, 415599, 415607, 415620, 415639, 415650, 415653, 415691, 415707, 415708, 415715, 415723, 415746, 415749, 415753, 415760, 415768, 415773, 415783, 415786, 415794, 415803, 415804, 415823, 415829, 415839, 415847, 415850, 415852, 415856, 415865, 415871, 415872, 415883, 415900, 415916, 415942, 415968, 415982, 415987, 415993, 415996, 416012, 416013, 416017, 416020, 416022, 416032, 416035, 416044, 416045, 416063, 416069, 416077, 416098, 416103, 416115, 416129, 416137, 416141, 416142, 416164, 416166, 416170, 416178, 416199, 416209, 416212, 416246, 416270, 416279, 416292, 416300, 416305, 416321, 416340, 416356, 416362, 416366, 416371, 416376, 416382, 416407, 416415, 416416, 416428, 416436, 416437, 416439, 416440, 416447, 416448, 416458, 416459, 416485, 416486, 416501, 416502, 416508, 416509, 416511, 416516, 416520, 416525, 416527, 416544, 416547, 416553, 416596, 416599, 416635, 416638, 416648, 416652, 416655, 416658, 416665, 416669, 416695, 416696, 416699, 416717, 416733, 416746, 416763, 416765, 416768, 416787, 416788, 416793, 416813, 416823, 416844, 416847, 416853, 416857, 416866, 416880, 416881, 416897, 416910, 416924, 416932, 416937, 416946, 416953, 416962, 416968, 416979, 417008, 417057, 417058, 417061, 417087, 417094, 417103, 417115, 417126, 417128, 417146, 417176, 417193, 417201, 417211, 417212, 417214, 417235, 417238, 417265, 417272, 417275, 417284, 417285, 417291, 417293, 417295, 417298, 417299, 417344, 417350, 417357, 417374, 417381, 417390, 417391, 417421, 417428, 417433, 417434, 417456, 417458, 417459, 417473, 417487, 417488, 417490, 417494, 417512, 417536, 417539, 417543, 417555, 417564, 417567, 417579, 417586, 417590, 417599, 417606, 417608, 417615, 417622, 417626, 417629, 417639, 417648, 417652, 417666, 417684, 417695, 417697, 417698, 417724, 417740, 417745, 417749, 417756, 417762, 417767, 417772, 417774, 417788, 417794, 417799, 417811, 417814, 417817, 417822, 417828, 417837, 417842, 417848, 417920, 417933, 417953, 417954, 417955, 417973, 418002, 418017, 418028, 418030, 418070, 418087, 418105, 418114, 418116, 418121, 418122, 418142, 418148, 418153, 418158, 418175, 418179, 418188, 418206, 418213, 418234, 418241, 418244, 418247, 418254, 418257, 418263, 418274, 418275, 418295, 418312, 418318, 418322, 418325, 418357, 418375, 418397, 418404, 418457, 418468, 418474, 418478, 418488, 418492, 418532, 418545, 418551, 418558, 418569, 418584, 418585, 418602, 418613, 418623, 418628, 418630, 418638, 418666, 418667, 418669, 418699, 418706, 418707, 418745, 418765, 418769, 418776, 418783, 418788, 418802, 418810, 418816, 418821, 418826, 418845, 418847, 418849, 418871, 418884, 418886, 418887, 418899, 418908, 418910, 418912, 418920, 418936, 418963, 418991, 419005, 419027, 419035, 419040, 419073, 419078, 419088, 419102, 419106, 419128, 419132, 419136, 419137, 419171, 419178, 419181, 419182, 419183, 419191, 419206, 419208, 419211, 419212, 419215, 419226, 419228, 419242, 419245, 419275, 419281, 419287, 419312, 419325, 419338, 419345, 419363, 419377, 419378, 419379, 419383, 419396, 419398, 419400, 419413, 419429, 419434, 419447, 419454, 419466, 419476, 419478, 419482, 419486, 419487, 419492, 419507, 419511, 419512, 419514, 419522, 419536, 419543, 419545, 419553, 419558, 419567, 419578, 419587, 419619, 419628, 419639, 419651, 419664, 419705, 419707, 419715, 419718, 419729, 419737, 419748, 419749, 419752, 419760, 419766, 419780, 419813, 419821, 419837, 419843, 419844, 419849, 419852, 419855, 419865, 419871, 419881, 419887, 419901, 419909, 419912, 419920, 419927, 419949, 419955, 419961, 419965, 419969, 419976, 419987, 419989, 420011, 420019, 420025, 420058, 420059, 420080, 420092, 420100, 420101, 420114, 420128, 420140, 420151, 420152, 420158, 420160, 420179, 420194, 420211, 420218, 420230, 420241, 420253, 420254, 420268, 420271, 420287, 420300, 420306, 420313, 420319, 420335, 420339, 420351, 420360, 420364, 420365, 420371, 420374, 420385, 420404, 420411, 420415, 420430, 420453, 420462, 420483, 420484, 420489, 420500, 420508, 420512, 420514, 420533, 420562, 420571, 420580, 420582, 420583, 420588, 420630, 420638, 420640, 420647, 420660, 420675, 420682, 420693, 420696, 420698, 420703, 420716, 420768, 420773, 420806, 420813, 420817, 420823, 420826, 420830, 420835, 420844, 420853, 420857, 420863, 420870, 420881, 420894, 420898, 420912, 420924, 420928, 420950, 420951, 420953, 420954, 420966, 420972, 420980, 420984, 420989, 420997, 421011, 421029, 421040, 421046, 421054, 421063, 421066, 421068, 421087, 421090, 421107, 421116, 421118, 421129, 421135, 421137, 421162, 421166, 421176, 421182, 421186, 421193, 421195, 421201, 421219, 421225, 421234, 421238, 421241, 421245, 421247, 421257, 421261, 421267, 421291, 421301, 421316, 421336, 421346, 421384, 421391, 421398, 421407, 421421, 421441, 421462, 421466, 421468, 421476, 421483, 421494, 421505, 421506, 421514, 421518, 421526, 421527, 421548, 421553, 421554, 421561, 421573, 421584, 421606, 421611, 421615, 421633, 421644, 421647, 421656, 421658, 421661, 421677, 421680, 421690, 421705, 421714, 421724, 421730, 421734, 421745, 421746, 421753, 421756, 421760, 421771, 421775, 421776, 421779, 421788, 421802, 421824, 421825, 421830, 421836, 421864, 421869, 421872, 421876, 421882, 421921, 421926, 421928, 421929, 421933, 421936, 421944, 421954, 421962, 421975, 421981, 422003, 422017, 422023, 422031, 422045, 422057, 422059, 422081, 422084, 422092, 422097, 422100, 422101, 422103, 422107, 422109, 422123, 422124, 422133, 422135, 422140, 422142, 422148, 422154, 422158, 422163, 422166, 422178, 422180, 422188, 422193, 422213, 422227, 422233, 422240, 422241, 422247, 422255, 422277, 422308, 422322, 422329, 422343, 422346, 422366, 422370, 422374, 422381, 422385, 422386, 422407, 422410, 422416, 422430, 422438, 422440, 422451, 422455, 422456, 422482, 422484, 422491, 422517, 422524, 422534, 422544, 422545, 422546, 422550, 422557, 422558, 422559, 422584, 422585, 422597, 422599, 422603, 422615, 422632, 422641, 422661, 422663, 422674, 422676, 422694, 422696, 422717, 422719, 422723, 422732, 422734, 422747, 422753, 422761, 422762, 422769, 422784, 422791, 422801, 422803, 422808, 422819, 422823, 422838, 422849, 422850, 422869, 422874, 422884, 422896, 422904, 422905, 422907, 422915, 422939, 422942, 422943, 422955, 422960, 422983, 422993, 422994, 423000, 423023, 423032, 423055, 423058, 423072, 423082, 423083, 423087, 423094, 423095, 423099, 423100, 423103, 423104, 423120, 423123, 423126, 423130, 423133, 423143, 423148, 423158, 423161, 423177, 423181, 423183, 423200, 423201, 423205, 423250, 423265, 423287, 423291, 423295, 423310, 423329, 423335, 423354, 423357, 423365, 423366, 423372, 423379, 423400, 423401, 423410, 423413, 423431, 423432, 423437, 423445, 423451, 423463, 423466, 423471, 423480, 423489, 423498, 423499, 423509, 423516, 423525, 423527, 423529, 423545, 423559, 423566, 423572, 423574, 423581, 423582, 423587, 423590, 423594, 423599, 423607, 423612, 423616, 423629, 423650, 423653, 423657, 423661, 423683, 423707, 423712, 423734, 423735, 423740, 423745, 423778, 423788, 423814, 423822, 423825, 423848, 423863, 423873, 423884, 423893, 423896, 423899, 423916, 423918, 423936, 423949, 423955, 423967, 423986, 424004, 424007, 424009, 424011, 424016, 424021, 424024, 424035, 424038, 424042, 424060, 424068, 424081, 424083, 424101, 424103, 424106, 424127, 424134, 424168, 424175, 424176, 424181, 424204, 424224, 424226, 424257, 424269, 424282, 424284, 424292, 424303, 424308, 424309, 424311, 424322, 424324, 424326, 424331, 424367, 424383, 424390, 424409, 424411, 424440, 424444, 424452, 424456, 424458, 424461, 424473, 424475, 424476, 424485, 424494, 424514, 424518, 424522, 424531, 424552, 424554, 424574, 424582, 424584, 424595, 424613, 424614, 424629, 424638, 424645, 424654, 424658, 424659, 424662, 424667, 424678, 424685, 424690, 424692, 424694, 424738, 424745, 424756, 424764, 424774, 424787, 424807, 424829, 424834, 424843, 424854, 424859, 424871, 424888, 424892, 424895, 424901, 424915, 424921, 424939, 424948, 424953, 424974, 424985, 424994, 425005, 425015, 425022, 425035, 425038, 425043, 425050, 425052, 425070, 425080, 425087, 425092, 425112, 425118, 425119, 425120, 425131, 425135, 425138, 425142, 425153, 425161, 425199, 425202, 425246, 425249, 425255, 425264, 425272, 425282, 425284, 425289, 425313, 425321, 425325, 425342, 425362, 425363, 425364, 425409, 425412, 425414, 425448, 425453, 425474, 425492, 425503, 425534, 425536, 425538, 425546, 425554, 425557, 425568, 425595, 425635, 425639, 425643, 425661, 425675, 425679, 425690, 425692, 425696, 425701, 425703, 425729, 425753, 425758, 425763, 425772, 425775, 425776, 425780, 425791, 425792, 425798, 425804, 425810, 425816, 425840, 425842, 425850, 425861, 425874, 425877, 425896, 425897, 425898, 425907, 425916, 425918, 425923, 425930, 425938, 425944, 425946, 425953, 425962, 425963, 425978, 425992, 425994, 426008, 426017, 426031, 426040, 426048, 426052, 426081, 426086, 426088, 426111, 426112, 426123, 426124, 426134, 426137, 426145, 426150, 426160, 426171, 426179, 426181, 426184, 426196, 426215, 426220, 426232, 426246, 426257, 426261, 426276, 426283, 426284, 426298, 426302, 426307, 426308, 426320, 426329, 426342, 426354, 426357, 426361, 426368, 426374, 426380, 426392, 426399, 426416, 426421, 426426, 426432, 426448, 426451, 426458, 426475, 426484, 426494, 426495, 426498, 426501, 426517, 426528, 426537, 426569, 426586, 426594, 426600, 426603, 426608, 426615, 426622, 426627, 426654, 426665, 426668, 426675, 426682, 426685, 426687, 426700, 426710, 426711, 426732, 426736, 426760, 426774, 426783, 426795, 426801, 426818, 426820, 426847, 426856, 426861, 426866, 426868, 426871, 426897, 426914, 426923, 426929, 426931, 426933, 426934, 426941, 426944, 426953, 426973, 426984, 426985, 426992, 426994, 426999, 427001, 427005, 427015, 427029, 427033, 427039, 427043, 427053, 427054, 427057, 427070, 427072, 427092, 427093, 427106, 427124, 427139, 427144, 427153, 427154, 427156, 427162, 427166, 427169, 427174, 427205, 427210, 427215, 427216, 427252, 427276, 427300, 427305, 427340, 427354, 427358, 427364, 427420, 427439, 427468, 427476, 427482, 427485, 427489, 427496, 427508, 427510, 427516, 427526, 427538, 427550, 427556, 427631, 427633, 427643, 427646, 427650, 427660, 427702, 427729, 427739, 427758, 427768, 427771, 427778, 427779, 427788, 427799, 427802, 427813, 427819, 427821, 427824, 427830, 427835, 427847, 427849, 427859, 427871, 427885, 427898, 427899, 427907, 427915, 427916, 427928, 427936, 427952, 427959, 427968, 427972, 427977, 427981, 427986, 427992, 428002, 428004, 428006, 428048, 428050, 428059, 428070, 428080, 428083, 428093, 428104, 428119, 428130, 428140, 428142, 428153, 428166, 428176, 428179, 428183, 428186, 428198, 428201, 428203, 428221, 428228, 428241, 428243, 428250, 428256, 428260, 428279, 428291, 428307, 428318, 428324, 428336, 428344, 428348, 428365, 428375, 428388, 428393, 428402, 428411, 428415, 428420, 428436, 428440, 428453, 428460, 428479, 428518, 428539, 428545, 428556, 428573, 428585, 428610, 428616, 428618, 428624, 428634, 428649, 428650, 428669, 428697, 428698, 428701, 428728, 428744, 428753, 428756, 428762, 428772, 428773, 428784, 428792, 428796, 428798, 428802, 428812, 428818, 428823, 428832, 428845, 428850, 428853, 428857, 428867, 428871, 428880, 428894, 428908, 428919, 428925, 428943, 428959, 428962, 428966, 428978, 428990, 428995, 429034, 429039, 429053, 429063, 429067, 429091, 429096, 429114, 429118, 429124, 429126, 429143, 429149, 429169, 429177, 429180, 429196, 429198, 429208, 429225, 429230, 429232, 429239, 429244, 429258, 429269, 429272, 429286, 429296, 429301, 429314, 429316, 429341, 429343, 429346, 429347, 429355, 429359, 429365, 429366, 429369, 429371, 429375, 429379, 429390, 429393, 429424, 429426, 429444, 429450, 429458, 429463, 429467, 429484, 429488, 429502, 429522, 429525, 429527, 429537, 429542, 429555, 429560, 429564, 429570, 429839, 429849, 429851, 429860, 429866, 429883, 429884, 429889, 429899, 429903, 429905, 429924, 429931, 429933, 429940, 429944, 429949, 429954, 429956, 429973, 429980, 429987, 429988, 429990, 429998, 430004, 430018, 430020, 430023, 430026, 430028, 430040, 430046, 430052, 430056, 430063, 430065, 430067, 430071, 430073, 430076, 430089, 430097, 430108, 430112, 430128, 430133, 430138, 430152, 430163, 430168, 430172, 430178, 430186, 430190, 430194, 430203, 430205, 430221, 430224, 430226, 430228, 430237, 430258, 430277, 430301, 430318, 430320, 430326, 430335, 430355, 430368, 430369, 430373, 430382, 430389, 430394, 430400, 430411, 430418, 430432, 430459, 430461, 430470, 430476, 430477, 430482, 430487, 430490, 430498, 430508, 430516, 430522, 430531, 430534, 430545, 430556, 430562, 430563, 430572, 430578, 430582, 430591, 430603, 430604, 430608, 430613, 430621, 430626, 430627, 430628, 430636, 430639, 430640, 430643, 430645, 430654, 430658, 430660, 430673, 430674, 430677, 430680, 430684, 430689, 430696, 430706, 430713, 430721, 430728, 430733, 430736, 430750, 430751, 430759, 430767, 430786, 430794, 430808, 430814, 430818, 430821, 430826, 430829, 430831, 430835, 430839, 430858, 430863, 430880, 430888, 430890, 430897, 430900, 430914, 430915, 430917, 430920, 430924, 430933, 430934, 430937, 430941, 430952, 430968, 430971, 430975, 430980, 430987, 430989, 430993, 431006, 431014, 431019, 431025, 431026, 431030, 431039, 431054, 431064, 431074, 431075, 431091, 431107, 431120, 431123, 431128, 431129, 431132, 431137, 431159, 431163, 431168, 431173, 431180, 431188, 431194, 431204, 431205, 431208, 431214, 431219, 431224, 431236, 431242, 431247, 431253, 431258, 431260, 431261, 431272, 431275, 431276, 431279, 431296, 431315, 431318, 431323, 431328, 431335, 431337, 431347, 431351, 431361, 431376, 431382, 431383, 431387, 431408, 431409, 431410, 431419, 431422, 431435, 431441, 431458, 431463, 431468, 431476, 431491, 431492, 431497, 431498, 431512, 431518, 431525, 431526, 431536, 431567, 431580, 431582, 431590, 431609, 431619, 431623, 431630, 431635, 431636, 431644, 431645, 431657, 431658, 431667, 431678, 431685, 431688, 431699, 431700, 431705, 431707, 431710, 431718, 431726, 431728, 431736, 431743, 431750, 431754, 431784, 431805, 431815, 431828, 431835, 431837, 431844, 431847, 431849, 431852, 431856, 431859, 431874, 431887, 431889, 431892, 431898, 431919, 431923, 431929, 431938, 431939, 431957, 431965, 431975, 431978, 432000, 432001, 432012, 432023, 432029, 432042, 432058, 432061, 432067, 432073, 432074, 432077, 432084, 432093, 432096, 432103, 432110, 432120, 432123, 432144, 432151, 432156, 432170, 432171, 432184, 432190, 432196, 432200, 432205, 432209, 432212, 432225, 432227, 432229, 432235, 432242, 432245, 432250, 432254, 432264, 432268, 432281, 432282, 432289, 432294, 432296, 432304, 432309, 432313, 432316, 432326, 432331, 432333, 432339, 432345, 432352, 432356, 432360, 432368, 432376, 432383, 432386, 432391, 432404, 432410, 432415, 432419, 432423, 432428, 432441, 432450, 432456, 432462, 432465, 432470, 432475, 432480, 432492, 432501, 432515, 432528, 432533, 432536, 432543, 432546, 432553, 432558, 432569, 432584, 432586, 432593, 432599, 432602, 432604, 432608, 432618, 432620, 432624, 432634, 432644, 432648, 432654, 432660, 432667, 432673, 432686, 432702, 432705, 432712, 432717, 432720, 432728, 432744, 432745, 432762, 432764, 432765, 432780, 432786, 432788, 432809, 432821, 432846, 432866, 432867, 432872, 432901, 432904, 432908, 432911, 432919, 432934, 432941, 432953, 432970, 432973, 432977, 432983, 432998, 433008, 433012, 433023, 433030, 433035, 433047, 433051, 433060, 433066, 433074, 433081, 433085, 433094, 433106, 433109, 433115, 433126, 433130, 433136, 433139, 433156, 433159, 433163, 433169, 433177, 433190, 433196, 433201, 433207, 433213, 433219, 433222, 433225, 433230, 433246, 433254, 433257, 433260, 433266, 433270, 433277, 433278, 433284, 433285, 433293, 433298, 433306, 433320, 433328, 433331, 433346, 433349, 433355, 433360, 433365, 433370, 433375, 433387, 433397, 433403, 433406, 433408, 433412, 433415, 433417, 433422, 433436, 433446, 433449, 433453, 433456, 433475, 433484, 433488, 433491, 433498, 433514, 433515, 433526, 433528, 433533, 433544, 433569, 433573, 433586, 433591, 433598, 433614, 433619, 433623, 433625, 433629, 433632, 433633, 433637, 433646, 433652, 433658, 433661, 433668, 433675, 433679, 433681, 433688, 433692, 433697, 433704, 433705, 433714, 433717, 433727, 433730, 433736, 433743, 433748, 433752, 433772, 433775, 433777, 433781, 433788, 433796, 433808, 433816, 433821, 433828, 433833, 433836, 433854, 433860, 433864, 433866, 433880, 433886, 433895, 433899, 433901, 433914, 433923, 433931, 433938, 433945, 433948, 433955, 433963, 433972, 433977, 433981, 433984, 433987, 433993, 434005, 434011, 434013, 434019, 434023, 434028, 434035, 434042, 434045, 434047, 434049, 434052, 434066, 434081, 434084, 434087, 434093, 434097, 434104, 434106, 434110, 434116, 434120, 434132, 434144, 434145, 434151, 434162, 434167, 434171, 434177, 434182, 434190, 434196, 434204, 434220, 434237, 434263, 434267, 434272, 434293, 434310, 434315, 434326, 434331, 434334, 434345, 434383, 434397, 434402, 434406, 434409, 434416, 434424, 434428, 434433, 434434, 434435, 434461, 434468, 434470, 434471, 434473, 434474, 434479, 434489, 434490, 434499, 434501, 434514, 434525, 434529, 434536, 434541, 434545, 434546, 434551, 434556, 434561, 434562, 434566, 434575, 434581, 434582, 434586, 434589, 434592, 434598, 434603, 434607, 434614, 434628, 434631, 434649, 434650, 434651, 434658, 434664, 434670, 434674, 434680, 434687, 434690, 434705, 434711, 434716, 434721, 434727, 434732, 434746, 434751, 434753, 434761, 434765, 434766, 434769, 434795, 434796, 434802, 434804, 434808, 434815, 434816, 434820, 434823, 434824, 434831, 434839, 434857, 434858, 434870, 434872, 434877, 434880, 434886, 434896, 434912, 434914, 434923, 434926, 434935, 434966, 434973, 434977, 434978, 434992, 434995, 434998, 435004, 435012, 435016, 435025, 435026, 435031, 435036, 435037, 435039, 435048, 435055, 435067, 435071, 435074, 435082, 435086, 435092, 435102, 435105, 435107, 435120, 435137, 435143, 435166, 435188, 435233, 435245, 435246, 435256, 435257, 435258, 435278, 435285, 435291, 435302, 435327, 435330, 435334, 435347, 435352, 435360, 435361, 435372, 435376, 435378, 435379, 435381, 435389, 435396, 435406, 435407, 435413, 435422, 435429, 435432, 435434, 435448, 435454, 435468, 435471, 435491, 435496, 435526, 435564, 435570, 435575, 435579, 435623, 435628, 435631, 435635, 435663, 435664, 435676, 435677, 435702, 435714, 435725, 435726, 435728, 435736, 435738, 435744, 435754, 435755, 435760, 435772, 435778, 435780, 435802, 435806, 435807, 435808, 435812, 435813, 435835, 435855, 435873, 435884, 435889, 435905, 435925, 435926, 435938, 435950, 435955, 435956, 435963, 435966, 435967, 435999, 436001, 436006, 436017, 436027, 436030, 436033, 436037, 436038, 436040, 436052, 436063, 436075, 436076, 436087, 436095, 436107, 436109, 436110, 436115, 436117, 436122, 436125, 436127, 436134, 436143, 436147, 436154, 436163, 436164, 436165, 436172, 436185, 436188, 436196, 436202, 436203, 436211, 436214, 436216, 436224, 436227, 436231, 436235, 436238, 436254, 436256, 436257, 436258, 436264, 436298, 436307, 436314, 436325, 436336, 436345, 436354, 436355, 436356, 436368, 436377, 436384, 436385, 436396, 436412, 436419, 436432, 436438, 436464, 436470, 436581, 436604, 436641, 436657, 436675, 436680, 436686, 436688, 436692, 436694, 436702, 436718, 436721, 436733, 436734, 436738, 436741, 436748, 436751, 436759, 436767, 436768, 436777, 436796, 436803, 436815, 436818, 436821, 436831, 436834, 436845, 436856, 436861, 436863, 436868, 436873, 436878, 436879, 436880, 436885, 436886, 436891, 436896, 436898, 436900, 436901, 436906, 436909, 436910, 436915, 436921, 436926, 436927, 436929, 436936, 436937, 436954, 436955, 436986, 436990, 436994, 437007, 437009, 437018, 437028, 437030, 437037, 437041, 437045, 437062, 437070, 437084, 437086, 437097, 437098, 437104, 437110, 437113, 437125, 437131, 437133, 437134, 437137, 437144, 437160, 437164, 437173, 437175, 437182, 437195, 437205, 437219, 437229, 437233, 437243, 437253, 437256, 437259, 437270, 437273, 437275, 437291, 437294, 437307, 437310, 437313, 437315, 437327, 437328, 437339, 437341, 437362, 437368, 437387, 437388, 437394, 437409, 437411, 437426, 437440, 437452, 437455, 437462, 437466, 437468, 437476, 437477, 437482, 437496, 437503, 437510, 437515, 437518, 437533, 437547, 437553, 437578, 437589, 437605, 437610, 437615, 437617, 437620, 437662, 437663, 437669, 437682, 437685, 437693, 437719, 437728, 437729, 437735, 437740, 437749, 437759, 437767, 437771, 437772, 437777, 437782, 437793, 437800, 437813, 437816, 437818, 437825, 437835, 437836, 437841, 437849, 437874, 437883, 437887, 437888, 437893, 437897, 437905, 437909, 437911, 437918, 437922, 437947, 437968, 437970, 437979, 437991, 437992, 437993, 437995, 438002, 438005, 438011, 438031, 438038, 438040, 438056, 438067, 438071, 438078, 438080, 438088, 438093, 438097, 438101, 438102, 438113, 438115, 438120, 438125, 438129, 438130, 438139, 438143, 438159, 438164, 438168, 438185, 438190, 438193, 438194, 438196, 438197, 438201, 438207, 438208, 438215, 438216, 438218, 438220, 438222, 438228, 438231, 438236, 438239, 438240, 438244, 438254, 438256, 438257, 438264, 438267, 438272, 438273, 438275, 438288, 438327, 438333, 438339, 438340, 438343, 438352, 438354, 438370, 438378, 438379, 438396, 438399, 438411, 438423, 438428, 438431, 438432, 438445, 438448, 438455, 438461, 438466, 438467, 438474, 438482, 438486, 438491, 438499, 438507, 438511, 438513, 438550, 438552, 438557, 438567, 438575, 438577, 438585, 438597, 438626, 438631, 438637, 438638, 438644, 438645, 438658, 438659, 438682, 438717, 438718, 438728, 438739, 438745, 438747, 438753, 438768, 438777, 438781, 438788, 438794, 438818, 438820, 438821, 438835, 438858, 438869, 438876, 438879, 438884, 438890, 438910, 438940, 438945, 438965, 438977, 438982, 438992, 438993, 438995, 439001, 439023, 439024, 439028, 439031, 439033, 439039, 439042, 439044, 439048, 439051, 439056, 439063, 439064, 439068, 439074, 439075, 439077, 439087, 439092, 439105, 439110, 439115, 439116, 439137, 439150, 439152, 439161, 439162, 439164, 439166, 439167, 439173, 439199, 439201, 439206, 439234, 439236, 439258, 439271, 439278, 439287, 439290, 439291, 439292, 439298, 439300, 439305, 439313, 439315, 439318, 439320, 439323, 439340, 439346, 439348, 439351, 439356, 439373, 439374, 439392, 439396, 439397, 439398, 439409, 439413, 439417, 439437, 439441, 439444, 439454, 439467, 439474, 439484, 439491, 439500, 439505, 439506, 439512, 439514, 439516, 439518, 439519, 439526, 439536, 439545, 439550, 439556, 439557, 439561, 439568, 439571, 439575, 439586, 439591, 439604, 439610, 439612, 439616, 439629, 439635, 439642, 439649, 439656, 439663, 439666, 439677, 439687, 439688, 439699, 439713, 439714, 439728, 439729, 439732, 439753, 439764, 439783, 439793, 439798, 439799, 439805, 439813, 439823, 439825, 439826, 439836, 439847, 439850, 439861, 439873, 439877, 439886, 439898, 439900, 439907, 439913, 439916, 439917, 439921, 439923, 439926, 439928, 439950, 439952, 439970, 440006, 440008, 440014, 440020, 440025, 440035, 440048, 440054, 440072, 440092, 440098, 440107, 440108, 440122, 440131, 440148, 440175, 440188, 440201, 440209, 440223, 440233, 440270, 440273, 440285, 440287, 440292, 440301, 440303, 440309, 440337, 440348, 440371, 440387, 440390, 440397, 440406, 440408, 440419, 440420, 440422, 440440, 440451, 440455, 440462, 440477, 440490, 440494, 440509, 440565, 440578, 440584, 440592, 440619, 440622, 440639, 440641, 440665, 440671, 440672, 440679, 440688, 440692, 440700, 440702, 440703, 440711, 440723, 440729, 440770, 440776, 440780, 440788, 440791, 440807, 440817, 440818, 440821, 440826, 440848, 440856, 440873, 440879, 440881, 440892, 440896, 440898, 440903, 440906, 440908, 440919, 440930, 440938, 440939, 440949, 440953, 440955, 440964, 440967, 440972, 440976, 440980, 440991, 441003, 441005, 441015, 441026, 441033, 441043, 441045, 441054, 441072, 441076, 441088, 441089, 441094, 441096, 441125, 441135, 441146, 441167, 441172, 441176, 441179, 441200, 441204, 441210, 441211, 441233, 441261, 441265, 441305, 441307, 441312, 441317, 441337, 441342, 441352, 441388, 441389, 441412, 441414, 441423, 441427, 441447, 441454, 441466, 441476, 441508, 441527, 441537, 441538, 441544, 441560, 441561, 441572, 441590, 441593, 441624, 441640, 441642, 441646, 441652, 441672, 441679, 441685, 441695, 441732, 441765, 441771, 441787, 441791, 441801, 441821, 441823, 441826, 441834, 441835, 441836, 441839, 441840, 441846, 441854, 441859, 441864, 441869, 441884, 441887, 441919, 441923, 441939, 441959, 441963, 441964, 441971, 441979, 441981, 441987, 441994, 441995, 441997, 441999, 442008, 442011, 442012, 442013, 442023, 442029, 442031, 442037, 442041, 442052, 442053, 442055, 442057, 442088, 442102, 442110, 442118, 442121, 442125, 442136, 442149, 442154, 442155, 442166, 442172, 442176, 442180, 442186, 442197, 442200, 442231, 442232, 442236, 442241, 442242, 442244, 442255, 442264, 442268, 442294, 442298, 442299, 442303, 442308, 442319, 442320, 442321, 442328, 442330, 442333, 442340, 442355, 442362, 442370, 442373, 442397, 442401, 442419, 442429, 442434, 442435, 442438, 442443, 442446, 442447, 442450, 442469, 442498, 442503, 442506, 442525, 442531, 442533, 442535, 442541, 442543, 442548, 442549, 442551, 442552, 442558, 442559, 442560, 442562, 442570, 442576, 442578, 442580, 442588, 442591, 442619, 442636, 442647, 442650, 442656, 442677, 442679, 442692, 442693, 442706, 442713, 442724, 442729, 442732, 442733, 442776, 442784, 442788, 442800, 442803, 442817, 442828, 442841, 442848, 442850, 442861, 442864, 442873, 442881, 442883, 442890, 442891, 442905, 442911, 442919, 442923, 442929, 442934, 442935, 442939, 442942, 442954, 442955, 442973, 442978, 442980, 442981, 442986, 442995, 442999, 443016, 443026, 443033, 443037, 443039, 443042, 443048, 443052, 443057, 443061, 443064, 443073, 443077, 443083, 443089, 443095, 443107, 443110, 443112, 443113, 443124, 443129, 443134, 443137, 443147, 443154, 443159, 443168, 443190, 443204, 443207, 443209, 443217, 443235, 443236, 443244, 443251, 443254, 443268, 443289, 443300, 443301, 443306, 443307, 443321, 443329, 443341, 443344, 443364, 443368, 443379, 443381, 443387, 443397, 443408, 443434, 443437, 443439, 443440, 443443, 443460, 443464, 443471, 443480, 443490, 443491, 443504, 443507, 443515, 443521, 443524, 443544, 443553, 443561, 443569, 443570, 443580, 443582, 443592, 443593, 443597, 443604, 443605, 443614, 443630, 443633, 443635, 443638, 443641, 443642, 443643, 443663, 443665, 443675, 443678, 443679, 443686, 443692, 443696, 443702, 443705, 443707, 443717, 443728, 443731, 443742, 443745, 443751, 443764, 443778, 443790, 443794, 443798, 443806, 443811, 443813, 443820, 443821, 443826, 443827, 443838, 443841, 443850, 443862, 443863, 443865, 443866, 443867, 443870, 443874, 443895, 443897, 443899, 443906, 443918, 443922, 443924, 443928, 443934, 443940, 443947, 443950, 443953, 443954, 443965, 443966, 443969, 443971, 443990, 443991, 443995, 444004, 444006, 444008, 444009, 444010, 444013, 444021, 444042, 444043, 444045, 444046, 444054, 444063, 444064, 444068, 444070, 444071, 444072, 444074, 444079, 444081, 444082, 444087, 444088, 444101, 444109, 444113, 444118, 444123, 444124, 444138, 444139, 444146, 444153, 444155, 444159, 444160, 444163, 444172, 444174, 444192, 444209, 444214, 444226, 444235, 444239, 444240, 444242, 444244, 444246, 444250, 444256, 444257, 444258, 444260, 444265, 444267, 444269, 444274, 444278, 444288, 444296, 444301, 444305, 444308, 444311, 444315, 444318, 444329, 444349, 444354, 444357, 444361, 444368, 444376, 444383, 444386, 444398, 444404, 444407, 444415, 444418, 444419, 444423, 444431, 444443, 444449, 444453, 444474, 444477, 444483, 444488, 444491, 444494, 444516, 444521, 444528, 444532, 444549, 444551, 444561, 444564, 444565, 444589, 444599, 444602, 444605, 444617, 444630, 444631, 444633, 444640, 444650, 444654, 444656, 444666, 444668, 444672, 444693, 444699, 444708, 444717, 444719, 444731, 444748, 444750, 444751, 444770, 444773, 444775, 444776, 444781, 444794, 444798, 444805, 444812, 444819, 444827, 444830, 444831, 444841, 444844, 444846, 444848, 444854, 444855, 444870, 444875, 444886, 444893, 444899, 444916, 444920, 444931, 444932, 444937, 444938, 444958, 444961, 444974, 444980, 444984, 444990, 444991, 444996, 445001, 445005, 445007, 445021, 445032, 445035, 445042, 445043, 445045, 445050, 445054, 445059, 445068, 445070, 445082, 445092, 445099, 445114, 445115, 445116, 445118, 445119, 445120, 445121, 445126, 445127, 445130, 445133, 445148, 445151, 445164, 445166, 445167, 445185, 445191, 445199, 445207, 445208, 445209, 445211, 445220, 445227, 445236, 445238, 445262, 445264, 445271, 445279, 445283, 445294, 445295, 445312, 445313, 445337, 445347, 445349, 445350, 445358, 445370, 445372, 445373, 445377, 445379, 445394, 445401, 445403, 445413, 445414, 445416, 445418, 445420, 445423, 445436, 445448, 445457, 445475, 445476, 445477, 445489, 445492, 445496, 445504, 445509, 445515, 445523, 445530, 445539, 445540, 445541, 445543, 445546, 445558, 445564, 445576, 445586, 445592, 445600, 445606, 445608, 445616, 445630, 445642, 445643, 445665, 445666, 445676, 445677, 445679, 445696, 445697, 445702, 445713, 445725, 445727, 445736, 445743, 445752, 445754, 445756, 445765, 445783, 445784, 445798, 445802, 445813, 445817, 445829, 445839, 445842, 445850, 445854, 445866, 445875, 445902, 445907, 445912, 445922, 445923, 445926, 445930, 445936, 445938, 445947, 445948, 445951, 445955, 445958, 445963, 445965, 445970, 446002, 446047, 446049, 446052, 446054, 446071, 446080, 446087, 446093, 446094, 446096, 446101, 446102, 446105, 446106, 446112, 446122, 446124, 446129, 446132, 446134, 446143, 446149, 446154, 446165, 446166, 446169, 446171, 446174, 446178, 446179, 446181, 446195, 446197, 446206, 446209, 446218, 446220, 446222, 446226, 446238, 446251, 446264, 446269, 446292, 446303, 446313, 446318, 446363, 446378, 446389, 446400, 446408, 446409, 446422, 446426, 446431, 446436, 446439, 446440, 446455, 446469, 446474, 446489, 446501, 446504, 446512, 446515, 446517, 446535, 446540, 446546, 446555, 446570, 446572, 446586, 446594, 446598, 446617, 446618, 446619, 446625, 446643, 446645, 446650, 446666, 446671, 446677, 446682, 446688, 446690, 446693, 446696, 446713, 446715, 446716, 446719, 446720, 446732, 446738, 446742, 446747, 446754, 446762, 446764, 446767, 446770, 446772, 446775, 446784, 446794, 446801, 446813, 446816, 446835, 446891, 446892, 446900, 446906, 446921, 446935, 446938, 446942, 446949, 446952, 446970, 446971, 446981, 446986, 446990, 447014, 447019, 447027, 447057, 447062, 447083, 447086, 447087, 447100, 447104, 447109, 447111, 447118, 447129, 447132, 447139, 447156, 447169, 447174, 447180, 447182, 447192, 447202, 447203, 447205, 447210, 447217, 447220, 447224, 447242, 447273, 447280, 447286, 447288, 447289, 447294, 447298, 447301, 447303, 447318, 447325, 447326, 447328, 447342, 447348, 447358, 447364, 447368, 447376, 447379, 447381, 447392, 447403, 447418, 447422, 447425, 447432, 447439, 447444, 447445, 447459, 447462, 447464, 447478, 447480, 447493, 447495, 447497, 447498, 447507, 447517, 447530, 447549, 447554, 447560, 447567, 447571, 447610, 447619, 447632, 447635, 447642, 447650, 447654, 447675, 447678, 447686, 447688, 447693, 447696, 447698, 447725, 447738, 447751, 447777, 447784, 447788, 447789, 447815, 447817, 447824, 447827, 447828, 447832, 447833, 447835, 447850, 447853, 447856, 447858, 447864, 447866, 447867, 447875, 447876, 447883, 447885, 447886, 447908, 447915, 447923, 447962, 447969, 447979, 447982, 447984, 448002, 448006, 448012, 448017, 448023, 448038, 448063, 448065, 448066, 448074, 448088, 448092, 448095, 448100, 448103, 448110, 448117, 448132, 448140, 448141, 448157, 448158, 448163, 448170, 448175, 448178, 448189, 448193, 448203, 448210, 448211, 448213, 448235, 448238, 448249, 448250, 448260, 448263, 448267, 448275, 448286, 448287, 448291, 448292, 448297, 448298, 448312, 448313, 448318, 448320, 448321, 448336, 448341, 448348, 448354, 448358, 448363, 448367, 448371, 448376, 448377, 448389, 448394, 448402, 448403, 448408, 448422, 448428, 448430, 448442, 448444, 448446, 448449, 448461, 448462, 448486, 448501, 448502, 448508, 448520, 448523, 448526, 448552, 448556, 448557, 448570, 448574, 448579, 448589, 448605, 448610, 448622, 448624, 448635, 448641, 448661, 448665, 448701, 448702, 448705, 448706, 448707, 448709, 448722, 448738, 448754, 448760, 448761, 448768, 448773, 448777, 448790, 448793, 448802, 448803, 448804, 448807, 448808, 448814, 448815, 448828, 448836, 448839, 448850, 448857, 448859, 448865, 448871, 448872, 448877, 448884, 448890, 448896, 448901, 448917, 448919, 448925, 448938, 448941, 448949, 448965, 448974, 448976, 448981, 448994, 448995, 448996, 449006, 449014, 449022, 449024, 449027, 449032, 449038, 449042, 449047, 449049, 449054, 449056, 449057, 449058, 449060, 449062, 449077, 449079, 449080, 449086, 449096, 449100, 449111, 449125, 449145, 449147, 449151, 449179, 449182, 449188, 449193, 449203, 449213, 449220, 449227, 449232, 449257, 449272, 449282, 449288, 449309, 449311, 449312, 449317, 449323, 449327, 449330, 449335, 449343, 449346, 449347, 449359, 449360, 449361, 449383, 449394, 449402, 449409, 449427, 449428, 449429, 449446, 449450, 449457, 449458, 449483, 449484, 449490, 449492, 449499, 449500, 449504, 449505, 449516, 449526, 449531, 449539, 449541, 449543, 449544, 449550, 449557, 449559, 449564, 449566, 449571, 449574, 449581, 449582, 449592, 449596, 449601, 449614, 449616, 449618, 449645, 449649, 449654, 449657, 449661, 449676, 449677, 449729, 449731, 449753, 449757, 449762, 449768, 449769, 449771, 449794, 449800, 449810, 449814, 449815, 449817, 449818, 449819, 449825, 449828, 449843, 449846, 449853, 449858, 449874, 449875, 449881, 449889, 449905, 449909, 449919, 449924, 449926, 449931, 449932, 449934, 449947, 449950, 449960, 449967, 449970, 449972, 449983, 449984, 449986, 449989, 449996, 450017, 450024, 450031, 450033, 450038, 450047, 450055, 450058, 450059, 450062, 450066, 450074, 450079, 450080, 450092, 450108, 450120, 450122, 450123, 450128, 450132, 450145, 450164, 450179, 450187, 450199, 450210, 450246, 450261, 450264, 450279, 450281, 450285, 450295, 450298, 450300, 450309, 450321, 450326, 450332, 450341, 450344, 450347, 450348, 450358, 450368, 450376, 450379, 450390, 450391, 450400, 450432, 450436, 450438, 450477, 450498, 450505, 450516, 450518, 450536, 450541, 450548, 450549, 450550, 450551, 450552, 450554, 450558, 450561, 450570, 450599, 450600, 450605, 450607, 450629, 450630, 450639, 450648, 450649, 450655, 450657, 450666, 450670, 450697, 450700, 450702, 450704, 450705, 450707, 450710, 450712, 450714, 450718, 450721, 450731, 450749, 450750, 450753, 450757, 450759, 450770, 450777, 450787, 450790, 450794, 450807, 450818, 450835, 450842, 450854, 450860, 450862, 450868, 450869, 450874, 450886, 450900, 450903, 450904, 450920, 450925, 450933, 450934, 450935, 450940, 450951, 450974, 450979, 450980, 450981, 450982, 450983, 450990, 450993, 450996, 451013, 451015, 451020, 451021, 451023, 451026, 451029, 451030, 451032, 451033, 451034, 451041, 451043, 451045, 451052, 451054, 451060, 451063, 451073, 451078, 451100, 451106, 451108, 451120, 451134, 451138, 451144, 451146, 451152, 451161, 451162, 451164, 451173, 451176, 451179, 451183, 451190, 451193, 451206, 451216, 451223, 451236, 451240, 451242, 451249, 451257, 451258, 451267, 451269, 451276, 451284, 451285, 451291, 451292, 451297, 451318, 451319, 451320, 451323, 451324, 451333, 451354, 451364, 451367, 451373, 451388, 451409, 451412, 451417, 451421, 451422, 451425, 451426, 451428, 451437, 451441, 451443, 451466, 451467, 451469, 451474, 451485, 451496, 451504, 451506, 451516, 451544, 451545, 451546, 451549, 451555, 451571, 451572, 451576, 451580, 451582, 451588, 451625, 451628, 451632, 451641, 451645, 451646, 451648, 451655, 451656, 451657, 451658, 451661, 451668, 451675, 451676, 451679, 451683, 451708, 451723, 451729, 451731, 451745, 451748, 451765, 451777, 451782, 451788, 451789, 451791, 451795, 451803, 451806, 451807, 451811, 451814, 451821, 451828, 451833, 451858, 451869, 451870, 451871, 451876, 451877, 451878, 451886, 451895, 451901, 451914, 451916, 451917, 451920, 451922, 451931, 451932, 451939, 451949, 451953, 451957, 451959, 451964, 451973, 451974, 451978, 451982, 451985, 451998, 452001, 452008, 452011, 452012, 452018, 452019, 452026, 452027, 452041, 452056, 452057, 452062, 452064, 452068, 452077, 452080, 452089, 452111, 452114, 452115, 452116, 452127, 452130, 452132, 452133, 452140, 452142, 452144, 452147, 452148, 452154, 452156, 452160, 452166, 452167, 452169, 452178, 452179, 452180, 452181, 452184, 452185, 452186, 452188, 452200, 452214, 452228, 452237, 452244, 452254, 452256, 452260, 452266, 452276, 452278, 452280, 452283, 452284, 452296, 452298, 452300, 452329, 452337, 452340, 452346, 452353, 452361, 452364, 452367, 452379, 452393, 452404, 452413, 452426, 452429, 452433, 452445, 452453, 452456, 452472, 452474, 452476, 452480, 452483, 452484, 452485, 452490, 452493, 452496, 452500, 452512, 452514, 452515, 452520, 452522, 452541, 452579, 452655, 452672, 452686, 452692, 452694, 452696, 452707, 452713, 452724, 452730, 452731, 452735, 452746, 452748, 452756, 452766, 452770, 452784, 452791, 452792, 452797, 452816, 452818, 452826, 452827, 452832, 452877, 452879, 452882, 452885, 452886, 452902, 452915, 452918, 452935, 452942, 452944, 452945, 452951, 452964, 452966, 452973, 452977, 452982, 452995, 453000, 453024, 453025, 453030, 453035, 453042, 453053, 453060, 453070, 453082, 453086, 453090, 453093, 453097, 453108, 453111, 453112, 453130, 453134, 453141, 453145, 453149, 453153, 453155, 453156, 453162, 453165, 453173, 453179, 453184, 453185, 453202, 453205, 453210, 453223, 453224, 453230, 453232, 453236, 453243, 453246, 453247, 453249, 453255, 453268, 453287, 453298, 453309, 453316, 453321, 453322, 453324, 453328, 453333, 453336, 453350, 453362, 453363, 453370, 453384, 453393, 453404, 453433, 453437, 453444, 453445, 453455, 453459, 453505, 453513, 453522, 453540, 453542, 453549, 453552, 453553, 453555, 453562, 453567, 453571, 453583, 453595, 453596, 453600, 453606, 453618, 453621, 453629, 453631, 453639, 453640, 453659, 453668, 453673, 453684, 453695, 453696, 453715, 453725, 453730, 453731, 453736, 453740, 453744, 453751, 453765, 453774, 453779, 453782, 453788, 453791, 453796, 453816, 453819, 453820, 453827, 453835, 453841, 453851, 453853, 453854, 453865, 453866, 453875, 453877, 453880, 453885, 453886, 453889, 453893, 453895, 453901, 453924, 453932, 453934, 453935, 453949, 453954, 453957, 453965, 453968, 453970, 453978, 453984, 453989, 453996, 454009, 454010, 454012, 454015, 454019, 454026, 454029, 454031, 454034, 454044, 454062, 454067, 454075, 454080, 454083, 454093, 454094, 454111, 454122, 454124, 454131, 454139, 454142, 454152, 454158, 454160, 454165, 454168, 454181, 454182, 454185, 454196, 454199, 454204, 454205, 454211, 454214, 454221, 454244, 454255, 454256, 454264, 454265, 454267, 454303, 454305, 454329, 454336, 454339, 454345, 454371, 454372, 454377, 454378, 454379, 454424, 454425, 454430, 454439, 454445, 454449, 454450, 454452, 454454, 454461, 454475, 454483, 454489, 454492, 454502, 454511, 454513, 454515, 454516, 454526, 454529, 454531, 454541, 454542, 454548, 454565, 454572, 454584, 454595, 454599, 454604, 454606, 454608, 454611, 454612, 454615, 454617, 454618, 454620, 454621, 454639, 454641, 454646, 454650, 454653, 454658, 454671, 454675, 454683, 454685, 454688, 454710, 454718, 454722, 454723, 454738, 454746, 454755, 454775, 454776, 454787, 454788, 454797, 454798, 454812, 454814, 454816, 454817, 454820, 454842, 454846, 454858, 454865, 454868, 454880, 454882, 454896, 454900, 454901, 454905, 454923, 454933, 454938, 454947, 454951, 454958, 454962, 454963, 454971, 454972, 454979, 454984, 455011, 455014, 455017, 455020, 455025, 455032, 455034, 455036, 455051, 455055, 455056, 455059, 455060, 455065, 455067, 455072, 455080, 455097, 455113, 455121, 455135, 455137, 455147, 455154, 455166, 455169, 455200, 455201, 455205, 455216, 455218, 455228, 455234, 455240, 455256, 455263, 455270, 455272, 455273, 455281, 455301, 455305, 455312, 455315, 455318, 455320, 455326, 455328, 455330, 455341, 455346, 455356, 455370, 455372, 455386, 455389, 455413, 455414, 455421, 455428, 455429, 455432, 455433, 455442, 455445, 455449, 455451, 455452, 455463, 455466, 455468, 455483, 455507, 455512, 455517, 455527, 455544, 455546, 455548, 455566, 455574, 455575, 455583, 455585, 455586, 455592, 455601, 455602, 455604, 455605, 455607, 455610, 455620, 455635, 455649, 455655, 455668, 455672, 455679, 455690, 455692, 455700, 455710, 455721, 455725, 455732, 455734, 455739, 455750, 455758, 455760, 455762, 455766, 455768, 455783, 455790, 455804, 455813, 455814, 455842, 455846, 455852, 455856, 455865, 455867, 455869, 455875, 455882, 455887, 455900, 455903, 455917, 455924, 455931, 455935, 455936, 455958, 455962, 455966, 455969, 455985, 456007, 456031, 456061, 456064, 456069, 456078, 456082, 456087, 456094, 456098, 456111, 456113, 456125, 456127, 456133, 456134, 456148, 456162, 456171, 456176, 456177, 456188, 456191, 456198, 456205, 456216, 456233, 456245, 456253, 456266, 456268, 456277, 456278, 456280, 456282, 456291, 456292, 456293, 456298, 456300, 456308, 456310, 456314, 456321, 456339, 456342, 456351, 456361, 456367, 456380, 456392, 456394, 456406, 456410, 456430, 456431, 456434, 456439, 456455, 456459, 456463, 456469, 456473, 456477, 456485, 456493, 456512, 456531, 456551, 456580, 456583, 456586, 456597, 456608, 456613, 456619, 456639, 456647, 456677, 456684, 456686, 456694, 456695, 456702, 456713, 456719, 456720, 456721, 456733, 456741, 456747, 456749, 456775, 456778, 456779, 456781, 456813, 456817, 456821, 456834, 456836, 456846, 456852, 456854, 456885, 456899, 456905, 456907, 456909, 456914, 456934, 456941, 456943, 456949, 456982, 456984, 457002, 457004, 457008, 457013, 457035, 457063, 457065, 457068, 457070, 457073, 457090, 457102, 457111, 457118, 457119, 457127, 457128, 457132, 457136, 457143, 457147, 457150, 457153, 457161, 457184, 457214, 457224, 457234, 457249, 457250, 457260, 457262, 457264, 457275, 457282, 457286, 457293, 457296, 457303, 457308, 457322, 457326, 457346, 457354, 457355, 457357, 457358, 457360, 457365, 457366, 457369, 457377, 457409, 457429, 457441, 457457, 457470, 457473, 457478, 457480, 457482, 457502, 457507, 457510, 457514, 457524, 457534, 457535, 457536, 457544, 457557, 457562, 457564, 457566, 457571, 457579, 457583, 457587, 457594, 457599, 457613, 457619, 457620, 457630, 457631, 457642, 457654, 457663, 457669, 457682, 457683, 457704, 457729, 457892, 457895, 457901, 457904, 457907, 457908, 457910, 457915, 457920, 457923, 457924, 457933, 457935, 457936, 457943, 457946, 457947, 457967, 457970, 457992, 458000, 458005, 458008, 458021, 458022, 458027, 458032, 458043, 458080, 458121, 458122, 458131, 458133, 458135, 458142, 458143, 458144, 458152, 458165, 458170, 458173, 458180, 458198, 458205, 458207, 458215, 458221, 458224, 458227, 458230, 458232, 458243, 458259, 458275, 458277, 458284, 458293, 458295, 458307, 458316, 458317, 458318, 458327, 458340, 458348, 458359, 458372, 458402, 458403, 458419, 458420, 458422, 458444, 458445, 458461, 458463, 458464, 458470, 458490, 458501, 458512, 458526, 458532, 458538, 458544, 458550, 458591, 458604, 458610, 458619, 458620, 458625, 458632, 458635, 458643, 458648, 458669, 458671, 458682, 458692, 458699, 458700, 458702, 458713, 458724, 458730, 458732, 458745, 458746, 458770, 458779, 458784, 458796, 458803, 458804, 458815, 458818, 458828, 458839, 458840, 458853, 458856, 458875, 458889, 458893, 458908, 458925, 458938, 458940, 458967, 458968, 458978, 458999, 459014, 459020, 459022, 459024, 459025, 459039, 459048, 459053, 459059, 459064, 459071, 459086, 459089, 459091, 459092, 459103, 459104, 459105, 459106, 459115, 459119, 459126, 459131, 459135, 459139, 459150, 459157, 459158, 459164, 459167, 459184, 459190, 459193, 459203, 459216, 459225, 459238, 459242, 459247, 459265, 459292, 459302, 459306, 459309, 459316, 459318, 459319, 459322, 459335, 459341, 459347, 459350, 459351, 459360, 459369, 459383, 459390, 459459, 459472, 459475, 459483, 459489, 459492, 459496, 459497, 459498, 459500, 459508, 459510, 459515, 459516, 459529, 459540, 459544, 459548, 459550, 459552, 459563, 459583, 459600, 459616, 459626, 459636, 459638, 459643, 459645, 459652, 459654, 459655, 459660, 459661, 459675, 459676, 459696, 459703, 459706, 459707, 459723, 459725, 459728, 459734, 459739, 459746, 459748, 459758, 459762, 459773, 459785, 459787, 459801, 459809, 459827, 459831, 459839, 459851, 459853, 459856, 459859, 459864, 459880, 459888, 459891, 459911, 459923, 459937, 459952, 459955, 459961, 459971, 459972, 459979, 459980, 459985, 459986, 459992, 459999, 460008, 460015, 460017, 460018, 460032, 460046, 460050, 460062, 460063, 460082, 460091, 460092, 460124, 460137, 460153, 460174, 460189, 460207, 460211, 460214, 460216, 460222, 460231, 460234, 460237, 460250, 460251, 460253, 460258, 460259, 460290, 460317, 460321, 460325, 460334, 460340, 460342, 460343, 460357, 460364, 460366, 460379, 460380, 460382, 460385, 460394, 460397, 460401, 460415, 460418, 460421, 460434, 460457, 460499, 460516, 460519, 460520, 460523, 460524, 460545, 460549, 460558, 460563, 460565, 460567, 460569, 460578, 460586, 460587, 460589, 460600, 460610, 460611, 460617, 460618, 460623, 460625, 460633, 460635, 460650, 460655, 460662, 460675, 460680, 460691, 460700, 460702, 460705, 460720, 460723, 460736, 460738, 460739, 460745, 460747, 460748, 460761, 460768, 460772, 460783, 460786, 460809, 460817, 460821, 460832, 460843, 460847, 460865, 460869, 460873, 460876, 460910, 460913, 460919, 460929, 460948, 460949, 460953, 460961, 460971, 460973, 460981, 460985, 460989, 460992, 460993, 460997, 461005, 461008, 461009, 461014, 461023, 461024, 461030, 461047, 461052, 461060, 461066, 461074, 461089, 461095, 461103, 461107, 461114, 461137, 461148, 461165, 461178, 461195, 461210, 461241, 461255, 461257, 461262, 461265, 461267, 461270, 461279, 461281, 461286, 461315, 461316, 461318, 461342, 461351, 461352, 461355, 461369, 461371, 461382, 461388, 461389, 461392, 461400, 461410, 461418, 461437, 461438, 461451, 461467, 461485, 461494, 461504, 461508, 461509, 461520, 461526, 461539, 461553, 461554, 461560, 461574, 461576, 461577, 461592, 461606, 461607, 461608, 461610, 461615, 461627, 461643, 461648, 461650, 461652, 461655, 461671, 461679, 461684, 461702, 461708, 461713, 461714, 461720, 461749, 461758, 461764, 461765, 461770, 461772, 461779, 461786, 461787, 461788, 461804, 461816, 461854, 461864, 461879, 461906, 461916, 461922, 461938, 461943, 461954, 461962, 461964, 461977, 461982, 461991, 462014, 462019, 462024, 462030, 462036, 462038, 462044, 462050, 462055, 462066, 462080, 462082, 462097, 462103, 462108, 462115, 462133, 462136, 462137, 462150, 462151, 462152, 462156, 462158, 462160, 462161, 462166, 462175, 462179, 462185, 462186, 462191, 462198, 462209, 462215, 462220, 462236, 462240, 462244, 462253, 462256, 462259, 462271, 462274, 462279, 462280, 462283, 462284, 462292, 462305, 462309, 462315, 462319, 462324, 462331, 462333, 462335, 462340, 462342, 462346, 462350, 462352, 462354, 462361, 462363, 462365, 462366, 462367, 462369, 462374, 462386, 462388, 462395, 462403, 462407, 462409, 462411, 462423, 462425, 462436, 462438, 462445, 462458, 462462, 462466, 462467, 462473, 462476, 462478, 462485, 462492, 462500, 462501, 462502, 462508, 462519, 462520, 462528, 462533, 462542, 462548, 462554, 462558, 462560, 462564, 462586, 462596, 462598, 462599, 462603, 462607, 462615, 462619, 462620, 462625, 462643, 462644, 462652, 462653, 462668, 462693, 462694, 462725, 462727, 462731, 462737, 462738, 462748, 462750, 462757, 462764, 462771, 462779, 462781, 462784, 462797, 462798, 462815, 462816, 462818, 462819, 462824, 462830, 462844, 462856, 462873, 462874, 462880, 462887, 462890, 462900, 462906, 462910, 462913, 462922, 462925, 462927, 462928, 462930, 462938, 462944, 462959, 462966, 462972, 462973, 462978, 462988, 462989, 463007, 463009, 463013, 463018, 463021, 463029, 463046, 463055, 463061, 463062, 463064, 463076, 463078, 463080, 463081, 463089, 463091, 463095, 463112, 463123, 463126, 463129, 463133, 463141, 463145, 463149, 463156, 463158, 463164, 463166, 463176, 463182, 463185, 463189, 463190, 463201, 463204, 463210, 463211, 463216, 463218, 463223, 463240, 463246, 463249, 463254, 463279, 463294, 463296, 463299, 463301, 463304, 463306, 463309, 463311, 463313, 463316, 463317, 463323, 463345, 463349, 463356, 463367, 463407, 463421, 463434, 463440, 463442, 463443, 463444, 463454, 463457, 463462, 463469, 463475, 463479, 463482, 463484, 463488, 463495, 463497, 463498, 463502, 463508, 463517, 463528, 463531, 463536, 463547, 463551, 463573, 463591, 463608, 463613, 463620, 463630, 463631, 463632, 463639, 463641, 463645, 463654, 463657, 463660, 463663, 463667, 463669, 463671, 463672, 463673, 463680, 463681, 463687, 463689, 463690, 463691, 463718, 463723, 463731, 463735, 463748, 463752, 463753, 463758, 463762, 463766, 463770, 463771, 463772, 463789, 463791, 463795, 463814, 463826, 463829, 463831, 463833, 463839, 463843, 463846, 463852, 463857, 463858, 463859, 463863, 463864, 463869, 463873, 463875, 463887, 463889, 463892, 463899, 463900, 463901, 463907, 463908, 463922, 463926, 463931, 463933, 463934, 463943, 463948, 463954, 463956, 463970, 463974, 463979, 463993, 463996, 463997, 464006, 464008, 464017, 464022, 464023, 464027, 464029, 464031, 464032, 464036, 464057, 464058, 464060, 464061, 464065, 464080, 464085, 464091, 464092, 464099, 464102, 464109, 464110, 464116, 464118, 464134, 464135, 464136, 464141, 464144, 464149, 464152, 464154, 464168, 464169, 464174, 464180, 464192, 464200, 464204, 464208, 464212, 464216, 464229, 464234, 464246, 464253, 464258, 464267, 464268, 464272, 464288, 464294, 464326, 464331, 464338, 464343, 464346, 464350, 464351, 464363, 464376, 464392, 464397, 464401, 464412, 464415, 464416, 464419, 464422, 464424, 464426, 464428, 464430, 464432, 464436, 464443, 464444, 464449, 464455, 464461, 464464, 464470, 464471, 464476, 464482, 464485, 464497, 464498, 464500, 464510, 464518, 464521, 464529, 464545, 464585, 464599, 464600, 464601, 464618, 464628, 464629, 464632, 464633, 464635, 464642, 464667, 464669, 464677, 464684, 464686, 464687, 464689, 464690, 464694, 464705, 464710, 464711, 464721, 464728, 464729, 464737, 464743, 464750, 464751, 464766, 464773, 464778, 464787, 464789, 464790, 464797, 464801, 464804, 464806, 464808, 464810, 464811, 464826, 464827, 464835, 464840, 464844, 464855, 464857, 464864, 464867, 464869, 464870, 464876, 464882, 464887, 464890, 464893, 464896, 464899, 464906, 464907, 464923, 464924, 464926, 464935, 464937, 464940, 464942, 464950, 464954, 464955, 464957, 464959, 464960, 464964, 464977, 464982, 464986, 464993, 464996, 465019, 465029, 465038, 465050, 465051, 465055, 465059, 465062, 465065, 465071, 465075, 465076, 465091, 465105, 465112, 465115, 465126, 465135, 465144, 465145, 465148, 465156, 465160, 465161, 465176, 465183, 465199, 465200, 465220, 465223, 465226, 465232, 465238, 465239, 465243, 465244, 465252, 465254, 465256, 465262, 465281, 465291, 465296, 465300, 465302, 465305, 465321, 465327, 465331, 465342, 465369, 465374, 465382, 465389, 465392, 465395, 465398, 465401, 465406, 465413, 465422, 465423, 465427, 465430, 465438, 465440, 465445, 465463, 465467, 465483, 465484, 465491, 465493, 465495, 465500, 465516, 465517, 465533, 465535, 465539, 465542, 465559, 465564, 465566, 465570, 465572, 465575, 465577, 465580, 465581, 465597, 465602, 465603, 465604, 465614, 465629, 465634, 465638, 465641, 465642, 465645, 465657, 465665, 465671, 465672, 465698, 465709, 465710, 465733, 465735, 465737, 465743, 465744, 465745, 465748, 465749, 465758, 465760, 465767, 465770, 465797, 465798, 465802, 465804, 465814, 465817, 465828, 465952, 465957, 465965, 465976, 465983, 465993, 466029, 466035, 466036, 466043, 466046, 466053, 466060, 466062, 466076, 466083, 466084, 466086, 466107, 466130, 466133, 466136, 466141, 466155, 466163, 466167, 466185, 466188, 466194, 466213, 466214, 466216, 466225, 466233, 466238, 466261, 466270, 466287, 466299, 466302, 466303, 466317, 466323, 466331, 466334, 466353, 466354, 466363, 466366, 466369, 466376, 466377, 466391, 466392, 466395, 466408, 466414, 466422, 466424, 466426, 466430, 466472, 466483, 466487, 466518, 466560, 466569, 466576, 466588, 466597, 466601, 466610, 466618, 466621, 466627, 466628, 466634, 466643, 466645, 466649, 466659, 466678, 466680, 466692, 466722, 466746, 466748, 466758, 466761, 466765, 466813, 466825, 466829, 466835, 466850, 466860, 466862, 466878, 466887, 466890, 466891, 466897, 466911, 466933, 466934, 466951, 466955, 466966, 466969, 466975, 466978, 466992, 467004, 467027, 467038, 467039, 467041, 467050, 467059, 467060, 467076, 467098, 467100, 467103, 467104, 467127, 467131, 467152, 467163, 467170, 467215, 467224, 467225, 467278, 467301, 467336, 467338, 467345, 467355, 467365, 467380, 467381, 467390, 467413, 467424, 467439, 467442, 467450, 467456, 467484, 467488, 467496, 467520, 467576, 467577, 467583, 467597, 467646, 467650, 467663, 467669, 467670, 467672, 467689, 467701, 467704, 467706, 467737, 467743, 467754, 467771, 467774, 467799, 467802, 467821, 467843, 467844, 467856, 467868, 467873, 467884, 467886, 467893, 467902, 467963, 467971, 467979, 467984, 468011, 468014, 468037, 468046, 468054, 468059, 468060, 468078, 468082, 468085, 468097, 468107, 468108, 468133, 468141, 468166, 468175, 468195, 468212, 468247, 468254, 468255, 468259, 468282, 468284, 468300, 468314, 468326, 468334, 468340, 468342, 468343, 468364, 468367, 468394, 468396, 468404, 468446, 468485, 468488, 468494, 468503, 468507, 468531, 468542, 468543, 468546, 468549, 468552, 468554, 468562, 468571, 468583, 468620, 468625, 468634, 468639, 468640, 468646, 468649, 468661, 468669, 468674, 468687, 468728, 468735, 468746, 468777, 468786, 468794, 468797, 468805, 468807, 468810, 468820, 468826, 468838, 468843, 468852, 468853, 468855, 468861, 468864, 468866, 468872, 468874, 468875, 468876, 468878, 468880, 468887, 468946, 468963, 468971, 468978, 468982, 468991, 469025, 469046, 469047, 469050, 469052, 469063, 469099, 469102, 469105, 469107, 469108, 469109, 469111, 469112, 469114, 469121, 469126, 469132, 469134, 469140, 469174, 469187, 469193, 469199, 469205, 469209, 469233, 469234, 469255, 469271, 469284, 469288, 469295, 469301, 469302, 469309, 469349, 469352, 469355, 469380, 469401, 469403, 469412, 469414, 469424, 469435, 469439, 469441, 469461, 469465, 469470, 469475, 469486, 469492, 469525, 469546, 469559, 469589, 469591, 469613, 469618, 469634, 469641, 469664, 469666, 469680, 469702, 469720, 469724, 469730, 469736, 469741, 469747, 469748, 469750, 469755, 469758, 469784, 469788, 469797, 469811, 469834, 469839, 469842, 469845, 469853, 469854, 469856, 469868, 469890, 469896, 469904, 469908, 469910, 469916, 469923, 469924, 469926, 469947, 469997, 469999, 470014, 470016, 470017, 470040, 470047, 470058, 470092, 470109, 470140, 470197, 470308, 470338, 470614, 470642, 470657, 470669, 470675, 470693, 470735, 470739, 470763, 470772, 470774, 470782, 470786, 470793, 470799, 470806, 470808, 470811, 470815, 470818, 470843, 470844, 470851, 470854, 470871, 470880, 470884, 470888, 470889, 470907, 470912, 470931, 470946, 470959, 470962, 470967, 470984, 471010, 471025, 471055, 471056, 471072, 471074, 471082, 471093, 471119, 471127, 471166, 471204, 471205, 471207, 471211, 471212, 471216, 471218, 471228, 471246, 471270, 471291, 471294, 471321, 471383, 471416, 471432, 471445, 471457, 471476, 471493, 471497, 471498, 471501, 471504, 471507, 471508, 471524, 471527, 471533, 471536, 471545, 471564, 471582, 471584, 471586, 471591, 471610, 471618, 471662, 471684, 471701, 471727, 471729, 471740, 471741, 471801, 471812, 471835, 471843, 471849, 471852, 471866, 471875, 471883, 471884, 471888, 471905, 471918, 471951, 471958, 471985, 472051, 472052, 472061, 472073, 472097, 472124, 472131, 472160, 472177, 472182, 472184, 472188, 472192, 472200, 472223, 472224, 472247, 472264, 472266, 472272, 472288, 472312, 472326, 472331, 472344, 472374, 472378, 472385, 472398, 472408, 472421, 472435, 472457, 472460, 472463, 472465, 472469, 472477, 472486, 472494, 472520, 472523, 472557, 472567, 472602, 472607, 472674, 472684, 472688, 472689, 472720, 472731, 472740, 472745, 472784, 472802, 472816, 472844, 472906, 472919, 472957, 472962, 472983, 472989, 473034, 473162, 473197, 473202, 473215, 473241, 473245, 473248, 473250, 473251, 473252, 473284, 473313, 473321, 473341, 473343, 473366, 473401, 473426, 473469, 473481, 473506, 473517, 473519, 473579, 473580, 473600, 473653, 473685, 473784, 473785, 473886, 473893, 473895, 473897, 473898, 473907, 473908, 473932, 473940, 473945, 473956, 473960, 473965, 473973, 473985, 474148, 474269, 474270, 474277, 474295, 474306, 474309, 474321, 474333, 474336, 474355, 474363, 474365, 474368, 474397, 474399, 474405, 474415, 474421, 474451, 474462, 474476, 474509, 474510, 474511, 474512, 474514, 474519, 474524, 474534, 474540, 474545, 474565, 474568, 474572, 474575, 474577, 474587, 474593, 474608, 474616, 474630, 474644, 474650, 474652, 474656, 474683, 474692, 474707, 474722, 474727, 474729, 474732, 474742, 474750, 474760, 474782, 474785, 474788, 474793, 474797, 474808, 474829, 474833, 474837, 474838, 474845, 474856, 474864, 474868, 474872, 474880, 474882, 474901, 474906, 474908, 474912, 474919, 474921, 474937, 474949, 474951, 474959, 474972, 474976, 474988, 474994, 475002, 475006, 475009, 475010, 475051, 475059, 475071, 475075, 475079, 475098, 475101, 475119, 475126, 475127, 475135, 475139, 475142, 475146, 475147, 475168, 475171, 475180, 475189, 475208, 475226, 475246, 475250, 475269, 475294, 475297, 475303, 475307, 475314, 475319, 475323, 475324, 475327, 475331, 475350, 475352, 475353, 475374, 475382, 475383, 475403, 475414, 475418, 475429, 475431, 475434, 475445, 475454, 475467, 475477, 475487, 475489, 475491, 475498, 475501, 475509, 475514, 475521, 475523, 475529, 475540, 475544, 475554, 475564, 475567, 475568, 475581, 475594, 475598, 475606, 475609, 475613, 475626, 475638, 475648, 475650, 475651, 475654, 475682, 475693, 475697, 475698, 475700, 475713, 475718, 475719, 475724, 475728, 475737, 475739, 475774, 475800, 475802, 475807, 475812, 475821, 475835, 475841, 475858, 475886, 475896, 475901, 475920, 475937, 475939, 475942, 475958, 475959, 475971, 475972, 475982, 475983, 475988, 475989, 476005, 476007, 476009, 476016, 476023, 476052, 476068, 476070, 476080, 476083, 476097, 476100, 476101, 476117, 476118, 476119, 476124, 476134, 476137, 476139, 476157, 476166, 476167, 476172, 476179, 476180, 476182, 476206, 476215, 476222, 476241, 476243, 476255, 476265, 476269, 476272, 476278, 476285, 476310, 476319, 476326, 476338, 476341, 476351, 476371, 476372, 476375, 476378, 476384, 476393, 476419, 476424, 476433, 476439, 476453, 476467, 476476, 476483, 476487, 476491, 476512, 476514, 476515, 476520, 476521, 476532, 476535, 476540, 476550, 476566, 476577, 476579, 476587, 476593, 476604, 476614, 476615, 476624, 476633, 476647, 476651, 476660, 476668, 476670, 476671, 476685, 476686, 476691, 476697, 476719, 476722, 476725, 476729, 476733, 476736, 476757, 476762, 476782, 476783, 476785, 476793, 476799, 476804, 476809, 476814, 476830, 476843, 476848, 476849, 476855, 476860, 476875, 476891, 476900, 476902, 476915, 476916, 476918, 476924, 476931, 476939, 476945, 476972, 477006, 477014, 477017, 477023, 477036, 477038, 477051, 477053, 477059, 477071, 477074, 477082, 477098, 477102, 477106, 477107, 477110, 477126, 477128, 477130, 477133, 477169, 477173, 477179, 477180, 477203, 477209, 477221, 477222, 477223, 477225, 477228, 477247, 477258, 477265, 477268, 477280, 477300, 477310, 477315, 477325, 477327, 477336, 477340, 477351, 477366, 477389, 477398, 477408, 477413, 477440, 477450, 477455, 477465, 477472, 477492, 477506, 477523, 477525, 477537, 477539, 477559, 477593, 477596, 477605, 477606, 477618, 477621, 477628, 477638, 477639, 477652, 477668, 477676, 477685, 477692, 477698, 477714, 477716, 477717, 477729, 477731, 477751, 477758, 477763, 477787, 477791, 477795, 477806, 477832, 477854, 477856, 477860, 477885, 477895, 477903, 477905, 477908, 477928, 477933, 477942, 477948, 477978, 477984, 477986, 477995, 478003, 478006, 478009, 478013, 478016, 478018, 478022, 478029, 478033, 478034, 478043, 478063, 478075, 478092, 478126, 478140, 478149, 478165, 478167, 478178, 478180, 478185, 478189, 478199, 478204, 478210, 478212, 478214, 478240, 478257, 478271, 478273, 478276, 478294, 478309, 478312, 478316, 478328, 478331, 478357, 478381, 478407, 478414, 478417, 478422, 478445, 478450, 478472, 478473, 478490, 478497, 478536, 478557, 478572, 478578, 478596, 478609, 478635, 478640, 478643, 478647, 478649, 478656, 478671, 478683, 478688, 478700, 478704, 478713, 478715, 478721, 478729, 478731, 478735, 478737, 478747, 478755, 478759, 478761, 478768, 478788, 478793, 478798, 478813, 478823, 478830, 478836, 478844, 478846, 478848, 478852, 478858, 478862, 478864, 478865, 478881, 478895, 478903, 478904, 478926, 478927, 478930, 478939, 478942, 478946, 478956, 478959, 478973, 478985, 478998, 479004, 479032, 479037, 479054, 479066, 479070, 479071, 479075, 479117, 479119, 479158, 479182, 479190, 479200, 479202, 479217, 479220, 479221, 479281, 479296, 479298, 479311, 479313, 479319, 479342, 479343, 479360, 479391, 479393, 479425, 479435, 479437, 479449, 479454, 479463, 479464, 479470, 479474, 479477, 479478, 479480, 479492, 479494, 479495, 479518, 479521, 479526, 479576, 479590, 479597, 479614, 479620, 479621, 479648, 479650, 479655, 479683, 479701, 479703, 479706, 479723, 479729, 479730, 479744, 479760, 479775, 479782, 479790, 479793, 479797, 479804, 479810, 479844, 479846, 479856, 479857, 479895, 479898, 479901, 479918, 479919, 479920, 479924, 479929, 479930, 479933, 479940, 479953, 479960, 479964, 479978, 479988, 479990, 479992, 479998, 480021, 480023, 480028, 480034, 480036, 480068, 480072, 480074, 480082, 480087, 480091, 480112, 480114, 480117, 480125, 480138, 480158, 480167, 480175, 480183, 480184, 480202, 480204, 480208, 480214, 480215, 480224, 480230, 480242, 480246, 480250, 480265, 480272, 480275, 480284, 480298, 480302, 480319, 480320, 480325, 480329, 480342, 480359, 480367, 480369, 480373, 480391, 480435, 480438, 480441, 480442, 480443, 480445, 480451, 480455, 480470, 480473, 480476, 480478, 480480, 480488, 480492, 480499, 480500, 480507, 480511, 480528, 480532, 480533, 480534, 480544, 480580, 480583, 480585, 480586, 480589, 480590, 480617, 480624, 480628, 480633, 480659, 480665, 480673, 480686, 480690, 480707, 480726, 480729, 480731, 480739, 480743, 480747, 480759, 480764, 480775, 480782, 480785, 480786, 480789, 480795, 480796, 480806, 480812, 480816, 480851, 480863, 480872, 480873, 480876, 480882, 480883, 480884, 480892, 480897, 480900, 480904, 480910, 480911, 480919, 480920, 480921, 480931, 480941, 480948, 480950, 480993, 481006, 481044, 481092, 481108, 481122, 481128, 481130, 481133, 481175, 481200, 481204, 481217, 481218, 481227, 481231, 481275, 481285, 481292, 481304, 481309, 481311, 481320, 481340, 481347, 481352, 481354, 481359, 481376, 481420, 481422, 481430, 481436, 481451, 481452, 481465, 481479, 481486, 481559, 481562, 481565, 481567, 481568, 481569, 481571, 481586, 481656, 481668, 481669, 481678, 481691, 481696, 481701, 481703, 481706, 481714, 481717, 481719, 481759, 481760, 481771, 481780, 481782, 481792, 481800, 481808, 481813, 481820, 481831, 481832, 481834, 481835, 481857, 481865, 481876, 481879, 481882, 481883, 481891, 481901, 481904, 481906, 481910, 481911, 481913, 481916, 481929, 481939, 481942, 481943, 481969, 481974, 481975, 481981, 481985, 482024, 482036, 482038, 482054, 482077, 482084, 482127, 482129, 482136, 482138, 482145, 482195, 482203, 482204, 482207, 482213, 482217, 482221, 482237, 482238, 482246, 482248, 482268, 482271, 482277, 482313, 482315, 482323, 482329, 482336, 482343, 482351, 482354, 482357, 482358, 482359, 482363, 482403, 482408, 482421, 482426, 482432, 482437, 482444, 482447, 482455, 482456, 482459, 482463, 482468, 482474, 482484, 482485, 482488, 482491, 482497, 482502, 482505, 482509, 482518, 482522, 482523, 482524, 482527, 482528, 482532, 482543, 482545, 482548, 482549, 482567, 482574, 482578, 482580, 482582, 482583, 482589, 482593, 482599, 482601, 482609, 482611, 482618, 482627, 482644, 482656, 482657, 482663, 482669, 482674, 482675, 482677, 482703, 482779, 482790, 483404, 483419, 483504, 483524, 483535, 483556, 483558, 483559, 483572, 483635, 483653, 483676, 483684, 483696, 483701, 483709, 483754, 483766, 483779, 483790, 483808, 483813, 483828, 483841, 483857, 483870, 483937, 483954, 483977, 483979, 483990, 484005, 484007, 484016, 484054, 484060, 484065, 484068, 484094, 484103, 484108, 484118, 484119, 484131, 484141, 484170, 484187, 484191, 484211, 484217, 484240, 484244, 484281, 484285, 484292, 484299, 484302, 484320, 484325, 484335, 484340, 484354, 484355, 484372, 484380, 484385, 484405, 484412, 484413, 484493, 484495, 484502, 484511, 484513, 484519, 484529, 484561, 484568, 484576, 484586, 484624, 484631, 484643, 484704, 484711, 484724, 484727, 484730, 484738, 484752, 484760, 484773, 484779, 484781, 484782, 484785, 484828, 484830, 484834, 484838, 484876, 484882, 484887, 484934, 484942, 484944, 484952, 484997, 485000, 485003, 485007, 485010, 485018, 485032, 485071, 485082, 485083, 485103, 485129, 485175, 485180, 485181, 485182, 485238, 485245, 485255, 485257, 485279, 485280, 485285, 485318, 485394, 485401, 485406, 485410, 485415, 485416, 485473, 485479, 485482, 486548, 486553, 486558, 486572, 486583, 486584, 486590, 486596, 486610, 486625, 486641, 486642, 486645, 486652, 486659, 486666, 486673, 486680, 486685, 486686, 486697, 486705, 486726, 486729, 486730, 486731, 486736, 486749, 486752, 486754, 486756, 486778, 486779, 486782, 486784, 486808, 486821, 486825, 486833, 486836, 486841, 486845, 486855, 486866, 486873, 486879, 486881, 486887, 486901, 486905, 486906, 486907, 486955, 486968, 486970, 486976, 486980, 486983, 486994, 487004, 487008, 487029, 487033, 487034, 487045, 487057, 487059, 487068, 487077, 487081, 487100, 487101, 487104, 487110, 487114, 487127, 487130, 487132, 487143, 487149, 487150, 487154, 487158, 487178, 487199, 487203, 487213, 487214, 487218, 487238, 487240, 487252, 487262, 487275, 487280, 487289, 487293, 487307, 487310, 487314, 487320, 487324, 487337, 487343, 487357, 487377, 487381, 487391, 487400, 487410, 487424, 487426, 487434, 487445, 487470, 487486, 487492, 487495, 487499, 487506, 487507, 487515, 487527, 487539, 487541, 487554, 487555, 487571, 487580, 487581, 487586, 487588, 487592, 487593, 487597, 487604, 487606, 487610, 487620, 487626, 487650, 487651, 487652, 487656, 487662, 487664, 487677, 487678, 487704, 487706, 487718, 487720, 487742, 487757, 487761, 487780, 487787, 487795, 487801, 487818, 487854, 487865, 487868, 487879, 487885, 487886, 487894, 487919, 487924, 487932, 487950, 487957, 487970, 487982, 487996, 488014, 488022, 488024, 488033, 488035, 488038, 488046, 488051, 488057, 488058, 488060, 488062, 488063, 488073, 488094, 488101, 488103, 488111, 488122, 488124, 488136, 488138, 488154, 488160, 488168, 488195, 488196, 488209, 488216, 488217, 488220, 488229, 488238, 488256, 488290, 488297, 488304, 488305, 488310, 488311, 488321, 488332, 488344, 488345, 488367, 488373, 488380, 488385, 488399, 488410, 488414, 488423, 488430, 488436, 488439, 488440, 488446, 488455, 488468, 488471, 488489, 488491, 488497, 488536, 488540, 488563, 488573, 488582, 488589, 488596, 488600, 488640, 488683, 488750, 488751, 488752, 488763, 488768, 488770, 488825, 488837, 488842, 488960, 488967, 489001, 489003, 489016, 489050, 489059, 489061, 489066, 489105, 489108, 489110, 489129, 489149, 489151, 489161, 489162, 489169, 489180, 489185, 489192, 489198, 489200, 489217, 489220, 489226, 489230, 489233, 489238, 489242, 489255, 489256, 489283, 489299, 489304, 489311, 489316, 489318, 489321, 489332, 489339, 489341, 489345, 489354, 489357, 489366, 489374, 489382, 489386, 489389, 489398, 489400, 489407, 489408, 489411, 489416, 489421, 489424, 489425, 489436, 489457, 489458, 489459, 489470, 489471, 489475, 489480, 489484, 489491, 489505, 489506, 489527, 489533, 489535, 489537, 489538, 489546, 489548, 489558, 489565, 489567, 489569, 489576, 489577, 489584, 489586, 489590, 489603, 489606, 489607, 489608, 489615, 489617, 489620, 489628, 489630, 489631, 489641, 489643, 489644, 489647, 489657, 489662, 489665, 489669, 489673, 489679, 489699, 489723, 489727, 489728, 489740, 489752, 489795, 489797, 489826, 489829, 489830, 489859, 489871, 489879, 489888, 489896, 489898, 489905, 489906, 489912, 489913, 489916, 489938, 489944, 489958, 489965, 489980, 489992, 489998, 490000, 490017, 490019, 490032, 490033, 490044, 490054, 490081, 490088, 490105, 490116, 490119, 490124, 490125, 490130, 490132, 490141, 490161, 490162, 490168, 490175, 490180, 490188, 490199, 490205, 490210, 490237, 490244, 490245, 490248, 490249, 490264, 490268, 490272, 490283, 490286, 490294, 490304, 490312, 490316, 490321, 490328, 490340, 490348, 490356, 490358, 490366, 490367, 490373, 490383, 490387, 490398, 490401, 490431, 490436, 490437, 490439, 490448, 490469, 490470, 490477, 490480, 490483, 490489, 490491, 490493, 490498, 490506, 490508, 490510, 490515, 490516, 490544, 490547, 490548, 490570, 490583, 490584, 490592, 490610, 490611, 490621, 490630, 490639, 490644, 490649, 490650, 490657, 490673, 490676, 490680, 490682, 490683, 490686, 490689, 490694, 490703, 490725, 490731, 490748, 490761, 490775, 490776, 490784, 490785, 490787, 490789, 490791, 490793, 490805, 490808, 490815, 490823, 490832, 490833, 490835, 490841, 490843, 490846, 490847, 490866, 490867, 490871, 490876, 490878, 490888, 490895, 490899, 490900, 490906, 490907, 490912, 490932, 490933, 490935, 490946, 490947, 490949, 490951, 490955, 490958, 490959, 490968, 490975, 490976, 490980, 491006, 491007, 491008, 491020, 491024, 491032, 491034, 491037, 491039, 491041, 491042, 491046, 491048, 491069, 491070, 491079, 491080, 491082, 491084, 491087, 491090, 491094, 491099, 491106, 491107, 491110, 491111, 491112, 491116, 491118, 491119, 491130, 491134, 491135, 491150, 491168, 491171, 491176, 491180, 491181, 491187, 491199, 491200, 491201, 491219, 491223, 491233, 491237, 491238, 491240, 491243, 491247, 491250, 491255, 491256, 491258, 491261, 491265, 491270, 491271, 491272, 491276, 491278, 491280, 491287, 491291, 491305, 491313, 491318, 491319, 491320, 491321, 491323, 491325, 491326, 491327, 491329, 491330, 491335, 491342, 491345, 491346, 491365, 491371, 491373, 491376, 491377, 491390, 491396, 491397, 491408, 491412, 491417, 491418, 491420, 491426, 491434, 491436, 491444, 491448, 491454, 491455, 491463, 491465, 491478, 491484, 491488, 491506, 491507, 491529, 491533, 491534, 491546, 491557, 491558, 491563, 491579, 491594, 491596, 491600, 491603, 491624, 491635, 491636, 491652, 491656, 491659, 491662, 491664, 491665, 491669, 491672, 491675, 491680, 491685, 491687, 491689, 491690, 491694, 491696, 491705, 491716, 491723, 491727, 491730, 491735, 491736, 491739, 491746, 491757, 491763, 491767, 491774, 491776, 491780, 491784, 491788, 491791, 491796, 491798, 491834, 491836, 491837, 491845, 491846, 491848, 491854, 491860, 491866, 491874, 491876, 491877, 491878, 491887, 491895, 491896, 491900, 491904, 491909, 491912, 491913, 491916, 491918, 491920, 491936, 491940, 491945, 491947, 491953, 491960, 491964, 491968, 491979, 491986, 491991, 491992, 492000, 492021, 492022, 492035, 492054, 492055, 492056, 492080, 492132, 492135, 492146, 492155, 492171, 492179, 492189, 492191, 492192, 492209, 492215, 492219, 492236, 492240, 492242, 492247, 492250, 492270, 492286, 492292, 492312, 492315, 492323, 492327, 492341, 492385, 492390, 492397, 492424, 492429, 492430, 492440, 492441, 492442, 492443, 492451, 492459, 492479, 492482, 492488, 492500, 492516, 492519, 492521, 492522, 492523, 492525, 492535, 492574, 492576, 492578, 492582, 492585, 492588, 492592, 492600, 492610, 492612, 492618, 492632, 492639, 492648, 492674, 492691, 492694, 492701, 492714, 492715, 492717, 492720, 492730, 492731, 492749, 492761, 492766, 492771, 492777, 492785, 492806, 492811, 492814, 492822, 492826, 492849, 492850, 492861, 492864, 492866, 492872, 492888, 492895, 492908, 492918, 492929, 492936, 492940, 492942, 492968, 492982, 493008, 493023, 493029, 493033, 493035, 493042, 493056, 493066, 493075, 493106, 493130, 493132, 493142, 493146, 493150, 493158, 493160, 493165, 493174, 493184, 493191, 493207, 493214, 493217, 493222, 493225, 493229, 493233, 493259, 493286, 493291, 493300, 493302, 493319, 493334, 493343, 493360, 493376, 493385, 493386, 493387, 493391, 493394, 493399, 493400, 493408, 493411, 493413, 493420, 493423, 493424, 493425, 493426, 493434, 493444, 493452, 493466, 493468, 493469, 493490, 493491, 493497, 493508, 493509, 493511, 493512, 493514, 493515, 493527, 493546, 493561, 493566, 493567, 493574, 493595, 493616, 493618, 493626, 493641, 493650, 493653, 493655, 493683, 493686, 493690, 493702, 493710, 493727, 493738, 493752, 493762, 493765, 493780, 493782, 493784, 493788, 493793, 493802, 493809, 493812, 493817, 493830, 493861, 493868, 493886, 493888, 493892, 493897, 493907, 493912, 493915, 493916, 493925, 493927, 493947, 493949, 493965, 493967, 493972, 493975, 493979, 493990, 493992, 494000, 494003, 494006, 494008, 494016, 494050, 494059, 494066, 494067, 494071, 494075, 494083, 494089, 494090, 494097, 494103, 494104, 494112, 494119, 494123, 494124, 494125, 494133, 494137, 494145, 494164, 494168, 494169, 494184, 494211, 494236, 494251, 494256, 494259, 494263, 494276, 494279, 494291, 494293, 494297, 494307, 494309, 494310, 494324, 494335, 494348, 494368, 494378, 494379, 494382, 494390, 494391, 494392, 494398, 494414, 494428, 494434, 494441, 494458, 494460, 494461, 494469, 494476, 494488, 494489, 494494, 494495, 494496, 494502, 494521, 494523, 494528, 494536, 494537, 494538, 494548, 494555, 494578, 494592, 494594, 494595, 494607, 494617, 494627, 494645, 494647, 494648, 494659, 494660, 494665, 494667, 494676, 494680, 494684, 494685, 494688, 494689, 494700, 494701, 494713, 494727, 494750, 494752, 494754, 494758, 494765, 494769, 494783, 494789, 494791, 494801, 494808, 494818, 494826, 494828, 494830, 494839, 494846, 494852, 494856, 494858, 494865, 494875, 494881, 494903, 494910, 494913, 494918, 494922, 494928, 494962, 494963, 494966, 494967, 494981, 494983, 494987, 494993, 495005, 495018, 495022, 495023, 495024, 495039, 495042, 495048, 495054, 495075, 495079, 495092, 495104, 495115, 495136, 495137, 495140, 495145, 495148, 495156, 495163, 495165, 495166, 495169, 495178, 495179, 495188, 495204, 495217, 495226, 495232, 495238, 495249, 495251, 495254, 495256, 495283, 495289, 495291, 495292, 495298, 495299, 495307, 495308, 495313, 495314, 495330, 495333, 495339, 495349, 495353, 495354, 495361, 495367, 495369, 495371, 495376, 495399, 495402, 495403, 495410, 495426, 495441, 495470, 495475, 495477, 495480, 495481, 495495, 495499, 495500, 495503, 495508, 495517, 495519, 495525, 495534, 495535, 495544, 495548, 495564, 495580, 495585, 495593, 495602, 495617, 495622, 495635, 495664, 495666, 495678, 495681, 495689, 495710, 495724, 495726, 495737, 495767, 495769, 495772, 495774, 495776, 495795, 495797, 495800, 495802, 495810, 495826, 495829, 495837, 495842, 495845, 495852, 495868, 495870, 495877, 495881, 495890, 495904, 496171, 496175, 496185, 496189, 496190, 496193, 496195, 496197, 496198, 496199, 496207, 496226, 496227, 496228, 496236, 496243, 496244, 496245, 496247, 496263, 496277, 496286, 496290, 496299, 496301, 496325, 496336, 496341, 496367, 496403, 496405, 496417, 496428, 496431, 496454, 496457, 496470, 496477, 496494, 496504, 496516, 496518, 496535, 496546, 496557, 496564, 496565, 496570, 496576, 496580, 496603, 496611, 496617, 496626, 496636, 496643, 496650, 496664, 496665, 496678, 496680, 496684, 496703, 496704, 496711, 496720, 496726, 496727, 496730, 496731, 496737, 496742, 496748, 496750, 496756, 496762, 496777, 496783, 496792, 496805, 496818, 496834, 496836, 496846, 496876, 496880, 496881, 496904, 496915, 496920, 496923, 496933, 496939, 496940, 496950, 496960, 496972, 496974, 496986, 497004, 497011, 497014, 497022, 497031, 497063, 497075, 497078, 497084, 497100, 497103, 497109, 497114, 497117, 497125, 497143, 497207, 497243, 497252, 497255, 497260, 497273, 497278, 497280, 497288, 497321, 497329, 497337, 497348, 497354, 497355, 497356, 497369, 497377, 497378, 497382, 497396, 497420, 497446, 497453, 497464, 497474, 497482, 497487, 497494, 497498, 497510, 497513, 497517, 497519, 497529, 497534, 497535, 497541, 497545, 497552, 497561, 497563, 497566, 497575, 497582, 497583, 497584, 497594, 497600, 497603, 497607, 497608, 497637, 497647, 497658, 497659, 497669, 497676, 497677, 497683, 497688, 497690, 497705, 497707, 497713, 497720, 497724, 497726, 497727, 497733, 497738, 497747, 497751, 497753, 497758, 497759, 497769, 497778, 497780, 497786, 497794, 497796, 497799, 497800, 497813, 497826, 497835, 497837, 497844, 497851, 497855, 497886, 497890, 497896, 497898, 497904, 497911, 497923, 497925, 497929, 497943, 497945, 497950, 497951, 497967, 497984, 497994, 497995, 497998, 498001, 498003, 498008, 498016, 498024, 498031, 498033, 498035, 498036, 498037, 498045, 498052, 498053, 498057, 498059, 498060, 498068, 498078, 498086, 498094, 498107, 498110, 498112, 498113, 498132, 498141, 498154, 498155, 498158, 498160, 498165, 498192, 498195, 498210, 498211, 498213, 498223, 498229, 498234, 498235, 498238, 498260, 498261, 498265, 498273, 498277, 498279, 498281, 498292, 498316, 498319, 498331, 498334, 498335, 498347, 498350, 498361, 498363, 498372, 498381, 498388, 498392, 498395, 498405, 498409, 498414, 498419, 498421, 498422, 498424, 498442, 498459, 498467, 498473, 498479, 498489, 498491, 498492, 498508, 498509, 498532, 498534, 498543, 498549, 498558, 498568, 498577, 498582, 498589, 498592, 498594, 498597, 498603, 498614, 498621, 498636, 498637, 498640, 498655, 498656, 498674, 498680, 498689, 498690, 498691, 498694, 498697, 498715, 498717, 498723, 498735, 498739, 498743, 498755, 498770, 498776, 498779, 498785, 498787, 498799, 498800, 498811, 498821, 498833, 498838, 498843, 498844, 498856, 498866, 498870, 498873, 498879, 498886, 498891, 498902, 498910, 498931, 498939, 498954, 498963, 498974, 498981, 498985, 499000, 499002, 499007, 499019, 499027, 499029, 499046, 499047, 499056, 499060, 499062, 499066, 499071, 499108, 499119, 499121, 499126, 499128, 499135, 499319, 499320, 499324, 499330, 499353, 499369, 499371, 499374, 499376, 499378, 499387, 499403, 499410, 499416, 499418, 499419, 499423, 499424, 499427, 499433, 499438, 499445, 499446, 499458, 499462, 499463, 499464, 499473, 499487, 499499, 499500, 499506, 499514, 499524, 499539, 499541, 499542, 499549, 499557, 499558, 499565, 499567, 499584, 499587, 499589, 499597, 499608, 499618, 499622, 499623, 499631, 499638, 499639, 499653, 499656, 499661, 499663, 499667, 499689, 499695, 499697, 499702, 499713, 499718, 499720, 499723, 499729, 499733, 499738, 499748, 499754, 499760, 499765, 499766, 499767, 499777, 499779, 499795, 499799, 499801, 499811, 499824, 499832, 499835, 499839, 499843, 499844, 499850, 499859, 499865, 499868, 499878, 499881, 499886, 499889, 499890, 499905, 499918, 499921, 499933, 499944, 499948, 499957, 499958, 499960, 499961, 499972, 499974, 499996, 500003, 500015, 500016, 500022, 500043, 500047, 500050, 500053, 500054, 500058, 500066, 500081, 500082, 500087, 500093, 500103, 500104, 500109, 500116, 500126, 500140, 500163, 500166, 500175, 500183, 500185, 500186, 500189, 500204, 500214, 500215, 500228, 500234, 500240, 500244, 500247, 500256, 500272, 500275, 500283, 500304, 500309, 500314, 500333, 500336, 500342, 500343, 500347, 500348, 500351, 500356, 500360, 500374, 500377, 500385, 500388, 500393, 500394, 500400, 500401, 500402, 500414, 500423, 500444, 500445, 500446, 500448, 500458, 500471, 500476, 500477, 500482, 500483, 500491, 500497, 500500, 500501, 500506, 500508, 500512, 500519, 500533, 500535, 500537, 500569, 500572, 500585, 500590, 500595, 500597, 500602, 500624, 500630, 500632, 500637, 500638, 500644, 500646, 500652, 500663, 500665, 500667, 500672, 500680, 500688, 500695, 500697, 500702, 500724, 500726, 500727, 500739, 500741, 500751, 500752, 500757, 500771, 500791, 500793, 500794, 500796, 500814, 500816, 500822, 500823, 500829, 500832, 500836, 500855, 500861, 500864, 500871, 500880, 500887, 500897, 500900, 500903, 500905, 500916, 500918, 500926, 500927, 500928, 500930, 500932, 500933, 500934, 500937, 500941, 500947, 500957, 500960, 500961, 500965, 500969, 500970, 500971, 500973, 500981, 500983, 500990, 500992, 500994, 500996, 500998, 501004, 501009, 501012, 501014, 501038, 501040, 501041, 501046, 501051, 501056, 501059, 501060, 501063, 501070, 501072, 501081, 501086, 501094, 501096, 501105, 501106, 501107, 501109, 501117, 501126, 501127, 501129, 501130, 501137, 501139, 501144, 501146, 501153, 501155, 501160, 501168, 501169, 501170, 501174, 501178, 501194, 501196, 501210, 501214, 501225, 501226, 501236, 501238, 501239, 501243, 501257, 501260, 501261, 501264, 501268, 501274, 501277, 501280, 501285, 501286, 501289, 501297, 501298, 501301, 501306, 501314, 501332, 501335, 501337, 501339, 501341, 501342, 501343, 501347, 501362, 501368, 501376, 501382, 501387, 501388, 501409, 501416, 501417, 501419, 501424, 501427, 501428, 501433, 501441, 501443, 501456, 501466, 501470, 501477, 501481, 501486, 501487, 501498, 501507, 501508, 501510, 501512, 501518, 501525, 501526, 501532, 501534, 501540, 501564, 501567, 501572, 501575, 501579, 501591, 501592, 501596, 501598, 501603, 501606, 501610, 501612, 501613, 501619, 501622, 501628, 501641, 501642, 501655, 501657, 501663, 501664, 501667, 501671, 501675, 501677, 501681, 501682, 501685, 501687, 501689, 501694, 501697, 501699, 501704, 501716, 501731, 501733, 501735, 501738, 501740, 501748, 501752, 501771, 501777, 501784, 501786, 501787, 501801, 501802, 501819, 501824, 501828, 501834, 501850, 501855, 501860, 501869, 501872, 501877, 501881, 501889, 501892, 501896, 501910, 501915, 501917, 501923, 501925, 501932, 501935, 501938, 501939, 501944, 501951, 501953, 501954, 501980, 501984, 501995, 501996, 502004, 502008, 502009, 502010, 502017, 502021, 502022, 502023, 502024, 502044, 502068, 502077, 502078, 502079, 502085, 502087, 502096, 502097, 502123, 502129, 502138, 502155, 502200, 502206, 502208, 502211, 502212, 502217, 502219, 502222, 502223, 502228, 502234, 502239, 502240, 502243, 502245, 502250, 502254, 502263, 502275, 502281, 502287, 502288, 502306, 502310, 502327, 502328, 502333, 502343, 502346, 502353, 502354, 502363, 502364, 502368, 502370, 502372, 502376, 502380, 502385, 502386, 502397, 502409, 502422, 502439, 502443, 502453, 502455, 502461, 502462, 502467, 502469, 502478, 502483, 502484, 502489, 502497, 502502, 502510, 502513, 502518, 502537, 502540, 502549, 502555, 502562, 502566, 502569, 502578, 502585, 502591, 502598, 502605, 502616, 502619, 502620, 502623, 502625, 502632, 502637, 502641, 502647, 502652, 502670, 502673, 502681, 502685, 502689, 502697, 502698, 502702, 502712, 502714, 502718, 502722, 502728, 502734, 502739, 502750, 502755, 502766, 502770, 502792, 502793, 502798, 502803, 502804, 502808, 502812, 502821, 502825, 502827, 502828, 502841, 502852, 502856, 502857, 502866, 502873, 502883, 502887, 502890, 502892, 502893, 502905, 502907, 502916, 502917, 502930, 502932, 502936, 502957, 502964, 502967, 502973, 502978, 502984, 502986, 502998, 503023, 503043, 503054, 503067, 503072, 503078, 503080, 503092, 503106, 503112, 503115, 503116, 503125, 503141, 503145, 503151, 503152, 503160, 503168, 503171, 503172, 503184, 503187, 503192, 503194, 503200, 503202, 503204, 503205, 503221, 503224, 503227, 503232, 503235, 503238, 503239, 503260, 503261, 503274, 503285, 503292, 503293, 503308, 503312, 503315, 503324, 503332, 503338, 503339, 503340, 503341, 503345, 503352, 503354, 503361, 503370, 503371, 503376, 503378, 503386, 503387, 503390, 503392, 503394, 503396, 503403, 503406, 503424, 503441, 503443, 503447, 503454, 503459, 503461, 503462, 503463, 503470, 503471, 503472, 503480, 503486, 503488, 503490, 503494, 503500, 503508, 503526, 503528, 503529, 503539, 503542, 503549, 503555, 503556, 503577, 503578, 503581, 503582, 503587, 503592, 503601, 503607, 503611, 503614, 503623, 503642, 503652, 503667, 503674, 503684, 503685, 503696, 503699, 503713, 503715, 503719, 503720, 503721, 503725, 503729, 503733, 503739, 503751, 503754, 503765, 503775, 503787, 503789, 503790, 503792, 503793, 503795, 503796, 503797, 503800, 503802, 503806, 503819, 503830, 503831, 503832, 503833, 503834, 503836, 503837, 503838, 503839, 503840, 503842, 503844, 503845, 503846, 503849, 503850, 503851, 503852, 503853, 503854, 503855, 503856, 503857, 503860, 503861, 503862, 503863, 503864, 503865, 503866, 503867, 503868, 503870, 503871, 503872, 503873, 503874, 503876, 503877, 503891, 503892, 503898, 503899, 503900, 503901, 503902, 503905, 503911, 503912, 503918, 503922, 503924, 503935, 503941, 503945, 503949, 503951, 503952, 503962, 503968, 503970, 503972, 503978, 503981, 503982, 503983, 503993, 503995, 503998, 504000, 504010, 504026, 504039, 504048, 504049, 504058, 504059, 504071, 504084, 504091, 504096, 504097, 504106, 504113, 504118, 504120, 504137, 504140, 504143, 504144, 504147, 504148, 504160, 504169, 504174, 504176, 504181, 504184, 504187, 504188, 504190, 504200, 504207, 504222, 504223, 504224, 504228, 504229, 504231, 504233, 504239, 504240, 504242, 504245, 504246, 504251, 504261, 504273, 504278, 504307, 504308, 504311, 504315, 504321, 504331, 504335, 504336, 504347, 504358, 504364, 504365, 504368, 504377, 504380, 504384, 504385, 504386, 504402, 504406, 504418, 504419, 504423, 504424, 504426, 504427, 504431, 504441, 504451, 504452, 504463, 504467, 504470, 504479, 504483, 504494, 504497, 504512, 504515, 504526, 504529, 504531, 504537, 504547, 504548, 504549, 504551, 504557, 504558, 504566, 504580, 504589, 504591, 504598, 504602, 504605, 504610, 504611, 504612, 504613, 504614, 504616, 504617, 504618, 504620, 504622, 504623, 504624, 504625, 504627, 504630, 504631, 504632, 504633, 504634, 504635, 504638, 504639, 504640, 504641, 504643, 504644, 504647, 504649, 504651, 504652, 504653, 504654, 504655, 504656, 504657, 504660, 504661, 504663, 504666, 504668, 504671, 504673, 504674, 504679, 504680, 504684, 504687, 504692, 504695, 504698, 504708, 504728, 504730, 504747, 504758, 504764, 504766, 504768, 504769, 504773, 504785, 504786, 504793, 504800, 504801, 504806, 504810, 504814, 504818, 504821, 504826, 504830, 504832, 504833, 504840, 504844, 504850, 504853, 504868, 504872, 504884, 504886, 504892, 504897, 504899, 504901, 504906, 504923, 504928, 504929, 504933, 504942, 504949, 504970, 504972, 504976, 504977, 504982, 504983, 504986, 505005, 505013, 505022, 505023, 505024, 505033, 505043, 505048, 505049, 505061, 505062, 505064, 505066, 505068, 505071, 505072, 505074, 505075, 505086, 505090, 505097, 505101, 505104, 505110, 505118, 505128, 505130, 505131, 505132, 505139, 505144, 505145, 505156, 505157, 505159, 505161, 505173, 505176, 505177, 505180, 505189, 505194, 505196, 505203, 505208, 505219, 505228, 505229, 505240, 505241, 505254, 505265, 505272, 505277, 505287, 505288, 505291, 505292, 505298, 505301, 505314, 505330, 505334, 505337, 505342, 505343, 505347, 505348, 505365, 505372, 505374, 505381, 505389, 505404, 505410, 505420, 505422, 505430, 505431, 505442, 505445, 505454, 505456, 505458, 505464, 505470, 505478, 505481, 505491, 505499, 505527, 505529, 505532, 505537, 505555, 505559, 505570, 505579, 505588, 505589, 505594, 505596, 505605, 505606, 505615, 505622, 505623, 505624, 505633, 505637, 505639, 505645, 505650, 505652, 505653, 505654, 505655, 505660, 505661, 505670, 505671, 505677, 505684, 505693, 505695, 505705, 505717, 505723, 505727, 505733, 505737, 505744, 505747, 505752, 505757, 505758, 505772, 505775, 505796, 505800, 505805, 505815, 505822, 505845, 505847, 505848, 505863, 505873, 505880, 505893, 505894, 505899, 505904, 505911, 505918, 505921, 505922, 505928, 505935, 505937, 505940, 505941, 505943, 505946, 505951, 505954, 505957, 505958, 505960, 505963, 505966, 505976, 505977, 505982, 505998, 505999, 506002, 506027, 506033, 506043, 506044, 506051, 506056, 506062, 506063, 506064, 506069, 506070, 506072, 506078, 506099, 506114, 506118, 506121, 506127, 506139, 506147, 506150, 506156, 506157, 506165, 506172, 506174, 506175, 506179, 506199, 506201, 506202, 506207, 506208, 506212, 506214, 506219, 506221, 506230, 506231, 506238, 506257, 506258, 506267, 506272, 506279, 506282, 506290, 506294, 506297, 506298, 506310, 506313, 506314, 506330, 506339, 506350, 506357, 506359, 506361, 506367, 506369, 506376, 506379, 506380, 506391, 506392, 506399, 506414, 506415, 506426, 506429, 506434, 506435, 506437, 506438, 506462, 506480, 506497, 506498, 506500, 506501, 506504, 506507, 506513, 506514, 506520, 506524, 506527, 506531, 506534, 506542, 506545, 506550, 506555, 506557, 506567, 506572, 506574, 506587, 506594, 506602, 506624, 506627, 506629, 506631, 506632, 506633, 506635, 506644, 506646, 506650, 506657, 506660, 506667, 506668, 506679, 506698, 506702, 506713, 506723, 506727, 506730, 506751, 506760, 506763, 506764, 506768, 506769, 506776, 506782, 506787, 506806, 506807, 506808, 506811, 506826, 506852, 506867, 506886, 506907, 506912, 506914, 506929, 506930, 506948, 506956, 506962, 506968, 506969, 506977, 506980, 506981, 507001, 507002, 507006, 507008, 507019, 507030, 507047, 507050, 507052, 507054, 507071, 507086, 507089, 507101, 507114, 507118, 507120, 507125, 507127, 507148, 507151, 507155, 507168, 507193, 507216, 507227, 507233, 507235, 507241, 507248, 507257, 507260, 507275, 507294, 507298, 507302, 507319, 507343, 507349, 507357, 507358, 507376, 507387, 507398, 507408, 507415, 507432, 507436, 507441, 507443, 507447, 507472, 507482, 507487, 507517, 507519, 507524, 507525, 507537, 507550, 507554, 507559, 507560, 507562, 507564, 507574, 507581, 507583, 507585, 507587, 507593, 507602, 507615, 507633, 507634, 507635, 507641, 507649, 507664, 507671, 507674, 507675, 507690, 507691, 507698, 507705, 507707, 507719, 507728, 507745, 507753, 507761, 507773, 507787, 507791, 507801, 507806, 507812, 507813, 507817, 507821, 507826, 507830, 507836, 507841, 507844, 507869, 507871, 507874, 507875, 507880, 507886, 507893, 507909, 507920, 507923, 507926, 507928, 507937, 507948, 507952, 507968, 507980, 507987, 507988, 507993, 507996, 507999, 508009, 508014, 508024, 508030, 508058, 508060, 508064, 508070, 508079, 508081, 508086, 508092, 508098, 508116, 508131, 508134, 508147, 508151, 508161, 508168, 508176, 508182, 508189, 508197, 508200, 508203, 508231, 508235, 508253, 508258, 508262, 508266, 508273, 508281, 508297, 508298, 508303, 508308, 508317, 508332, 508343, 508349, 508353, 508356, 508360, 508363, 508367, 508371, 508377, 508382, 508399, 508411, 508435, 508448, 508454, 508459, 508485, 508486, 508489, 508492, 508494, 508507, 508511, 508519, 508520, 508525, 508541, 508548, 508564, 508565, 508569, 508573, 508575, 508596, 508597, 508605, 508606, 508621, 508622, 508628, 508631, 508632, 508641, 508643, 508644, 508650, 508655, 508660, 508672, 508678, 508679, 508698, 508705, 508734, 508748, 508752, 508755, 508763, 508767, 508783, 508797, 508798, 508808, 508815, 508823, 508834, 508864, 508889, 508909, 508912, 508916, 508922, 508924, 508926, 508933, 508947, 508949, 508950, 508954, 508959, 508961, 508967, 508972, 509033, 509045, 509046, 509064, 509071, 509083, 509117, 509120, 509136, 509137, 509143, 509145, 509154, 509156, 509159, 509168, 509175, 509177, 509185, 509191, 509206, 509228, 509238, 509242, 509243, 509246, 509253, 509261, 509264, 509268, 509276, 509280, 509281, 509289, 509313, 509317, 509333, 509336, 509337, 509340, 509346, 509351, 509376, 509379, 509391, 509400, 509407, 509410, 509414, 509424, 509425, 509428, 509433, 509445, 509451, 509463, 509485, 509496, 509501, 509512, 509515, 509533, 509537, 509544, 509566, 509574, 509579, 509585, 509589, 509593, 509602, 509605, 509616, 509619, 509627, 509642, 509661, 509668, 509673, 509683, 509687, 509700, 509702, 509703, 509705, 509710, 509715, 509721, 509723, 509724, 509726, 509729, 509730, 509749, 509773, 509774, 509777, 509779, 509794, 509798, 509804, 509805, 509814, 509815, 509822, 509836, 509845, 509850, 509857, 509866, 509878, 509888, 509889, 509893, 509904, 509913, 509917, 509919, 509928, 509933, 509940, 509942, 509956, 509965, 509970, 509978, 509982, 509985, 509993, 510008, 510015, 510026, 510035, 510036, 510043, 510044, 510048, 510054, 510071, 510086, 510089, 510101, 510107, 510112, 510133, 510136, 510140, 510141, 510175, 510178, 510198, 510205, 510207, 510208, 510212, 510230, 510235, 510237, 510240, 510244, 510245, 510247, 510255, 510261, 510263, 510265, 510286, 510296, 510305, 510310, 510326, 510332, 510333, 510335, 510342, 510345, 510352, 510373, 510375, 510376, 510386, 510391, 510394, 510418, 510424, 510427, 510436, 510440, 510448, 510471, 510475, 510484, 510487, 510492, 510494, 510496, 510499, 510506, 510510, 510525, 510533, 510545, 510547, 510551, 510555, 510557, 510559, 510565, 510568, 510591, 510616, 510619, 510623, 510640, 510660, 510665, 510666, 510668, 510670, 510673, 510677, 510682, 510696, 510708, 510721, 510727, 510738, 510759, 510784, 510801, 510810, 510812, 510815, 510819, 510832, 510834, 510835, 510841, 510846, 510852, 510854, 510866, 510869, 510873, 510882, 510908, 510914, 510917, 510920, 510921, 510927, 510928, 510940, 510957, 510960, 510961, 510963, 510985, 510986, 510988, 510993, 510994, 511013, 511018, 511019, 511029, 511031, 511034, 511036, 511037, 511040, 511053, 511054, 511058, 511072, 511086, 511122, 511130, 511148, 511151, 511154, 511162, 511167, 511168, 511170, 511183, 511197, 511210, 511216, 511223, 511244, 511249, 511252, 511255, 511258, 511266, 511273, 511279, 511285, 511290, 511312, 511314, 511316, 511317, 511320, 511327, 511332, 511369, 511375, 511377, 511381, 511409, 511410, 511423, 511433, 511442, 511443, 511447, 511455, 511460, 511470, 511476, 511500, 511503, 511514, 511516, 511517, 511525, 511549, 511550, 511551, 511568, 511577, 511581, 511589, 511607, 511611, 511624, 511636, 511650, 511655, 511671, 511672, 511707, 511712, 511722, 511744, 511754, 511757, 511758, 511760, 511767, 511773, 511793, 511794, 511817, 511818, 511837, 511839, 511848, 511852, 511874, 511875, 511878, 511885, 511891, 511900, 511909, 511917, 511921, 511925, 511936, 511939, 511945, 511954, 511961, 511962, 511967, 511982, 511994, 512001, 512005, 512028, 512031, 512047, 512059, 512062, 512063, 512064, 512076, 512077, 512082, 512089, 512092, 512093, 512102, 512107, 512108, 512118, 512127, 512139, 512157, 512162, 512173, 512176, 512178, 512183, 512191, 512195, 512201, 512202, 512210, 512215, 512221, 512244, 512245, 512250, 512261, 512262, 512277, 512285, 512292, 512300, 512306, 512319, 512322, 512333, 512336, 512341, 512370, 512382, 512385, 512387, 512389, 512399, 512402, 512407, 512413, 512428, 512461, 512463, 512474, 512475, 512476, 512478, 512481, 512483, 512489, 512505, 512508, 512511, 512513, 512542, 512554, 512555, 512558, 512559, 512569, 512574, 512595, 512598, 512601, 512613, 512617, 512620, 512633, 512652, 512655, 512662, 512670, 512671, 512674, 512682, 512685, 512689, 512694, 512696, 512697, 512702, 512704, 512707, 512709, 512714, 512722, 512726, 512732, 512734, 512746, 512749, 512752, 512753, 512772, 512774, 512782, 512789, 512815, 512839, 512849, 512852, 512857, 512861, 512866, 512869, 512873, 512887, 512895, 512897, 512899, 512903, 512923, 512926, 512933, 512947, 512963, 512975, 512985, 513000, 513006, 513010, 513014, 513029, 513031, 513034, 513040, 513055, 513057, 513072, 513077, 513082, 513091, 513100, 513106, 513107, 513110, 513113, 513116, 513117, 513119, 513125, 513127, 513146, 513157, 513161, 513172, 513182, 513185, 513216, 513218, 513226, 513228, 513242, 513245, 513246, 513249, 513258, 513267, 513268, 513286, 513287, 513294, 513301, 513302, 513305, 513313, 513317, 513321, 513333, 513340, 513344, 513367, 513372, 513383, 513385, 513402, 513403, 513406, 513425, 513429, 513440, 513446, 513448, 513449, 513469, 513470, 513473, 513478, 513484, 513502, 513524, 513535, 513559, 513602, 513610, 513629, 513634, 513652, 513654, 513656, 513667, 513672, 513689, 513703, 513706, 513713, 513715, 513718, 513720, 513725, 513732, 513733, 513736, 513750, 513761, 513774, 513777, 513779, 513783, 513791, 513797, 513803, 513811, 513816, 513828, 513831, 513839, 513845, 513847, 513856, 513860, 513878, 513886, 513890, 513893, 513897, 513900, 513912, 513917, 513928, 513937, 513967, 513989, 513995, 514005, 514008, 514019, 514022, 514041, 514044, 514049, 514058, 514074, 514082, 514093, 514110, 514111, 514148, 514160, 514217, 514248, 514272, 514278, 514332, 514357, 514397, 514409, 514430, 514503, 514512, 514522, 514527, 514533, 514534, 514542, 514548, 514558, 514568, 514583, 514620, 514625, 514635, 514652, 514668, 514669, 514673, 514693, 514723, 514724, 514779, 514794, 514800, 514867, 514926, 515029, 515173, 515175, 515185, 515186, 515189, 515190, 515196, 515197, 515208, 515209, 515211, 515214, 515216, 515231, 515249, 515256, 515259, 515262, 515269, 515270, 515274, 515276, 515280, 515281, 515300, 515301, 515311, 515318, 515319, 515325, 515333, 515339, 515342, 515343, 515345, 515351, 515354, 515355, 515358, 515359, 515360, 515361, 515363, 515372, 515374, 515376, 515380, 515388, 515390, 515407, 515408, 515414, 515436, 515445, 515451, 515455, 515457, 515460, 515466, 515474, 515475, 515476, 515488, 515491, 515500, 515501, 515510, 515511, 515516, 515527, 515543, 515555, 515579, 515591, 515597, 515606, 515609, 515616, 515622, 515623, 515626, 515633, 515649, 515666, 515679, 515682, 515687, 515690, 515703, 515711, 515713, 515727, 515737, 515764, 515772, 515773, 515775, 515778, 515784, 515802, 515814, 515819, 515821, 515823, 515824, 515828, 515829, 515830, 515833, 515842, 515856, 515859, 515860, 515871, 515873, 515874, 515877, 515884, 515893, 515897, 515900, 515901, 515907, 515910, 515914, 515918, 515922, 515937, 515945, 515947, 515951, 515952, 515962, 515974, 515978, 516007, 516011, 516013, 516016, 516030, 516040, 516044, 516055, 516057, 516060, 516067, 516075, 516076, 516086, 516097, 516098, 516099, 516104, 516109, 516120, 516122, 516125, 516133, 516143, 516146, 516147, 516175, 516180, 516186, 516193, 516214, 516229, 516271, 516272, 516276, 516278, 516282, 516291, 516295, 516300, 516304, 516324, 516334, 516335, 516337, 516339, 516351, 516356, 516359, 516362, 516363, 516369, 516384, 516391, 516421, 516428, 516439, 516445, 516448, 516467, 516468, 516475, 516480, 516484, 516488, 516490, 516498, 516500, 516503, 516507, 516511, 516512, 516514, 516516, 516519, 516529, 516533, 516534, 516537, 516540, 516544, 516573, 516576, 516596, 516602, 516620, 516629, 516636, 516643, 516648, 516655, 516677, 516681, 516689, 516709, 516719, 516725, 516734, 516735, 516753, 516759, 516777, 516798, 516800, 516805, 516809, 516817, 516819, 516827, 516836, 516842, 516843, 516854, 516866, 516873, 516876, 516877, 516881, 516898, 516906, 516907, 516915, 516920, 516925, 516926, 516938, 516940, 516948, 516953, 516955, 516956, 516957, 516958, 516965, 516968, 516970, 516971, 516974, 516976, 517001, 517007, 517011, 517014, 517016, 517017, 517028, 517030, 517036, 517037, 517038, 517045, 517060, 517061, 517062, 517066, 517069, 517077, 517080, 517083, 517086, 517087, 517090, 517093, 517096, 517099, 517100, 517104, 517108, 517111, 517127, 517131, 517133, 517140, 517146, 517157, 517179, 517183, 517184, 517187, 517196, 517197, 517198, 517203, 517204, 517222, 517225, 517231, 517233, 517239, 517241, 517256, 517278, 517279, 517292, 517300, 517319, 517328, 517331, 517332, 517333, 517337, 517340, 517341, 517346, 517348, 517350, 517352, 517353, 517354, 517359, 517362, 517364, 517366, 517371, 517373, 517376, 517377, 517380, 517394, 517396, 517400, 517405, 517406, 517412, 517414, 517417, 517427, 517432, 517438, 517441, 517448, 517449, 517451, 517452, 517453, 517461, 517463, 517470, 517479, 517481, 517482, 517495, 517496, 517498, 517508, 517509, 517519, 517520, 517536, 517544, 517550, 517557, 517562, 517565, 517568, 517574, 517586, 517592, 517599, 517606, 517611, 517616, 517619, 517623, 517628, 517635, 517639, 517647, 517649, 517651, 517654, 517656, 517661, 517662, 517666, 517671, 517676, 517677, 517679, 517684, 517685, 517687, 517689, 517696, 517705, 517709, 517714, 517732, 517739, 517741, 517742, 517746, 517750, 517752, 517759, 517763, 517767, 517770, 517773, 517774, 517777, 517781, 517787, 517792, 517794, 517795, 517798, 517806, 517808, 517810, 517812, 517815, 517820, 517825, 517830, 517836, 517840, 517842, 517851, 517861, 517864, 517870, 517873, 517876, 517878, 517880, 517887, 517890, 517891, 517892, 517899, 517902, 517922, 517929, 517931, 517937, 517946, 517947, 517958, 517961, 517970, 517983, 517984, 517986, 517994, 518006, 518011, 518012, 518026, 518029, 518034, 518035, 518041, 518049, 518051, 518061, 518063, 518075, 518083, 518085, 518093, 518097, 518104, 518110, 518115, 518122, 518126, 518131, 518134, 518141, 518142, 518158, 518165, 518185, 518211, 518214, 518219, 518224, 518225, 518235, 518239, 518240, 518244, 518271, 518283, 518290, 518296, 518299, 518306, 518309, 518320, 518330, 518331, 518356, 518358, 518361, 518363, 518365, 518371, 518373, 518397, 518403, 518404, 518412, 518418, 518420, 518424, 518429, 518432, 518446, 518456, 518460, 518477, 518480, 518482, 518491, 518495, 518500, 518503, 518507, 518509, 518510, 518514, 518516, 518525, 518526, 518533, 518535, 518539, 518544, 518550, 518557, 518564, 518567, 518570, 518572, 518575, 518586, 518590, 518597, 518598, 518600, 518602, 518605, 518607, 518611, 518616, 518618, 518628, 518631, 518638, 518640, 518642, 518662, 518664, 518665, 518667, 518681, 518693, 518695, 518702, 518707, 518713, 518715, 518718, 518725, 518728, 518729, 518735, 518736, 518739, 518753, 518754, 518761, 518763, 518770, 518780, 518800, 518804, 518825, 518831, 518843, 518844, 518846, 518854, 518856, 518860, 518861, 518875, 518882, 518883, 518886, 518887, 518888, 518900, 518908, 518911, 518917, 518919, 518923, 518931, 518935, 518952, 518957, 518958, 518973, 518981, 518986, 519040, 519041, 519056, 519080, 519082, 519104, 519131, 519133, 519141, 519145, 519147, 519183, 519206, 519207, 519212, 519217, 519230, 519232, 519233, 519256, 519257, 519263, 519264, 519277, 519281, 519282, 519301, 519306, 519310, 519319, 519323, 519332, 519333, 519334, 519343, 519344, 519374, 519398, 519400, 519402, 519427, 519431, 519442, 519454, 519462, 519468, 519475, 519478, 519490, 519491, 519502, 519505, 519520, 519527, 519539, 519542, 519548, 519550, 519551, 519565, 519570, 519574, 519577, 519603, 519606, 519621, 519622, 519631, 519644, 519647, 519659, 519680, 519690, 519694, 519698, 519704, 519713, 519715, 519731, 519734, 519736, 519737, 519748, 519760, 519762, 519765, 519786, 519787, 519809, 519832, 519833, 519835, 519888, 519894, 519895, 519905, 519927, 519938, 519951, 519953, 519955, 519966, 519970, 519984, 519986, 520001, 520009, 520035, 520038, 520057, 520081, 520086, 520090, 520093, 520111, 520119, 520120, 520127, 520147, 520166, 520171, 520174, 520198, 520200, 520221, 520244, 520253, 520262, 520266, 520277, 520287, 520296, 520312, 520323, 520324, 520344, 520348, 520352, 520359, 520363, 520367, 520376, 520381, 520395, 520398, 520399, 520405, 520409, 520417, 520418, 520429, 520444, 520446, 520447, 520454, 520457, 520459, 520460, 520486, 520488, 520496, 520500, 520504, 520506, 520508, 520531, 520532, 520535, 520544, 520573, 520593, 520597, 520623, 520624, 520647, 520650, 520680, 520683, 520687, 520692, 520693, 520700, 520704, 520711, 520712, 520732, 520741, 520742, 520745, 520747, 520759, 520782, 520790, 520802, 520808, 520813, 520817, 520821, 520847, 520849, 520853, 520856, 520861, 520863, 520872, 520881, 520887, 520890, 520893, 520894, 520919, 520921, 520926, 520930, 520932, 520951, 520964, 520973, 521002, 521007, 521009, 521010, 521014, 521025, 521041, 521044, 521051, 521061, 521063, 521065, 521070, 521076, 521098, 521112, 521125, 521127, 521130, 521140, 521141, 521149, 521168, 521176, 521182, 521201, 521204, 521205, 521216, 521223, 521231, 521238, 521241, 521243, 521257, 521258, 521264, 521267, 521277, 521284, 521290, 521358, 521360, 521365, 521377, 521384, 521387, 521393, 521399, 521402, 521404, 521411, 521416, 521422, 521430, 521431, 521439, 521444, 521446, 521469, 521471, 521490, 521523, 521533, 521543, 521559, 521562, 521572, 521578, 521589, 521609, 521610, 521611, 521617, 521621, 521630, 521640, 521656, 521657, 521671, 521675, 521680, 521690, 521692, 521702, 521709, 521712, 521741, 521744, 521750, 521756, 521767, 521784, 521785, 521808, 521833, 521835, 521840, 521848, 521855, 521865, 521866, 521896, 521929, 521931, 521945, 521952, 521953, 521957, 521960, 521965, 521966, 521969, 521972, 521980, 521985, 521992, 521997, 522005, 522006, 522009, 522014, 522017, 522020, 522023, 522045, 522059, 522063, 522079, 522082, 522087, 522094, 522099, 522133, 522144, 522152, 522154, 522155, 522158, 522191, 522197, 522201, 522204, 522210, 522215, 522220, 522233, 522237, 522278, 522301, 522313, 522315, 522332, 522336, 522346, 522359, 522362, 522366, 522419, 522454, 522458, 522463, 522484, 522491, 522492, 522498, 522502, 522531, 522561, 522565, 522566, 522568, 522582, 522592, 522600, 522607, 522638, 522652, 522668, 522694, 522706, 522713, 522718, 522725, 522735, 522789, 522791, 522793, 522808, 522820, 522825, 522827, 522845, 522849, 522857, 522862, 522875, 522883, 522896, 522902, 522919, 522923, 522927, 522936, 522937, 522942, 522944, 522945, 522956, 522962, 522967, 522970, 522975, 522982, 522984, 522992, 522993, 523016, 523021, 523022, 523033, 523036, 523042, 523045, 523048, 523065, 523072, 523077, 523078, 523082, 523087, 523088, 523097, 523101, 523103, 523117, 523118, 523120, 523143, 523152, 523159, 523210, 523213, 523215, 523224, 523227, 523239, 523244, 523247, 523249, 523252, 523256, 523262, 523267, 523271, 523289, 523290, 523303, 523306, 523323, 523324, 523325, 523326, 523343, 523348, 523364, 523366, 523375, 523398, 523423, 523434, 523448, 523451, 523452, 523456, 523458, 523485, 523488, 523511, 523518, 523527, 523533, 523534, 523542, 523543, 523555, 523560, 523567, 523568, 523578, 523581, 523591, 523594, 523601, 523603, 523608, 523627, 523631, 523635, 523636, 523641, 523644, 523657, 523668, 523670, 523671, 523707, 523713, 523714, 523717, 523730, 523743, 523745, 523754, 523799, 523804, 523812, 523819, 523820, 523827, 523830, 523842, 523859, 523863, 523897, 523911, 523921, 523922, 523926, 523927, 523935, 523949, 523956, 523973, 523974, 523988, 524008, 524018, 524053, 524074, 524084, 524088, 524097, 524136, 524138, 524143, 524151, 524158, 524160, 524169, 524177, 524203, 524215, 524219, 524225, 524228, 524236, 524238, 524241, 524247, 524252, 524268, 524269, 524272, 524282, 524283, 524295, 524300, 524302, 524307, 524311, 524322, 524326, 524332, 524345, 524355, 524363, 524364, 524368, 524391, 524396, 524399, 524419, 524424, 524427, 524440, 524447, 524454, 524461, 524801, 524804, 524808, 524822, 524840, 524854, 524857, 524905, 524915, 524916, 524935, 524959, 524971, 524979, 524983, 524987, 524991, 524996, 525003, 525008, 525012, 525015, 525022, 525030, 525031, 525049, 525070, 525073, 525083, 525107, 525108, 525120, 525126, 525129, 525136, 525142, 525144, 525156, 525178, 525197, 525199, 525212, 525230, 525232, 525233, 525234, 525235, 525242, 525244, 525268, 525274, 525275, 525288, 525292, 525295, 525297, 525298, 525306, 525316, 525329, 525352, 525358, 525365, 525366, 525367, 525372, 525382, 525396, 525442, 525445, 525457, 525465, 525472, 525483, 525486, 525509, 525514, 525544, 525581, 525604, 525605, 525606, 525621, 525629, 525632, 525635, 525653, 525673, 525678, 525679, 525685, 525689, 525699, 525730, 525749, 525752, 525757, 525769, 525771, 525772, 525784, 525794, 525822, 525824, 525828, 525833, 525840, 525845, 525862, 525872, 525878, 525890, 525905, 525912, 525928, 525934, 525949, 525955, 525961, 525965, 525988, 525993, 526006, 526013, 526016, 526020, 526026, 526036, 526050, 526051, 526078, 526080, 526110, 526131, 526142, 526151, 526161, 526167, 526173, 526176, 526180, 526191, 526195, 526205, 526211, 526220, 526223, 526231, 526232, 526233, 526249, 526261, 526271, 526276, 526285, 526287, 526293, 526296, 526307, 526309, 526318, 526347, 526351, 526361, 526362, 526379, 526389, 526399, 526407, 526412, 526417, 526418, 526422, 526435, 526438, 526452, 526461, 526462, 526466, 526470, 526480, 526489, 526492, 526502, 526506, 526508, 526513, 526521, 526522, 526534, 526551, 526562, 526564, 526581, 526593, 526600, 526621, 526640, 526652, 526655, 526673, 526676, 526678, 526683, 526706, 526716, 526718, 526720, 526737, 526738, 526739, 526751, 526755, 526771, 526776, 526784, 526799, 526804, 526806, 526820, 526829, 526834, 526842, 526844, 526855, 526858, 526876, 526883, 526885, 526893, 526901, 526905, 526922, 526937, 526942, 526944, 526951, 526952, 526966, 526990, 526993, 526995, 527013, 527021, 527022, 527029, 527031, 527037, 527040, 527042, 527052, 527053, 527055, 527057, 527058, 527060, 527062, 527068, 527099, 527103, 527106, 527113, 527115, 527132, 527133, 527152, 527162, 527180, 527183, 527191, 527195, 527209, 527216, 527224, 527233, 527248, 527252, 527255, 527257, 527272, 527316, 527325, 527327, 527357, 527367, 527373, 527391, 527395, 527410, 527434, 527444, 527484, 527503, 527507, 527508, 527513, 527517, 527537, 527539, 527542, 527551, 527554, 527556, 527558, 527571, 527573, 527589, 527590, 527596, 527609, 527610, 527611, 527622, 527625, 527633, 527637, 527643, 527651, 527652, 527654, 527681, 527686, 527706, 527730, 527738, 527758, 527766, 527771, 527782, 527801, 527805, 527815, 527817, 527818, 527820, 527832, 527835, 527837, 527838, 527842, 527843, 527852, 527859, 527860, 527862, 527871, 527873, 527879, 527881, 527884, 527891, 527898, 527910, 527921, 527922, 527929, 527934, 527935, 527936, 527941, 527944, 527945, 527947, 527948, 527952, 527953, 527957, 527958, 527959, 527960, 527961, 527966, 527969, 527973, 527978, 527982, 527990, 528001, 528008, 528009, 528015, 528016, 528021, 528026, 528041, 528046, 528048, 528059, 528066, 528068, 528074, 528077, 528086, 528087, 528090, 528091, 528114, 528115, 528118, 528122, 528124, 528129, 528137, 528138, 528139, 528141, 528143, 528145, 528159, 528168, 528183, 528187, 528188, 528198, 528205, 528218, 528226, 528228, 528242, 528245, 528250, 528252, 528259, 528262, 528268, 528288, 528306, 528310, 528313, 528322, 528330, 528340, 528347, 528348, 528349, 528357, 528358, 528366, 528374, 528376, 528377, 528379, 528383, 528387, 528390, 528392, 528399, 528411, 528422, 528424, 528433, 528445, 528446, 528448, 528455, 528466, 528468, 528472, 528476, 528485, 528490, 528498, 528500, 528508, 528511, 528518, 528523, 528527, 528528, 528530, 528534, 528546, 528547, 528559, 528564, 528574, 528579, 528584, 528594, 528600, 528602, 528603, 528623, 528624, 528631, 528632, 528642, 528648, 528657, 528660, 528661, 528665, 528667, 528677, 528679, 528709, 528712, 528714, 528727, 528730, 528731, 528734, 528738, 528739, 528742, 528744, 528753, 528764, 528765, 528770, 528779, 528780, 528781, 528784, 528794, 528800, 528805, 528809, 528812, 528815, 528830, 528836, 528852, 528857, 528866, 528871, 528878, 528881, 528883, 528885, 528890, 528892, 528894, 528898, 528901, 528919, 528920, 528921, 528922, 528925, 528927, 528942, 528947, 528959, 528969, 528970, 528972, 528978, 528988, 528990, 529005, 529007, 529016, 529018, 529066, 529070, 529093, 529112, 529122, 529127, 529136, 529137, 529145, 529150, 529155, 529160, 529181, 529183, 529193, 529194, 529201, 529204, 529230, 529236, 529239, 529243, 529250, 529285, 529289, 529299, 529300, 529304, 529330, 529332, 529342, 529381, 529420, 529422, 529434, 529437, 529464, 529484, 529493, 529514, 529524, 529527, 529528, 529535, 529543, 529550, 529565, 529597, 529602, 529611, 529621, 529635, 529660, 529662, 529667, 529682, 529684, 529694, 529697, 529700, 529721, 529722, 529737, 529762, 529775, 529805, 529818, 529830, 529839, 529859, 529868, 529891, 529903, 529914, 529915, 529921, 529929, 529945, 529952, 529954, 529955, 529972, 529976, 530007, 530010, 530024, 530029, 530031, 530038, 530041, 530053, 530055, 530059, 530071, 530072, 530088, 530099, 530107, 530117, 530122, 530128, 530129, 530141, 530149, 530150, 530165, 530170, 530179, 530183, 530201, 530214, 530216, 530219, 530221, 530244, 530250, 530257, 530275, 530278, 530288, 530300, 530310, 530316, 530318, 530319, 530333, 530342, 530348, 530359, 530364, 530373, 530394, 530412, 530417, 530431, 530432, 530433, 530436, 530442, 530451, 530454, 530458, 530464, 530476, 530483, 530498, 530529, 530541, 530552, 530554, 530570, 530572, 530579, 530585, 530589, 530604, 530607, 530611, 530613, 530615, 530628, 530632, 530635, 530638, 530641, 530647, 530652, 530681, 530686, 530689, 530702, 530714, 530718, 530729, 530753, 530763, 530769, 530776, 530784, 530803, 530804, 530811, 530847, 530870, 530882, 530888, 530891, 530899, 530906, 530911, 530924, 530925, 530926, 530930, 530937, 530943, 530969, 530973, 530974, 530981, 530990, 530991, 530992, 530998, 530999, 531005, 531007, 531027, 531031, 531036, 531061, 531092, 531100, 531123, 531132, 531133, 531139, 531140, 531144, 531153, 531163, 531174, 531189, 531190, 531191, 531192, 531193, 531208, 531248, 531260, 531261, 531265, 531267, 531280, 531285, 531294, 531300, 531306, 531307, 531308, 531310, 531312, 531314, 531338, 531339, 531353, 531366, 531373, 531374, 531376, 531407, 531415, 531419, 531422, 531431, 531438, 531449, 531475, 531501, 531509, 531525, 531527, 531529, 531542, 531551, 531558, 531567, 531585, 531598, 531600, 531605, 531616, 531617, 531618, 531629, 531632, 531637, 531647, 531671, 531677, 531681, 531691, 531693, 531705, 531710, 531721, 531729, 531767, 531781, 531803, 531813, 531816, 531838, 531846, 531847, 531848, 531851, 531855, 531894, 531897, 531906, 531907, 531917, 531918, 531919, 531951, 531960, 531967, 531975, 531979, 531981, 531984, 531988, 531991, 531994, 531996, 532002, 532003, 532012, 532023, 532026, 532028, 532030, 532043, 532053, 532070, 532085, 532094, 532114, 532130, 532134, 532136, 532140, 532143, 532151, 532159, 532160, 532170, 532185, 532186, 532187, 532191, 532201, 532203, 532224, 532243, 532244, 532247, 532250, 532251, 532256, 532265, 532266, 532273, 532275, 532281, 532282, 532290, 532295, 532315, 532341, 532450, 532522, 532576, 532709, 532826, 532850, 532894, 532912, 532917, 532927, 532942, 532965, 532971, 532973, 532974, 532975, 532987, 532998, 533001, 533015, 533025, 533027, 533043, 533053, 533061, 533092, 533093, 533101, 533107, 533114, 533118, 533145, 533157, 533164, 533201, 533219, 533238, 533269, 533299, 533301, 533313, 533325, 533342, 533344, 533349, 533352, 533353, 533381, 533383, 533384, 533387, 533395, 533407, 533416, 533417, 533419, 533429, 533430, 533431, 533434, 533441, 533443, 533444, 533445, 533451, 533453, 533455, 533461, 533475, 533480, 533481, 533483, 533487, 533508, 533511, 533514, 533516, 533533, 533535, 533550, 533559, 533562, 533569, 533579, 533591, 533595, 533601, 533624, 533638, 533640, 533656, 533681, 533685, 533687, 533688, 533709, 533723, 533728, 533740, 533747, 533748, 533754, 533762, 533768, 533779, 533783, 533784, 533811, 533814, 533828, 533829, 533840, 533852, 533855, 533857, 533858, 533859, 533874, 533879, 533884, 533886, 533898, 533907, 533915, 533922, 533928, 533944, 533946, 533956, 533963, 533967, 533978, 533980, 533994, 534012, 534025, 534033, 534036, 534040, 534057, 534059, 534060, 534062, 534064, 534067, 534068, 534074, 534086, 534090, 534091, 534119, 534122, 534158, 534181, 534183, 534187, 534190, 534195, 534199, 534203, 534204, 534214, 534220, 534234, 534242, 534244, 534246, 534260, 534271, 534272, 534274, 534276, 534278, 534279, 534282, 534287, 534294, 534305, 534306, 534309, 534323, 534327, 534342, 534351, 534352, 534357, 534374, 534383, 534387, 534388, 534393, 534403, 534407, 534423, 534431, 534435, 534437, 534448, 534449, 534452, 534459, 534477, 534482, 534484, 534493, 534502, 534505, 534510, 534527, 534532, 534536, 534545, 534551, 534557, 534561, 534570, 534584, 534590, 534593, 534613, 534618, 534619, 534623, 534626, 534628, 534630, 534631, 534639, 534650, 534654, 534656, 534670, 534678, 534679, 534687, 534691, 534692, 534699, 534703, 534705, 534710, 534724, 534726, 534740, 534741, 534742, 534743, 534744, 534747, 534748, 534755, 534763, 534764, 534767, 534779, 534781, 534784, 534796, 534805, 534807, 534825, 534835, 534841, 534846, 534847, 534851, 534853, 534854, 534864, 534868, 534870, 534871, 534878, 534895, 534896, 534898, 534902, 534905, 534907, 534908, 534913, 534922, 534932, 534937, 534938, 534955, 534972, 534975, 534978, 534992, 534993, 534996, 534999, 535013, 535018, 535019, 535023, 535033, 535052, 535053, 535054, 535060, 535062, 535082, 535083, 535089, 535097, 535123, 535129, 535147, 535148, 535150, 535161, 535174, 535176, 535178, 535186, 535197, 535199, 535205, 535208, 535209, 535222, 535224, 535225, 535230, 535238, 535244, 535246, 535249, 535252, 535266, 535268, 535269, 535279, 535280, 535282, 535286, 535297, 535299, 535304, 535308, 535318, 535333, 535339, 535351, 535352, 535354, 535360, 535376, 535397, 535398, 535409, 535416, 535440, 535448, 535457, 535467, 535470, 535475, 535494, 535495, 535500, 535506, 535508, 535512, 535514, 535516, 535535, 535539, 535546, 535553, 535556, 535559, 535568, 535574, 535575, 535580, 535582, 535584, 535585, 535588, 535590, 535591, 535593, 535595, 535613, 535624, 535633, 535640, 535647, 535650, 535656, 535659, 535670, 535672, 535676, 535684, 535685, 535686, 535691, 535714, 535722, 535728, 535740, 535749, 535750, 535755, 535773, 535776, 535791, 535811, 535814, 535819, 535827, 535829, 535832, 535834, 535836, 535837, 535838, 535845, 535861, 535868, 535874, 535884, 535890, 535892, 535901, 535918, 535926, 535934, 535943, 535944, 535962, 535983, 535984, 535999, 536016, 536019, 536029, 536040, 536041, 536044, 536052, 536056, 536058, 536067, 536068, 536072, 536096, 536099, 536104, 536107, 536118, 536119, 536121, 536141, 536143, 536144, 536170, 536177, 536182, 536184, 536187, 536188, 536203, 536204, 536208, 536226, 536228, 536231, 536232, 536246, 536247, 536255, 536256, 536263, 536266, 536280, 536303, 536307, 536310, 536325, 536333, 536337, 536338, 536342, 536348, 536355, 536377, 536378, 536385, 536393, 536403, 536411, 536415, 536417, 536420, 536423, 536436, 536438, 536442, 536445, 536452, 536454, 536462, 536484, 536498, 536499, 536544, 536553, 536573, 536580, 536583, 536590, 536603, 536630, 536637, 536641, 536681, 536689, 536706, 536709, 536721, 536728, 536730, 536731, 536733, 536737, 536746, 536754, 536763, 536767, 536783, 536801, 536803, 536815, 536834, 536836, 536846, 536873, 536898, 536918, 536931, 536939, 536963, 536979, 536981, 536983, 536986, 537026, 537034, 537064, 537100, 537118, 537121, 537136, 537147, 537151, 537163, 537169, 537173, 537175, 537180, 537199, 537208, 537209, 537217, 537221, 537226, 537234, 537239, 537240, 537266, 537272, 537276, 537277, 537286, 537294, 537302, 537305, 537319, 537326, 537334, 537353, 537357, 537369, 537376, 537380, 537391, 537406, 537418, 537441, 537442, 537448, 537467, 537482, 537492, 537514, 537557, 537565, 537575, 537576, 537582, 537585, 537586, 537599, 537603, 537613, 537628, 537631, 537671, 537685, 537689, 537724, 537732, 537733, 537740, 537744, 538039, 538157, 538637, 538696, 538831, 539209, 539314, 539441, 539474, 539722, 539952, 539961, 540560, 540562, 540584, 540902, 541196, 541993, 542015, 542034, 542040, 542041, 542042, 542046, 542050, 542056, 542065, 542066, 542071, 542072, 542076, 542078, 542087, 542091, 542092, 542099, 542100, 542105, 542181, 542255, 542382, 542556, 542624, 542713, 542740, 542799, 542898, 542985, 543026, 543124, 543155, 543177, 543189, 543222, 543322, 543345, 543418, 543482, 543635, 543721, 543723, 543869, 543971, 544093, 544100, 544208, 544236, 544279, 544302, 544410, 544470, 544651, 544657, 544754, 544835, 544967, 545051, 545351, 545387, 545461, 545465, 545472, 545480, 545481, 545492, 545513, 545519, 545541, 545543, 545548, 545551, 545568, 545569, 545574, 545625, 545632, 545648, 545670, 545693, 545702, 545706, 545712, 545716, 545726, 545761, 545768, 545774, 545775, 545819, 545820, 545830, 545836, 545855, 545964, 545974, 545987, 545995, 545998, 546000, 546006, 546014, 546015, 546016, 546022, 546032, 546044, 546067, 546070, 546077, 546079, 546081, 546082, 546087, 546090, 546099, 546103, 546108, 546110, 546112, 546135, 546136, 546141, 546169, 546173, 546189, 546196, 546201, 546203, 546219, 546226, 546231, 546234, 546239, 546248, 546256, 546257, 546274, 546285, 546293, 546298, 546309, 546329, 546335, 546336, 546353, 546362, 546368, 546370, 546376, 546384, 546386, 546395, 546410, 546412, 546424, 546447, 546450, 546469, 546471, 546483, 546484, 546499, 546514, 546516, 546520, 546539, 546541, 546545, 546561, 546576, 546628, 546629, 546640, 546645, 546656, 546731, 546732, 546734, 546759, 546784, 546797, 546833, 546834, 546846, 546857, 546861, 546867, 546871, 546885, 546892, 546893, 546909, 546916, 546928, 546938, 546949, 546956, 546957, 546982, 546990, 547016, 547048, 547051, 547052, 547059, 547083, 547086, 547098, 547105, 547110, 547114, 547138, 547146, 547169, 547173, 547181, 547184, 547186, 547215, 547222, 547224, 547227, 547234, 547237, 547239, 547247, 547255, 547271, 547277, 547280, 547282, 547283, 547286, 547298, 547310, 547311, 547317, 547322, 547326, 547342, 547343, 547349, 547353, 547395, 547412, 547452, 547466, 547485, 547494, 547505, 547530, 547551, 547556, 547561, 547587, 547588, 547596, 547598, 547602, 547610, 547637, 547638, 547664, 547678, 547683, 547698, 547701, 547722, 547745, 547782, 547790, 547799, 547811, 547820, 547864, 547883, 547893, 547919, 547944, 547950, 547994, 548014, 548036, 548037, 548052, 548077, 548099, 548103, 548136, 548162, 548191, 548203, 548207, 548210, 548215, 548219, 548243, 548265, 548268, 548277, 548283, 548290, 548301, 548325, 548327, 548357, 548369, 548391, 548401, 548411, 548423, 548424, 548436, 548471, 548499, 548500, 548502, 548504, 548521, 548531, 548575, 548577, 548595, 548616, 548621, 548627, 548628, 548651, 548665, 548669, 548674, 548697, 548704, 548708, 548711, 548732, 548743, 548754, 548773, 548781, 548785, 548811, 548817, 548827, 548851, 548857, 548866, 548878, 548899, 548904, 548905, 548911, 548932, 548937, 548952, 548957, 548990, 548993, 548998, 549098, 549107, 549114, 549115, 549116, 549119, 549124, 549125, 549126, 549139, 549149, 549156, 549167, 549171, 549172, 549186, 549199, 549203, 549214, 549241, 549244, 549260, 549279, 549289, 549315, 549317, 549330, 549344, 549345, 549359, 549422, 549427, 549432, 549435, 549440, 549447, 549448, 549452, 549469, 549470, 549506, 549520, 549539, 549555, 549560, 549561, 549572, 549580, 549600, 549614, 549633, 549654, 549655, 549661, 549664, 549666, 549674, 549677, 549684, 549695, 549698, 549705, 549706, 549708, 549731, 549733, 549735, 549745, 549773, 549782, 549789, 549801, 549820, 549830, 549841, 549846, 549850, 549855, 549871, 549872, 549926, 549936, 549944, 549947, 549948, 550009, 550014, 550020, 550032, 550048, 550061, 550065, 550087, 550102, 550108, 550123, 550127, 550131, 550141, 550183, 550197, 550201, 550219, 550231, 550244, 550278, 550283, 550306, 550323, 550331, 550345, 550349, 550352, 550355, 550359, 550360, 550403, 550404, 550432, 550453, 550464, 550468, 550476, 550480, 550483, 550523, 550531, 550574, 550587, 550593, 550595, 550596, 550606, 550615, 550623, 550635, 550657, 550667, 550668, 550686, 550688, 550699, 550701, 550702, 550703, 550707, 550712, 550718, 550743, 550756, 550798, 550800, 550804, 550831, 550834, 550840, 550864, 550869, 550904, 550913, 550914, 550928, 550936, 550938, 550948, 550965, 550982, 550985, 550986, 550996, 551000, 551010, 551024, 551026, 551032, 551045, 551048, 551052, 551058, 551061, 551072, 551076, 551111, 551113, 551129, 551136, 551147, 551149, 551176, 551178, 551197, 551199, 551264, 551289, 551308, 551328, 551335, 551352, 551372, 551389, 551400, 551450, 551463, 551473, 551478, 551493, 551499, 551524, 551549, 551575, 551576, 551611, 551656, 551680, 551688, 551695, 551697, 551714, 551757, 551805, 551814, 551819, 551842, 551865, 551870, 551871, 551879, 551892, 551896, 551897, 551903, 551904, 551914, 551940, 551943, 551945, 551950, 551952, 551956, 551960, 551965, 551977, 551980, 552009, 552013, 552018, 552045, 552048, 552053, 552054, 552092, 552101, 552103, 552114, 552115, 552121, 552122, 552147, 552175, 552188, 552191, 552209, 552221, 552237, 552255, 552264, 552285, 552304, 552308, 552327, 552374, 552384, 552411, 552432, 552433, 552463, 552498, 552502, 552520, 552523, 552561, 552574, 552582, 552616, 552621, 552638, 552658, 552660, 552663, 552664, 552672, 552677, 552694, 552699, 552713, 552723, 552724, 552729, 552756, 552797, 552800, 552813, 552818, 552824, 552827, 552840, 552851, 552872, 552878, 552884, 552901, 552906, 552914, 552929, 552941, 552954, 552960, 552984, 552996, 553004, 553008, 553029, 553032, 553041, 553043, 553045, 553052, 553069, 553078, 553089, 553130, 553169, 553175, 553185, 553197, 553201, 553237, 553242, 553262, 553271, 553288, 553334, 553357, 553408, 553410, 553419, 553425, 553440, 553447, 553470, 553551, 553563, 553689, 553690, 553727, 553743, 553781, 553789, 553808, 553885, 553931, 553934, 553970, 553975, 553976, 553986, 554003, 554031, 554104, 554158, 554262, 554281, 554288, 554290, 554299, 554331, 554349, 554373, 554400, 554414, 554420, 554430, 554451, 554513, 554633, 554642, 554705, 554708, 554717, 554722, 554800, 554810, 554812, 554849, 554876, 554920, 554930, 554948, 554960, 554997, 555131, 555136, 555141, 555159, 555166, 555191, 555200, 555207, 555265, 555269, 555271, 555274, 555300, 555302, 555303, 555306, 555314, 555316, 555318, 555336, 555344, 555347, 555357, 555367, 555376, 555413, 555420, 555424, 555427, 555437, 555455, 555466, 555471, 555476, 555479, 555480, 555503, 555543, 555547, 555567, 555577, 555579, 555584, 555595, 555607, 555617, 555619, 555654, 555655, 555661, 555666, 555673, 555692, 555705, 555706, 555712, 555715, 555721, 555743, 555747, 555758, 555759, 555764, 555796, 555799, 555806, 555825, 555829, 555863, 555871, 555872, 555874, 555883, 555896, 555897, 555909, 555917, 555925, 555926, 555932, 555948, 555970, 556000, 556005, 556026, 556029, 556037, 556043, 556056, 556060, 556064, 556070, 556086, 556103, 556107, 556112, 556136, 556138, 556139, 556149, 556163, 556169, 556175, 556178, 556183, 556187, 556193, 556195, 556203, 556205, 556208, 556213, 556215, 556229, 556251, 556253, 556257, 556259, 556268, 556270, 556275, 556277, 556280, 556287, 556313, 556318, 556330, 556339, 556353, 556375, 556380, 556381, 556382, 556426, 556427, 556428, 556431, 556432, 556433, 556437, 556443, 556447, 556452, 556457, 556462, 556495, 556511, 556519, 556523, 556536, 556554, 556574, 556582, 556590, 556605, 556609, 556610, 556616, 556622, 556639, 556650, 556651, 556653, 556712, 556719, 556736, 556745, 556757, 556765, 556767, 556769, 556786, 556789, 556802, 556804, 556807, 556814, 556822, 556828, 556829, 556831, 556833, 556834, 556848, 556851, 556855, 556858, 556863, 556874, 556879, 556883, 556891, 556901, 556918, 556943, 556944, 556945, 556947, 556964, 556966, 556985, 556994, 556995, 556997, 557017, 557021, 557039, 557044, 557056, 557060, 557071, 557086, 557089, 557098, 557102, 557106, 557109, 557140, 557152, 557162, 557165, 557168, 557175, 557184, 557199, 557211, 557213, 557231, 557248, 557249, 557278, 557281, 557285, 557299, 557303, 557308, 557310, 557320, 557323, 557335, 557348, 557351, 557368, 557373, 557404, 557409, 557412, 557420, 557428, 557445, 557451, 557486, 557498, 557522, 557540, 557543, 557544, 557578, 557605, 557610, 557629, 557645, 557646, 557673, 557675, 557692, 557729, 557751, 557762, 557768, 557781, 557784, 557788, 557808, 557811, 557814, 557822, 557825, 557840, 557852, 557861, 557865, 557895, 557905, 557915, 557928, 557934, 557941, 557942, 557945, 557948, 557953, 557968, 557992, 557997, 558031, 558034, 558048, 558054, 558058, 558062, 558070, 558079, 558081, 558086, 558096, 558104, 558118, 558124, 558132, 558134, 558146, 558147, 558150, 558172, 558177, 558183, 558195, 558209, 558215, 558218, 558220, 558233, 558236, 558251, 558255, 558260, 558262, 558281, 558294, 558303, 558330, 558338, 558342, 558364, 558376, 558379, 558387, 558392, 558417, 558426, 558429, 558430, 558464, 558469, 558471, 558504, 558526, 558528, 558538, 558553, 558569, 558570, 558573, 558577, 558581, 558584, 558588, 558597, 558598, 558601, 558611, 558622, 558624, 558632, 558634, 558642, 558651, 558661, 558668, 558678, 558681, 558697, 558730, 558733, 558737, 558750, 558774, 558801, 558805, 558809, 558810, 558817, 558820, 558823, 558835, 558837, 558841, 558848, 558869, 558871, 558875, 558876, 558887, 558890, 558892, 558895, 558902, 558927, 558949, 558951, 558959, 558964, 558970, 558985, 559016, 559020, 559026, 559027, 559028, 559029, 559054, 559062, 559077, 559082, 559084, 559111, 559118, 559122, 559166, 559192, 559200, 559206, 559215, 559221, 559236, 559237, 559256, 559267, 559270, 559275, 559282, 559285, 559303, 559312, 559316, 559319, 559322, 559329, 559336, 559344, 559380, 559381, 559415, 559423, 559441, 559447, 559468, 559474, 559475, 559484, 559487, 559488, 559490, 559502, 559504, 559505, 559507, 559517, 559527, 559529, 559542, 559548, 559549, 559561, 559582, 559589, 559590, 559599, 559609, 559626, 559640, 559675, 559683, 559690, 559695, 559696, 559699, 559703, 559705, 559710, 559712, 559719, 559720, 559747, 559751, 559760, 559761, 559768, 559772, 559791, 559796, 559800, 559803, 559810, 559812, 559850, 559863, 559875, 559877, 559879, 559889, 559906, 559907, 559908, 559944, 559958, 559969, 559970, 559983, 559987, 560014, 560017, 560032, 560035, 560037, 560050, 560061, 560083, 560084, 560103, 560117, 560121, 560134, 560142, 560144, 560150, 560151, 560157, 560171, 560191, 560199, 560210, 560214, 560216, 560217, 560222, 560236, 560244, 560247, 560250, 560256, 560265, 560274, 560276, 560278, 560285, 560291, 560292, 560299, 560301, 560309, 560328, 560341, 560351, 560361, 560366, 560378, 560386, 560403, 560409, 560412, 560435, 560447, 560450, 560451, 560456, 560466, 560491, 560496, 560503, 560505, 560520, 560536, 560538, 560554, 560564, 560567, 560569, 560607, 560619, 560632, 560665, 560670, 560682, 560698, 560701, 560705, 560709, 560710, 560717, 560722, 560733, 560740, 560743, 560754, 560756, 560762, 560763, 560765, 560773, 560776, 560785, 560788, 560794, 560822, 560832, 560836, 560838, 560846, 560870, 560875, 560879, 560880, 560882, 560884, 560891, 560892, 560897, 560901, 560907, 560909, 560911, 560913, 560923, 560930, 560937, 560942, 560944, 560962, 560978, 561000, 561014, 561019, 561034, 561036, 561037, 561072, 561075, 561077, 561081, 561093, 561096, 561105, 561128, 561143, 561155, 561156, 561160, 561171, 561181, 561188, 561190, 561206, 561217, 561226, 561242, 561247, 561256, 561323, 561328, 561329, 561348, 561412, 561431, 561458, 561473, 561485, 561500, 561548, 561580, 561584, 561628, 561672, 561676, 561688, 561701, 561702, 561736, 561741, 561841, 561873, 561880, 561884, 561885, 561896, 561972, 561979, 561997, 562004, 562005, 562012, 562079, 562162, 562172, 562284, 562294, 562334, 562339, 562341, 562355, 562356, 562540, 562574, 562575, 562587, 562645, 562695, 562735, 562740, 562747, 562764, 562766, 562771, 562803, 562883, 562905, 562934, 562935, 562948, 562972, 562977, 562979, 562980, 562982, 563019, 563025, 563027, 563041, 563045, 563047, 563057, 563073, 563077, 563094, 563108, 563113, 563120, 563127, 563128, 563138, 563140, 563157, 563164, 563166, 563188, 563202, 563206, 563214, 563219, 563232, 563236, 563237, 563245, 563250, 563271, 563278, 563279, 563311, 563312, 563318, 563322, 563335, 563346, 563352, 563371, 563375, 563391, 563400, 563412, 563418, 563427, 563435, 563438, 563441, 563477, 563478, 563491, 563494, 563498, 563509, 563543, 563551, 563575, 563583, 563593, 563594, 563600, 563610, 563611, 563612, 563640, 563652, 563665, 563674, 563679, 563680, 563699, 563702, 563764, 563784, 563797, 563824, 563830, 563837, 563844, 563851, 563853, 563868, 563870, 563873, 563879, 563882, 563891, 563902, 563910, 563912, 563921, 563946, 563963, 563988, 563993, 564054, 564061, 564064, 564065, 564073, 564077, 564084, 564103, 564105, 564107, 564121, 564156, 564160, 564165, 564166, 564168, 564188, 564199, 564200, 564204, 564212, 564246, 564283, 564285, 564289, 564323, 564335, 564351, 564371, 564373, 564417, 564433, 564454, 564455, 564487, 564531, 564553, 564580, 564593, 564603, 564607, 564643, 564656, 564690, 564692, 564700, 564743, 564749, 564774, 564847, 564852, 564861, 564867, 564884, 564886, 564888, 564890, 564892, 564902, 564926, 564938, 564945, 564953, 564957, 564971, 564978, 564990, 565003, 565008, 565042, 565071, 565074, 565094, 565099, 565148, 565151, 565165, 565171, 565172, 565176, 565177, 565187, 565188, 565194, 565195, 565206, 565207, 565210, 565216, 565239, 565240, 565241, 565243, 565249, 565253, 565259, 565266, 565288, 565295, 565297, 565300, 565310, 565321, 565333, 565366, 565370, 565376, 565381, 565386, 565392, 565402, 565403, 565408, 565410, 565414, 565415, 565418, 565422, 565440, 565442, 565463, 565464, 565465, 565466, 565474, 565492, 565494, 565496, 565497, 565502, 565515, 565518, 565525, 565533, 565539, 565560, 565564, 565571, 565579, 565583, 565586, 565587, 565594, 565596, 565610, 565614, 565615, 565616, 565618, 565623, 565626, 565635, 565644, 565650, 565652, 565653, 565659, 565665, 565666, 565685, 565693, 565695, 565696, 565707, 565710, 565724, 565729, 565738, 565740, 565742, 565744, 565748, 565750, 565758, 565764, 565765, 565784, 565789, 565812, 565820, 565829, 565832, 565869, 565879, 565887, 565891, 565910, 565914, 565920, 565922, 565933, 565936, 565938, 565940, 565948, 565951, 565954, 565959, 565963, 565978, 565979, 565987, 565989, 565992, 566001, 566013, 566029, 566030, 566048, 566052, 566053, 566054, 566058, 566060, 566064, 566066, 566068, 566072, 566078, 566086, 566092, 566095, 566105, 566106, 566113, 566114, 566116, 566120, 566126, 566127, 566134, 566137, 566141, 566145, 566151, 566159, 566166, 566187, 566190, 566191, 566194, 566195, 566199, 566205, 566211, 566216, 566221, 566230, 566232, 566233, 566235, 566237, 566239, 566240, 566257, 566261, 566262, 566269, 566274, 566278, 566282, 566293, 566294, 566297, 566304, 566305, 566319, 566323, 566330, 566332, 566333, 566346, 566350, 566355, 566364, 566368, 566374, 566380, 566386, 566401, 566418, 566426, 566432, 566433, 566437, 566457, 566461, 566463, 566487, 566489, 566497, 566517, 566524, 566525, 566539, 566547, 566550, 566554, 566562, 566582, 566603, 566616, 566623, 566624, 566632, 566637, 566644, 566652, 566655, 566670, 566675, 566696, 566697, 566707, 566720, 566721, 566724, 566740, 566749, 566754, 566758, 566764, 566766, 566781, 566794, 566796, 566804, 566808, 566820, 566828, 566835, 566855, 566858, 566863, 566885, 566892, 566899, 566903, 566915, 566921, 566923, 566932, 566934, 566940, 566943, 566944, 566946, 566953, 566971, 566974))) AND "video"."x" < 180 AND "video"."y" < 160 AND "video"."duration" > 300 AND "video"."x" > 90 AND "video"."y" > 80 ) ORDER BY "video"."id" DESC
 
</pre>
<p>Toujours faire gaffe au SQL que genère son ORM :)</p>


