Re: PEP: Generalised String Coercion
hi, i guess that anyone reading this pep will agree that *something* must be done to the state of unicode affairs in python. there are zillions of modules out there that have str() scattered all over the place, and they all *break* on the first mention of düsseldorf... i'm not quite sure myself how to evolve python to make it grow from unicode-enabled to unicode-perfect, so for me some discussion would be a good thing. only two micro-remarks to the pep as it stands: 1) i dislike the naming of the function ``text()`` -- i´ve been using the word 'text' for a long time to mean 'some appropriate representation of character data', i.e. mostly something that would pass :: assert isinstance(x,basestring) i feel this is a fairly common way of defining the term, so to me a function `` text(x)`` should really * return its argument unaltered if it passes ``isinstance(x,basestring)``, * try to return spefically a unicode object (by using the ``x.__unicode__()`` method, where available) * or return an 8bit-string (from ``x.__repr__()`` or ``x.__str__()``) as discussed later on in the pep, it is conceivable to assign the functionality of the ``text()`` function of the pep to ``basestring`` -- that would make perfect sense to me (not sure whether that stands scrutiny in the big picture, tho). 2) really minor: somewhere near the beginning it says :: def text(obj): return '%s' % obj and the claim is that this "behaves as desired" except for unicode-issues, which is incorrect. the second line must read :: return '%s' % ( obj, ) or else it will fail if ``obj`` is a tuple that is not of length one. cheers, _wolf -- http://mail.python.org/mailman/listinfo/python-list
Re: Revised PEP 349: Allow str() to return unicode strings
neil, i just intended to worry that returning a unicode object from ``str()`` would break assumptions about the way that 'type definers' like ``str()``, ``int()``, ``float()`` and so on work, but i quickly realized that e.g. ``int()`` does return a long where appropriate! since the principle works there one may surmise it will also work for ``str()`` in the long run. one point i don't seem to understand right now is why it says in the function definition:: if type(s) is str or type(s) is unicode: ... instead of using ``isinstance()``. Testing for ``type()`` means that instances of derived classes (that may or may not change nothing or almost nothing to the underlying class) when passed to a function that uses ``str()`` will behave in a different way! isn't it more realistic and commonplace to assume that derivatives of a class do fulfill the requirements of the underlying class? -- which may turn out to be wrong! but still... the code as it stands means i have to remember that *in this special case only* (when deriving from ``unicode``), i have to add a ``__str__()`` method myself that simply returns ``self``. then of course, one could change ``unicode.__str__()`` to return ``self``, itself, which should work. but then, why so complicated? i suggest to change said line to:: if isinstance( s, ( str, unicode ) ): ... any objections? _wolf -- http://mail.python.org/mailman/listinfo/python-list
command line micro wiki written in Python
I've created a command line utility for managing text files. It's written in Python: https://github.com/paul-wolf/yewdoc-client It makes heavy use of the fantastic Click module by Armin Ronacher: http://click.pocoo.org/5/ This can be thought of in different ways: * A micro-wiki * A note-taking application * A file manager The key aspects are * Entirely command-line driven * Text documents only with a slight preference for Markdown * Make it easy to operate on documents without having to remember where they are or the exact names * Editor agnostic (vim, emacs, Sublime, Atom, etc.) Here's how to create a document: yd edit "shopping list" After editing, saving, closing, you can find again: ➜ yd ls -l shop 15981278 md 61 2017-01-20 12:15:43 shopping list While some people might gasp at the idea of a command line wiki, I find using the command line with a text editor like emacs the best workflow. I also like not having to worry about where a file of this kind is located. You can also use it to track configuration files: yd take ~/.emacs --symlink Now, I can edit this. Because it's a link to the actual file - having used the `--symlink` option, the configuration file will be updated: ➜ yd ls -l emacs 1c608cd7 md 113 2016-12-16 10:53:24 emacs ln 183a5b80 txt 5608 2017-01-15 12:59:39 /Users/paul/.emacs Using the cloud sync options lets me get my current config file wherever I am, completely up-to-date. For a more wiki-like experience, I can load all the documents with a common tag so: yd browse wolf This converts all the documents tagged with 'wolf' and loads them in a browser with a simple navigation sidebar. Convert a Markdown document called "Python3" to .odt: ➜ yd convert Python3 odt python3.odt There is an optional cloud syncronisation feature that connects to a specific endpoint, https://doc.yew.io: ➜ yd sync This requires registration at https://doc.yew.io, which can also be done via command line. But that is entirely optional. I'd be interested in feedback if there is any interest in using this kind of utility. I'll expose a python API so bulk operations can be done easily on the command line or via scripts. -- https://mail.python.org/mailman/listinfo/python-list
Re: command line micro wiki written in Python
On Tuesday, 31 January 2017 23:39:41 UTC, Ben Finney wrote: > The Python community has a stronger (?) preference for reStructuredText > format. Can that be the default? > > That is, I want my text files to be named ‘foo’ (no suffix) or ‘foo.txt’ > (because they're primarily text), and have the default be to parse them > as reStructuredText. Good point. It should at least be possible to provide an arbitrary default so you can have rst as default for new files. And perhaps as you say also start with rst as the main default. Regarding no suffix, whatever the default is gets used for newly created files, but not for the 'take' command which I use mainly to link to (with --symlink) config files, like: yd take ~/.emacs for instance. -- https://mail.python.org/mailman/listinfo/python-list
Template language for random string generation
This is a proposal with a working implementation for a random string generation template syntax for Python. `strgen` is a module for generating random strings in Python using a regex-like template language. Example: >>> from strgen import StringGenerator as SG >>> SG("[\l\d]{8:15}&[\d]&[\p]").render() u'F0vghTjKalf4^mGLk' The template ([\l\d]{8:15}&[\d]&[\p]) generates a string from 8 to 15 characters in length with letters, digits. It is guaranteed to have at least one digit (maybe more) and exactly one punctuation character. If you look at various forums, like Stackoverflow, on how to generate random strings with Python, especially for passwords and other hopefully secure tokens, you will see dozens of variations of this: >>> import random >>> import string >>> mypassword = ''.join(random.choice(string.ascii_uppercase + string.digits) for x in range(10)) There is nothing wrong with this (it's the right answer and is very fast), but it leads developers to constantly: * Use cryptographically weak methods * Forget that the above does not guarantee a result that includes the different classes of characters * Doesn't include variable length or minimum length output * It's a lot of typing and the resulting code is vastly different each time making it hard to understand what features were implemented, especially for those new to the language * You can extend the above to include whatever requirements you want, but it's a constant exercise in wheel reinvention that is extremely verbose, error prone and confusing for exactly the same purposes each time This application (generation of random strings for passwords, vouchers, secure ids, test data, etc.) is so general, it seems to beg for a general solution. So, why not have a standard way of expressing these using a simple template language? strgen: * Is far less verbose than commonly offered solutions * Trivial editing of the pattern lets you incorporate additional important features (variable length, minimum length, additional character classes, etc.) * Uses a pattern language superficially similar to regular expressions, so it's easy to learn * Uses SystemRandom class (if available, or falls back to Random) * Supports > 2.6 through 3.3 * Supports unicode * Uses a parse tree, so you can have complex - nested - expressions to do tricky data generation tasks, especially for test data generation In my opinion, it would make using Python for this application much easier and more consistent for very common requirements. The template language could easily be a cross-language standard like regex. You can `pip install strgen`. It's on Github: https://github.com/paul-wolf/strgen -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Friday, 8 August 2014 10:22:33 UTC+1, Chris Angelico wrote: > But I eyeballed your code, and I'm seeing a lot of > u'string' prefixes, which aren't supported on 3.0-3.2 (they were > reinstated in 3.3 as per PEP 414), so a more likely version set would > > be 2.6+, 3.3+. What's the actual version support? > ChrisA I'm going to have to assume you are right that I only tested on 3.3, skipping > 2.7 and < 3.3. I'll create an issue for that. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Friday, 8 August 2014 12:20:36 UTC+1, Ned Batchelder wrote: > On 8/8/14 5:42 AM, Paul Wolf wrote: > > Don't bother trying to support <=3.2. It will be far more difficult > > than it is worth in terms of adoption of the library. > > Also, you don't need to write a "proposal" for your library. You've > > written the library, and it's on PyPI. You aren't trying to add it to Thanks for that. I'll follow that advice. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Friday, 8 August 2014 12:29:09 UTC+1, Chris Angelico wrote: > Debian Wheezy can spin up a Python 3 from source anyway, and > > presumably ditto for any other Linux distro that's distributing 3.1 or > > 3.2; most other platforms should have a more modern Python available > > one way or another. > > > > ChrisA Yes, agreed. I'll update the version info. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Friday, 8 August 2014 23:03:18 UTC+1, Ian wrote: > On Fri, Aug 8, 2014 at 3:01 AM, Paul Wolf wrote: > > > * Uses SystemRandom class (if available, or falls back to Random) > A simple improvement would be to also allow the user to pass in a > Random object That is not a bad idea. I'll create an issue for it. It is a design goal to use the standard library within the implementation so users have a guarantee about exactly how the data is generated. But your suggestion is not inconsistent with that. > > Have you given any thought to adding a validation mode, where the user > provides a template and a string and wants to know if the string > matches the template? Isn't that what regular expressions are? Or do you have a clarifying use case? strgen is provided as the converse of regular expressions. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Sunday, 10 August 2014 13:43:04 UTC+1, Devin Jeanpierre wrote: > On Fri, Aug 8, 2014 at 2:01 AM, Paul Wolf wrote: > > > This is a proposal with a working implementation for a random string > > generation template syntax for Python. `strgen` is a module for generating > > random strings in Python using a regex-like template language. Example: > > > > > > >>> from strgen import StringGenerator as SG > > > >>> SG("[\l\d]{8:15}&[\d]&[\p]").render() > > > u'F0vghTjKalf4^mGLk' > > > > Why aren't you using regular expressions? I am all for conciseness, > > but using an existing format is so helpful... > > > > Unfortunately, the equivalent regexp probably looks like > > r'(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[a-zA-Z0-9]{8:15}' > > > > (I've been working on this kind of thing with regexps, but it's still > > incomplete.) > > > > > * Uses SystemRandom class (if available, or falls back to Random) > > > > This sounds cryptographically weak. Isn't the normal thing to do to > > use a cryptographic hash function to generate a pseudorandom sequence? > > > > Someone should write a cryptographically secure pseudorandom number > > generator library for Python. :( > > > > (I think OpenSSL comes with one, but then you can't choose the seed.) > > > > -- Devin > Why aren't you using regular expressions? I guess you answered your own question with your example: * No one will want to write that expression * The regex expression doesn't work anyway * The purpose of regex is just too different from the purpose of strgen The purpose of strgen is to make life easier for developers and provide benefits that get pushed downstream (to users of the software that gets produced with it). Adopting a syntax similar to regex is only necessary or useful to the extent it achieves that. I should also clarify that when I say the strgen template language is the converse of regular expressions, this is the case conceptually, not formally. Matching text strings is fundamentally different from producing randomized strings. For instance, a template language that validates the output would have to do frequency analysis. But that is getting too far off the purpose of strgen, although such a mechanism would certainly have its place. > This sounds cryptographically weak. Whether using SystemRandom is cryptographically weak is not something I'm taking up here. Someone already suggested allowing the class to accept a different random source provider. That's an excellent idea. I wanted to make sure strgen does whatever they would do anyway hand-coding using the Python Standard Library except vastly more flexible, easier to edit and shorter. strgen is two things: a proposed standard way of expressing a string generation specification that relies heavily on randomness and a wrapper around the standard library. I specifically did not want to try to write better cryptographic routines. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Sunday, 10 August 2014 17:47:48 UTC+1, Ian wrote: > On Sun, Aug 10, 2014 at 10:34 AM, Paul Wolf wrote: > > > For instance, a template language that validates the output would have to > > do frequency analysis. But that is getting too far off the purpose of > > strgen, although such a mechanism would certainly have its place. > > > > I don't think that would be necessary. The question being asked with > > validation is "can this string be generated from this template", not > > "is this string generated from this template with relatively high > > probability". Sorry, I meant frequency incidence within a produced string. And I understood Devin's point to be: For any given strgen expression that produces a set of strings, is there always a regex expression that captures the exact same set. And therefore is it not theoretically the case (leaving aside verbosity) that one of the syntaxes is superfluous (strgen). I think that is an entirely valid and interesting question. I'd have said before that it is not the case, but now I'm not so sure. I would still be sure that the strgen syntax is more fit for purpose for generating strings than regex on the basis of easy-of-use. -- https://mail.python.org/mailman/listinfo/python-list
Re: Template language for random string generation
On Sunday, 10 August 2014 17:31:01 UTC+1, Steven D'Aprano wrote: > Devin Jeanpierre wrote: > > > > > On Fri, Aug 8, 2014 at 2:01 AM, Paul Wolf wrote: > > >> This is a proposal with a working implementation for a random string > > >> generation template syntax for Python. `strgen` is a module for > > >> generating random strings in Python using a regex-like template language. > > >> Example: > > >> > > >> >>> from strgen import StringGenerator as SG > > >> >>> SG("[\l\d]{8:15}&[\d]&[\p]").render() > > >> u'F0vghTjKalf4^mGLk' > > > > > > Why aren't you using regular expressions? I am all for conciseness, > > > but using an existing format is so helpful... > > > > You've just answered your own question: > > > > > Unfortunately, the equivalent regexp probably looks like > > > r'(?=.*[0-9])(?=.*[A-Z])(?=.*[a-z])[a-zA-Z0-9]{8:15}' > > > > Apart from being needlessly verbose, regex syntax is not appropriate because > > it specifies too much, specifies too little, and specifies the wrong > > things. It specifies too much: regexes like ^ and $ are meaningless in this > > case. It specifies too little: there's no regex for the "shuffle operator". > > And it specifies the wrong things: regexes like (?= ...) as used in your > > example are for matching, not generating strings, and it isn't clear > > what "match any character but don't consume any of the string" means when > > generating strings. > > > > Personally, I think even the OP's specified language is too complex. For > > example, it supports literal text, but given the use-case (password > > generators) do we really want to support templates like "password[\d]"? I > > don't think so, and if somebody did, they can trivially say "password" + > > SG('[\d]').render(). > > > > Larry Wall (the creator of Perl) has stated that one of the mistakes with > > Perl's regular expression mini-language is that the Huffman coding is > > wrong. Common things should be short, uncommon things can afford to be > > longer. Since the most common thing for password generation is to specify > > character classes, they should be short, e.g. d rather than [\d] (one > > character versus four). > > > > The template given could potentially be simplified to: > > > > "(LD){8:15}&D&P" > > > > where the round brackets () are purely used for grouping. Character codes > > are specified by a single letter. (I use uppercase to avoid the problem > > that l & 1 look very similar. YMMV.) The model here is custom format codes > > from spreadsheets, which should be comfortable to anyone who is familiar > > with Excel or OpenOffice. If you insist on having the facility to including > > literal text in your templates, might I suggest: > > > > "'password'd" # Literal string "password", followed by a single digit. > > > > but personally I believe that for the use-case given, that's a mistake. > > > > Alternatively, date/time templates use two-character codes like %Y %m etc, > > which is better than > > > > > > > > > (I've been working on this kind of thing with regexps, but it's still > > > incomplete.) > > > > > >> * Uses SystemRandom class (if available, or falls back to Random) > > > > > > This sounds cryptographically weak. Isn't the normal thing to do to > > > use a cryptographic hash function to generate a pseudorandom sequence? > > > > I don't think that using a good, but not cryptographically-strong, random > > number generator to generate passwords is a serious vulnerability. What's > > your threat model? Attacks on passwords tend to be one of a very few: > > > > - dictionary attacks (including tables of common passwords and > > simple transformations of words, e.g. 'pas5w0d'); > > > > - brute force against short and weak passwords; > > > > - attacking the hash function used to store passwords (not the password > > itself), e.g. rainbow tables; > > > > - keyloggers or some other way of stealing the password (including > > phishing sites and the ever-popular "beat them with a lead pipe > > until they give up the password"); > &
Parsing data from pyserial
I'm trying to get data through my serial port from a CMUcam. This gizmo tracks a color and returns a packet of data. The packet has nine data points (well, really eight since the first point is just a packet header) separated by spaces as follows: M xxx xxx xxx xxx xxx xxx xxx xxx Here is the code I am using (python v24): import serial ser=serial.Serial('com1',baudrate=115200, bytesize=8, parity='N', stopbits=1,xonxoff=0, timeout=1) ser.write("PM 1") #This sets the CMUcam to poll mode for i in range(0,100,1): ser.write("TC 016 240 100 240 016 240\r\n") reading = ser.read(40) print reading components = reading.split() print components ser.close Here is an example output: M 37 79 3 4 59 124 86 25 ['59', '123', '87', '25', 'M', '37', '79', '3', '4', '59', '124', '86', '25', 'M '] M 38 77 3 2 59 124 86 25 ['39', '85', '26', 'M', '38', '77', '3', '2', '59', '124', '86', '25', 'M', '38' , '7'] My problem is that I am trying to get each data point of the packet into a separate variable. Ordinarily, this would be easy, as I would just parse the packet, read the array and assign each element to a variable eg. mx = components[1]. However, that doesn't work here because the original packet and the array that I got from using the split() method are different. If I were to try read the array created in the first example output, mx would be 123 instead of 37 like it is in the packet. In the second example, the array is 85 while the packet is 38. As near as I can figure out, pyserial is reading a stream of data and helpfully rearranging it so that it fits the original packet format M xxx xxx xxx xxx xxx xxx xxx xxx. I would have thought the split() method that I used on original packet (ie the "reading" variable) would have just returned an array with nine elements like the packet has. This is not the case, and I am at a loss about how to fix this. I've searched the archive here and elsewhere with no luck. Any help REALLY appreciated! Wolf :) Get your own "800" number Voicemail, fax, email, and a lot more http://www.ureach.com/reg/tag -- http://mail.python.org/mailman/listinfo/python-list
Parsing data from pyserial, an (inefficient) solution
I want to thank everybody who tried to help me, and also to post my solution, even though I dont think it is a very good one. Many of you correctly guessed that there was an \r included with the packet from the CUMcam, and you were correct. The actual format of the packet is: M xxx xxx xxx xxx xxx xxx xxx xxx\r. Unfortunately, splitting the packet using \r wouldnt help because the format of the data stream that I get with the components variable (after I split the reading file according to M) generally doesnt include a complete packet at first. For example, I get: [xxx xxx xxx\r, yyy yyy yyy yyy yyy yyy yyy yyy/r, zzz zzz zzz] Therefore, data from before the first \r (which I have shown as xxx) generally is incomplete and I need to go on to the second packet. Also, for those of you who suggested some kind of delay before reading the serial port, you were right. The first packet from the CMUcam is always a null. Anyway, here is my code: # This program reads a serial port hookup up to a CMUcam version 1. # It tracks the middle of a green object and provides a confidence estimate import serial ser=serial.Serial('com1',baudrate=115200, bytesize=8, parity='N', stopbits=1,xonxoff=0, timeout=1) ser.write("TC 016 240 100 240 016 240\r\n") #This line orders the CMUcam to track green reading = ser.read(40) # CMUcam's first data packet is null, so this line gets it out of the way for i in range(0,100,1): reading = ser.read(40) components = reading.split("M") components = components[1] if len(components) > 23: # If shorter than 24 it won't have enough data for a full packet subcomponents = components.split() mx = int(subcomponents[0]) my = int(subcomponents[1]) confidence = int(subcomponents[7]) print mx, my, confidence ser.close The really sad thing is that I get a perfectly constructed packet from the reading variable, and that gets butchered when I try to slice it up to pick out individual elements. Since pyserial doesnt do anything to rearrange the data, then the CMUcam must do the heavy lifting of extracting a perfect packet from the data stream. Its a real shame I couldnt use it because the program would be more efficient. FWIW, this code will analyze 2-3 frames per second on my computer, which is enough for my purposes. In case you couldnt tell from the questions/code, I am a total beginner, and I really appreciate this list. All I needed was a hand, not a handout. Wolves are willing to hunt for their supper. Get your own "800" number Voicemail, fax, email, and a lot more http://www.ureach.com/reg/tag -- http://mail.python.org/mailman/listinfo/python-list
Parsing data from pyserial (final resolution)
After going back and reading everybody's suggestions, I finally got a simple, efficient solution. As was pointed out to me in several posts, I needed to use readline rather than read. That's obvious to me now ... but isn't everything obvious once you understand it :) Anyway, I am posting my code on the (slim) chance that someone new to python and interested in robotics might find it useful: # # This program reads a serial port hookup up to a CMUcam1. # It tracks the middle of a green object and provides a confidence estimate import serial ser=serial.Serial('com1',baudrate=115200, bytesize=8, parity='N', stopbits=1,xonxoff=0, timeout=1) ser.write("TC 016 240 100 240 016 240\r\n") #This line orders the CMUcam to track green for i in range(0,100,1): reading = ser.readline(eol="\r") components = reading.split() mx = int(components[1]) my = int(components[2]) confidence = int(components[8]) print mx, my, confidence ser.close This code will read 5-6 frames per second, which should be plenty for most vision processing applications. Once again, I really want to thank those who took the time to help me. The good news is that I learned something from all my mistakes. Happy Hunting Wolf Get your own "800" number Voicemail, fax, email, and a lot more http://www.ureach.com/reg/tag -- http://mail.python.org/mailman/listinfo/python-list
Integrate JpegEnhancer in PSPX on XP
Hi all, I've read somewhere that any suitable program - exe file - could be run by a script in Paint Shop Pro on Windows XP/SP3. JpegEnhancer from www.vicman.net/jpegenhancer/ is a well known stand alone app. requiring to juggle an image between PSP and JpegEnhancer via HD - a extremely undesirable situation for very many reasons. If my assumption holds true, JpegEnhancer would rather behave just as an ordinary PSP python script, taking hold of the bitmap in RAM, doing its job and leaving the result in PSP smartly for further processing as required - including PSP' undo and redo. I had a look at http://docs.python.org/library/subprocess.html, but that's over my head by far. Is there a friendly person here in this Python domain, willing to supply a little know how for me and others to further our addiction to photography? Very many thanks in advance and kind regards - flowe -- http://mail.python.org/mailman/listinfo/python-list
For loop comprehensions
It occurred to me as I was writing a for loop that I would like to write it in generator comprehension syntax, eg. for a in b if c: rather than using one of the more verbose but allowable syntaxes: for a in (x for x in b if c): for a in b: if not c: continue Python 3.1 does not support "for comprehensions", and a few cursory searches of PEPs and this list don't turn up anything. I like the idea enough to suggest it though I'm unfamiliar with the PEP/feature request process (PEP 1 pointed me here). What do other people think? --Ben -- http://mail.python.org/mailman/listinfo/python-list
Re: For loop comprehensions
On Feb 11, 3:47 pm, Westley Martínez wrote: > No, too confusing. Then people'll want compound loops e.g.: > > for a in b if c while d else return x: > print('Ha ha I'm so clever!') On Feb 11, 6:34 pm, Steven D'Aprano wrote: > There's nothing wrong with writing > > for x in iterable: > if condition(x): > process(x) > > The existing syntax is clear and obvious. There's no clear benefit to > shifting the if clause to the for expression: it complicates the parser, > and any benefit (if any!) only applies to a tiny fraction of for loops. > You save one line, which is trivial. You may save one indentation level, > which might, sometimes, be useful, but more often will also be trivial. > If there's an advantage to the suggestion, it's small. My reasons for suggesting this are more to align for-loop syntax with generator expression/list comprehension syntax than to add completely new functionality to for-loops. I had observed that what I had typed initially before realizing it was incorrect: for a in b if c: f(a) was equivalent (and nearly syntactically so) to [f(a) for a in b if c] minus the generation of a list. I understand there are more verbose ways to accomplish the same goal (such as filter or multiple lines). But there are also more verbose ways to construct a list (such as filter or multiple lines). That is why I decided to suggest it. On Feb 11, 7:54 pm, Terry Reedy wrote: > Already proposed and rejected. See archives for python-ideas or the > gmane.comp.python.ideas mirror. Thanks for pointing me in the right direction, and sorry for bringing it up a third (if not more!) time. For posterity, http://groups.google.com/group/python-ideas/browse_thread/thread/87eee156ac2c3a24/61621e7779b5b255, and earlier, http://groups.google.com/group/python-ideas/browse_thread/thread/e2d076fe35ece873/862674672b4de683. The latter brings up a good point about parsing: how will we be sure after reading 'for a in b if c' whether this is a comprehension or whether (b if c) begins a ternary expression (and we should expect a 'else d' to follow). Well, my suggestion is to bring for-loop syntax in line with comprehension syntax, and: >>> [a for a in range(10) if False else [99]] SyntaxError: invalid syntax >>> [a for a in (range(10) if False else [99])] [99] >>> for a in range(10) if False else [99]: print(a) ... 99 So as it stands now in 3.1, comprehensions don't permit the ternary expression without parenthesizing it, but for-loops do. So my suggestion would have the side effect of requiring parentheses for that latter expression, as comprehensions do. :/ Thanks again, --Ben -- http://mail.python.org/mailman/listinfo/python-list