614 shaares
121 results
tagged
programming
If you wanna make custom editors in Unity, be wary of the headaches.
That being said, you could always check the "newly" released Unity C# reference code on how they tackle their own Editors.
For instance, you see some fancy thing they did in their SpriteRenderer editor OnInspectorGUI, go look up the code and get inspired by their magic!
That being said, you could always check the "newly" released Unity C# reference code on how they tackle their own Editors.
For instance, you see some fancy thing they did in their SpriteRenderer editor OnInspectorGUI, go look up the code and get inspired by their magic!
Basically replacing this
class A:
def __init__(self, b, c, d, e):
self.b = b
self.c = c
self.d = d
self.e = e
by
class A:
def __init__(self, b, c, d, e):
# You can edit parameters' value here before they are being stored
for k, v in vars().items():
setattr(self, k, v)
By me.
class A:
def __init__(self, b, c, d, e):
self.b = b
self.c = c
self.d = d
self.e = e
by
class A:
def __init__(self, b, c, d, e):
# You can edit parameters' value here before they are being stored
for k, v in vars().items():
setattr(self, k, v)
By me.
[path_to_script]\python-no-autoclose.py "$(FULL_CURRENT_PATH)"
In the menu Run > Run, put this in the text field and hit Save, give it a name and a key combination. Personally I used Shift+F5. Be wary than all key combinations might not work, try it to make sure or change it.
The script:
import sys
import traceback
import subprocess
import os
import pathlib
if sys.argv[1:]: # Failsafe
try:
os.chdir(str(pathlib.Path(sys.argv[1]).parent))
except Exception as e:
traceback.print_exc()
try:
subprocess.call(['python', sys.argv[1]])
except Exception as e:
traceback.print_exc()
else:
print('I\'m very confused...')
print()
input('Press Enter to exit.')
In the menu Run > Run, put this in the text field and hit Save, give it a name and a key combination. Personally I used Shift+F5. Be wary than all key combinations might not work, try it to make sure or change it.
The script:
import sys
import traceback
import subprocess
import os
import pathlib
if sys.argv[1:]: # Failsafe
try:
os.chdir(str(pathlib.Path(sys.argv[1]).parent))
except Exception as e:
traceback.print_exc()
try:
subprocess.call(['python', sys.argv[1]])
except Exception as e:
traceback.print_exc()
else:
print('I\'m very confused...')
print()
input('Press Enter to exit.')
I don't have any experience with compiling Java so I'm just leaving this here for future me.
1) Download Java JDK (Any version should be fine)
2) If you're lucky to have a .gradle file in your app directory, download Gradle. (You can then add gradle to your PATH, but that's optional)
3) Go in the directory where your .gradle file is situated and run
PATH_TO_YOUR_GRADLE/bin/gradle build
4) The compiled .jar will be situated in build/libs
That's it!
1) Download Java JDK (Any version should be fine)
2) If you're lucky to have a .gradle file in your app directory, download Gradle. (You can then add gradle to your PATH, but that's optional)
3) Go in the directory where your .gradle file is situated and run
PATH_TO_YOUR_GRADLE/bin/gradle build
4) The compiled .jar will be situated in build/libs
That's it!
Sauvegarder les métadonnées EXIF avec PIL.
Quick and simple backdoor to control your computers/turtles (from ComputerCraft) from outside Minecraft. Here featuring with Python.
Ils sont sympas sur le tchat PHP de SO.
Quelques amis m'ont donné des exemples de codes à propos des exceptions en PHP, que j'ai, un peu trop souvent rechigné.
C'est *bô*. Jugez-en par vous même:
http://3v4l.org/NJJjO
function (╯°□°)╯︵┻━┻(){throw new ┻━┻;}
class ┻━┻ extends Exception {public function __construct() {parent::__construct("Please respect tables! ┬─┬ノ(ಠ_ಠノ)");} public function __toString(){return "┬─┬";}}
// try/catch
try { (╯°□°)╯︵┻━┻ (); } catch ( ┻━┻ $niceguy) {echo $niceguy->getMessage();}
// ok now lets see an uncaught one
(╯°□°)╯︵┻━┻
();
// Output:
Please respect tables! ┬─┬ノ(ಠ_ಠノ)
Fatal error: Uncaught ┬─┬
Et http://3v4l.org/TkNpc
class JeromeException extends Exception
{
protected $boobies = [];
function __construct($message = null, $code = 0, Exception $previous = null, $arrayOfBoobies = [])
{
$this->boobies = $arrayOfBoobies;
}
function getTraceEx()
{
return $this->getTrace() + ['boobies' => $this->boobies];
}
}
function jeromeIsExceptional()
{
try {
throw new JeromeException('herro', 0, null, ['34B', '32C', '36D']);
}
catch (JeromeException $e) {
var_dump($e->getTraceEx());
}
}
jeromeIsExceptional();
Quelques amis m'ont donné des exemples de codes à propos des exceptions en PHP, que j'ai, un peu trop souvent rechigné.
C'est *bô*. Jugez-en par vous même:
http://3v4l.org/NJJjO
function (╯°□°)╯︵┻━┻(){throw new ┻━┻;}
class ┻━┻ extends Exception {public function __construct() {parent::__construct("Please respect tables! ┬─┬ノ(ಠ_ಠノ)");} public function __toString(){return "┬─┬";}}
// try/catch
try { (╯°□°)╯︵┻━┻ (); } catch ( ┻━┻ $niceguy) {echo $niceguy->getMessage();}
// ok now lets see an uncaught one
(╯°□°)╯︵┻━┻
();
// Output:
Please respect tables! ┬─┬ノ(ಠ_ಠノ)
Fatal error: Uncaught ┬─┬
Et http://3v4l.org/TkNpc
class JeromeException extends Exception
{
protected $boobies = [];
function __construct($message = null, $code = 0, Exception $previous = null, $arrayOfBoobies = [])
{
$this->boobies = $arrayOfBoobies;
}
function getTraceEx()
{
return $this->getTrace() + ['boobies' => $this->boobies];
}
}
function jeromeIsExceptional()
{
try {
throw new JeromeException('herro', 0, null, ['34B', '32C', '36D']);
}
catch (JeromeException $e) {
var_dump($e->getTraceEx());
}
}
jeromeIsExceptional();
Nice!
Bon, sachant que sebsauvage lit rarement ses mails, je vais tenter de le contacter par ici. :)
Ton implémentation est non sécurisée. C'est mal car d'autres personnes risquent de s'en inspirer sans savoir les problèmes liés à cette implémentation.
1) " Warning - When comparing the output of hexdigest() to an externally-supplied digest during a verification routine, it is recommended to use the compare_digest() function instead of the == operator to reduce the vulnerability to timing attacks." https://docs.python.org/3.4/library/hmac.html#hmac.HMAC.hexdigest
2) "The digestmod argument to the hmac.new() function may now be any hash digest name recognized by hashlib. In addition, the current behavior in which the value of digestmod defaults to MD5 is deprecated: in a future version of Python there will be no default value. (Contributed by Christian Heimes in issue 17276.)" https://docs.python.org/3/whatsnew/3.4.html#hmac
Donc il faudrait mieux commencer à spécifier une valeur pour digestmod.
Comme suggéré par l'issue (1) et cette réponse sur SO (2), je proposerais d'utiliser SHA-256 ou SHA-512 comme suit :
hmac.compare_digest(hmac.new(key, name, digestmod=hashlib.sha256).hexdigest(), signature)
(+ remplacer partout où il faut bien sure et ne pas oublier import hashlib)
(1) https://bugs.python.org/issue17276
"As of now the hash algorithm for HMAC defaults to MD5. However MD5 is considered broken. HMAC-MD5 is still ok but shall not be used in new code. Applications should slowly migrate away from HMAC-MD5 and use a more modern algorithm like HMAC-SHA256.
Therefore I propose that default digestmod should be deprecated in Python 3.4 and removed in 3.5. Starting with Python 3.5 developer are forced to choose a hash algorithm like SHA256. Our documentation shall suggest it, too."
(2) http://crypto.stackexchange.com/a/9340/18518
"Yes, there are currently no known attacks on HMAC-MD5.
[…]
However, this does not mean you should use HMAC-MD5 in new cryptosystem designs. To paraphrase Bruce Schneier, "attacks only get better, never worse." We already have practical collision attacks for MD5, showing that it does not meet its original security goals; it's possible that, any day now, someone might figure out a way to turn those into a preimage attack, which would compromise the security of HMAC-MD5. A much better choice would be to use HMAC with a hash function having no known attacks, such as SHA-2 or SHA-3."
Ton implémentation est non sécurisée. C'est mal car d'autres personnes risquent de s'en inspirer sans savoir les problèmes liés à cette implémentation.
1) " Warning - When comparing the output of hexdigest() to an externally-supplied digest during a verification routine, it is recommended to use the compare_digest() function instead of the == operator to reduce the vulnerability to timing attacks." https://docs.python.org/3.4/library/hmac.html#hmac.HMAC.hexdigest
2) "The digestmod argument to the hmac.new() function may now be any hash digest name recognized by hashlib. In addition, the current behavior in which the value of digestmod defaults to MD5 is deprecated: in a future version of Python there will be no default value. (Contributed by Christian Heimes in issue 17276.)" https://docs.python.org/3/whatsnew/3.4.html#hmac
Donc il faudrait mieux commencer à spécifier une valeur pour digestmod.
Comme suggéré par l'issue (1) et cette réponse sur SO (2), je proposerais d'utiliser SHA-256 ou SHA-512 comme suit :
hmac.compare_digest(hmac.new(key, name, digestmod=hashlib.sha256).hexdigest(), signature)
(+ remplacer partout où il faut bien sure et ne pas oublier import hashlib)
(1) https://bugs.python.org/issue17276
"As of now the hash algorithm for HMAC defaults to MD5. However MD5 is considered broken. HMAC-MD5 is still ok but shall not be used in new code. Applications should slowly migrate away from HMAC-MD5 and use a more modern algorithm like HMAC-SHA256.
Therefore I propose that default digestmod should be deprecated in Python 3.4 and removed in 3.5. Starting with Python 3.5 developer are forced to choose a hash algorithm like SHA256. Our documentation shall suggest it, too."
(2) http://crypto.stackexchange.com/a/9340/18518
"Yes, there are currently no known attacks on HMAC-MD5.
[…]
However, this does not mean you should use HMAC-MD5 in new cryptosystem designs. To paraphrase Bruce Schneier, "attacks only get better, never worse." We already have practical collision attacks for MD5, showing that it does not meet its original security goals; it's possible that, any day now, someone might figure out a way to turn those into a preimage attack, which would compromise the security of HMAC-MD5. A much better choice would be to use HMAC with a hash function having no known attacks, such as SHA-2 or SHA-3."
Woaaah, PHP ne cessera jamais de m'impressioner, dans le mauvais sens du terme.
>.<"
(Source: http://stackoverflow.com/a/2950046/1524913 )
>.<"
(Source: http://stackoverflow.com/a/2950046/1524913 )
Quelques conseils issus de mon expérience personnelle avec GreaseMonkey…
J'en ai chié quelques fois, donc si ça peut en aider quelques un… Sait-on jamais ! :D
J'en ai chié quelques fois, donc si ça peut en aider quelques un… Sait-on jamais ! :D
So, except few exceptions, almost all passwords shouldn't have "any" limit on the size of them upward (= no maximum length). Riiiight? :)
(Since they aren't supposed to be stored in raw form anyway and most (if not all?) hashing algorithm accept any size of password and always return unique constant length string)
So why HTML doesnt prevent bad ideas to be working? Like setting a maximum length on a password input… The way I see it, that would just not work and be reported in the console for debbugging purpose.
For the things I, so called "exceptions", I was thinking about PIN codes for instance. I could imagine letting HTML implements a new tag (or a new type of input tag) allowing a max length, but surely it would surely be abused though… Maybe those "PIN code" input should allow one fixed-length of password (as expected from a PIN code anyway and that would induce way less abuse too):
Finally, my browser (maybe some others too, mine is currently Palemoon, a implementation of Firefox) only prevent me to type more characters when I reach the maximum allowed by max-length, …, it doesnt warn me, it does nothing but preventing… The problem is that, if it was plain text, I could notice it easily, but as it is a password input and that my password is longer than the visible length of the field, then I have no fucking clue that what I'm currently typing is thrown away as I type it… -_-
So, some fucking warning would be appreciated at least!
(Since they aren't supposed to be stored in raw form anyway and most (if not all?) hashing algorithm accept any size of password and always return unique constant length string)
So why HTML doesnt prevent bad ideas to be working? Like setting a maximum length on a password input… The way I see it, that would just not work and be reported in the console for debbugging purpose.
For the things I, so called "exceptions", I was thinking about PIN codes for instance. I could imagine letting HTML implements a new tag (or a new type of input tag) allowing a max length, but surely it would surely be abused though… Maybe those "PIN code" input should allow one fixed-length of password (as expected from a PIN code anyway and that would induce way less abuse too):
Finally, my browser (maybe some others too, mine is currently Palemoon, a implementation of Firefox) only prevent me to type more characters when I reach the maximum allowed by max-length, …, it doesnt warn me, it does nothing but preventing… The problem is that, if it was plain text, I could notice it easily, but as it is a password input and that my password is longer than the visible length of the field, then I have no fucking clue that what I'm currently typing is thrown away as I type it… -_-
So, some fucking warning would be appreciated at least!
Bonne question … (Good question)
Peu de réponses … (Few answers)
Peu de réponses … (Few answers)
Ouuh, de chouettes infos que nous avons là. :o
Hop je pause ça là pour plus tard
[22:00:13] Lunatick: En gros Kineticjs => control du canva en génial, fonction avancées, events de tout types (click, touch) géré nativement
[22:00:13] Lunatick: et Tweenmax ça permet d'animer n'importe quel valeur numérique sur le temps, un peu comme une transition CSS mais sur ce qu'on veut
[22:00:28] Lunatick: donc la Combinaison de Kineticjs + GSAP Tweenmax = des animation/jeu en js fluides et simple à écrire
[22:00:28] Lunatick: L'avantage de Tweenmax c'est aussi que n'importe quoi peut etre animé, exemple ça peut etre la largeur d'un élément du DOM, un nombre lambda ou les prop de n'importe quel objet
[22:03:41] Lunatick: avec en prime une la possibilité d'appeler une fonction en callback au début, à la fin, et à chaque mise a jour de l'item que tu "animes"
Hop je pause ça là pour plus tard
[22:00:13] Lunatick: En gros Kineticjs => control du canva en génial, fonction avancées, events de tout types (click, touch) géré nativement
[22:00:13] Lunatick: et Tweenmax ça permet d'animer n'importe quel valeur numérique sur le temps, un peu comme une transition CSS mais sur ce qu'on veut
[22:00:28] Lunatick: donc la Combinaison de Kineticjs + GSAP Tweenmax = des animation/jeu en js fluides et simple à écrire
[22:00:28] Lunatick: L'avantage de Tweenmax c'est aussi que n'importe quoi peut etre animé, exemple ça peut etre la largeur d'un élément du DOM, un nombre lambda ou les prop de n'importe quel objet
[22:03:41] Lunatick: avec en prime une la possibilité d'appeler une fonction en callback au début, à la fin, et à chaque mise a jour de l'item que tu "animes"
J'avais commencé par faire le tout avec GreaseMonkey mais j'ai eu des probs avec le setTimeout tué par GreaseMonkey.
Du coup, j'ai fais un code très rapide en PHP; Il est fonctionnel (c'était le but).
Mais pour MEGA, le téléchargement coince à la fin, sûrement un prob de compatibilité du au domaine différent (127.0.0.1 dans mon cas).
Du coup Oros m'a aidé à résoudre le problème GreaseMonkey - je n'ai toujours pas compris pourquoi son code fonctionne et pas le mien, … mais au moins son code fonctionne! :
window.setTimeout('function wait() {if(document.getElementsByClassName("new-download-red-button").length==0){setTimeout("wait()",1000);}else{document.getElementsByClassName("new-download-red-button")[0].click();}}wait();', 1000);
Source: https://www.ecirtam.net/links/?XoFKOQ
Ça pourrait sûrement très facilement être entièrement porté à GreaseMonkey du coup …
Pour finir, dans mon cas, pour que ça reste quand même "pratique" (car au moins avec greaseMonkey, aucun clic requis), j'ai, personnellement, tout plein de pages bourrées de ces liens, donc j'ai un quick snippet pour changer tous les liens de la page pour qu'ils passent tous via mon script, et lorsqu'un cas n'est pas géré, mon script redirige vers la page normal.
javascript:var%20links=document.getElementsByTagName('a');for(var%20i%20=%200;%20i%20<%20links.length;%20i++){void(links[i].href%20=%20'http://127.0.0.1/test.php?url='+links[i].href);}
Du coup, j'ai fais un code très rapide en PHP; Il est fonctionnel (c'était le but).
Mais pour MEGA, le téléchargement coince à la fin, sûrement un prob de compatibilité du au domaine différent (127.0.0.1 dans mon cas).
Du coup Oros m'a aidé à résoudre le problème GreaseMonkey - je n'ai toujours pas compris pourquoi son code fonctionne et pas le mien, … mais au moins son code fonctionne! :
window.setTimeout('function wait() {if(document.getElementsByClassName("new-download-red-button").length==0){setTimeout("wait()",1000);}else{document.getElementsByClassName("new-download-red-button")[0].click();}}wait();', 1000);
Source: https://www.ecirtam.net/links/?XoFKOQ
Ça pourrait sûrement très facilement être entièrement porté à GreaseMonkey du coup …
Pour finir, dans mon cas, pour que ça reste quand même "pratique" (car au moins avec greaseMonkey, aucun clic requis), j'ai, personnellement, tout plein de pages bourrées de ces liens, donc j'ai un quick snippet pour changer tous les liens de la page pour qu'ils passent tous via mon script, et lorsqu'un cas n'est pas géré, mon script redirige vers la page normal.
javascript:var%20links=document.getElementsByTagName('a');for(var%20i%20=%200;%20i%20<%20links.length;%20i++){void(links[i].href%20=%20'http://127.0.0.1/test.php?url='+links[i].href);}
Quoi ?! Relayer le problème en utilisant la connexion via Google/FB & co? C'est une blague ?
J'ai pas encore regardé le reste de la vidéo. :)
J'ai pas encore regardé le reste de la vidéo. :)
Ouais, c'est chiant ça…
Ceci dit, non merci, je ne veux pas utilise les touches directionnelles personnellement.
Étant droitier, ce n'est pas pour rien que ces touches là sont devenues célèbres comme secondes touches de direction.
Je me vois mal avec ma main gauche à droite de mon clavier avec ma main droite pas loin. Enfin c'est ptet une question de préférence habitude. Mais je suis beaucoup plus confortable (habitué ?) lorsque j'ai un main de chaque côté. (Puis ça réduit les mouvements nécessaires. L'air de rien c'est super important. Voir clavier BÉPO & co)
Ce que je trouve par contre que les développeurs auraient du faire depuis longtemps serait de :
1) Normaliser ça.
2) Les assigner à un nom (Les touches gauche, droite, haut et bas sont "souvent" référencables par leur nom non? Sinon évidemment, si c'est uniquement par leur code c'est "too bad"), tel que ALTERNATIVE_LEFT ou quelques chose ainsi, qui varieraient donc dynamiquement d'un clavier AZERTY à un clavier QWERTY. Etc.
Ou alors faut tenter de se venger et sortir plein de jeux avec les touches QZSD par défaut. Lulz. (#rire_jaune)
Ceci dit, non merci, je ne veux pas utilise les touches directionnelles personnellement.
Étant droitier, ce n'est pas pour rien que ces touches là sont devenues célèbres comme secondes touches de direction.
Je me vois mal avec ma main gauche à droite de mon clavier avec ma main droite pas loin. Enfin c'est ptet une question de préférence habitude. Mais je suis beaucoup plus confortable (habitué ?) lorsque j'ai un main de chaque côté. (Puis ça réduit les mouvements nécessaires. L'air de rien c'est super important. Voir clavier BÉPO & co)
Ce que je trouve par contre que les développeurs auraient du faire depuis longtemps serait de :
1) Normaliser ça.
2) Les assigner à un nom (Les touches gauche, droite, haut et bas sont "souvent" référencables par leur nom non? Sinon évidemment, si c'est uniquement par leur code c'est "too bad"), tel que ALTERNATIVE_LEFT ou quelques chose ainsi, qui varieraient donc dynamiquement d'un clavier AZERTY à un clavier QWERTY. Etc.
Ou alors faut tenter de se venger et sortir plein de jeux avec les touches QZSD par défaut. Lulz. (#rire_jaune)
Et toc!
Oooouh, je connaissais pas inspect.getsource, c'est génial. ^-^
Petit guide d'optimisation en Python.
Nice reading.
Nice reading.
AttributeError: 'itertools.count' object has no attribute 'next'
Arf …
Le code suivant ne fonctionne donc plus en Python 3 :
>>> import itertools, collections
>>> value_to_numeric_map = collections.defaultdict(itertools.count().next)
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
>>> value_to_numeric_map['c']
2
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
La première solution venant à l'esprit serait d'avoir à instancier une variable :
>>> c = itertools.count()
>>> value_to_numeric_map = collections.defaultdict(lambda a: next(c))
Et ça fonctionne très bien.
Mais personnellement, je préfère lorsque ça reste one-line, donc voici une alternative one-line :
J'utilise lambda pour créer une encapsulation (closure).
value_to_numeric_map = collections.defaultdict((lambda c: (lambda: next(c)))(itertools.count()))
Arf …
Le code suivant ne fonctionne donc plus en Python 3 :
>>> import itertools, collections
>>> value_to_numeric_map = collections.defaultdict(itertools.count().next)
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
>>> value_to_numeric_map['c']
2
>>> value_to_numeric_map['a']
0
>>> value_to_numeric_map['b']
1
La première solution venant à l'esprit serait d'avoir à instancier une variable :
>>> c = itertools.count()
>>> value_to_numeric_map = collections.defaultdict(lambda a: next(c))
Et ça fonctionne très bien.
Mais personnellement, je préfère lorsque ça reste one-line, donc voici une alternative one-line :
J'utilise lambda pour créer une encapsulation (closure).
value_to_numeric_map = collections.defaultdict((lambda c: (lambda: next(c)))(itertools.count()))
Ouuuuuh, y a des trucs vachement chouettes !
Comme "1.14 Grouping adjacent list items using zip", c'est brillant, utilisé plusieurs instances du même objet iter pour regrouper les éléments ensemble. <3 (Même si j'avoue que la deuxième méthode est ptet plus lisible :D )
Ou "1.30 Using default dictionaries to represent simple trees" : Miam !
Etc.
(via http://sebsauvage.net/links/?3ASd0g )
Comme "1.14 Grouping adjacent list items using zip", c'est brillant, utilisé plusieurs instances du même objet iter pour regrouper les éléments ensemble. <3 (Même si j'avoue que la deuxième méthode est ptet plus lisible :D )
Ou "1.30 Using default dictionaries to represent simple trees" : Miam !
Etc.
(via http://sebsauvage.net/links/?3ASd0g )
Lien précédent : http://www.olissea.com/mb/links/1/?ibR8_g
EDIT: J'ai trouvé ce problème ceci dit: https://bugs.php.net/bug.php?id=65045
Mais j'ignore si je suis vraiment concerné : ça dépend en effet si mon script capture ces séquences à problèmes mais il me semble qu'il ne capture que les séquences valides de 4 bytes, donc pas de problème normalement.
Également, j'ai pas trop compris comment ça se fait, mais lorsque j'applique htmlspecialchars sur les séquences données sur la page, l'output n'est pas vide. Ne devrait-il pas l'être (vu que htmlspecialchars renvoie stupidement une chaîne vide lorsqu'il reçoit de l'UTF-8 invalide normalement ?).
Mmmmmh.
</EDIT>
"Plop.
Après mainte péripéties et échecs, je pense avoir trouver quelque chose de "potable".
Voir le code avec coloration syntaxique (un peu différent, manque une source) : http://sebsauvage.net/paste/?e249576d75ee9946#jBpv2UCufTQ4UC2WnTtM11gfolfGkQi61brf11pFORU=
<?php
# "😒" est codé sur 4 bytes
$body = 'lol😒a☺';
echo 'before: ',$body,'<br />'; # Output: lol😒a☺
echo 'length: ',strlen($body),'<br />'; # Output: 11 (😒 = 4, ☺ = 3)
# Le but est de remplacer uniquement les caractères de plus de 3 bytes par leur entité HTML.
# Afin d'obtenir ce code dans le cas de notre exemple
echo '😒','<br />'; # Fourni par https://duckduckgo.com/?q=html+%F0%9F%98%92
# Récupération des caractères de plus de 3 bytes uniquement
# Source: http://stackoverflow.com/a/1401716/1524913
# $body = preg_replace('/[\xF0-\xF7][\x80-\xBF]{3}/', '�', $body); # Yeah! It works!
# Ne fonctionne pas. htmlentities ne connaît pas tous les caractères unicode ( http://stackoverflow.com/a/13942507/1524913 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return htmlentities($m[0], ENT_COMPAT, 'UTF-8');}, $body); # Ignore complètement 😒
# La solution proposée au lien précédemment cité : Ne fonctionne pas non plus
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return str_replace('\\u','&#x',trim(json_encode($m[0]),'"')).';';}, $body);
# Output: lol��a☺ car json_encode considère ça comme deux caractères de deux bytes et renvoie "\ud83d\ude12"
# Ne fonctionne pas ( http://php.net/manual/en/function.htmlentities.php#107985 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_encode_numericentity($m[0], array(0x0, 0xffff, 0, 0xffff), 'UTF-8');}, $body); # Ignore complètement 😒
# Fonctionne !!! Mais renvoie 😒 au lieu de 😒 (Pas vraiment un problème en soit)
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8');}, $body);
# Si on veut vraiment la version hexadécimal
$body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return '&#x'.dechex(substr(mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8'), 2)).';';}, $body);
echo 'after: ',$body,'<br />'; # Output: lol😒a☺
?> "
EDIT: J'ai trouvé ce problème ceci dit: https://bugs.php.net/bug.php?id=65045
Mais j'ignore si je suis vraiment concerné : ça dépend en effet si mon script capture ces séquences à problèmes mais il me semble qu'il ne capture que les séquences valides de 4 bytes, donc pas de problème normalement.
Également, j'ai pas trop compris comment ça se fait, mais lorsque j'applique htmlspecialchars sur les séquences données sur la page, l'output n'est pas vide. Ne devrait-il pas l'être (vu que htmlspecialchars renvoie stupidement une chaîne vide lorsqu'il reçoit de l'UTF-8 invalide normalement ?).
Mmmmmh.
</EDIT>
"Plop.
Après mainte péripéties et échecs, je pense avoir trouver quelque chose de "potable".
Voir le code avec coloration syntaxique (un peu différent, manque une source) : http://sebsauvage.net/paste/?e249576d75ee9946#jBpv2UCufTQ4UC2WnTtM11gfolfGkQi61brf11pFORU=
<?php
# "😒" est codé sur 4 bytes
$body = 'lol😒a☺';
echo 'before: ',$body,'<br />'; # Output: lol😒a☺
echo 'length: ',strlen($body),'<br />'; # Output: 11 (😒 = 4, ☺ = 3)
# Le but est de remplacer uniquement les caractères de plus de 3 bytes par leur entité HTML.
# Afin d'obtenir ce code dans le cas de notre exemple
echo '😒','<br />'; # Fourni par https://duckduckgo.com/?q=html+%F0%9F%98%92
# Récupération des caractères de plus de 3 bytes uniquement
# Source: http://stackoverflow.com/a/1401716/1524913
# $body = preg_replace('/[\xF0-\xF7][\x80-\xBF]{3}/', '�', $body); # Yeah! It works!
# Ne fonctionne pas. htmlentities ne connaît pas tous les caractères unicode ( http://stackoverflow.com/a/13942507/1524913 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return htmlentities($m[0], ENT_COMPAT, 'UTF-8');}, $body); # Ignore complètement 😒
# La solution proposée au lien précédemment cité : Ne fonctionne pas non plus
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return str_replace('\\u','&#x',trim(json_encode($m[0]),'"')).';';}, $body);
# Output: lol��a☺ car json_encode considère ça comme deux caractères de deux bytes et renvoie "\ud83d\ude12"
# Ne fonctionne pas ( http://php.net/manual/en/function.htmlentities.php#107985 )
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_encode_numericentity($m[0], array(0x0, 0xffff, 0, 0xffff), 'UTF-8');}, $body); # Ignore complètement 😒
# Fonctionne !!! Mais renvoie 😒 au lieu de 😒 (Pas vraiment un problème en soit)
# $body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8');}, $body);
# Si on veut vraiment la version hexadécimal
$body = preg_replace_callback('/[\xF0-\xF7][\x80-\xBF]{3}/', function($m){return '&#x'.dechex(substr(mb_convert_encoding($m[0], 'HTML-ENTITIES', 'UTF-8'), 2)).';';}, $body);
echo 'after: ',$body,'<br />'; # Output: lol😒a☺
?> "
Any idea anyone? (Thanks in advance :))
EDIT: Solution: http://www.olissea.com/mb/links/1/?_F3x0g
EDIT: J'ai trouvé ça mais ça ne fonctionne pas chez moi malheureusement . :( J'ignore pourquoi. http://webcollab.sourceforge.net/unicode.html ( Character Validation )
"Helloooo
Quelqu'un aurait-il une idée afin de stocker de l'UTF-8 façon correcte avec MySQL d'une version antérieur à MySQL 5.5 ?
Background: Avant MySQL5.5, il n'y a que l'option utf8 et non l'option utf8mb4 permettant (enfin!) de stocker des caractères codés sur 4 bytes ("I wish I was kidding" - Source ).
What I've tried so far / Ce que j'ai déjà essayé :
J'avais pensé à peut-être utilisé un champ de type BINARY (ou BLOB), ce qui me permettrait d'y stocker ce que j'y veux (le problème serait donc résolu) mais cela apporte aussi son lot d'inconvénients…
- Memory overhead pour accéder à des champs de type TEXT ou BLOB. (Boarf, pas très grave, j'utilise déjà un champ TEXT)
- Impossibilité d'utiliser ses champs dans une clause WHERE et donc, je suppose, également dans un LIKE afin de faire une recherche dans la base de données. Right?
(J'aurais du garder les sources parlant de ces dits inconvénients… sorry)
Côté PHP je pourrais essayer de détecter les caractères sur 4 bytes (ça serait lourd par contre) mais j'ignore même ce que j'en ferais… Les convertir en entité HTML ?
Je refuse de me mettre à utiliser htmlentities au lieu d'htmlspecialchars :( (fin, ça serait trop triste quoi)"
EDIT: Solution: http://www.olissea.com/mb/links/1/?_F3x0g
EDIT: J'ai trouvé ça mais ça ne fonctionne pas chez moi malheureusement . :( J'ignore pourquoi. http://webcollab.sourceforge.net/unicode.html ( Character Validation )
"Helloooo
Quelqu'un aurait-il une idée afin de stocker de l'UTF-8 façon correcte avec MySQL d'une version antérieur à MySQL 5.5 ?
Background: Avant MySQL5.5, il n'y a que l'option utf8 et non l'option utf8mb4 permettant (enfin!) de stocker des caractères codés sur 4 bytes ("I wish I was kidding" - Source ).
What I've tried so far / Ce que j'ai déjà essayé :
J'avais pensé à peut-être utilisé un champ de type BINARY (ou BLOB), ce qui me permettrait d'y stocker ce que j'y veux (le problème serait donc résolu) mais cela apporte aussi son lot d'inconvénients…
- Memory overhead pour accéder à des champs de type TEXT ou BLOB. (Boarf, pas très grave, j'utilise déjà un champ TEXT)
- Impossibilité d'utiliser ses champs dans une clause WHERE et donc, je suppose, également dans un LIKE afin de faire une recherche dans la base de données. Right?
(J'aurais du garder les sources parlant de ces dits inconvénients… sorry)
Côté PHP je pourrais essayer de détecter les caractères sur 4 bytes (ça serait lourd par contre) mais j'ignore même ce que j'en ferais… Les convertir en entité HTML ?
Je refuse de me mettre à utiliser htmlentities au lieu d'htmlspecialchars :( (fin, ça serait trop triste quoi)"
Bronco: "Une petite idée d'amélioration possible pour pickypaste: serait-il possible d'étendre la durée de validité du message pour le user ? (ou de cocher une case "permettre au destinataire de prolonger la durée de validité")
ça permettrait de ne pas perdre direct le message si on n'a pas le temps d'y répondre dès la lecture ^^"
J'aime beaucoup l'idée (si je l'ai bien comprise), mais je ne vois pas trop (pas encore ?) comment on pourrait implémenter ça par contre…
(Le fait que PickyPaste utilise un zerobin externe au lieu d'être un fork de zerobin limite quelques possibilités ou rend les choses plus complexes...)
ça permettrait de ne pas perdre direct le message si on n'a pas le temps d'y répondre dès la lecture ^^"
J'aime beaucoup l'idée (si je l'ai bien comprise), mais je ne vois pas trop (pas encore ?) comment on pourrait implémenter ça par contre…
(Le fait que PickyPaste utilise un zerobin externe au lieu d'être un fork de zerobin limite quelques possibilités ou rend les choses plus complexes...)
Juste avoir une fonction correcte, facile à utiliser, qui ne me renvoie pas une chaîne de caractère vide si l'input contient de l'utf-8 invalide.
Et, dût ma contrainte technique, la seule alternative que j'ai (ENT_IGNORE) est déconseillée … Doh.
( EDIT: [Je raconte ma vie]
Pis PHP ne cesse de m'épater dans le mauvais sens et plus j'investigue plus j'suis aberré.
M'enfin … ça n'a pas que du mauvais, ça m'aide à me forcer à faire plus de Python et moins de PHP.
Pour ceux qui continuent à me demander pourquoi je fais encore du PHP je répondrais que les vieilles habitudes ont la vie dure, qu'il faudrait que je transcrive tout mes scripts PHP vers Python, c'est beaucoup de boulot … tellement qu'on préfère souvent la simplicité de continuer les vieilles habitudes et/ou quand on a pas le choix / temps et qu'on a besoin que qu'une appli ou autre soit fonctionnelle dans les temps. Et malheureusement, j'ai encore trop de setup à faire pour que je puisse le faire via Python, mais ça vient ptit à ptit. ☺
)
EDIT 2:
Je pense que le plus simple/efficace serait, comme je l'avais fait une fois sans vraiment avoir étudier la question en profondeur, serait de juste réimplémenter la fonction via str_replace qui lui est apparemment 100% utf-8 safe.
À vérifier.
Et, dût ma contrainte technique, la seule alternative que j'ai (ENT_IGNORE) est déconseillée … Doh.
( EDIT: [Je raconte ma vie]
Pis PHP ne cesse de m'épater dans le mauvais sens et plus j'investigue plus j'suis aberré.
M'enfin … ça n'a pas que du mauvais, ça m'aide à me forcer à faire plus de Python et moins de PHP.
Pour ceux qui continuent à me demander pourquoi je fais encore du PHP je répondrais que les vieilles habitudes ont la vie dure, qu'il faudrait que je transcrive tout mes scripts PHP vers Python, c'est beaucoup de boulot … tellement qu'on préfère souvent la simplicité de continuer les vieilles habitudes et/ou quand on a pas le choix / temps et qu'on a besoin que qu'une appli ou autre soit fonctionnelle dans les temps. Et malheureusement, j'ai encore trop de setup à faire pour que je puisse le faire via Python, mais ça vient ptit à ptit. ☺
)
EDIT 2:
Je pense que le plus simple/efficace serait, comme je l'avais fait une fois sans vraiment avoir étudier la question en profondeur, serait de juste réimplémenter la fonction via str_replace qui lui est apparemment 100% utf-8 safe.
À vérifier.
J'essaie de trouver quelle serait la meilleure utilisation de htmlspecialchars si on ne possède pas encore PHP 5.4 (contraintes techniques).
D'une part, par défaut, si vous passez une chaîne contenant de l'UTF-8 invalide, htmlspecialchars vous retournera une chaîne complètement vide. ("Pratique")
Pour remédier à ça, il vous faut utiliser ENT_IGNORE ou ENT_SUBSTITUTE. ........ MAIS la doc déconseille l'utilisation de ENT_IGNORE pour des raisons de sécurité. ( http://unicode.org/reports/tr36/#Deletion_of_Noncharacters )
(Source: http://stackoverflow.com/q/11088953/1524913 )
Seulement voilà, ENT_SUBSTITUE est uniquement disponible à partir de PHP 5.4.0. (Donc je fais quoi… ?)
Notez égaaaaaaalement qu'il est impossible de spécifier les paramètres par défaut de htmlspecialchars et qu'il vaudrait mieux donc que vous créez votre propre wrapper.
Puis j'ai également trouvé cette perle … jugez par vous-même. ._."
"Error handling in htmlspecialchars before PHP 5.4 was … uhm, let’s call it “unintuitive”:
If you passed a string containing an “invalid code unit sequence” (which is Unicode slang for “not encoded correctly”) htmlspecialchars would return an empty string. Well, okay, so far so good. The funny thing was that it additionally would throw an error, but only if error display was disabled. So it would only error if errors are hidden. Nice, innit?"
(Source: http://nikic.github.io/2012/01/28/htmlspecialchars-improvements-in-PHP-5-4.html)
Cette page-ci n'est pas mal non plus: http://stackoverflow.com/q/13745353/1524913
D'une part, par défaut, si vous passez une chaîne contenant de l'UTF-8 invalide, htmlspecialchars vous retournera une chaîne complètement vide. ("Pratique")
Pour remédier à ça, il vous faut utiliser ENT_IGNORE ou ENT_SUBSTITUTE. ........ MAIS la doc déconseille l'utilisation de ENT_IGNORE pour des raisons de sécurité. ( http://unicode.org/reports/tr36/#Deletion_of_Noncharacters )
(Source: http://stackoverflow.com/q/11088953/1524913 )
Seulement voilà, ENT_SUBSTITUE est uniquement disponible à partir de PHP 5.4.0. (Donc je fais quoi… ?)
Notez égaaaaaaalement qu'il est impossible de spécifier les paramètres par défaut de htmlspecialchars et qu'il vaudrait mieux donc que vous créez votre propre wrapper.
Puis j'ai également trouvé cette perle … jugez par vous-même. ._."
"Error handling in htmlspecialchars before PHP 5.4 was … uhm, let’s call it “unintuitive”:
If you passed a string containing an “invalid code unit sequence” (which is Unicode slang for “not encoded correctly”) htmlspecialchars would return an empty string. Well, okay, so far so good. The funny thing was that it additionally would throw an error, but only if error display was disabled. So it would only error if errors are hidden. Nice, innit?"
(Source: http://nikic.github.io/2012/01/28/htmlspecialchars-improvements-in-PHP-5-4.html)
Cette page-ci n'est pas mal non plus: http://stackoverflow.com/q/13745353/1524913
Petite mise à jour de PickyPaste.
La version indev (le lien que je viens de passer), renvoie le lien vers la version indev, c'est mieux.
À la proposition de Bronco, j'ai rajouté un chtit lien "Répondre via PickyPaste" si l'utilisateur a spécifié son adresse email.
Voilà, c'tout.
La version indev (le lien que je viens de passer), renvoie le lien vers la version indev, c'est mieux.
À la proposition de Bronco, j'ai rajouté un chtit lien "Répondre via PickyPaste" si l'utilisateur a spécifié son adresse email.
Voilà, c'tout.
Un petit Minecraft codé en 500 lignes Python.
Depuis le projet a grossit et contient + de 8000 lignes.
Depuis le projet a grossit et contient + de 8000 lignes.
Ok, so there's no fucking way to sanitize filenames out there?
I've been mainly looking for Python solutions but still it feels like there is none.
I mean, I'm talking about solutions that would be offered by the system itself, so that you don't have to code a sanitizer yourself for each existing os possible.
Doh!
EDIT: This is a nice solution if you don't care both about loosing completely (but reversible) the original filename and readability for humans.
http://stackoverflow.com/a/295150/1524913
I've been mainly looking for Python solutions but still it feels like there is none.
I mean, I'm talking about solutions that would be offered by the system itself, so that you don't have to code a sanitizer yourself for each existing os possible.
Doh!
EDIT: This is a nice solution if you don't care both about loosing completely (but reversible) the original filename and readability for humans.
http://stackoverflow.com/a/295150/1524913
Je trouve que les opérations SQL s’effectuant sur l’ensemble d’une table et qui affecte celle-ci, on devrait être obligé de l’indiquer explicitement et non implicitement comme c’est le cas pour le moment …
Je parle de faire une DELETE ou un UPDATE sans spécifier de clause WHERE (et donc affecter toute la table) par inadvertance.
En effet, l’erreur/l’oubli étant humain, il est beaucoup plus simple de commencer à écrire sa requête puis oublier de spécifier la clause WHERE.
Alors que si on était obligé de spécifier, par exemple, un simple ALL, l'erreur se produirait bien moins souvent et l'oubli ne ferait rien de critique.
C'est peu contraignant et ça sauverait des vies.
Je trouve que c'est vraiment un cas de bad design. Ça serait facile à implémenter en plus.
Je parle de faire une DELETE ou un UPDATE sans spécifier de clause WHERE (et donc affecter toute la table) par inadvertance.
En effet, l’erreur/l’oubli étant humain, il est beaucoup plus simple de commencer à écrire sa requête puis oublier de spécifier la clause WHERE.
Alors que si on était obligé de spécifier, par exemple, un simple ALL, l'erreur se produirait bien moins souvent et l'oubli ne ferait rien de critique.
C'est peu contraignant et ça sauverait des vies.
Je trouve que c'est vraiment un cas de bad design. Ça serait facile à implémenter en plus.
Tiens, … fonctionnalité intéressante.
Permet de scan du code PHP et le décomposer.
[Caca PHP, oui je sais …]
Permet de scan du code PHP et le décomposer.
[Caca PHP, oui je sais …]
C'est sérieux en plus ._.'
via eijebong
via eijebong
Bouh, c'est mal !
" Hello,
Just noticed that the default HTML errors (like 404 Not Found) are:
1) Not using HTML5 yet.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2) Don't indicate their encoding, which raises a message in the Fiefox console:
" The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol. "
Cordially. "
" Hello,
Just noticed that the default HTML errors (like 404 Not Found) are:
1) Not using HTML5 yet.
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2) Don't indicate their encoding, which raises a message in the Fiefox console:
" The character encoding of the HTML document was not declared. The document will render with garbled text in some browser configurations if the document contains characters from outside the US-ASCII range. The character encoding of the page must be declared in the document or in the transfer protocol. "
Cordially. "
Flask ne semble pas supporter la possibilité de retourner des générateurs comme WSGI peut le faire et je ne suis pas sûr qu'ils prévoient que ça soit le cas un jour … ( voir https://github.com/mitsuhiko/flask/pull/684 )
Mais bon perso je trouve ça super sympa de pouvoir yield du contenu lorsqu'on veut dans son code. Un peu comme je pouvais le faire avec cgi ou en PHPouet.
De plus je suis entrain de migrer d'un code pur WSGI à Flask (sous les conseils de Link Mauve si je ne me méprend pas) - pour l'instant j'en suis toujours à l'étape "c'est relou". Pourvu que ça ne dure pas -, du coup c'est plus sympa pour moi de pouvoir conserver cette façon là.
(Note: J'avais également pas envie de devoir spécifier un décorateur @generator pour toutes mes fonctions contenant un yield, j'ai donc décidé de décorer app.route directement (mais ce fut un peu plus compliqué à mettre en place))
from functools import wraps
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
# Decorator to make Flask accept generators
@wraps(app.route)
def route_accept_generators(*args, **kwargs):
route = route_accept_generators.app_route(*args, **kwargs) # Getting our route decorator.
# Decorating it.
@wraps(route)
def decorated(f):
# Make so that the function that will be called return a valid Flask answer in case of returning a generator.
@wraps(f)
def function_accept_generators(*args, **kwargs):
r = f(*args, **kwargs)
if isinstance(r, types.GeneratorType):
# return Response(r, direct_passthrough=True) # Solution proposed here: http://flask.pocoo.org/mailinglist/archive/2010/11/3/using-yield/#478b0c1829b5263700da1db7d2d22c79
return Response(stream_with_context(r)) # Solution found here: http://stackoverflow.com/q/13386681/1524913
return r
return route(function_accept_generators)
return decorated
# Store the function so that it doesn't make an infinite recursion call
# Because accessing from app.route rather than directly)
# And storing it in itself instead of creating another standalone variable
route_accept_generators.app_route = app.route
app.route = route_accept_generators
Mais bon perso je trouve ça super sympa de pouvoir yield du contenu lorsqu'on veut dans son code. Un peu comme je pouvais le faire avec cgi ou en PHPouet.
De plus je suis entrain de migrer d'un code pur WSGI à Flask (sous les conseils de Link Mauve si je ne me méprend pas) - pour l'instant j'en suis toujours à l'étape "c'est relou". Pourvu que ça ne dure pas -, du coup c'est plus sympa pour moi de pouvoir conserver cette façon là.
(Note: J'avais également pas envie de devoir spécifier un décorateur @generator pour toutes mes fonctions contenant un yield, j'ai donc décidé de décorer app.route directement (mais ce fut un peu plus compliqué à mettre en place))
from functools import wraps
from flask import Flask, Response, stream_with_context
app = Flask(__name__)
# Decorator to make Flask accept generators
@wraps(app.route)
def route_accept_generators(*args, **kwargs):
route = route_accept_generators.app_route(*args, **kwargs) # Getting our route decorator.
# Decorating it.
@wraps(route)
def decorated(f):
# Make so that the function that will be called return a valid Flask answer in case of returning a generator.
@wraps(f)
def function_accept_generators(*args, **kwargs):
r = f(*args, **kwargs)
if isinstance(r, types.GeneratorType):
# return Response(r, direct_passthrough=True) # Solution proposed here: http://flask.pocoo.org/mailinglist/archive/2010/11/3/using-yield/#478b0c1829b5263700da1db7d2d22c79
return Response(stream_with_context(r)) # Solution found here: http://stackoverflow.com/q/13386681/1524913
return r
return route(function_accept_generators)
return decorated
# Store the function so that it doesn't make an infinite recursion call
# Because accessing from app.route rather than directly)
# And storing it in itself instead of creating another standalone variable
route_accept_generators.app_route = app.route
app.route = route_accept_generators
Intéressant !
Ne vous faites pas avoir !
Ne vous faites pas avoir !
x))))
Quelques trucs avancés Python.
Savoir ça pourrait bien vous sauvez quelques heures de votre vie.
"For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary." → You cannot modify magic method directly from an instance, for instance, doing that wont work:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
"In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass:" → When a magic method is used and not called explicitely, then all special methods like __getattribute__ are also bypassed.
For instance:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Savoir ça pourrait bien vous sauvez quelques heures de votre vie.
"For custom classes, implicit invocations of special methods are only guaranteed to work correctly if defined on an object’s type, not in the object’s instance dictionary." → You cannot modify magic method directly from an instance, for instance, doing that wont work:
>>> class C:
... pass
...
>>> c = C()
>>> c.__len__ = lambda: 5
>>> len(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'C' has no len()
"In addition to bypassing any instance attributes in the interest of correctness, implicit special method lookup generally also bypasses the __getattribute__() method even of the object’s metaclass:" → When a magic method is used and not called explicitely, then all special methods like __getattribute__ are also bypassed.
For instance:
>>> class Meta(type):
... def __getattribute__(*args):
... print("Metaclass getattribute invoked")
... return type.__getattribute__(*args)
...
>>> class C(object, metaclass=Meta):
... def __len__(self):
... return 10
... def __getattribute__(*args):
... print("Class getattribute invoked")
... return object.__getattribute__(*args)
...
>>> c = C()
>>> c.__len__() # Explicit lookup via instance
Class getattribute invoked
10
>>> type(c).__len__(c) # Explicit lookup via type
Metaclass getattribute invoked
10
>>> len(c) # Implicit lookup
10
Infos intéressantes pour l'utilisation d'sqlite3 avec Python.
Je garde ça sous la main.
EDIT:
" > - Are there any peculiarities with using curs.executemany(...) vs. multiple
> curs.execute(...) ? I read a notice, sqlite3 does internally some caching,
> hence both should be similarly fast, but in my case executemany(...) is
> quite a bit faster
How many times are you calling execute vs a single executemany? The
python call overhead will add up for thousands of calls.
The relevant source code is here if you're interested:
http://svn.python.org/projects/python/trunk/Modules/_sqlite/cursor.c
> Further, I am not quite sure about the standard usage of the cursor object
> and also the proper commiting the transactions and closing the connection.
Standard usage is here:
http://docs.python.org/lib/module-sqlite3.html
If the database supports transactions then cursors automatically use
transactions. Your changes only get committed when you call .commit().
Otherwise your changes are lost.
In the specific case of sqllite, some statements (like CREATE TABLE,
ALTER TABLE, etc) also cause a commit. This is probably where your
confusion comes from. Since this isn't part of the python DB API spec
(http://www.python.org/dev/peps/pep-0249/) I wouldn't rely on it.
Otherwise you will have problems with other databases.
Also, in your specific case you're using an 'in memory' sqllite db. So
there are less concerns with losing data between db sessions, etc. But
with most databases (on disk, running across the network on a server)
this becomes important.
> Should one create a cursor of a connection and call the execute ... methods
> of the cursor -
> or is it better to call the shortcut execute etc. methods of the Connection
> object directly (as suggested in the docs:
> http://docs.python.org/lib/node351.html (or are there specific use cases for
> both approaches)?
I suggest that you use the standard cursor methods instead, so you can
run your code against non-sqllite databases. The performance etc
should be the same as using the direct method. Like the page says,
it's main benefit is consiseness.
>
> When the transactions should be commited? (creating, altering a table, or
> also selecting the results ?)
> There seem to be some implicit handling of the transactions (
> http://docs.python.org/lib/sqlite3-Controlling-Transactions.html#sqlite3-Controlling-Transactions
> ); hence I am not sure about the standard usage of these methods; the same
> is true of connection.close() - or are these calls eventually unnecessary?
As a general rule, always use .commit() and .close(). Otherwise:
- No .commit() - you will lose db changes since the last commit or
"non-DML, non-query statement" (in the case of sqllite)
- No .close() - Your database connection will only close when your db
objects are garbage collected.
> conn_tags_DB = sqlite3.connect(':memory:')
> curs = self.conn_tags_DB.cursor()
> curs.execute('CREATE TABLE IF NOT EXISTS "%s" ("%s", UNIQUE("%s"))' %
> (self.text_name, index_col_name, index_col_name))
> curs.execute(u'INSERT OR REPLACE INTO "%s"("%s") VALUES (?)' %
> (self.text_name, index_col_name), (0,))
> for new_col in act_db_columns[1:]: # adds the needed columns (except of the
> first one: index_col_name)
> curs.execute('ALTER TABLE "%s" ADD "%s" TEXT' % (self.text_name,
> new_col))
> curs.executemany('INSERT OR REPLACE INTO "%s" VALUES (%s)' %
> (self.text_name, question_marks), tags_seq)
> self.conn_tags_DB.commit()
>
> Are there maybe any comments or hints on a more elegant/efficient solution?
>
I think that dynamically creating schema (tables, based on text file
structure is a bad idea. A few reasons:
- This forces you to dynamically generate all your queries dynamically
- Not all strings are valid table/column names
- This forces the app to run as database administrator (maybe not
important for sqllite, but definitely an issue if you change to
another dbm).
- Potentially huge stability/security problems - text files can
potentially break system tables, overwrite users, etc, etc.
You're violating several rules on db design/usage.
I strongly recommend that you use a better database logic. ie, create
tables and records in advance (setup script, as db admin user if
applicable), then only use delete/insert/update/select statements (as
restricted user, if applicable).
If this is too much trouble, then I suggest storing your database in
regular Python structures instead, and use pickle/yaml/etc to write to
disk. Your current version uses a 'in memory' database, so the end
result is the same. You'll get a large performance boost also.
> Now, what's the usual way to access the database? Is it
> possible/wise/standard ... to leave the connection open for the subsequent
> queries during the whole run of the app; could even the cursor eventually be
> present as a class method, or should it rather be created repeatedly with
> each call? (After populating, the db shouldn't be modified, but only read.)
It depends. If your app is simple, single threaded, then a single
connection (global or passed through args) should be fine. Only use
multiple cursors if you need them (multiple threads, multiple
databases, multiple transaction/db isolation levels, etc).
David.
"
Je garde ça sous la main.
EDIT:
" > - Are there any peculiarities with using curs.executemany(...) vs. multiple
> curs.execute(...) ? I read a notice, sqlite3 does internally some caching,
> hence both should be similarly fast, but in my case executemany(...) is
> quite a bit faster
How many times are you calling execute vs a single executemany? The
python call overhead will add up for thousands of calls.
The relevant source code is here if you're interested:
http://svn.python.org/projects/python/trunk/Modules/_sqlite/cursor.c
> Further, I am not quite sure about the standard usage of the cursor object
> and also the proper commiting the transactions and closing the connection.
Standard usage is here:
http://docs.python.org/lib/module-sqlite3.html
If the database supports transactions then cursors automatically use
transactions. Your changes only get committed when you call .commit().
Otherwise your changes are lost.
In the specific case of sqllite, some statements (like CREATE TABLE,
ALTER TABLE, etc) also cause a commit. This is probably where your
confusion comes from. Since this isn't part of the python DB API spec
(http://www.python.org/dev/peps/pep-0249/) I wouldn't rely on it.
Otherwise you will have problems with other databases.
Also, in your specific case you're using an 'in memory' sqllite db. So
there are less concerns with losing data between db sessions, etc. But
with most databases (on disk, running across the network on a server)
this becomes important.
> Should one create a cursor of a connection and call the execute ... methods
> of the cursor -
> or is it better to call the shortcut execute etc. methods of the Connection
> object directly (as suggested in the docs:
> http://docs.python.org/lib/node351.html (or are there specific use cases for
> both approaches)?
I suggest that you use the standard cursor methods instead, so you can
run your code against non-sqllite databases. The performance etc
should be the same as using the direct method. Like the page says,
it's main benefit is consiseness.
>
> When the transactions should be commited? (creating, altering a table, or
> also selecting the results ?)
> There seem to be some implicit handling of the transactions (
> http://docs.python.org/lib/sqlite3-Controlling-Transactions.html#sqlite3-Controlling-Transactions
> ); hence I am not sure about the standard usage of these methods; the same
> is true of connection.close() - or are these calls eventually unnecessary?
As a general rule, always use .commit() and .close(). Otherwise:
- No .commit() - you will lose db changes since the last commit or
"non-DML, non-query statement" (in the case of sqllite)
- No .close() - Your database connection will only close when your db
objects are garbage collected.
> conn_tags_DB = sqlite3.connect(':memory:')
> curs = self.conn_tags_DB.cursor()
> curs.execute('CREATE TABLE IF NOT EXISTS "%s" ("%s", UNIQUE("%s"))' %
> (self.text_name, index_col_name, index_col_name))
> curs.execute(u'INSERT OR REPLACE INTO "%s"("%s") VALUES (?)' %
> (self.text_name, index_col_name), (0,))
> for new_col in act_db_columns[1:]: # adds the needed columns (except of the
> first one: index_col_name)
> curs.execute('ALTER TABLE "%s" ADD "%s" TEXT' % (self.text_name,
> new_col))
> curs.executemany('INSERT OR REPLACE INTO "%s" VALUES (%s)' %
> (self.text_name, question_marks), tags_seq)
> self.conn_tags_DB.commit()
>
> Are there maybe any comments or hints on a more elegant/efficient solution?
>
I think that dynamically creating schema (tables, based on text file
structure is a bad idea. A few reasons:
- This forces you to dynamically generate all your queries dynamically
- Not all strings are valid table/column names
- This forces the app to run as database administrator (maybe not
important for sqllite, but definitely an issue if you change to
another dbm).
- Potentially huge stability/security problems - text files can
potentially break system tables, overwrite users, etc, etc.
You're violating several rules on db design/usage.
I strongly recommend that you use a better database logic. ie, create
tables and records in advance (setup script, as db admin user if
applicable), then only use delete/insert/update/select statements (as
restricted user, if applicable).
If this is too much trouble, then I suggest storing your database in
regular Python structures instead, and use pickle/yaml/etc to write to
disk. Your current version uses a 'in memory' database, so the end
result is the same. You'll get a large performance boost also.
> Now, what's the usual way to access the database? Is it
> possible/wise/standard ... to leave the connection open for the subsequent
> queries during the whole run of the app; could even the cursor eventually be
> present as a class method, or should it rather be created repeatedly with
> each call? (After populating, the db shouldn't be modified, but only read.)
It depends. If your app is simple, single threaded, then a single
connection (global or passed through args) should be fine. Only use
multiple cursors if you need them (multiple threads, multiple
databases, multiple transaction/db isolation levels, etc).
David.
"
J'aime bien ce talk :)
Je l'ai vu il y a longtemps mais je suis retombé dessus récemment ^^
Je l'ai vu il y a longtemps mais je suis retombé dessus récemment ^^
Je sens que je vais oublier ça …
"Python looks up special methods only on the class, ignoring anything defined on the instance."
"Python looks up special methods only on the class, ignoring anything defined on the instance."
Interesdasting
Ça y est, je me sers de mon shaarli pour envoyer des messages aux personnes offlines maintenant …
Désolé buddy j'avais pas vu ton message j'étais en mode veille.
Du coup, si tu (ou d'autres) sont intéressés par un projet Python, n'hésite pas à check :
https://github.com/JeromeJ/Devutopia
http://devutopia.net/
Je préviens que le design est pas encore fait :p
(Et pour la licence on va sûrement passer en CopyLeft)
(Wink, wink, les tags ;) à ta demande expresse :D)
Désolé buddy j'avais pas vu ton message j'étais en mode veille.
Du coup, si tu (ou d'autres) sont intéressés par un projet Python, n'hésite pas à check :
https://github.com/JeromeJ/Devutopia
http://devutopia.net/
Je préviens que le design est pas encore fait :p
(Et pour la licence on va sûrement passer en CopyLeft)
(Wink, wink, les tags ;) à ta demande expresse :D)
Commen j'ai pas moyen de te mailer ou autres, je poste ça ici et ptet qu'ainsi tu verras mon message.
J'ai plus simple que ce que la solution que je t'avais proposé.
À savoir, ça : [k for k in myDict if k in myOtherDict] mais avec des .keys() en plus inutile.
En fait c'était tout con, on peut faire ça :
>>> {"a":22, "b":33, "c":24}.keys() & {"a":33, "b":57, "d":78}
{'a', 'b'}
.keys() renvoit une view qui se comporte comme un set, d'où la possibilité d'utiliser l'opérateur "&" normalement propre aux sets. ( http://www.python.org/dev/peps/pep-3106/ )
Et pas vraiment besoin d'utiliser .keys sur le dico de droite (je pense pas que ça impacte les performances), le "set-like" returner par .keys() sait effectuer l'opération "&" sur un dict (car par défaut quand tu itères un dict, ça itère sur les clés, faut utiliser .items() ou .values() sinon).
(Wink, wink, les tags ;) )
J'ai plus simple que ce que la solution que je t'avais proposé.
À savoir, ça : [k for k in myDict if k in myOtherDict] mais avec des .keys() en plus inutile.
En fait c'était tout con, on peut faire ça :
>>> {"a":22, "b":33, "c":24}.keys() & {"a":33, "b":57, "d":78}
{'a', 'b'}
.keys() renvoit une view qui se comporte comme un set, d'où la possibilité d'utiliser l'opérateur "&" normalement propre aux sets. ( http://www.python.org/dev/peps/pep-3106/ )
Et pas vraiment besoin d'utiliser .keys sur le dico de droite (je pense pas que ça impacte les performances), le "set-like" returner par .keys() sait effectuer l'opération "&" sur un dict (car par défaut quand tu itères un dict, ça itère sur les clés, faut utiliser .items() ou .values() sinon).
(Wink, wink, les tags ;) )
So, what do you think? ;)
(I'd also like to bring those advantages to everybody, not only programmers and nerd ;D aha)
(I'd also like to bring those advantages to everybody, not only programmers and nerd ;D aha)
DO WANT ;D
Je veux coder en Piet !
Je veux coder en Piet !
Hop ! Je garde sous le coude !
Source: http://lehollandaisvolant.net/index.php?d=2013/09/20/22/09/18-quelques-rapides-codes-php-js-ou-html#id5ce348
Source: http://lehollandaisvolant.net/index.php?d=2013/09/20/22/09/18-quelques-rapides-codes-php-js-ou-html#id5ce348
Intéressant. Surtout lorsqu'on sait que 3/4 des flux (chiffre arbitraire) base leur Atom ID sur le permalink. Shaarli lui même fait ça.
J'avais au début penser à une simple info à rajouter dans le lien après l'ancre (avec la clé de déchiffrement) mais je pense qu'on peut mieux faire.
* En effet, voyez-vous, ça induit un problème :
Si j'envoie un lien "Burn After Reading" sur un réseau non fiable, disons par exemple Skype, mais que l'information sur quand il expire serait elle-même contenue dans l'URL.
Alors, le méchant réseau (ça pourrait très bien être chez vous, à votre boulot, etc. = tout ce qui n'est pas chiffré bout-à-bout) pourrait éventuellement récupérer cette date d'expiration et tenter de l'ouvrir juste avant expiration.
De cette manière si vous avez oublié de l'ouvrir, il peut aisément savoir le moment le plus propice pour l'ouvrir sans risquer de se faire chopper.
En effet il est très peu probable que vous parveniez à l'ouvrir entre le moment où il l'a ouvert et le moment où il a expiré, tout au plus, cela vous laisserait seulement avec un doute qu'il se peut qu'il y ait eu un lag ou que les horloges entre vous et le serveur soient un peu décalées mais qu'au final, dans tous les cas, vous êtes peut-être arrivé un peu trop tard (Fin bref ça reste quand même extrême).
* SOLUTION:
La solution serait, je pense, et afin de ne pas être obligé de garder la métadonnée (quand ce paste était censé expiré) même après suppression du contenu des pastes expiré (pour clean up) d'avoir une clée privée côté serveur et d'avoir l'information de quand le paste devait expiré chiffré dans l'URL du paste et envoyé au serveur lors de la tentative de récupération du paste. Alors, si le serveur ne peut pas servir ce paste, il déchiffre l'information stockée dans l'URL (seul lui le peut, car elle aura été chiffré par sa clé publique) et il affichera l'information.
De cette manière on garde la fonctionnalité sans donner un moyen facile pour un réseau espion d'exploiter une faille potentielle.
(Seule faiblesse que je vois c'est que la clé privée privée du serveur est unique, y aurait-il moyen de, plutôt, la lier à l'id du paste ?
Genre peut-on créer une paire de clé à partir de "salt du serveur (privé, unique) + id du past" qui servirait à chiffrer l'info de façon unique pour chaque paste ?)
* En effet, voyez-vous, ça induit un problème :
Si j'envoie un lien "Burn After Reading" sur un réseau non fiable, disons par exemple Skype, mais que l'information sur quand il expire serait elle-même contenue dans l'URL.
Alors, le méchant réseau (ça pourrait très bien être chez vous, à votre boulot, etc. = tout ce qui n'est pas chiffré bout-à-bout) pourrait éventuellement récupérer cette date d'expiration et tenter de l'ouvrir juste avant expiration.
De cette manière si vous avez oublié de l'ouvrir, il peut aisément savoir le moment le plus propice pour l'ouvrir sans risquer de se faire chopper.
En effet il est très peu probable que vous parveniez à l'ouvrir entre le moment où il l'a ouvert et le moment où il a expiré, tout au plus, cela vous laisserait seulement avec un doute qu'il se peut qu'il y ait eu un lag ou que les horloges entre vous et le serveur soient un peu décalées mais qu'au final, dans tous les cas, vous êtes peut-être arrivé un peu trop tard (Fin bref ça reste quand même extrême).
* SOLUTION:
La solution serait, je pense, et afin de ne pas être obligé de garder la métadonnée (quand ce paste était censé expiré) même après suppression du contenu des pastes expiré (pour clean up) d'avoir une clée privée côté serveur et d'avoir l'information de quand le paste devait expiré chiffré dans l'URL du paste et envoyé au serveur lors de la tentative de récupération du paste. Alors, si le serveur ne peut pas servir ce paste, il déchiffre l'information stockée dans l'URL (seul lui le peut, car elle aura été chiffré par sa clé publique) et il affichera l'information.
De cette manière on garde la fonctionnalité sans donner un moyen facile pour un réseau espion d'exploiter une faille potentielle.
(Seule faiblesse que je vois c'est que la clé privée privée du serveur est unique, y aurait-il moyen de, plutôt, la lier à l'id du paste ?
Genre peut-on créer une paire de clé à partir de "salt du serveur (privé, unique) + id du past" qui servirait à chiffrer l'info de façon unique pour chaque paste ?)