[issue1945] Document back ported C functions
John Lenton added the comment: This is the same as the previous patch, but I added the versionadded notation in the rst, and the info in refcounts.dat to get the return value info in the docs. Added file: http://bugs.python.org/file9461/1945-2.diff __ Tracker [EMAIL PROTECTED] http://bugs.python.org/issue1945 __ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue2112] mmap.error should be a subclass of EnvironmentError and not a direct EnvironmentError
John Lenton added the comment: Ran the regression test with this patch, all ok (on Ubuntu Gutsy). Attached diff is the same, with the addition of the NEWS entry. -- nosy: +Chipaca Added file: http://bugs.python.org/file9443/mmap3.diff __ Tracker [EMAIL PROTECTED] http://bugs.python.org/issue2112 __ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue1945] Document back ported C functions
John Lenton added the comment: Copied documentation from the py3k branch for the functions mentioned in the .h's (those were: PyLong_FromSsize_t, PyLong_FromSize_t, PyLong_AsSsize_t, PyUnicode_FromStringAndSize, PyUnicode_FromString, PyUnicode_FromFormat, and PyUnicode_FromFormatV). Tested by building the documentation; everything seems to be in order. Added NEWS entry. -- nosy: +Chipaca Added file: http://bugs.python.org/file9454/1945.diff __ Tracker [EMAIL PROTECTED] http://bugs.python.org/issue1945 __ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue1675533] setup.py LDFLAGS regexp is wrong
John Lenton added the comment: This was fixed in r57389 by georg.brandl by changing the replacement string '' to ' ' (turning the option into a non-option). Steps to reproduce this on Ubuntu Feisty, before that revision, were: $ mkdir banana $ sudo mv /usr/include/sqlite3.h banana/ $ make clean ./configure make [...] Failed to find the necessary bits to build these modules: _sqlite3 bsddb185 sunaudiodev [...] $ make clean CPPFLAGS=-Ibanana ./configure make Failed to find the necessary bits to build these modules: bsddb185 sunaudiodev $ make clean CPPFLAGS=-Ibanana\ -Rmango ./configure make Failed to find the necessary bits to build these modules: _sqlite3 bsddb185 sunaudiodev -- nosy: +Chipaca _ Tracker [EMAIL PROTECTED] http://bugs.python.org/issue1675533 _ ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue976880] mmap needs a rfind method
John Lenton added the comment: Attached patch adds two things: an 'end' argument to find, and an 'rfind' method. This includes minimal tests for rfind, but as I actually refactored find and rfind into a single method, tests covering find also cover most of rfind :). I added 'end' first because the refactoring seemed more natural (symmetric?) after that. Also included are updated docs, and NEWS. -- nosy: +Chipaca Added file: http://bugs.python.org/file9219/mmap.rfind.patch Tracker [EMAIL PROTECTED] http://bugs.python.org/issue976880 ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue976880] mmap needs a rfind method
John Lenton added the comment: New patch, with small change after being reviewed by amk. Still against revision 60082. Added file: http://bugs.python.org/file9223/mmap.rfind.patch Tracker [EMAIL PROTECTED] http://bugs.python.org/issue976880 ___ Python-bugs-list mailing list Unsubscribe: http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
module placeholder
Once again I'm working on code that has several 'providers' of different features, and I thought I'd ask the list what better solutions it has to this other than what I've come up with. Currently, the cleanest way I can find is to say import foo foo.config(bar='baz') # from this point on, foo.bar is provided by foo.bars.baz this could be widget sets, database connectors, persistance layers, RPC, you name it. This is very easy to do: # foo.py def config(bar_name=DEFAULT_BAR_NAME): global bar bar = __import__('foo.' + bar_name, globals(), locals(), bar_name) This would work fine if people wanted to use this (once its configured) as 'import foo; foo.bar.funkyFunction()', but no! they want to be able to do 'from foo.bar import funkyFunction', which is reasonable really because I'm just as lazy as they are. So what I've come up with is def config(bar_name=DEFAULT_BAR_NAME): global bar barModule = __import__('foo.' + bar_name, globals(), locals(), bar_name) bar.faultFrom(barModule) class proxyModule(new.module): def faultFrom(self, other): self.__other = other self.__name__ = other.__name__ self.__file__ = other.__file__ + ' [proxied]' def __getattr__(self, attr): return getattr(self.__other, attr) bar = proxyModule('bar proxy') and this is the bit that feels ugly: is there a better way to have an object that can be imported from a file and that behaves like a module, but that isn't filled in until some point down the road? -- http://mail.python.org/mailman/listinfo/python-list
Re: Recognizing the Arrival of a New File
On Tue, Mar 08, 2005 at 08:43:04AM -0600, Greg Lindstrom wrote: I am writing an application where I need to recognize when a file arrives in a given directory. Files may arrive at any time during the course of the day. Do I set up a cron job to poll the directory every few minutes? Write a daemon to monitor the directory? Or is there some other more common/accepted way to perform this task? I'm using Python 2.3 on Linux. you could use dnotify; unfortunately although the fcntl wrapper in python would suffice, there is AFAIK no way to do sigaction. Fortunately there is a dnotify program which is easy enough to use, both from python or directly. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Knghtbrd 2fort5 sucks enough to have its own gravity ... signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: web status display for long running program
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 Brian Roberts wrote: | I have a command line Python program that sometimes takes a bit | (several minutes) to run. I want to provide an optional method for an | impatient user (me!) to check the status of the program. The type and | amount of status information doesn't fit nicely into a --verbose or | logger -- either too little or too much information at different | points. dd and pppd (and probably others) solve this problem by registering a signal handler that either toggles debug or prints status information to stderr. - -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Work consists of whatever a body is obliged to do. Play consists of whatever a body is not obliged to do. -- Mark Twain -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.0 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://enigmail.mozdev.org iD8DBQFCHpMZcxEeCh6qRm8RAg11AKCek0hV6QCHw6fm3TM3KAJIXPb1RQCg4qhy HMr5y+w7fxESkJ2vQ0GEmm0= =c4bs -END PGP SIGNATURE- -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Thu, Feb 17, 2005 at 10:20:58PM -0800, Michele Simionato wrote: Ok, I have yet another question: what is the difference between fcntl.lockf and fcntl.flock? The man page of my Linux system says that flock is implemented independently of fcntl, however it does not say if I should use it in preference over fcntl or not. it depends on what you want to do: as the manpages say, flock is present on most Unices, but lockf is POSIX; flock is BSD, lockf is SYSV (although its in XPG4.2, so you have it on newer Unices of any flavor); on Linux, lockf works over NFS (if the server supports it), and gives you access to mandatory locking if you want it. You can't mix lockf and flock (by this I mean: you can get a LOCK_EX via flock and via lockf on the same file at the same time). So: use whichever you feel more comfortable with, although if you are pretty confident your program will run mostly on Linux there is a bias towards lockf given its extra capabilities there. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: ¡¡ QQuuiittaa eell LLooccaall EEcchhoo,, MMaannoolloo !! signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: how can i randomly choose keys in dictionary
On Fri, Feb 18, 2005 at 09:35:30AM +0100, Thomas Guettler wrote: Am Thu, 17 Feb 2005 18:13:46 -0800 schrieb neutrinman: Hi,there. How can I choose a key in dictionary randomly? Say, random.choice() in lists, or in lists: lists = [1,2,3,4] position = random.range(len(lists)) word = lists[position] Hi, try this: import random mydict={1: one, 2: two} print mydict[random.choice(mydict.keys())] if you're going to do that, why don't you do print random.choice(mydict.values()) ? -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Quien da parte de sus cohechos, de sus tuertos hace derechos. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: [perl-python] exercise: partition a list by equivalence
On Thu, Feb 17, 2005 at 03:46:20PM -0800, Xah Lee wrote: here's another interesting algorithmic exercise, again from part of a larger program in the previous series. Here's the original Perl documentation: =pod merge($pairings) takes a list of pairs, each pair indicates the sameness of the two indexes. Returns a partitioned list of same indexes. For example, if the input is merge( [ [1,2], [2,4], [5,6] ] ); that means 1 and 2 are the same. 2 and 4 are the same. Therefore 1==2==4. The result returned is [[4,2,1],[6,5]]; (ordering of the returned list and sublists are not specified.) =cut in Python: def merge(pairings): rev = {} res = [] for pairing in pairings: first, second = pairing has_first = first in rev has_second = second in rev if has_first and has_second: rev[first].extend(rev[second]) rev[second][:] = [] rev[second] = rev[first] elif has_first: rev[first].append(second) rev[second] = rev[first] elif has_second: rev[second].append(first) rev[first] = rev[second] else: copy = [first, second] res.append(copy) rev[first] = rev[second] = copy return filter(None, res) and in Perl: sub merge($) { my %rev = (); my @res = (); my ($pairing, $first, $second, $has_first, $has_second); foreach $pairing (@{$_[0]}) { ($first, $second) = @$pairing; $has_first = exists $rev{$first}; $has_second = exists $rev{$second}; if ($has_first and $has_second) { push @{$rev{$first}}, @{$rev{$second}}; @{$rev{$second}} = (); $rev{$second} = $rev{$first}; } elsif (exists $rev{$first}) { push @{$rev{$first}}, $second; $rev{$second} = $rev{$first}; } elsif (exists $rev{$second}) { push @{$rev{$second}}, $first; $rev{$first} = $rev{$second}; } else { my @copy = ($first, $second); push @res, [EMAIL PROTECTED]; $rev{$first} = $rev{$second} = [EMAIL PROTECTED]; } } return [grep @$_, @res]; } although in Perl you wouldn't define it to take a reference to a list (as you did), but rather a list, and you wouldn't define it to return a reference to a list, but rather a list in list context (and possibly a reference in scalar context). Both versions are (IMHO) pretty clear (when the docstring/pod is included), and O(n) because dict/hash lookup and list appending/pushing is O(1) in both languages. Both versions can probably be tweaked for speed quite a bit, but I don't *think* there's a better-than-O(n) algorithm for this. Note that the Python version assumes that the pairs' elements are hashable; your example used numbers, so I thought it was pretty safe assumption. The Perl version has no such restriction. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Noble cosa es, aún para un anciano, el aprender. -- Sófocles. (497-406 a.C.) Filósofo griego. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Fri, Feb 18, 2005 at 07:57:21AM -0800, Michele Simionato wrote: Uhm ... I reading /usr/src/linux-2.4.27/Documentation/mandatory.txt The last section says: 6. Warning! --- Not even root can override a mandatory lock, so runaway processes can wreak havoc if they lock crucial files. The way around it is to change the file permissions (remove the setgid bit) before trying to read or write to it. Of course, that might be a bit tricky if the system is hung :-( so lockf locks do not look completely harmless ... if you read the whole file, you will have read that turning on mandatory locks is not trivial. I never said it was harmless, and in fact (as that section explains) it's a bad idea for most cases; there are some (very few) situations where you need it, however, and so you can get at that functionality. Having to mount your filesystem with special options and twiddling the permission bits is a pretty strong hint that the implementors didn't think it was a good idea for most cases, too. Hmm, just read that file, and it doesn't mention the have to mount with special options bit. But if you look in mount(8), you see an entry under the options list, mand Allow mandatory locks on this filesystem. See fcntl(2) and if you look in fcntl(2), you see that Mandatory locking (NonPOSIX.) The above record locks may be either advi sory or mandatory, and are advisory by default. To make use of mandatory locks, mandatory locking must be enabled (using the o mand option to mount(8)) for the file system containing the file to be locked and enabled on the file itself (by disabling group execute permis sion on the file and enabling the setGID permission bit). Advisory locks are not enforced and are useful only between cooperating processes. Mandatory locks are enforced for all processes. if I have come across as recommending mandatory locks in this thread, I apologize, as it was never my intention. It is a cool feature for the .001% of the time when you need it (and the case in discussion in this thread is not one of those), but other than that it's a very, very bad idea. In the same league of badness as SysV IPC; I'd still mention SysV IPC to someone who asked about IPC on Linux, however, because there are places where it is useful even though most times it's a stupid way to do things (yes, Oracle, *especially* you). -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: A pencil with no point needs no eraser. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: exercise: partition a list by equivalence
On Fri, Feb 18, 2005 at 03:21:10PM -0800, John Machin wrote: Not robust in the face of input like: [[1,1]] or [[1,2], [1,2]] or [[1,2], [2,1]] or [[1,2], [2,3], [3,1]] oops, my bad. needs if first == second: continue here if has_first and has_second: needs if rev[first] == rev[second]: continue here an 'is' is enough, and better. rev[first].extend(rev[second]) rev[second][:] = [] rev[second] = rev[first] elif has_first: rev[first].append(second) rev[second] = rev[first] elif has_second: rev[second].append(first) rev[first] = rev[second] else: copy = [first, second] res.append(copy) My reaction to the magic by which res grows was omigod that's the most horrible thing I've seen for quite a while but there was worse to come :-) what is magic about it? is it really that horrible? List appending is O(1) only in the amortised sense. Extending is not O(1) in any sense. Neither is the list comparison that is necessary for robustness (using your data structure, that is). You don't need to think. This problem has been extensively picked over by folk who are a lot smarter than us, starting from 30 years ago. Google for disjoint set and union-find. One gets the impression that the best possible algorithm would be slightly *worse* than O(n). Of course! I'd forgotten clean about union-find. And yes, it's O(n*log(n)) union and find, and my implementation is O(n**2) for union, O(1) for find; I'm pleased that, in spite of having forgotten about union-find, I reinvented (heh) something that is better than the naive implementation we saw in class. Now I'm even more worried about your dismissal of this as magic and horrible. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Why don't you fix your little problem... and light this candle? -- Alan Shepherd, the first man into space, Gemini program signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: exercise: partition a list by equivalence
On Fri, Feb 18, 2005 at 09:57:59PM -0800, John Machin wrote: this, together with you saying that it is hard to explain, makes me think that you aren't comfortable thinking of lists as mutable objects. How so? There is no connection between is/== and mutability. Let me amplify: The point about 'is' is a good one, and aids your redemption after your failure to have adequate guards caused your algorithm not to work. hey, it worked for all the test cases provided by the customer! :) and then some; I hadn't thought of checking for cycles nor repetetitions. [snip] You are confusing mutability of lists (without which they would be called tuples!) with my point that the 'res' list was having its contents fiddled with implicitly through other pointers. umm... nope, see, well, hair-splitting and all that, there is this list that holds the partitions; the partitions are lists of elements. There is a reverse mapping that, for each element, holds the partition that element is in. So basically you go down the list of pairings, modifying the partitions as you go. I'm certain if I had commented the function appropriately, we wouldn't be having this discussion :) Let me see if I can remedy that: def merge(pairings): merge(pairings) takes a list of pairs, each pair indicates the sameness of the two indexes. Returns a partitioned list of same indexes. For example, if the input is merge( [ [1,2], [2,4], [5,6] ] ); that means 1 and 2 are the same. 2 and 4 are the same. Therefore 1==2==4. The result returned is [[4,2,1],[6,5]]; (ordering of the returned list and sublists are not specified.) # the list of partitions, or partitioned list. # (each partition is a list of elements) res = [] # reverse mapping (element - partition it is in) rev = {} for pairing in pairings: first, second = pairing has_first = first in rev has_second = second in rev if has_first and has_second: # both elements already in a partition... if rev[first] is rev[second]: # both elements in same partition, nothing to do continue # joining the two partitions: # - grow one partition with the other one rev[first].extend(rev[second]) # - clear the other one rev[second][:] = [] # update reverse mapping rev[second] = rev[first] elif has_first: # partition already exists, just add an element to it rev[first].append(second) # update reverse mapping rev[second] = rev[first] elif has_second: # ditto rev[second].append(first) rev[first] = rev[second] else: # create partition from scratch if first == second: new = [first] else: new = [first, second] # add it to list of partitions res.append(new) # update reverse mapping rev[first] = rev[second] = new # remove empty partitions return filter(None, res) hrmph, I should hit the sack. Sorry if this is still ugly, I'm too tired to tell. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Todo bicho que camina va a parar cuando se canse. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Wed, Feb 16, 2005 at 10:43:42PM -0800, Michele Simionato wrote: snip simple example with flock What happens if for any reason the application crashes? Locked files will stay locked or not? And if yes, how do I unlock them? the operating system cleans up the lock. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Linux ext2fs has been stable for a long time, now it's time to break it -- Linuxkongreß '95 in Berlin signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: How to wrap a class's methods?
On Thu, Feb 17, 2005 at 07:32:55PM +, Grant Edwards wrote: I want to subclass an IMAP connection so that most of the methods raise an exception if the returned status isn't 'OK'. This works, but there's got to be a way to do it that doesn't involve so much duplication: class MyImap4_ssl(imaplib.IMAP4_SSL): def login(*args): s,r = imaplib.IMAP4_SSL.login(*args) if s!='OK': raise NotOK((s,r)) return r def list(*args): s,r = imaplib.IMAP4_SSL.list(*args) if s!='OK': raise NotOK((s,r)) return r def search(*args): s,r = imaplib.IMAP4_SSL.search(*args) if s!='OK': raise NotOK((s,r)) return r [and so on for another dozen methods] something like this: def NotOKVerified(orig): def f(*args): s, r = orig(*args) if s != 'OK': raise NotOK((s,r)) return r return f class MyImap4_ssl(IMAP4_SSL): pass for method_name in ('login', 'list', 'search'): setattr(MyImap4_ssl, method_name, getattr(IMAP4_SSL, method_name)) ? I'd usually put big fat warnings around this code, and explain exaclty why I need to do things this way... -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: To vacillate or not to vacillate, that is the question ... or is it? signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Thu, Feb 17, 2005 at 09:08:25PM +0100, Pierre Quentel wrote: Maybe you'll find this too naive, but why do you want to avoid concurrent accesses to a database that will be accessed 12 times a day ? because every sunday at 3am your boss and his wife will both try to use the script at the same time, and delete everything. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: If our behavior is strict, we do not need fun! signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: [EVALUATION] - E02 - ULTIMATE RECIPE TO RESOLVE ALL ISSUES
On Thu, Feb 17, 2005 at 06:49:38PM +, Stephen Kellett wrote: Next you'll be telling me the world is flat and held up by an infinite array of tortoises. no, of course not! It's an iterator. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Test-tube babies shouldn't throw stones. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: namespace collisions
On Thu, Feb 17, 2005 at 06:20:36PM +, Will McGugan wrote: Hi, I'm accumulating a number of small functions, which I have sensibly put in a single file called 'util.py'. But it occurs to me that with such a generic name it could cause problems with other modules not written by myself. Whats the best way of handling this? If I put it in a common location in my Python path, should I call it willsutil.py? local.util is probably a convention worth starting :) or you could go with WilMcGugan.util but ThatGetsOldFast. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: All my friends are getting married, Yes, they're all growing old, They're all staying home on the weekend, They're all doing what they're told. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Thu, Feb 17, 2005 at 12:42:55AM -0800, Michele Simionato wrote: John Lenton: the operating system cleans up the lock. So, are you effectively saying than a custom made solution based on flock can be quite reliable and it could be a reasonable choice to use shelve+flock for small/hobbysts sites? I always thought locking was a bad beast and feared to implement it myself, but maybe I was wrong afterall ... locking works very well, when it works. If you're on Linux, the manpage for flock has a NOTES section you should read. I don't know how direct the mapping between python's flock/lockf and the OSs flock/lockf are, you might want to look into that as well (but you'd only really care if you are in one of the corner cases mentioned in the referred NOTES section). In some weird corner cases you'd have to revert to some other locking scheme, but the same pattern applies, however: subclass whatever it is you want to use, wrapping the appropriate methods in try/finally lock/unlocks; you just want to change the flock to some other thing. Also, if you use something where the process doesn't terminate between calls (such as mod_python, I guess), you have to be sure to write the try/finallys around your locking code, because the OS only cleans up the lock when the process exits. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Keep emotionally active. Cater to your favorite neurosis. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Thu, Feb 17, 2005 at 09:02:37PM -0800, Michele Simionato wrote: John Lenton: Also, if you use something where the process doesn't terminate between calls (such as mod_python, I guess), you have to be sure to write the try/finallys around your locking code, because the OS only cleans up the lock when the process exits. This is what I feared. What happens in the case of a power failure? Am I left with locked files floating around? no. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Los hijos de los buenos, capa son de duelo signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: low-end persistence strategies?
On Tue, Feb 15, 2005 at 06:57:47PM -0800, Paul Rubin wrote: I've started a few threads before on object persistence in medium to high end server apps. This one is about low end apps, for example, a simple cgi on a personal web site that might get a dozen hits a day. The idea is you just want to keep a few pieces of data around that the cgi can update. Immediately, typical strategies like using a MySQL database become too big a pain. Any kind of compiled and installed 3rd party module (e.g. Metakit) is also too big a pain. But there still has to be some kind of concurrency strategy, even if it's something like crude file locking, or else two people running the cgi simultaneously can wipe out the data store. But you don't want crashing the app to leave a lock around if you can help it. Anyway, something like dbm or shelve coupled with flock-style file locking and a version of dbmopen that automatically retries after 1 second if the file is locked would do the job nicely, plus there could be a cleanup mechanism for detecting stale locks. Is there a standard approach to something like that, or should I just code it the obvious way? one easy way would be something along the lines of from ConfigParser import ConfigParser from fcntl import flock, LOCK_SH, LOCK_EX, LOCK_UN class LockedParser(ConfigParser): def _read(self, fp, fpname): flock(fp, LOCK_SH) # block until can read try: rv = super(LockedParser, self)._read(fp, fpname) finally: flock(fp, LOCK_UN) return rv def write(self, fp): flock(fp, LOCK_EX) # block until can write try: rv = super(LockedParser, self).write(fp) finally: flock(fp, LOCK_UN) return rv although you could do the same kind of stuff with csv, or even Pickle. Of course this doesn't work if what you're wanting to implement is a hit counter, but that is much easier: just grab a LOCK_EX, read in, write out, LOCK_UN. If you care about (not) overwriting changes, but fear you'll hold the lock for too long with the simple 'grab the lock and run' approach, you could save a version of the original file and compare before writing out. Complexity grows a lot, and you suddenly would be better off using pybsddb or somesuch. Of course I'm probably overlooking something, because it really can't be this easy, can it? -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: BOFH excuse #44: bank holiday - system operating credits not recharged signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Alternative to raw_input ?
On Fri, Feb 11, 2005 at 05:37:19PM +0100, BOOGIEMAN wrote: On Fri, 11 Feb 2005 16:35:19 +, Simon Brunning wrote: Err, why? It looks to ugly this way. I want to press any key without ENTER to continue read the documentation on readline. Hmm! it says Availability: Unix. Any particular reason? readline should be fine on OSX and Win32 -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: sugar daddy, n.: A man who can afford to raise cain. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: hard_decoding
On Wed, Feb 09, 2005 at 05:22:12PM -0700, Tamas Hegedus wrote: Hi! Do you have a convinient, easy way to remove special charachters from u'strings'? Replacing: ÀÁÂÃÄÅ= A èéêë = e etc. 'L0xe1szl0xf3' = Laszlo or something like that: 'L\xc3\xa1szl\xc3\xb3' = Laszlo for the examples you have given, this works: from unicodedata import normalize def strip_composition(unichar): Return the first character from the canonical decomposition of a unicode character. This wil typically be the unaccented version of the character passed in (in Latin regions, at least). return normalize('NFD', unichar)[0] def remove_special_chars(anystr): strip_composition of the whole string return ''.join(map(strip_composition, unicode(anystr))) for i in ('ÀÁÂÃÄÅ', 'èéêë', u'L\xe1szl\xf3', 'L\xc3\xa1szl\xc3\xb3'): print i, '-', remove_special_chars(i) produces: ÀÁÂÃÄÅ - AA èéêë - László - Laszlo László - Laszlo although building a translation mapping is, in general, faster. You could use the above to build that map automatically, like this: def build_translation(sample, table=None): Return a translation table that strips composition characters out of a sample unicode string. If a table is supplied, it will be updated. assert isinstance(sample, unicode), 'sample must be unicode' if table is None: table = {} for i in set(sample) - set(table): table[ord(i)] = ord(strip_composition(i)) return table this is much faster on larger strings, or if you have many strings, but know the alphabet (so you compute the table once). You might also try to build the table incrementally, for i in strings: i = i.translate(table) try: i.encode('ascii') except UnicodeEncodeError: table = build_translation(i, table) i = i.translate(table) stripped.append(i) of course this won't work if you have other, non-ascii but non-composite, chars in your strings. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: El que está en la aceña, muele; que el otro va y viene. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: multi threading in multi processor (computer)
On Wed, Feb 09, 2005 at 07:56:27AM -0800, [EMAIL PROTECTED] wrote: Hello Pierre, That's a pity, since when we have to run parallel, with single processor is really not efficient. To use more computers I think is cheaper than to buy super computer in developt country. and buying more, cheap computers gives you more processing power than buying less, multi-processor computers. So the best thing you can do is learn to leverage some distributed computing scheme. Take a look at Pyro, and its Event server. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: When the cup is full, carry it level. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: PyQt and Python 2.4 - also WinXP LnF?
On Wed, Feb 09, 2005 at 06:44:31PM -0800, Simon John wrote: I'm writing an XMMS remote control program, so it will be GPL when released (if it's ever good enough to release!) so I'm looking at buying the commercial PyQt3 or BlackAdder whilst waiting for the GPL PyQt4 may I observe that if you're writing anything to do with xmms, you stick to plain ol' gtk1? -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Hemos hallado al enemigo, y somos nosotros. -- Walt Kelly. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Big development in the GUI realm
On Tue, Feb 08, 2005 at 09:19:58PM -0200, Gabriel B. wrote: However, imagine simple situation: 1. I write proprietary program with open plugin api. I even make the api itself public domain. Program works by itself, does not contain any GPL-ed code. No need to continue. You write something that uses a plugin, Eolas sues you. Don't have to mind about trolltech not if you live in a sane country. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Preserve wildlife -- pickle a squirrel today! signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Confused with methods
On Mon, Feb 07, 2005 at 03:24:11PM +0100, Alex Martelli wrote: def always produces a function object and binds it to the name coming after keyword 'def'. Any such function object, no matter how produced and how bound hither and thither, always behaves in exactly the same way. This isn't exactly true: class C(object): ... def __new__(*a): pass ... C.__new__ function __new__ at 0x40088d4c class D(object): pass ... def __new__(*a): pass ... D.__new__ = __new__ D.__new__ unbound method D.__new__ of course, __new__ is special-cased (*some*body should've read import this, especially the part explicit is better than implicit). -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Al freír será el reír. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Confused with methods
On Mon, Feb 07, 2005 at 02:53:49PM +, Antoon Pardon wrote: The fact that a function in a class performs a lot of magic if it is called through an instance, that isn't performed otherwise, makes python inconsistent here. You may like the arrangement (and it isn't such a big deal IMO) but that doesn't make it consistent. I vote for accepting the fact (it goes with the practicality beats purity bit, because otherwise all our methods would have to start with an @instancemethod). This doesn't justify (IMVVHO) a new keyword, like you (was it you?) seemed to imply (do you really mean for instancemethod (or somesuch) and classmethod to become keywords?). I think it's fine the way it is: there's an implicit @instancemethod, and @staticmethod (which you'd have be the default if I read you right) has to be explicit, when in classes. I think __new__ being an exception to this is a (minor) wart, in fact it feels like premature optimization (how many __new__s do you write, that you can't stick a @staticmethod in front of them? -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Fun Facts, #14: In table tennis, whoever gets 21 points first wins. That's how it once was in baseball -- whoever got 21 runs first won. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Collapsing a list into a list of changes
On Mon, Feb 07, 2005 at 07:07:10PM +0100, Francis Girard wrote: Zut ! I'm very sorry that there is no good use case for the reduce function in Python, like Peter Otten pretends. That's an otherwise very useful tool for many use cases. At least on paper. Python documentation should say There is no good use case for the reduce function in Python and we don't know why we bother you offering it. I am guessing you are joking, right? I think Peter exaggerates when he says that there will be no good use cases for reduce; it is very useful, in writing very compact code when it does exactly what you want (and you have to go through hoops to do it otherwise). It also can be the fastest way to do something. For example, the fastest way to get the factorial of a (small enough) number in pure python is factorial = lambda n: reduce(operator.mul, range(1, n+1)) -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Laugh and the world thinks you're an idiot. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Collapsing a list into a list of changes
On Mon, Feb 07, 2005 at 09:39:11PM +0100, Peter Otten wrote: John Lenton wrote: For example, the fastest way to get the factorial of a (small enough) number in pure python is factorial = lambda n: reduce(operator.mul, range(1, n+1)) I see that you are seduced by the beauty of the expression. Otherwise, if you would really care for speed: [...] that's cheating: you moved the calculation into the setup. You aren't timing what you say you are. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: I'd rather push my Harley than ride a rice burner. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: a type without a __mro__?
On Sat, Feb 05, 2005 at 11:37:10AM +0100, Alex Martelli wrote: Can anybody suggest where to find (within the standard library) or how to easily make (e.g. in a C extension) a type without a __mro__, except for those (such as types.InstanceType) which are explicitly recorded in the dispatch table copy._deepcopy_dispatch...? would this do what you need? class C(type): def __getattribute__(self, attr): if attr == '__mro__': raise AttributeError, What, *me*, a __mro__? Nevah! return super(C, self).__getattribute__(attr) class D(object): __metaclass__ = C instances of D have a type that behaves as if it didn't have a __mro__. This isn't exactly what you asked for, but it might be enough. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: El tiempo cura los dolores y las querellas porque cambiamos. Ya no somos la misma persona. -- Blaise Pascal. (1600-1662) Filósofo y escritor francés. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: implicit conversion
On Mon, Jan 31, 2005 at 02:01:56PM +0100, Benjamin Schmeling wrote: Hi, I am working on exposing a bigint class to python. Now I've got the problem that methods which take an bigint as an parameter do not accept Python longs. For example: import _PythonLiDIA x=123L; c=_PythonLiDIA.bigint(); _PythonLiDIA.gcd(c,x); Traceback (most recent call last): File test.py, line 132, in ? _PythonLiDIA.gcd(a,x); Boost.Python.ArgumentError: Python argument types in _PythonLiDIA.gcd(bigint, long) did not match C++ signature: gcd(LiDIA::bigint, LiDIA::bigint) I don't know how to achieve implicit conversion at this point, turning an long automatically into an bigint. The other way round, turning an bigint into long can be realized by defining __long__. Can someone help me please? as later on you say you have a constructor to convert longs into your bigints, you should add a __coerce__ method to your class. General description of __coerce__: http://docs.python.org/ref/numeric-types.html#l2h-303 details on coercion rules: http://docs.python.org/ref/coercion-rules.html enjoy. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: BOFH excuse #309: firewall needs cooling signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: import doesn't work as i want
On Mon, Jan 31, 2005 at 04:52:24PM +0100, Olivier Noblanc ATOUSOFT wrote: Hello, In the botom of this post you will see my source code. The problem is when i launch main.py that doesn't make anything why ? I'm guessing you don't have an __init__.py in inc/ -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: /* now make a new head in the exact same spot */ -- Larry Wall in cons.c from the perl source code signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: OT: problems mirroring python-list to c.l.py?
On Sun, Jan 23, 2005 at 01:53:52PM -0500, Daniel Bickett wrote: Is there a reason that Google Groups isn't mirroring python-list exactly like it used to, or is it simply a conspiracy I'm not in on? You should not ask this kind of question in a public forum, and *you* should know better than to go around flapping your mouth like that. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Comer se ha de hacer en silencio, como los frailes en sus conventos. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: simultaneous multiple requests to very simple database
On Tue, Jan 18, 2005 at 11:26:46AM -0500, Eric S. Johansson wrote: I have an application where I need a very simple database, effectively a very large dictionary. The very large dictionary must be accessed from multiple processes simultaneously. I need to be able to lock records within the very large dictionary when records are written to. Estimated number of records will be in the ballpark of 50,000 to 100,000 in his early phase and 10 times that in the future. Each record will run about 100 to 150 bytes. speed is not a huge concern although I must complete processing in less than 90 seconds. The longer the delay however the greater number of processes must be running parallel in order to keep the throughput up. It's the usual trade-off we have all come to know and love. it is not necessary for the dictionary to persist beyond the life of the parent process although I have another project coming up in which this would be a good idea. at this point, I know they will be some kind souls suggesting various SQL solutions. While I appreciate the idea, unfortunately I do not have time to puzzle out yet another component. Someday I will figure it out because I really liked what I see with SQL lite but unfortunately, today is not that day (unless they will give me their work, home and cell phone numbers so I can call when I am stuck. ;-) I'm sure we could agree on a fee for me to do so :) So the solutions that come to mind are some form of dictionary in shared memory with locking semaphore scoreboard or a multithreaded process containing a single database (Python native dictionary, metakit, gdbm??) and have all of my processes speak to it using xmlrpc which leaves me with the question of how to make a multithreaded server using stock xmlrpc. berkley db (at least version 3, http://pybsddb.sourceforge.net/) supports multiple readers and writers, with fine-grained locking, it looks like a dictionary, and it isn't sql. The use you have in mind is a bit more complicated than the simple create-me-a-dictionary-in-a-file, but is pretty straightforward. The documentation mostly refers you to the C API, but fortunately it (the C API) is clear and well written. HTH -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Today is National Existential Ennui Awareness Day. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: strange note in fcntl docs
On Mon, Jan 17, 2005 at 09:54:46PM -0600, Skip Montanaro wrote: John And, even if they were, the note is *still* wrong and misleading: John fcntl is available on Windows, and os.open's flags won't be. Does this read better? [snip] yes, and it takes me back to considering why file objects don't have methods suck as lock, stat and mmap where those calls are available through other mechanisms... -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Yo mando a mi gato y mi gato manda a su rabo. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: lambda
On Mon, Jan 17, 2005 at 03:20:01PM +, Antoon Pardon wrote: Op 2005-01-17, John Lenton schreef [EMAIL PROTECTED]: knowledgeable and experienced users know when to ignore the rules. Then why seems there to be so few acknowledgement that these rules may indeed be broken by users. My experience is that anyone who suggests so runs the risk of being branded a (python) heretic. First you learn the basics, then you think you're knowledgeable and experienced, then you learn the rules, then you become one with the rules, and then you may break them. Most people suggesting these things haven't gotten past step #3. Using Craig's parallel to C's goto, every and all newbie using gotos should be lambasted: even if the use might be correct for the problem they are trying to solve, the reasons for its correctness are far too complex for them to grasp. But really, in practically any system, the rules are generalizations, and they exist because the particulars are too delicate to trust the unexperienced. The small print is unprintable. He dicho. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Yo siempre seré el futuro Nobel. Debe ser una tradición escandinava. -- Jorge Luis Borges. (1899-1986) Escritor argentino. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: lambda
On Mon, Jan 17, 2005 at 11:41:20AM +, Antoon Pardon wrote: Op 2005-01-17, Steve Holden schreef [EMAIL PROTECTED]: Antoon Pardon wrote: [...] A foolish consistency is the hobgoblin of little minds. Rules are made to be broken. Like only use immutables as dictionary keys. Fair enough, but don;t go advising newbies to do this. How about something like this. Because of the extra precautions one has to take when using mutables as hash keys, we advise newbies to stick with immutable keys until they have gathered enough knowledge and experience to adequatly weight the pro and cons of a mutable key solution against an immutable key solution. knowledgeable and experienced users know when to ignore the rules. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Una buena gran parte del arte del bien hablar consiste en saber mentir con gracia. -- Erasmo de Rotterdam. (1469-1536). signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
strange note in fcntl docs
In the fnctl docs for both python 2.3 and 2.4 there is a note at the bottom that says The os.open() function supports locking flags and is available on a wider variety of platforms than the lockf() and flock() functions, providing a more platform-independent file locking facility. however, in neither of those versions does os.open support any kind of mysterious locking flags, nor is there any reference in os to any kind of locking magic (nor do any C open()s I know of support any kind of locking semantics). The note seems bogus; am I missing something, or should it be elided? -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Are Linux users lemmings collectively jumping off of the cliff of reliable, well-engineered commercial software? -- Matt Welsh signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: finding/replacing a long binary pattern in a .bin file
On Wed, Jan 12, 2005 at 10:36:54PM -0800, yaipa wrote: What would be the common sense way of finding a binary pattern in a .bin file, say some 200 bytes, and replacing it with an updated pattern of the same length at the same offset? Also, the pattern can occur on any byte boundary in the file, so chunking through the code at 16 bytes a frame maybe a problem. The file itself isn't so large, maybe 32 kbytes is all and the need for speed is not so great, but the need for accuracy in the search/replacement is very important. ok, after having read the answers, I feel I must, once again, bring mmap into the discussion. It's not that I'm any kind of mmap expert, that I twirl mmaps for a living; in fact I barely have cause to use it in my work, but give me a break! this is the kind of thing mmap *shines* at! Let's say m is your mmap handle, a is the pattern you want to find, b is the pattern you want to replace, and n is the size of both a and b. You do this: p = m.find(a) m[p:p+n] = b and that is *it*. Ok, so getting m to be a mmap handle takes more work than open() (*) A *lot* more work, in fact, so maybe you're justified in not using it; some people can't afford the extra s = os.stat(fn).st_size m = mmap.mmap(f.fileno(), s) and now I'm all out of single-letter variables. *) why isn't mmap easier to use? I've never used it with something other than the file size as its second argument, and with its access argument in sync with open()'s second arg. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: If the aborigine drafted an IQ test, all of Western civilization would presumably flunk it. -- Stanley Garn signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Iteration over two sequences
Quite frequently, I find the need to iterate over two sequences at the same time, and I have a bit of a hard time finding a way to do this in a pythonic fashion. One example is a dot product. The straight-ahead C-like way of doing it would be: def dotproduct(a, b): psum = 0 for i in range(len(a)): psum += a[i]*b[i] return psum for this particular example, the most pythonic way is to do nothing at all, or, if you must call it dotproduct, from Numeric import dot as dotproduct -- http://mail.python.org/mailman/listinfo/python-list
Re: Iteration over two sequences
Downloading, installing, and getting to know numerical modules for Python is mext on my list :). However, I was under the impression that Numarray is preferred to Numeric -- is that correct? Are these two competing packages? (Hopefully this is not flame war bait...) Numeric's dot uses, if the appropriate libraries are installed, processor-tuned code (it tries to load blas, and an attempt to load blas will load atlas if present). Last time I checked numarray did not, and so Numeric's dot is (or was) faster than numarray's dot by an order of magnitude (and more, as the size of the array grew). -- http://mail.python.org/mailman/listinfo/python-list
Re: What strategy for random accession of records in massive FASTA file?
If you could help me figure out how to code a solution that won't be a resource whore, I'd be _very_ grateful. (I'd prefer to keep it in Python only, even though I know interaction with a relational database would provide the fastest method--the group I'm trying to write this for does not have access to a RDBMS.) You don't need a RDBMS; I'd put it in a DBM or CDB myself. -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing huge Sets() to disk
On Tue, Jan 11, 2005 at 12:33:42AM +0200, Simo Melenius wrote: John Lenton [EMAIL PROTECTED] writes: you probably want to look into building set-like objects ontop of tries, given the homogeneity of your language. You should see imrpovements both in size and speed. Ternary search trees give _much_ better space-efficiency compared to tries, at the expense of only slightly slower build and search time. This is especially essential as the OP mentioned he could have huge sets of data. hmm! sounds like *some*body needs to go read up on ternary trees, then. Ok, ok, I'm going... -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Fortune finishes the great quotations, #6 But, soft! What light through yonder window breaks? It's nothing, honey. Go back to sleep. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: fetching method names from a class, and the parameter list from a method
On Mon, Jan 10, 2005 at 08:29:40PM +0100, Philippe C. Martin wrote: Is this possible ? I am trying to have auto-completion working in a shell I wrote but I currently have the method lists done by hand (ie; if I add/subtract a method from that class, then my auto-completion is out of date). Same issue with method parameters. I have parsed through many of the attributes (ex: I use method.__doc__) but have not yet found a way to achieve the above goal. Is there a way? something like the following would be great: 1) list = Class.__methods__ 2) dict (because of default values: param = None) = Class.__method__[0].__params__ import inspect help(inspect) HTH -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: In Greene, New York, it is illegal to eat peanuts and walk backwards on the sidewalks when a concert is on. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: unicode mystery
On Mon, Jan 10, 2005 at 07:48:44PM -0800, Sean McIlroy wrote: I recently found out that unicode(\347, iso-8859-1) is the lowercase c-with-cedilla, so I set out to round up the unicode numbers of the extra characters you need for French, and I found them all just fine EXCEPT for the o-e ligature (oeuvre, etc). I examined the unicode characters from 0 to 900 without finding it; then I looked at www.unicode.org but the numbers I got there (0152 and 0153) didn't work. Can anybody put a help on me wrt this? (Do I need to give a different value for the second parameter, maybe?) isn't part of ISO 8859-1, so you can't get it that way. You can do one of u'\u0153' or, if you must, unicode(\305\223, utf-8) -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Lisp, Lisp, Lisp Machine, Lisp Machine is Fun. Lisp, Lisp, Lisp Machine, Fun for everyone. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: Writing huge Sets() to disk
you probably want to look into building set-like objects ontop of tries, given the homogeneity of your language. You should see imrpovements both in size and speed. -- http://mail.python.org/mailman/listinfo/python-list
Re: vga output
On Wed, Dec 29, 2004 at 07:57:53PM -0200, Gabriel Cosentino de Barros wrote: i'm writting an app to display images without X... i'm scared just to think about writting it in C... The hardware won't run X. and the CPU is very humble, around 20Mhz (and it must have fade outs). it run a minimalisc OpenBSD kernel. Anyone already did something similar and/or have any recomendations? svgalib should do what you want; I don't know if there are python bindings for it, but they should be pretty easy to make if not. -- John Lenton ([EMAIL PROTECTED]) -- Random fortune: Support wildlife -- vote for an orgy. signature.asc Description: Digital signature -- http://mail.python.org/mailman/listinfo/python-list
Re: consequences of not calling object.__init__?
in the code that follows, instances of E haven't been through D's rigorous initiation process .class C(object): .def __init__(self): .print C . .class D(object): .def __init__(self): .print D .super(D, self).__init__() . .class E(C, D): .def __init__(self): .print E .super(E, self).__init__() -- http://mail.python.org/mailman/listinfo/python-list