[Python-ideas] Curly braces expansion in shell-like matcher modules

Mathieu Bridon bochecha at fedoraproject.org
Tue Aug 17 21:39:27 CEST 2010


Hi,

On Tue, 2010-08-17 at 09:14 -0400, Fred Drake wrote:
> On Tue, Aug 17, 2010 at 9:03 AM, Antoine Pitrou <solipsis at pitrou.net> wrote:
> > IMO, fnmatch is the right place for such an enhancement.
> > (and, as the doc states, “glob uses fnmatch() to match pathname
> > segments”).
> 
> This is a good reason not to push the implementation down into glob,
> actually: the expansion may cross segment boundaries:
> 
>     for{bar/turtle,car/monkey}_test.*
> 
> should expand to the two patterns:
> 
>     foobar/turtle_test.*
>     foocar/monkey_test.*

Then I have the correct behavior with the attached patch against the
glob module. :)
(I still have to write some proper unit tests for it, this is only a
working proof of concept)

Note that I wrote this patch against the Python trunk, and tested it on
Python 2.5 (Windows XP) and Python 2.6 (Fedora 13). (I didn't have time
to actually build the Python trunk and run the unit tests yet)

To test it, I use the following dictionary where keys are the patterns I
want to try and values are the corresponding expected output.

d = {
        'foo.txt': 'foo.txt',
        'foo-{bar,baz}.txt': 'foo-bar.txt foo-baz.txt',
        'foo-{bar,baz-{toto,plouf}}.txt': 'foo-bar.txt foo-baz-plouf.txt
foo-baz-toto.txt',
        'foo-{bar,baz}-{toto,plouf}.txt': 'foo-bar-plouf.txt
foo-bar-toto.txt foo-baz-plouf.txt foo-baz-toto.txt',
        'foo-{}.txt': 'foo-{}.txt',
        'foo-{bar}.txt': 'foo-{bar}.txt',
        'foo-{bar.txt': 'foo-{bar.txt',
        'foo-bar}.txt': 'foo-bar}.txt',
        'foo-{bar{baz,plouf}.txt': 'foo-{barbaz.txt foo-{barplouf.txt',
        'foo-{bar,baz}-{toto}.txt': 'foo-bar-{toto}.txt
foo-baz-{toto}.txt',
        'foo-{bar,baz}-{toto.txt': 'foo-bar-{toto.txt
foo-baz-{toto.txt',
        'foo-{bar,baz}-toto}.txt': 'foo-bar-toto}.txt
foo-baz-toto}.txt',
        'tmp/foo.txt': 'tmp/foo.txt',
        'tmp/foo-{bar,baz}.txt': 'tmp/foo-bar.txt tmp/foo-baz.txt',
        'tmp/foo-{bar,baz-{toto,plouf}}.txt': 'tmp/foo-bar.txt
tmp/foo-baz-plouf.txt tmp/foo-baz-toto.txt',
        'tmp/foo-{bar,baz}-{toto,plouf}.txt': 'tmp/foo-bar-plouf.txt
tmp/foo-bar-toto.txt tmp/foo-baz-plouf.txt tmp/foo-baz-toto.txt',
        'tmp/foo-{}.txt': 'tmp/foo-{}.txt',
        'tmp/foo-{bar}.txt': 'tmp/foo-{bar}.txt',
        'tmp/foo-{bar.txt': 'tmp/foo-{bar.txt',
        'tmp/foo-bar}.txt': 'tmp/foo-bar}.txt',
        'tmp/foo-{bar{baz,plouf}.txt': 'tmp/foo-{barbaz.txt
tmp/foo-{barplouf.txt',
        'tmp/foo-{bar,baz}-{toto}.txt': 'tmp/foo-bar-{toto}.txt
tmp/foo-baz-{toto}.txt',
        'tmp/foo-{bar,baz}-{toto.txt': 'tmp/foo-bar-{toto.txt
tmp/foo-baz-{toto.txt',
        'tmp/foo-{bar,baz}-toto}.txt': 'tmp/foo-bar-toto}.txt
tmp/foo-baz-toto}.txt',
        '{tmp,tmp2}/foo.txt': 'tmp2/foo.txt tmp/foo.txt',
        '{tmp,tmp2}/foo-{bar,baz}.txt': 'tmp2/foo-bar.txt
tmp2/foo-baz.txt tmp/foo-bar.txt tmp/foo-baz.txt',
        '{tmp,tmp2}/foo-{bar,baz-{toto,plouf}}.txt': 'tmp2/foo-bar.txt
tmp2/foo-baz-plouf.txt tmp2/foo-baz-toto.txt tmp/foo-bar.txt
tmp/foo-baz-plouf.txt tmp/foo-baz-toto.txt',
        '{tmp,tmp2}/foo-{bar,baz}-{toto,plouf}.txt':
'tmp2/foo-bar-plouf.txt tmp2/foo-bar-toto.txt tmp2/foo-baz-plouf.txt
tmp2/foo-baz-toto.txt tmp/foo-bar-plouf.txt tmp/foo-bar-toto.txt
tmp/foo-baz-plouf.txt tmp/foo-baz-toto.txt',
        '{tmp,tmp2}/foo-{}.txt': 'tmp2/foo-{}.txt tmp/foo-{}.txt',
        '{tmp,tmp2}/foo-{bar}.txt': 'tmp2/foo-{bar}.txt
tmp/foo-{bar}.txt',
        '{tmp,tmp2}/foo-{bar.txt': 'tmp2/foo-{bar.txt tmp/foo-{bar.txt',
        '{tmp,tmp2}/foo-bar}.txt': 'tmp2/foo-bar}.txt tmp/foo-bar}.txt',
        '{tmp,tmp2}/foo-{bar{baz,plouf}.txt': 'tmp2/foo-{barbaz.txt
tmp2/foo-{barplouf.txt tmp/foo-{barbaz.txt tmp/foo-{barplouf.txt',
        '{tmp,tmp2}/foo-{bar,baz}-{toto}.txt': 'tmp2/foo-bar-{toto}.txt
tmp2/foo-baz-{toto}.txt tmp/foo-bar-{toto}.txt tmp/foo-baz-{toto}.txt',
        '{tmp,tmp2}/foo-{bar,baz}-{toto.txt': 'tmp2/foo-bar-{toto.txt
tmp2/foo-baz-{toto.txt tmp/foo-bar-{toto.txt tmp/foo-baz-{toto.txt',
        '{tmp,tmp2}/foo-{bar,baz}-toto}.txt': 'tmp2/foo-bar-toto}.txt
tmp2/foo-baz-toto}.txt tmp/foo-bar-toto}.txt tmp/foo-baz-toto}.txt',
        'tm{p/foo,p2/foo}.txt': 'tmp2/foo.txt tmp/foo.txt',
        'foo-bar*{txt,xml}': 'foo-bar-plouf.txt foo-bar-toto.txt
foo-bar-toto}.txt foo-bar-{toto.txt foo-bar-{toto}.txt foo-bar.txt
foo-bar}.txt',
        'foo?bar.{txt,xml}': 'foo-bar.txt',
        }

(note that those actually correspond to files I have in the current
folder so that they match)

Anyone can think about other interesting patterns involving braces?

Also, if the consensus is that glob is not the proper place, it would be
pretty straight-forward to do it in a module that would expand the
braces before calling glob on the resulting patterns.


-- 
Mathieu
-------------- next part --------------
A non-text attachment was scrubbed...
Name: glob-curly.patch
Type: text/x-patch
Size: 2414 bytes
Desc: not available
URL: <http://mail.python.org/pipermail/python-ideas/attachments/20100817/a9771d18/attachment.bin>


More information about the Python-ideas mailing list