[ python-Bugs-494589 ] os.path.expandvars deletes things on w32

SourceForge.net noreply at sourceforge.net
Tue Jan 16 17:03:42 CET 2007

Bugs item #494589, was opened at 2001-12-18 15:29
Message generated for change (Comment added) made by sjoerd
You can respond by visiting: 

Please note that this message will contain a full copy of the comment thread,
including the initial issue submission, for this request,
not just the latest update.
Category: Python Library
Group: None
Status: Open
Resolution: Accepted
Priority: 5
Private: No
Submitted By: Michael McCandless (mikemccand)
Assigned to: Nobody/Anonymous (nobody)
Summary: os.path.expandvars deletes things on w32

Initial Comment:

Try this:

  import os.path
  print os.path.expandvars('foo$doesnotexist')

On FreeBSD, Python 2.1, I get:


But on WIN32, Python 2.1, I get:


The docs explicitly states that variables that are not 
found will be left in place ... but on win32 that 
appears to not be the case.


>Comment By: Sjoerd Mullender (sjoerd)
Date: 2007-01-16 17:03

Logged In: YES 
Originator: NO

I can check this in.  I'll try to create some tests.


Comment By: Guido van Rossum (gvanrossum)
Date: 2007-01-16 16:52

Logged In: YES 
Originator: NO

Oh, I forgot. It needs a unit test (preferably one that tests each xxpath
module on each platform).


Comment By: Guido van Rossum (gvanrossum)
Date: 2007-01-16 16:50

Logged In: YES 
Originator: NO

Looks good. Sjoerd, can you check that in yourself or did you give up your


Comment By: Sjoerd Mullender (sjoerd)
Date: 2007-01-16 12:42

Logged In: YES 
Originator: NO

I got bit by this today and saw there was a bug report of over 6 years
The patch is trivial, though.
The attached patch may not solve the problem that the various
implementations of expandvars are made exactly the same again, but it does
solve the problem that this implementation doesn't do what it promises in
the doc string.  It also solves the problem noted by Tim of two consecutive
non-existing variables being treated differently.
File Added: ntpath.patch


Comment By: Behrang Dadsetan (bdadsetan)
Date: 2003-06-22 15:45

Logged In: YES 

tim_one is right. There is plenty of dodgy things hiding
behind the os.path world, especially when it comes to

There are two problems here. 
- Mismatch in between the doc strings of the different
implementation of expandvars and the "official"
os.path.expandvars documentation.
- the ntpath and dospath implementations are buggy when
compared to their comments/docstrings.

About the first problem, the inconsistency created some time
ago in between the different implementations tasks makes it
difficult to choose a solution. Everyone will probably agree
that all the platform specific implementations of expandvars
should have the same functionality. The one that should be
taken over will probably need to be announced by the BDFL.

Some rule which should not have let this here happen, and on
which I believe we all will agree on:
Same interface=same documentation->same functionality

To implement either copy paste exactly the same expandvars
definition from one platform to another (NT, DOS, POSIX), or
somehow rather arrange that when there is no specific
implementation for the platform, a "default" python
implementation is used on the os.path level. To maximize the
fruits of my small work, I would of course prefer that the
version below becomes the standard and that the
documentation get updated.

To be complete, shall the documentation remain unchanged and
the implementation of dos and nt gets adapted (copied from
posix), the mac implementation could remain unchanged. But I
feel its docstring and its documentation should be in line
with the rest of the implementations.

So my view point-> same interface, same documentation

For the second problem - as of now a real bug whatever we
decide, I wrote within this comment (hereafter) a new
expandvars version which fits the docstring documentation of
dospath.py and the comments of ntpath.py. Sorry you will be
getting no patch from me at the moment since sourceforge's
anonymous CVS access does not like me. Please note that my
version borrows alot from the posixpath.py implementation
and my changes are the ones of a python amateur who is open
to critic.

#expandvars() implementation
_varprog = None
_findquotes = None
def expandvars(path):
    """Expand paths containing shell variable
    The following rules apply:
        - no expansion within single quotes
        - no escape character, except for '$$' which is
translated into '$'
        - ${varname} is accepted.
        - varnames can be made out of letters, digits and
the character '_'"""
    global _varprog, _findquotes
    if '$' not in path:
        return path
    if not _varprog:
        import re
        _varprog = re.compile(r'\$(\w+|\{[^}]*\}|\$)')
        _findquotes = re.compile("'.*?'")
    quoteareas = []
    i = 0
    while 1:
        quotearea = _findquotes.search(path, i)
        if not quotearea:
        (i, j) = quotearea.span(0)
        quoteareas.append((i, j))
        i = j
    i = 0
    while 1:
        m = _varprog.search(path, i)
        if not m:
        i, j = m.span(0)
        for (quotebegin, quoteend) in quoteareas:
            if quotebegin < i and quoteend > i:
        if insidequotes:
            i = j
        name = m.group(1)
        if name[:1] == '$':
            path = path[:i] + '$' + path[j:]
            i = i + 1
            if name[:1] == '{' and name[-1:] == '}':
                name = name[1:-1]
            if os.environ.has_key(name):
                tail = path[j:]
                path = path[:i] + os.environ[name]
                i = len(path)
                path = path + tail
                i = j
    return path


Comment By: Tim Peters (tim_one)
Date: 2001-12-19 07:56

Logged In: YES 

Another bug:  with two adjacent envars that do exist, only 
the first is expanded (on Windows):

>>> os.path.expandvars('$TMP$TMP')

Another bug:  the Windows expandvars doesn't expand envars 
in single quotes, but the posixpath flavor does:

>>> ntpath.expandvars("'$TMP'")
>>> posixpath.expandvars("'$TMP'")

Another bug:  $$ is an escape sequence (meaning a single $) 
on Windows but not on Unix:

>>> ntpath.expandvars('$$')
>>> posixpath.expandvars('$$')

Unassigning from me, as this is a bottomless pit spanning 
platforms and bristling with backward-compatibility traps 
no matter what's done about it.  Somebody who cares enough 
should write a PEPlet to sort out the mess, else I'd just 
leave it alone.


Comment By: Guido van Rossum (gvanrossum)
Date: 2001-12-18 15:43

Logged In: YES 

Hm, I do understand it, the code is broken (compared to the

No time to fix it.


Comment By: Guido van Rossum (gvanrossum)
Date: 2001-12-18 15:35

Logged In: YES 

Confirmed, also in 2.2. I don't understand it, the code
looks OK.


You can respond by visiting: 

More information about the Python-bugs-list mailing list