unicode issue
Why don't work this code on Python 2.6? Or how can I do this job? _MAP = { # LATIN u'À': 'A', u'Á': 'A', u'Â': 'A', u'Ã': 'A', u'Ä': 'A', u'Å': 'A', u'Æ': 'AE', u'Ç':'C', u'È': 'E', u'É': 'E', u'Ê': 'E', u'Ë': 'E', u'Ì': 'I', u'Í': 'I', u'Î': 'I', u'Ï': 'I', u'Ð': 'D', u'Ñ': 'N', u'Ò': 'O', u'Ó': 'O', u'Ô': 'O', u'Õ': 'O', u'Ö':'O', u'Ő': 'O', u'Ø': 'O', u'Ù': 'U', u'Ú': 'U', u'Û': 'U', u'Ü': 'U', u'Ű': 'U', u'Ý': 'Y', u'Þ': 'TH', u'ß': 'ss', u'à':'a', u'á':'a', u'â': 'a', u'ã': 'a', u'ä':'a', u'å': 'a', u'æ': 'ae', u'ç': 'c', u'è': 'e', u'é': 'e', u'ê': 'e', u'ë': 'e', u'ì': 'i', u'í': 'i', u'î': 'i', u'ï': 'i', u'ð': 'd', u'ñ': 'n', u'ò': 'o', u'ó':'o', u'ô': 'o', u'õ': 'o', u'ö': 'o', u'ő': 'o', u'ø': 'o', u'ù': 'u', u'ú': 'u', u'û': 'u', u'ü': 'u', u'ű': 'u', u'ý': 'y', u'þ': 'th', u'ÿ': 'y', # LATIN_SYMBOLS u'©':'(c)', # GREEK u'α':'a', u'β':'b', u'γ':'g', u'δ':'d', u'ε':'e', u'ζ':'z', u'η':'h', u'θ':'8', u'ι':'i', u'κ':'k', u'λ':'l', u'μ':'m', u'ν':'n', u'ξ':'3', u'ο':'o', u'π':'p', u'ρ':'r', u'σ':'s', u'τ':'t', u'υ':'y', u'φ':'f', u'χ':'x', u'ψ':'ps', u'ω':'w', u'ά':'a', u'έ':'e', u'ί':'i', u'ό':'o', u'ύ':'y', u'ή':'h', u'ώ':'w', u'ς':'s', u'ϊ':'i', u'ΰ':'y', u'ϋ':'y', u'ΐ':'i', u'Α':'A', u'Β':'B', u'Γ':'G', u'Δ':'D', u'Ε':'E', u'Ζ':'Z', u'Η':'H', u'Θ':'8', u'Ι':'I', u'Κ':'K', u'Λ':'L', u'Μ':'M', u'Ν':'N', u'Ξ':'3', u'Ο':'O', u'Π':'P', u'Ρ':'R', u'Σ':'S', u'Τ':'T', u'Υ':'Y', u'Φ':'F', u'Χ':'X', u'Ψ':'PS', u'Ω':'W', u'Ά':'A', u'Έ':'E', u'Ί':'I', u'Ό':'O', u'Ύ':'Y', u'Ή':'H', u'Ώ':'W', u'Ϊ':'I', u'Ϋ':'Y', # TURKISH u'ş':'s', u'Ş':'S', u'ı':'i', u'İ':'I', u'ç':'c', u'Ç':'C', u'ü':'u', u'Ü':'U', u'ö':'o', u'Ö':'O', u'ğ':'g', u'Ğ':'G', # RUSSIAN u'а':'a', u'б':'b', u'в':'v', u'г':'g', u'д':'d', u'е':'e', u'ё':'yo', u'ж':'zh', u'з':'z', u'и':'i', u'й':'j', u'к':'k', u'л':'l', u'м':'m', u'н':'n', u'о':'o', u'п':'p', u'р':'r', u'с':'s', u'т':'t', u'у':'u', u'ф':'f', u'х':'h', u'ц':'c', u'ч':'ch', u'ш':'sh', u'щ':'sh', u'ъ':'', u'ы':'y', u'ь':'', u'э':'e', u'ю':'yu', u'я':'ya', u'А':'A', u'Б':'B', u'В':'V', u'Г':'G', u'Д':'D', u'Е':'E', u'Ё':'Yo', u'Ж':'Zh', u'З':'Z', u'И':'I', u'Й':'J', u'К':'K', u'Л':'L', u'М':'M', u'Н':'N', u'О':'O', u'П':'P', u'Р':'R', u'С':'S', u'Т':'T', u'У':'U', u'Ф':'F', u'Х':'H', u'Ц':'C', u'Ч':'Ch', u'Ш':'Sh', u'Щ':'Sh', u'Ъ':'', u'Ы':'Y', u'Ь':'', u'Э':'E', u'Ю':'Yu', u'Я':'Ya', # UKRAINIAN u'Є':'Ye', u'І':'I', u'Ї':'Yi', u'Ґ':'G', u'є':'ye', u'і':'i', u'ї':'yi', u'ґ':'g', # CZECH u'č':'c', u'ď':'d', u'ě':'e', u'ň':'n', u'ř':'r', u'š':'s', u'ť':'t', u'ů':'u', u'ž':'z', u'Č':'C', u'Ď':'D', u'Ě':'E', u'Ň':'N', u'Ř':'R', u'Š':'S', u'Ť':'T', u'Ů':'U', u'Ž':'Z', # POLISH u'ą':'a', u'ć':'c', u'ę':'e', u'ł':'l', u'ń':'n', u'ó':'o', u'ś':'s', u'ź':'z', u'ż':'z', u'Ą':'A', u'Ć':'C', u'Ę':'e', u'Ł':'L', u'Ń':'N', u'Ó':'o', u'Ś':'S', u'Ź':'Z', u'Ż':'Z', # LATVIAN u'ā':'a', u'č':'c', u'ē':'e', u'ģ':'g', u'ī':'i', u'ķ':'k', u'ļ':'l', u'ņ':'n', u'š':'s', u'ū':'u', u'ž':'z', u'Ā':'A', u'Č':'C', u'Ē':'E', u'Ģ':'G', u'Ī':'i', u'Ķ':'k', u'Ļ':'L', u'Ņ':'N', u'Š':'S', u'Ū':'u', u'Ž':'Z' } def downcode(name): """ >>> downcode(u"Žabovitá zmiešaná kaša") u'Zabovita zmiesana kasa' """ for key, value in _MAP.iteritems(): name = name.replace(key, value) return name -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
On 30. Sep., 09:41 h., Andre Engels wrote: > On Wed, Sep 30, 2009 at 9:34 AM, gentlestone wrote: > > Why don't work this code on Python 2.6? Or how can I do this job? > > Please be more specific than "it doesn't work": > * What exactly are you doing > * What were you expecting the result of that to be > * What is the actual result? > > -- > André Engels, andreeng...@gmail.com * What exactly are you doing replace non-ascii characters - see doctest documentation * What were you expecting the result of that to be see doctest documentation * What is the actual result? the actual result is unchanged name -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
On 30. Sep., 10:35 h., Andre Engels wrote: > I get the feeling that the problem is with the Python interactive > mode. It does not have full unicode support, so u"Žabovitá zmiešaná > kaša" is changed to u'\x8eabovit\xe1 zmie\x9aan\xe1 ka\x9aa'. If you > call your code from another program, it might work correctly. > > -- > André Engels, andreeng...@gmail.com thx a lot I spent 2 days of my life beacause of this so doctests are unuseable for non-engish users in python - seems to be -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
On 30. Sep., 10:43 h., gentlestone wrote: > On 30. Sep., 10:35 h., Andre Engels wrote: > > > I get the feeling that the problem is with the Python interactive > > mode. It does not have full unicode support, so u"Žabovitá zmiešaná > > kaša" is changed to u'\x8eabovit\xe1 zmie\x9aan\xe1 ka\x9aa'. If you > > call your code from another program, it might work correctly. > > > -- > > André Engels, andreeng...@gmail.com > > thx a lot > > I spent 2 days of my life beacause of this > > so doctests are unuseable for non-engish users in python - seems to be yes, you are right, now it works: def slugify(name): """ >>> slugify(u'\u017dabovit\xe1 zmie\u0161an\xe1 ka\u0161a s.r.o') u'zabovita-zmiesana-kasa-sro' """ for key, value in _MAP.iteritems(): name = name.replace(key, value) return defaultfilters.slugify(name) -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
On 30. Sep., 11:45 h., Dave Angel wrote: > gentlestone wrote: > > Why don't work this code on Python 2.6? Or how can I do this job? > > > _MAP = > > # LATIN > > u'À': 'A', u'Á': 'A', u'Â': 'A', u'Ã': 'A', u'Ä': 'A', u'Å': 'A', > > u'Æ': 'AE', u'Ç':'C', > > u'È': 'E', u'É': 'E', u'Ê': 'E', u'Ë': 'E', u'Ì': 'I', u'Í': 'I', > > u'Î': 'I', > > u'Ï': 'I', u'Ð': 'D', u'Ñ': 'N', u'Ò': 'O', u'Ó': 'O', u'Ô': 'O', > > u'Õ': 'O', u'Ö':'O', > > u'Ő': 'O', u'Ø': 'O', u'Ù': 'U', u'Ú': 'U', u'Û': 'U', u'Ü': 'U', > > u'Ű': 'U', > > u'Ý': 'Y', u'Þ': 'TH', u'ß': 'ss', u'à':'a', u'á':'a', u'â': 'a', > > u'ã': 'a', u'ä':'a', > > u'å': 'a', u'æ': 'ae', u'ç': 'c', u'è': 'e', u'é': 'e', u'ê': 'e', > > u'ë': 'e', > > u'ì': 'i', u'í': 'i', u'î': 'i', u'ï': 'i', u'ð': 'd', u'ñ': 'n', > > u'ò': 'o', u'ó':'o', > > u'ô': 'o', u'õ': 'o', u'ö': 'o', u'ő': 'o', u'ø': 'o', u'ù': 'u', > > u'ú': 'u', > > u'û': 'u', u'ü': 'u', u'ű': 'u', u'ý': 'y', u'þ': 'th', u'ÿ': 'y', > > # LATIN_SYMBOLS > > u'©':'(c)', > > # GREEK > > u'α':'a', u'β':'b', u'γ':'g', u'δ':'d', u'ε':'e', u'ζ':'z', > > u'η':'h', u'θ':'8', > > u'ι':'i', u'κ':'k', u'λ':'l', u'μ':'m', u'ν':'n', u'ξ':'3', > > u'ο':'o', u'π':'p', > > u'ρ':'r', u'σ':'s', u'τ':'t', u'υ':'y', u'φ':'f', u'χ':'x', > > u'ψ':'ps', u'ω':'w', > > u'ά':'a', u'έ':'e', u'ί':'i', u'ό':'o', u'ύ':'y', u'ή':'h', > > u'ώ':'w', u'ς':'s', > > u'ϊ':'i', u'ΰ':'y', u'ϋ':'y', u'ΐ':'i', > > u'Α':'A', u'Β':'B', u'Γ':'G', u'Δ':'D', u'Ε':'E', u'Ζ':'Z', > > u'Η':'H', u'Θ':'8', > > u'Ι':'I', u'Κ':'K', u'Λ':'L', u'Μ':'M', u'Ν':'N', u'Ξ':'3', > > u'Ο':'O', u'Π':'P', > > u'Ρ':'R', u'Σ':'S', u'Τ':'T', u'Υ':'Y', u'Φ':'F', u'Χ':'X', > > u'Ψ':'PS', u'Ω':'W', > > u'Ά':'A', u'Έ':'E', u'Ί':'I', u'Ό':'O', u'Ύ':'Y', u'Ή':'H', > > u'Ώ':'W', u'Ϊ':'I', u'Ϋ':'Y', > > # TURKISH > > u'ş':'s', u'Ş':'S', u'ı':'i', u'İ':'I', u'ç':'c', u'Ç':'C', > > u'ü':'u', u'Ü':'U', > > u'ö':'o', u'Ö':'O', u'ğ':'g', u'Ğ':'G', > > # RUSSIAN > > u'а':'a', u'б':'b', u'в':'v', u'г':'g', u'д':'d', u'е':'e', > > u'ё':'yo', u'ж':'zh', > > u'з':'z', u'и':'i', u'й':'j', u'к':'k', u'л':'l', u'м':'m', > > u'н':'n', u'о':'o', > > u'п':'p', u'р':'r', u'с':'s', u'т':'t', u'у':'u', u'ф':'f', > > u'х':'h', u'ц':'c', > > u'ч':'ch', u'ш':'sh', u'щ':'sh', u'ъ':'', u'ы':'y', u'ь':'', > > u'э':'e', u'ю':'yu', u'я':'ya', > > u'А':'A', u'Б':'B', u'В':'V', u'Г':'G', u'Д':'D', u'Е':'E', > > u'Ё':'Yo', u'Ж':'Zh', > > u'З':'Z', u'И':'I', u'Й':'J', u'К':'K', u'Л':'L', u'М':'M', > > u'Н':'N', u'О':'O', > > u'П':'P', u'Р':'R', u'С':'S', u'Т':'T', u'У':'U', u'Ф':'F', > > u'Х':'H', u'Ц':'C', > > u'Ч':'Ch', u'Ш':'Sh', u'Щ':'Sh', u'Ъ':'', u'Ы':'Y', u'Ь':'', > > u'Э':'E', u'Ю':'Yu', u'Я':'Ya', > > # UKRAINIAN > > u'Є':'Ye', u'І':'I', u'Ї':'Yi', u'Ґ':'G', u'є':'ye', u'і':'i', > > u'ї':'yi', u'ґ':'g', > > # CZECH > > u'č':'c', u'ď':'d', u'ě':'e', u'ň':'n', u'ř':'r', u'š':'s', > > u'ť':'t', u'ů':'u', > > u'ž':'z', u'Č':'C', u'Ď':'D', u'Ě':'E', u'Ň':'N', u'Ř':'R', > > u'Š':'S', u'Ť':'T', u'Ů':'U', u'Ž':'Z', > > # POLISH > > u'ą':'a', u'ć':'c', u'ę':'e', u'ł':'l', u'ń':'n', u'ó':'o', > > u'ś':'s', u'ź':'z', > > u'ż':'z', u'Ą':'A', u'Ć':'C', u'Ę':'e', u'Ł':'L', u'Ń':'N', > > u'Ó':'o', u'Ś':'S', > > u'Ź':'Z', u'Ż':'Z', > > # LATVIAN > > u'ā':'a', u'č':'c', u'ē':'e', u'ģ':'g', u'ī':'i', u'ķ':'k', > > u'ļ':'l', u'ņ':'n', > > u'š':'s', u'ū':'u', u'ž':'z', u'Ā':'A', u'Č':'C', u'Ē':'E', > > u'Ģ':'G', u'Ī':'i', > > u'Ķ':'k', u'Ļ':'L', u'Ņ':'N', u'Š':'S', u'Ū':'u', u'Ž':'Z' > > } > > > def downcode(name): > > """ > > >>> downcode(u"Žabovitá zmiešaná kaša") > > u'Zabovita zmiesana kasa' > > """ > > for key, value in _MAP.iteritems(): > > name =ame.replace(key, value) > > return name > > Works for me: > > rrr = downcode(u"Žabovitá zmiešaná kaša") > print repr(rrr) > print rrr > > prints out: > > u'Zabovita zmiesana kasa' > Zabovita zmiesana kasa > > I did have to add an encoding declaration as line 2 of the file: > > #-*- coding: latin-1 -*- > > and I had to convince my editor (Komodo) to save the file in utf-8. > > DaveA great, thanks you all, I changed utf-8 to latin-1 in the header and it works for me too how mutch time could I save, just ask in this forum -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
>save in utf-8 the coding declaration also has to be utf-8 ok, I understand, but what's the problem? Unfortunately seems to be the Python interactive mode doesn't have unicode support. It recognize the latin-1 encoding only. So I have 2 options, how to write doctest: 1. Replace native charaters with their encoded representation like u"\u017dabovit\xe1 zmie\u0161an\xe1 ka\u0161a" instead of u"Žabovitá zmiešaná kaša" 2. Use latin-1 encoding, where the file is saved in utf-8 The first is bad because doctest is a great documenttion tool and it is propably the main reason I use python. And something like u"\u017dabovit\xe1 zmie\u0161an\xe1 ka\u0161a" is not a best documentation style. But the tests work. The second is bad, because the declaration is incorrect and if I use it in Django model declaration for example I got bad data in the application. So what is the solution? Back to Java? :-) -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode issue
Thx for useful advices. They seems to be very clever. Thx to dajngo users comunity, I've got a nice solution, how to avoid unicode problems in doctests: """ >>> Osoba(meno = "Ľudmila".decode('utf-8'), priezvisko = "Šafářová".decode('utf-8')) """ It is - do not use unicode string at all. Instead of it create a unicode object by explicitly decoding a bytestring using the proper codec. -- http://mail.python.org/mailman/listinfo/python-list
Creating class instance from module and class name
Suppose I've saved the class name and (don't know how) I've also saved the Class's module (package path or I don't know what's the name for XYZ "from X.Y.Z import ...). How can I construct a new class according to saved informations? If I don't know what Class it could be, only I have the saved Class name? -- http://mail.python.org/mailman/listinfo/python-list
Re: Creating class instance from module and class name
On 6. Okt, 08:55 h., Steven D'Aprano wrote: > On Mon, 05 Oct 2009 23:32:27 -0700, gentlestone wrote: > > Suppose I've saved the class name and (don't know how) I've also saved > > the Class's module (package path or I don't know what's the name for XYZ > > "from X.Y.Z import ...). How can I construct a new class according to > > saved informations? If I don't know what Class it could be, only I have > > the saved Class name? > > If you have the module *object*, and the name of the class, then you can > do this: > > theclass = getattr(module, "MyClass") > > to get the class itself, and then call it as normal to instantiate it: > > instance = theclass(args) > > Classes are just like any other object in that regard. > > If you have the *name* of the module, you can import it first to get the > module object: > > module = __import__('module_name') > theclass = getattr(module, "MyClass") > instance = theclass(args) > > There may be some complications if you have a dotted package name, in > which case the docs for __import__ are your friend :) > > -- > Steven thx for help one more question - __class__ is the way for getting the classname from the class instance - how can I get the module name? -- http://mail.python.org/mailman/listinfo/python-list
AOP decorator?
Hi, suppose my source code looks like: import aspect_xy class Basic(object, aspect_xy.Basic): pass # basic attributes and methods ... and the source code of aspect_xy.py is: class Basic(object): pass # aspect extra attributes and methods ... how can I write this with decorators? I want something like: --- import aspect_xy @aspect_xy # extra attributes and methods ... class Basic(object): pass # basic attributes and methods ... -- I want to write class decorator function, which: 1. Takes the basic class as parameter 2. Find the same class name in aspect_xy.py 3. Inherit the found aspect class Is it possible? -- http://mail.python.org/mailman/listinfo/python-list
monkey patching with @classmethod
Hi, is there some well-known problems with class method monkey patching? I've got this error message: unbound method get_pocet_neocislovanych() must be called with Pozemok instance as first argument (got Subjekt instance instead) The method is declared as: @classmethod @monkeypatch(Dokument) def get_pocet_neocislovanych(cls, subjekt): return cls.objects.filter(subjekt = subjekt, cislo__isnull = True).count() # or pass, this line is not important and the monkey patch decorator is declared as: def monkeypatch(cls): def decorator(func): setattr(cls, func.__name__, func) return func return decorator If I move the method to class declaration (whitout monkey patching), everything is ok, but only if I've restarted the server. -- http://mail.python.org/mailman/listinfo/python-list
Re: monkey patching with @classmethod
On 3. Mar., 12:57 h., gentlestone wrote: > Hi, is there some well-known problems with class method monkey > patching? > > I've got this error message: > > unbound method get_pocet_neocislovanych() must be called with Pozemok > instance as first argument (got Subjekt instance instead) > > The method is declared as: > @classmethod > @monkeypatch(Dokument) > def get_pocet_neocislovanych(cls, subjekt): > return cls.objects.filter(subjekt = subjekt, cislo__isnull = > True).count() # or pass, this line is not important > > and the monkey patch decorator is declared as: > def monkeypatch(cls): > def decorator(func): > setattr(cls, func.__name__, func) > return func > return decorator > > If I move the method to class declaration (whitout monkey patching), > everything is ok, but only if I've restarted the server. for complexity, there is a code I call the method: def _application_menu(request, subjekt, aplikacia_url_name): return render_to_response('subjekty/aplikacia.html', { 'subjekt' : subjekt, 'aplikacia_url_name' : aplikacia_url_name, 'aplikacia_dictionary' : aplikacia_dictionary(aplikacia_url_name), 'listy' : [ (dokument_url_name, dict( get_verbose_name_plural = dokument.get_verbose_name_plural(), get_pocet_neocislovanych = dokument.get_pocet_neocislovanych(subjekt), get_pocet_celkom = dokument.get_pocet_celkom(subjekt), )) for dokument_url_name, dokument in aplikacia_dictionary(aplikacia_url_name)['listy'] ], }, context_instance = RequestContext(request)) unfortunately, sometimes it works, sometimes not, I cannot imagine the reason, why and when it works and not - even whitout monkey patching seems like some black magic -- http://mail.python.org/mailman/listinfo/python-list
Re: monkey patching with @classmethod
On 3. Mar., 13:09 h., Bruno Desthuilliers wrote: > gentlestone a écrit : > > > > > Hi, is there some well-known problems with class method monkey > > patching? > > > I've got this error message: > > > unbound method get_pocet_neocislovanych() must be called with Pozemok > > instance as first argument (got Subjekt instance instead) > > The method is declared as: > > @classmethod > > @monkeypatch(Dokument) > > def get_pocet_neocislovanych(cls, subjekt): > > return cls.objects.filter(subjekt = subjekt, cislo__isnull = > > True).count() # or pass, this line is not important > > > and the monkey patch decorator is declared as: > > def monkeypatch(cls): > > def decorator(func): > > setattr(cls, func.__name__, func) > > return func > > return decorator > > The decorators are applied in order. So you first add the yet > undecorated function as an attribute of the class, then pass the > function to classmethod. > > FWIW, this monkeypatch decorator is IMHO a plain waste of time. The > following code does the same thing and is (IMHO again) *much* more readable: > > def get_pocet_neocislovanych(cls, subjekt): > return cls.objects.filter( > subjekt=subjekt, > cislo__isnull= True > ).count() # or pass, this line is not important > > dokument.get_pocet_neocislovany...@classmethod(get_pocet_neocislovanych) > > Also, Django's BestPractice(tm) is to define such "query" methods on the > model's manager, not as a classmethod of the model. > > My 2 cents thx, I changed my definitions to manager style and have no more problems seems to be safe to use manager instead classmethod - do not know why :-) -- http://mail.python.org/mailman/listinfo/python-list
(a==b) ? 'Yes' : 'No'
Hi, how can I write the popular C/JAVA syntax in Python? Java example: return (a==b) ? 'Yes' : 'No' My first idea is: return ('No','Yes')[bool(a==b)] Is there a more elegant/common python expression for this? -- http://mail.python.org/mailman/listinfo/python-list
Usefull python tutorial
Can somebody give me an advise where I can found a really good online tutorial? All I found are useless. For example no tutorial I found explains this piece of code: someList = [element for element in otherList if element is not None] or this example: a = a or [] There are only stupid elementary examples in the tutorials I found. -- http://mail.python.org/mailman/listinfo/python-list
How can I format unicode strings?
return u"{}".format(self.name) this one doesn't work on unicode strings. I there a not old formatting style possibilty for unicode strings? Note: self.name can be unicode string! -- http://mail.python.org/mailman/listinfo/python-list
Re: How can I format unicode strings?
On 9. Sep., 12:31 h., Tim Northover wrote: > gentlestone writes: > > return u"{}".format(self.name) > > > this one doesn't work on unicode strings. I there a not old formatting > > style possibilty for unicode strings? > > It looks like you're trying to mix python 3.1 and 2.6. In 2.6 you have > to put a number inside the {} to tell it which argument to use. In 3.1 > all strings are unicode. > > Apparently when 2.7 is released it will backport the empty {} feature > from 3.1. Until then > > return u'{0}'.format(self.name) > > is what you should probably use. > > Tim. I have python 2.5 return u'{0}'.format(self.name) doesn't work eigther the error message i've got is: 'unicode' object has no attribute 'format' is the new formatting style newer then python 2.5? -- http://mail.python.org/mailman/listinfo/python-list