classification
Title: Add os.symlink() and os.path.islink() support for Windows
Type: enhancement Stage: resolved
Components: Library (Lib), Windows Versions: Python 3.2, Python 2.7
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: brian.curtin Nosy List: amaury.forgeotdarc, asvetlov, brian.curtin, eric.smith, ggenellina, giampaolo.rodola, jafo, jason.coombs, lemburg, loewis, nnorwitz, pitrou, r.david.murray, sorin, swarren
Priority: normal Keywords: needs review, patch

Created on 2006-10-16 15:21 by lemburg, last changed 2010-07-22 18:46 by brian.curtin. This issue is now closed.

Files
File name Uploaded Description Edit
windows symlink draft 18.patch eric.smith, 2010-01-16 22:47
failures.txt brian.curtin, 2010-01-16 23:59
patch25results_python64.txt brian.curtin, 2010-02-10 04:20 output of test results
windows symlink draft 29.patch jason.coombs, 2010-04-08 19:06
repeat_test.py jason.coombs, 2010-04-09 00:27
admin results - no patch.zip jason.coombs, 2010-04-09 00:28
admin results - patch 29.zip jason.coombs, 2010-04-09 00:28
guest results - patch 29.zip jason.coombs, 2010-04-09 00:28
posix-failures.patch jason.coombs, 2010-07-09 12:39
Messages (125)
msg54926 - (view) Author: Marc-Andre Lemburg (lemburg) * (Python committer) Date: 2006-10-16 15:21
NTFS version 5.0 and up has all the needed APIs for
creating hard links and symlinks (junctions), so it
should be possible to add support for both hard links
and symlinks to the posixmodule.

Here are a few references:

http://schinagl.priv.at/nt/hardlinkshellext/hardlinkshellext.html
(see list of links at the end of the page)

http://www.codeproject.com/w2k/junctionpoints.asp
(junction points only, but includes analysis and source
code)

Note: NTFS 5.0 is supported in Win 2k, XP, 2003 and later.
msg54927 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2006-10-17 15:47
Logged In: YES 
user_id=21627

We shouldn't expose junctions as symlinks. Instead, Vista
will get real symlinks, so we should use that:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/fileio/fs/createsymboliclink.asp
msg54928 - (view) Author: Neal Norwitz (nnorwitz) * (Python committer) Date: 2007-03-16 06:50
Note a similar feature request which also contains a possible patch: 478407
msg56068 - (view) Author: Stephen Warren (swarren) Date: 2007-09-21 04:49
I'd say that junction points were a great way to expose this feature
under Win32 - after all, isn't it specifically what they were designed for?

Incidentally, at least one other application uses them for exactly this
purpose; a commercial source control tool named Accurev supports
checked-in symlinks on Windows as well as *nix etc.

The added advantage of junction points over whatever new API Vista
exposes is that it'll work on at least XP (maybe even Win2K?)
msg56073 - (view) Author: Sean Reifschneider (jafo) * (Python committer) Date: 2007-09-21 09:25
swarren: According to the wikipedi article on junction points:

   They can only be used on folders, not files.
   They are being replaced by symbolic links.

The latter I take to mean junction points are being phased out, but I
couldn't find any information one way or another on it.

http://en.wikipedia.org/wiki/NTFS_junction_point
msg56075 - (view) Author: Stephen Warren (swarren) Date: 2007-09-21 16:04
Hmm. I just tested Accurev - whatever it does, it works for files too.
That said, it could be making hard-links, which I guess could be different.

Additionally, the sysinternals "junction" utility doesn't find any
junction points when probing the link files.

I'll see if I can find out how they implemented it...
msg56078 - (view) Author: Stephen Warren (swarren) Date: 2007-09-21 18:03
It seems that Accurev uses junction points for directories, and
hard-links for files. That's probably a little to disparate to implement
in Python?

Also, I tried sysinternals' junction.exe and whilst it allows one to
create junction points that point at files, you can't actually read the
file via the junction point - so it does seem that they only work for
directories:-(

Oh well, lets hope whatever new Vista API exists works better...
msg56084 - (view) Author: Sean Reifschneider (jafo) * (Python committer) Date: 2007-09-21 23:39
If the file links are on the same volume, it's probably using hard
links.  Symbolic links can cross file-systems, of course.  So it sounds
like the Junction Points aren't going to work to replace symlinks, and
they'll be Vista only.
msg82476 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-02-19 14:55
I've implemented symlink() for Windows in jaraco.windows v1.0, just
uploaded to pypi (http://pypi.python.org/pypi/jaraco.windows/1.0).  It
creates symlinks, so only works in Windows 6 and later, but it's
available for those platforms.

Hopefully something like this can be included in future Python versions.
msg87493 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-09 12:43
If I produce a patch for Python 3.1, can this capability possibly be
included in the release?  Are there any objections to the implementation
as found in jaraco.windows?
msg87496 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-09 13:38
With 3.1b1 already released, most likely this is too late for 3.1
(unless there would be a second beta, which is currently not planned).
msg87519 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-10 10:37
I see now that symlink is defined in posixmodule.c (which ends up as the
builtin module 'nt').

Then, in os.py, there's a short section that does effectively 'from nt
import *'.

Would it be unreasonable for a patch to add a new Python module
(something like _nt_supplemental.py or platform_windows.py) which
exposes symlink() and islink(), and then in os.py to import those
functions into the os namespace at the same time as importing the
functions from the nt namespace?

My reasoning here is twofold:

1) I don't want to additionally complicate posixmodule.c, and since
Windows doesn't have a posix symlink function, this doesn't seem like
the appropriate place anyway.
2) I don't want to clutter os.py with os-specific code.

This brings up two questions.

1) Is there a problem with the os module exposing names that aren't in
posixmodule.c, but are platform-specific?  I suspect not, but I want to
consider the possibility.
2) Where would be a good location for the platform-specific pure-python
module?  If there's no guidance, I'll just pick something and it can be
relocated (as necessary) when the patch is applied.
msg87530 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-10 17:12
> Would it be unreasonable for a patch to add a new Python module
> (something like _nt_supplemental.py or platform_windows.py) which
> exposes symlink() and islink(), and then in os.py to import those
> functions into the os namespace at the same time as importing the
> functions from the nt namespace?

How would you provide access to the system functions in pure Python?
If you think of using ctypes, then yes, that would be unreasonable.

> 1) I don't want to additionally complicate posixmodule.c, and since
> Windows doesn't have a posix symlink function, this doesn't seem like
> the appropriate place anyway.

Don't worry about that. The purpose of posixmodule.c is to be
system-specific.

> 1) Is there a problem with the os module exposing names that aren't in
> posixmodule.c, but are platform-specific?  I suspect not, but I want to
> consider the possibility.

In general, the os module shouldn't expose any functions that are
platform-specific. That's the whole point of the os module.

People tend to access functions of the posix module that are specific
to POSIX through the os module, but it isn't really meant this way.

> 2) Where would be a good location for the platform-specific pure-python
> module?

See above. There can't be such a thing.
msg87532 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-10 17:52
> How would you provide access to the system functions in pure Python?
> If you think of using ctypes, then yes, that would be unreasonable.

Would you elaborate just a bit more on why a ctypes implementation would be 
undesirable?  "What's New" for Python 2.5 states that "Perhaps developers will 
begin to write Python wrappers atop a library accessed through ctypes instead 
of extension modules, now that ctypes is included with core Python."  I 
acknowledge that because we're talking about the core, the use of ctypes may 
be discouraged, but I have no strong reasons to think so.  I can see for 
consistency sake that it might be preferable to call the Windows C APIs 
directly, but that to me seems like unnecessary complication and maintenance 
trouble, whereas ctypes abstracts the exact same library calls in a 
compiler-agnostic way.  In my experience, ctypes has been invaluable providing 
robust and clean interfaces to otherwise unexposed APIs. As you can see in 
jaraco.windows.filesystem, I was able to implement link(), islink(), and 
symlink() in just a few dozen lines of Python.  It seems like unnecessary work 
to port this to CPython APIs surrounded by ifdefs and potentially introducing 
new compiler issues.

So, to be clear, I don't have the experience to assert that a ctypes 
implementation is a proper one, but I have little reason to think otherwise 
and would very much appreciate a little guidance on why I wouldn't want to use 
ctypes given the positive experiences I've had thus far.

> Don't worry about that. The purpose of posixmodule.c is to be
> system-specific.

After your answer, I suspect this will be the approach I'll take.

> In general, the os module shouldn't expose any functions that are
> platform-specific. That's the whole point of the os module.
>
> People tend to access functions of the posix module that are specific
> to POSIX through the os module, but it isn't really meant this way.

But isn't that the way to write future-proof portable code?  If one writes 
code that calls os.symlink, and a future version of Python supports symlink in 
Windows, then the library that calls os.symlink may just work in Windows 
without any rewrite.  Indeed, isn't that the primary purpose of the os module, 
to provide a unified interface to platform-specific implementations of the 
same behavior?
msg87533 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-10 17:53
> How would you provide access to the system functions in pure Python?
> If you think of using ctypes, then yes, that would be unreasonable.

Would you elaborate just a bit more on why a ctypes implementation would be
undesirable?  "What's New" for Python 2.5 states that "Perhaps developers will
begin to write Python wrappers atop a library accessed through ctypes instead
of extension modules, now that ctypes is included with core Python."  I
acknowledge that because we're talking about the core, the use of ctypes may
be discouraged, but I have no strong reasons to think so.  I can see for
consistency sake that it might be preferable to call the Windows C APIs
directly, but that to me seems like unnecessary complication and maintenance
trouble, whereas ctypes abstracts the exact same library calls in a
compiler-agnostic way.  In my experience, ctypes has been invaluable providing
robust and clean interfaces to otherwise unexposed APIs. As you can see in
jaraco.windows.filesystem, I was able to implement link(), islink(), and
symlink() in just a few dozen lines of Python.  It seems like unnecessary work
to port this to CPython APIs surrounded by ifdefs and potentially introducing
new compiler issues.

So, to be clear, I don't have the experience to assert that a ctypes
implementation is a proper one, but I have little reason to think otherwise
and would very much appreciate a little guidance on why I wouldn't want to use
ctypes given the positive experiences I've had thus far.

> Don't worry about that. The purpose of posixmodule.c is to be
> system-specific.

After your answer, I suspect this will be the approach I'll take.

> In general, the os module shouldn't expose any functions that are
> platform-specific. That's the whole point of the os module.
>
> People tend to access functions of the posix module that are specific
> to POSIX through the os module, but it isn't really meant this way.

But isn't that the way to write future-proof portable code?  If one writes
code that calls os.symlink, and a future version of Python supports symlink in
Windows, then the library that calls os.symlink may just work in Windows
without any rewrite.  Indeed, isn't that the primary purpose of the os module,
to provide a unified interface to platform-specific implementations of the
same behavior?
msg87534 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-10 18:14
> Would you elaborate just a bit more on why a ctypes implementation would be
> undesirable?

ctypes is inherently insecure. It must be possible to use Python itself
with ctypes removed. Therefore, there is a strict policy not to use
ctypes in the core.

>> People tend to access functions of the posix module that are specific
>> to POSIX through the os module, but it isn't really meant this way.
> 
> But isn't that the way to write future-proof portable code?  If one writes
> code that calls os.symlink, and a future version of Python supports symlink in
> Windows, then the library that calls os.symlink may just work in Windows
> without any rewrite.  Indeed, isn't that the primary purpose of the os module,
> to provide a unified interface to platform-specific implementations of the
> same behavior?

Correct - but for that to work, it should really only expose functions
that work on all systems. It currently fails to do so, allowing people
to write applications that they believe to be portable, but actually
aren't portable at all.

However, it has always been that way, so the added portability that the
os module provides is really minor. Instead, portability is already
provided in posixmodule.c
msg88030 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-18 12:50
I've improved the symlink support in jaraco.windows (SVN).  It now
implements the symlink check based on the technique suggested by the
MSDN docs.

I've begun to port this functionality to CPython.  I'm attaching a patch
against /branches/py3k that I believe will expose the a symlink function
on Windows systems.  I don't have an environment set up to compile
Python, so the patch hasn't even been checked for valid syntax.

I would appreciate if someone could review the patch and comment on the
technique.  I'm looking for confirmation that this is a reasonable
approach, or suggestions.

Implementing os.link will probably follow the same technique.

The implementation for ntpath.symlink will be incongruent to the posix
implementation, because it can't use lstat (which doesn't appear to
reflect the symlink flag).  Can ntpath call back into the os module
(where a islink could be defined for Windows systems)?
msg88050 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-18 20:29
> I would appreciate if someone could review the patch and comment on the
> technique.

There are a few minor issues; overall, it looks correct:
- the test for "this is windows" should just use MS_WINDOWS.
- don't declare variables in the middle of a block; we use C89.
- the argument parsing looks incorrect; take a look at rename()
  for guidance. Supporting bytes is optional; IMO, requiring
  Unicode strings for the API would be fine.

I don't quite understand why you can't implement lstat, or why
you would want to call into ntpath. Take a look at how stat()
is implemented in the nt module.
msg88179 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-22 04:21
Thanks very much for the tips Martin.

I cleaned up the function per your suggestions.  I also implemented
islink by setting two flags in st_mode if the file is a symlink.  The
implementation was a little convoluted, but it might just work.

The current patch does compile for me with just a few compiler warnings,
which I hope can be easily shaken out.

..\..\Modules\posixmodule.c(4794) : warning C4013: 'CreateSymbolicLink'
undefined; assuming extern returning int
..\..\Modules\posixmodule.c(4803) : warning C4133: 'function' :
incompatible types - from 'PyObject *' to 'char *'
..\..\Modules\posixmodule.c(7174) : warning C4113: 'PyObject *(__cdecl
*)(PyObject *,PyObject *,PyObject *)' differs in parameter lists from
'PyCFunction'

The first warning might be a problem.  I understand from the docs
(http://msdn.microsoft.com/en-us/library/aa363866.aspx) that all I need
to do is include windows.h, which is already included... but still the
function prototype isn't present.  This might be because a preprocessor
declaration of WINVER isn't set high enough... but since the same
executable is built for all versions of Windows, how is this reconciled
in the compiler?
msg88213 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-22 19:58
> The first warning might be a problem.  I understand from the docs
> (http://msdn.microsoft.com/en-us/library/aa363866.aspx) that all I need
> to do is include windows.h, which is already included... but still the
> function prototype isn't present.  This might be because a preprocessor
> declaration of WINVER isn't set high enough... but since the same
> executable is built for all versions of Windows, how is this reconciled
> in the compiler?

Good point. Unfortunately, backwards compatibility requires this to
be hackish. We currently strive for compatibility with Windows 2000,
so we cannot statically reference these functions (unless we increase
the minimum required Windows version - but we surely have to support XP
for many years to come).

So, in essence, you need to GetProcAddress. See other examples in
posixmodule.c for how this is done, and raise an exception
(NotImplementedError? WindowsError with ERROR_CALL_NOT_IMPLEMENTED
?) if you can't find the function.
msg88265 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-24 16:06
Thanks again Martin for the guidance.  It proved quite helpful in completing 
this patch.

This latest version (3) compiles and has been tested under Windows Vista and 
Windows XP and behaves as expected (with a NotImplemented error under XP).

I did find that I had to tweak the behavior of stat.S_ISLNK because my 
implementation of the st_mode bits for a symlink has different values than 
that of a posix call.  I don't fully understand the implications of my 
implementation.

An alternate implementation would be to have set_symlink_stat[AW] reset all of 
the st_mode flags except for 0o120000, to be consistent with what is returned 
by a posix stat call.  This approach doesn't seem quite right either.  I would 
appreciate a comment on this by someone more familiar with this type of 
problem.

Other than that issue, what else needs to be addressed to get this patch 
integrated into the 3.1 or 3.1.1 release?
msg88270 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-05-24 17:24
The patch (v3) looks technically correct, with two minor issues: perhaps
one should release the handle to kernel32 (not sure whether other code
does it, or whether it matters), and I would inline the two new
functions into their single callers.

That aside, I sense a bigger issue of getting stat/lstat correct. In the
presence of symbolic links, stat(2) is supposed to look at the file that
is being linked to, whereas lstat is supposed to look at the link
itself. Currently, lstat and stat do the same thing on Windows, as the
assumption was that there are no symbolic links, anyway (in which case
lstat does indeed return the same as stat always). This assumption is no
longer correct - so the two functions need to be separated.

I don't know what the most efficient way is to do a real stat() on Vista
- ideally, the Get* APIs would take a flag to follow links. If that
doesn't work, we would need to resolve the link ourselves, and look at
the file being referenced. Possible errors (on POSIX) for stat then are
ENOENT (broken symlink), ELOOP (symlink loop), ENOTDIR (path component
in symlink value is not a directory), and EACCESS (path component in
symlink, or target file is not accessible). This is just FYI; we should
raise the appropriate Win32 errors (and hopefully, we don't have to do
it ourselves, anyway).
msg88609 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-05-31 20:47
I've completed another draft patch.  This new one separates the
implementation of lstat and stat for windows, the latter which traverses
symlinks for the target.

I've tested this.  It compiles and runs under Windows Vista.  It works
correctly with file symlinks.  It fails to correctly detect that a
directory symlink is a symlink.  This is due to the fact that Windows
symlinks can also be directories, and the os.islink which calls
stat.S_ISLNK doesn't mask out the directory bit when checking for
symlinkness.

I see a few possible solutions:

1) Change S_ISLNK to mask of the directory bit when in Windows.
2) Change os.islink to perform a different test when in Windows.
3) Change the implementation of win32_lstat and win32_lstat_w to erase
the directory bit when the path is a link.

At first glance, option 3 seems the most promising, but it hides the
fact that Windows cares about the directoryness of a symlink.  It is
possible, for example, to have a "directory symlink" referring to a file
object in the file system.  S_ISDIR would be true for the symlink and
false for the target.

I think I'm going to implement approach 3 in a subsequent patch unless I
hear objections.

I also still need to implement Martin's two suggestions (release
kernel32 handle, inline functions).

But I wanted to share this patch for any suggestions.
msg88954 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-06-05 17:29
I've now completed all of the aforementioned tasks.

1) Kernel32 does not need to be freed.  It is not freed by other calls
after which this additional code was modeled.  Additionally, the MSDN
indicates that it should only be freed by the module that loaded the
handle (which is not this one).

2) Functions that could be made inline have been made inline.

3) The todo, detection of whether a symlink target is a directory, has
been implemented.

4) A unit test with three tests has been added.  This test has not been
integrated into the larger test suite, but must be run explicitly (for
now).  The unit test passes with no failures on Windows Vista as written.

Some issues still remain.

A) In general, there is a implementation mismatch between Posix and
Windows symlinks.  In particular, Windows maintains that a symlink is
either for a directory or for a file, regardless of the existence of the
target.  Posix instead treats all symlinks like (special) files but
determines the directory status based on the target.  This mismatch
causes more specific problems.

B) Existing unit tests in test_os.py are going to fail (and maybe
others).  In particular, they will fail because they attempt to remove
symlinks to directories using os.remove.  Windows expects the use of
os.rmdir for directory-like symlinks (that is, symlinks who's original
destination was a directory or who's target_is_directory was set to true
at the time it was created).  The unit test included with the patch
illustrates some of these nuances.

C) Because lstat hides the directory status of a symlink (i.e. clears
S_IFLNK), it is not always possible to determine whether a symlink
should be removed using os.remove or os.rmdir.  Specifically, if the
symlink has no target or a directory symlink references a file, the user
will only know to call os.rmdir when os.remove fails with a WindowsError.

I see these issues break down into two categories:

I) How to remove a symlink?
  (a) Should os.remove be rewritten to handle directory symlinks on
Windows?  This method would provide the best compatibility with existing
code.
  (b) Or, do we require python authors to manually determine which
method to call to remove a symlink?  This approach is less intrusive,
but really doesn't provide an effective solution, as it's only partly
compatible with Posix implementations.

II) How to detect a directory symlink?  In either case of (I), there
needs to be an implementation to detect directoryness of a symlink.
  (a) Create a new function in posixmodule that exposes the directory
bit of a symlink, perhaps "is_symlink_directory", which always returns
false except on Windows.
  (b) Change win_lstat to leave the S_IFDIR bit in tact and modify
S_ISLNK to ignore that bit.  Then is_symlink_directory becomes
S_ISDIR(lstat_mode) and S_ISLNK(lstat_mode).

Alternately, maybe trying to fit the Windows APIs into Posix
compatibility is the wrong approach.  Maybe instead there should be a
Python abstraction layer for symlink handling.  I think we're close with
the existing approach, but I'm somewhat worried that we will continue to
find edge cases that break because of the differences in assumptions
about the two implementations.

I think this is getting very close.  I appreciate all the help and support.
msg89017 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-06-06 21:10
In the interest of expediency, I've implemented I.(a): specifically,
I've put a wrapper around DeleteFileW to check if the target is a
directory-symlink, and if it is, call RemoveDirectory instead.  I've
updated the test case to reflect this behavior.  Patch draft 6 includes
these changes.

Is there anything else that needs to be addressed before this can be merged?
msg90677 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-07-18 14:03
Now that Python 3.1 is released, can we talk about integrating this into
the 3.1.1 release?
msg90679 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2009-07-18 14:43
Standard policy is that new features only go into the next version (3.2
in this case).  3.1 will only get bug fixes now that it has been released.
msg90686 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-07-18 17:13
In many ways, this is a bug fix and not a new feature.  os.islink is
already in the ntpath module, but simply doesn't perform its intended
purpose. Similarly, os.symlink exists and is defined for unix platforms,
but is just absent on the Windows platform.  In other words, this patch
doesn't implement new features, but simply expands the platform support
for existing features.  Therefore, I believe this is a strong candidate
for a 3.1.1 target.

That said, if the maintainers would prefer to defer this capability to
3.2, then I would like to move forward with that effort.

Whatever the recommended approach, this effort is ready to move onto the
next step.
msg90687 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2009-07-18 17:38
I'm inclined to agree with you.
msg91700 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-08-18 15:15
Can this fix be considered for inclusion in 3.1.2?
msg91804 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-08-21 06:55
> Can this fix be considered for inclusion in 3.1.2?

I don't think it should be integrated into 3.1. It *is* a new feature.
msg91820 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-08-21 12:11
In that case, what needs to be done to integrate it into 3.2?
msg92171 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-09-02 15:48
I plan to look at this, and if it looks okay, commit it. Let me know if
anyone has any remaining issues.
msg92176 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-09-02 18:50
> I plan to look at this, and if it looks okay, commit it. Let me know if
> anyone has any remaining issues.

I have the general issue that the semantics of the Windows symlink
implementation are ill-defined. Specifically for the patch, I think
precise documentation of the implemented behavior is is missing (unless
it behaves like Unix symlink to the tiniest detail, which I doubt).
Without an exact specification of what it should do it is difficult
to tell whether it does that correctly.
msg92178 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-02 20:18
The deviance between the Unix and Windows symlink functions is apparent
in the signature, though not explicitly-defined in any formal
documentation.  Perhaps the following could be included as formal
documentation.  Should this documentation be added to os.rst, or would
another place be better?

The Windows version takes an additional, optional parameter,
target_is_directory, which defaults to False.

On Windows, a symlink represents a file or a directory, and does not
morph to the target dynamically.  For this reason, when creating a
symlink on Windows, if the target is not already present, the symlink
will default to being a file symlink.  If target_is_directory is set to
True, the symlink will be created as a directory symlink.  This
parameter is ignored if the target exists (and the symlink is created
with the same type as the target).
msg92182 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2009-09-02 20:38
> Should this documentation be added to os.rst, or would
> another place be better?

Definitely the current documentation of these APIs, yes.
The parameter should appear in the signature also, with then
the remark that it works Windows only.

There should also be a versionchanged markup.

I think there are also effects on stat/lstat, IIRC; if so,
they should be documented as well. If there are now differences,
ISTM that you can't find out whether a link is a directory symlink;
if so, *that* should be documented.
msg92277 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-05 14:59
I've made two subsequent patches. I found after reading the symlink
documentation that I had gotten the parameters mixed up.

This patch, tagged r4274, addresses that issue.
msg92278 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-05 15:01
This second patch adds the documentation to os.rst to formally define
the behavior of the symlink function in Windows. Only changes needed to
be made to the lstat and symlink functions.  readlink remains Unix-only.
We may consider implementing this method for Windows as well at a later
date.
msg92288 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-05 18:07
After a short time and some more learning about Mercurial, I discovered
how to rebase my local repository and create a new unified diff against
the latest py3k branch.  This latest patch (7) supercedes all previous
patches.

I hope this patch is suitable for painless merging into the py3k branch.

Eric, please let me know if you encounter any trouble merging it.
msg92411 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2009-09-08 08:57
Your patch re-adds the compatibility code with Windows 95
(unicode_file_names, check_gfax...), which has been removed two months
ago, see r73603 and r73675. Please remove it!
msg92413 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-08 11:19
Indeed. I see that now. I'll track down how that happened and see that we 
avoid regression.

> Amaury Forgeot d'Arc <amauryfa@gmail.com> added the comment:
>
> Your patch re-adds the compatibility code with Windows 95
> (unicode_file_names, check_gfax...), which has been removed two months
> ago, see r73603 and r73675. Please remove it!
msg92509 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-11 14:03
Just when I was starting to feel comfortable using Hg, this happens. It
appears that between my inexperience with Hg and the non-intuitive
TortoiseHg rebase merge tool, many of the changes I made to
posixmodule.c were lost and as amaury.forgeotdarc remarked, other
commits were reverted.

This means that except for the patches in this ticket, I've lost the
revision history for this work. No biggie.

I've rebuilt the patch from scratch (still against the old code base).
I'm including it here for posterity as draft 8. I'll be attempting once
again to rebase it against the parent's tip. Stay tuned.
msg92513 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-09-11 17:39
After only a few hours of fighting with Hg and gnashing of teeth, I've
merged the patch with the head of the SVN py3k branch.  I'm attaching
this as draft 9. This patch was created with Subversion and should be
suitable for easy merging.

I've compiled and tested the patched code and the three tests in
test_win_symlink.py all pass.

Please let me know if there's anything more I can do to help move this
forward.
msg93847 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-11 01:57
Thanks to some hints by eric.smith, I've run the regression tests with
this patch applied. It turns out there are still some outstanding issues
with draft 9.

One issue was in test_glob.py where broken symlinks would fail to be
matched by glob. This was due to the fact that lexists still needed to
be implemented in ntpath.py. Draft 10 includes this capability.

Another problem the regression tests elicited is more insidious. The
patch breaks test_os.test_1686475, which references issue1686475. The
new symlink-aware stat must traverse symlinks. Unfortunately, the
current method of resolving the symlink target (as recommended by
Microsoft) fails to work if the symlink target is in use (or otherwise a
handle cannot be obtained). Unfortunately, it's not possible to call
GetFinalPathNameByHandle without a handle, the same way as issue1686475
was addressed by using a different API call.

I'm still devising a workaround for this undesirable behavior, but I
wanted to report that progress is still being made and I wanted to
capture the intermediate patch for posterity.

Stay tuned for more info.
msg94395 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-23 22:08
After some in-depth analysis, I determined the following:

1) The new symlink-aware os.stat has to find the target of a symlink to
properly function.
2) The previously-proposed patch uses GetFilenameByHandle in os.stat to
find the target, but this fails when a handle can't be obtained (such as
when a symlink points to pagefile.sys.
3) Explorer doesn't use GetFilenameByHandle. I used ProcMon to monitor
the API calls when it looks up the properties for a symlink to
pagefile.sys. It appears to use CreateFile and DeviceIoControl to trace
through the symlink chain.

So, I've written a proof of concept that determines a symlink target
using these API calls. The code is in jaraco.windows.filesystem at
https://svn.jaraco.com/jaraco/python/jaraco.windows/jaraco/windows/filesystem.py:trace_symlink_target
.  For convenience, I've pasted the most relevant code segments at
http://paste.turbogears.org/paste/122986 .

I'd like to get comments on this implementation before porting this to
the C code and adding it to the os.stat call. One of the aspects that
makes me uncomfortable is the fact that I have to call relpath between
each iteration.

I have tested this approach fairly thoroughly. It appears to work under
all circumstances (through multiple symlinks across drives and
ultimately pointing at pagefile.sys).

If no one can suggest a better approach, I plan to code this into the patch.
msg94470 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-26 01:29
This new version of the patch provides a workaround for the issue1686475
regression. It simply falls back to the traditional (symlink-naive) stat
behavior when a handle cannot be obtained for the specified filename. 
My intention is that we can commit this patch (as it's still a strict
improvement over the previous behavior), and work out a fully-symlink
aware stat method in a subsequent patch.

There are still regression tests in test_posixpath.py that are failing
due to the non-implementation of realpath. I'll tackle this task next.
msg94498 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-26 18:22
This latest patch (12) adds os.readlink(). Unfortunately, this causes
more tests in test_posixpath.py to break. I'll continue to investigate.
msg94517 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-26 21:46
This latest patch (13) addresses the regressions in test_posixpath.py by
repeating a technique found in the new lstat. That is, if a handle can't
be obtained for GetFinalPathNameByHandle (because the target is in use),
it is assumed that the target does in fact exist and the attributes are
retrieved from the parent directory.
msg94522 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-26 22:12
The problem I'm encountering now is tests for posixpath.realpath are
failing on Windows. These tests were previously skipped under Windows
because there was no os.symlink. Now that Windows has os.symlink, these
regression tests fail (test_realpath_basic,
test_realpath_resolve_before_normalizing, test_realpath_resolve_first,
and test_realpath_resolve_parent).

What is the correct fix for this? Should posixpath.realpath work on
Windows? If not, should the tests just be ignored under Windows?
Otherwise, should posixpath.realpath be rewritten to be robust under
both operating systems? Or is there another approach?
msg94573 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-27 19:00
This latest patch (14) makes one minor change over the previous -
updates the documentation to include "Availability: Windows" for readlink.
msg94643 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-10-29 00:59
This patch (15) implements ntpath.samefile, which corrects the
regression in test_shutil.

By my tests, this corrects all regressions caused by this patch except
for those in test_posixpath.py previously mentioned. I believe these
failing tests are due to the fact that posixpath tests are inappropriate
on the Windows platform.

I propose we integrate this patch so it can have time to get feedback
from the community.
msg95368 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-11-17 08:47
When building on XP with "windows symlink draft 15.patch", I get:

Build started: Project: _hashlib, Configuration: Release|Win32
Performing Pre-Build Event...
Found a working perl at 'c:\opt\cygwin\bin\perl.exe'
Found an SSL directory at '..\..\openssl-0.9.8g'
Traceback (most recent call last):
  File "build_ssl.py", line 258, in <module>
    main()
  File "build_ssl.py", line 241, in main
    shutil.copy(r"crypto\buildinf_%s.h" % arch, r"crypto\buildinf.h")
  File "C:\home\eric\python\py3k\lib\shutil.py", line 102, in copy
    copyfile(src, dst)
  File "C:\home\eric\python\py3k\lib\shutil.py", line 50, in copyfile
    if _samefile(src, dst):
  File "C:\home\eric\python\py3k\lib\shutil.py", line 40, in _samefile
    return os.path.samefile(src, dst)
  File "C:\home\eric\python\py3k\lib\ntpath.py", line 635, in samefile
    return _getfinalpathname(f1) == _getfinalpathname(f2)
NotImplementedError: GetFinalPathNameByHandle not available on this platform
Project : error PRJ0019: A tool returned an error code from "Performing
Pre-Build Event..."
Build log was saved at
"file://C:\home\eric\python\py3k\PCbuild\Win32-temp-Release\_hashlib\BuildLog
.htm"
_hashlib - 1 error(s), 0 warning(s)
msg95757 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-11-27 01:40
Thanks Eric for the report. I had tested earlier on XP, but didn't do so
with the latest changes. It appears that a couple of modules didn't
behave well under XP. The latest patch (16) addresses these issues. In
particular, many tests use the presence of os.symlink to presume
symbolic link support, but under Windows XP, os.symlink exists but
raises a NotImplementedError when called. To address this, I added
test.support.has_symlink function which can be used to determine whether
the OS has symlink support (and not just a symlink function).

This raises the issue that it might be worthwhile to remove the symlink
and readlink methods at the os module init time if symlinks aren't
supported on the OS.

For now, this implementation should be adequate to move forward.
msg96015 - (view) Author: Andrew Svetlov (asvetlov) * (Python committer) Date: 2009-12-06 01:34
Jason, as I see you implemented os.samefile (actually ntpath.samefile) 
but  os.sameopenfile is still not implemented.

Looks like it's easy to do: while GetFinalPathNameByHandle already 
accept file handle you can use CRT function _get_osfhandle(fd) to 
convert file descriptors (arguments for sameopenfile) to file handles 
and pass it to GetFinalPathNameByHandle.

For me samefile and sameopenfile has very close semantic and I like to 
see both if it's possible.

Thanks.
msg96545 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-12-18 00:48
I apologize (again) Jason, for taking forever to move forward on this.

With patch 16 on XP, I get this error on test_platform:

======================================================================
ERROR: test_architecture_via_symlink (__main__.PlatformTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "Lib/test/test_platform.py", line 22, in
test_architecture_via_symlink
    os.symlink(real, link)
NotImplementedError: CreateSymbolicLinkW not found

----------------------------------------------------------------------
Ran 18 tests in 0.047s

FAILED (errors=1)
Traceback (most recent call last):
  File "Lib/test/test_platform.py", line 204, in <module>
    test_main()
  File "Lib/test/test_platform.py", line 200, in test_main
    PlatformTest
  File "c:\home\eric\python\py3k\lib\test\support.py", line 919, in
run_unittest
    _run_suite(suite)
  File "c:\home\eric\python\py3k\lib\test\support.py", line 902, in
_run_suite
    raise TestFailed(err)
test.support.TestFailed: Traceback (most recent call last):
  File "Lib/test/test_platform.py", line 22, in
test_architecture_via_symlink
    os.symlink(real, link)
NotImplementedError: CreateSymbolicLinkW not found

I'll try to spend some time tracking it down over the weekend, but feel
free to look it over.
msg96656 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-12-20 00:14
This attached patch addresses the issue Eric mentioned - I don't know
how I missed this before. I will attempt to run the tests on XP again
with this change, but have not yet done so.
msg96797 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2009-12-22 13:57
With patch 17 all tests pass on XP. I'm (still) working on getting a
Windows 7 environment to test there.
msg96823 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-12-23 01:00
Andrew, thanks for pointing out the apparent mismatch of having
ntpath.samefile but not ntpath.sameopenfile. Since this behavior doesn't
immediately affect the support of os.symlink, I've created a separate
issue, issue7566, to track that effort.
msg96824 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2009-12-23 01:02
Eric: That's great news. I was gearing up to test myself to see if I
could reproduce the issue, but I'm glad it works since you beat me to
it. Let me know if it would help to provide a Windows 7 VMWare Player
virtual machine.
msg97870 - (view) Author: sorin (sorin) Date: 2010-01-16 11:06
If you could provide a build I could run the tests on Windows 7 x64. 

This is a very old bug that I would like to see it solved.
msg97913 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-01-16 22:01
Most of the patch is outdated, but I could check out an updated patch on my Win7 64 machine.
msg97916 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-01-16 22:47
I don't see where the patch is outdated.

I'm attaching an updated patch 18 that works cleanly against r77557. It also fixes an unterminated comment.

XP runs correctly (without the new functionality) with this patch. However, on Windows 7 as a normal user I get a permission issue:

Python 3.2a0 (py3k, Jan 16 2010, 17:26:22) [MSC v.1500 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> os.symlink('python.exe', 'python-test.exe')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
WindowsError: [Error 1314] A required privilege is not held by the client: 'python.exe'

This is in a directory that I own, with a file that I own.

Jason: Is there something obvious that I'm missing? Or is some special (not out-of-the-box) permission really required?
msg97923 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-01-16 23:59
I'm getting failures in test_glob, test_os, test_platform, test_posixpath, test_shutil, and test_tarfile. failures.txt is attached with the results I see on Win 7 with a 64 bit build.

I'm not seeing the exception Eric saw. That worked for me as both an admin and regular user.
msg97924 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 00:01
I haven't seen this error. My first guess is its a regression due to  
win 7 or updates to the python code. I'll look into it.

Sent from my comm

On Jan 16, 2010, at 17:47, "Eric Smith" <report@bugs.python.org> wrote:

>
> Eric Smith <eric@trueblade.com> added the comment:
>
> I don't see where the patch is outdated.
>
> I'm attaching an updated patch 18 that works cleanly against r77557.  
> It also fixes an unterminated comment.
>
> XP runs correctly (without the new functionality) with this patch.  
> However, on Windows 7 as a normal user I get a permission issue:
>
> Python 3.2a0 (py3k, Jan 16 2010, 17:26:22) [MSC v.1500 32 bit  
> (Intel)] on win32
> Type "help", "copyright", "credits" or "license" for more information.
>>>> import os
>>>> os.symlink('python.exe', 'python-test.exe')
> Traceback (most recent call last):
>  File "<stdin>", line 1, in <module>
> WindowsError: [Error 1314] A required privilege is not held by the  
> client: 'python.exe'
>
> This is in a directory that I own, with a file that I own.
>
> Jason: Is there something obvious that I'm missing? Or is some  
> special (not out-of-the-box) permission really required?
>
> ----------
> Added file: http://bugs.python.org/file15921/windows symlink draft  
> 18.patch
>
> _______________________________________
> Python tracker <report@bugs.python.org>
> <http://bugs.python.org/issue1578269>
> _______________________________________
msg97978 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 21:42
Eric: I'm guessing the error you're seeing might be due to a UAC issue (http://en.wikipedia.org/wiki/User_Account_Control). I've been developing with UAC disabled (because working with the command-line in a UAC environment is a bit**).

Can you confirm that you're running your python.exe with Administrative privileges (and not just an Administrators account that's been demoted)? If you're launching Python.exe from a command-prompt, you may want to launch the prompt with "Run as Administrator".

I'm hoping that will straighten out this permission issue. I look forward to your reply.
msg97979 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 21:44
Brian: That's interesting. Many of those failures look very much like failures I've encountered and fixed, though I have been developing in a 32-bit environment. I'll run the tests on my 64-bit system and see if I can replicate.
msg97980 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-01-17 22:16
Yes, "Run as administrator" solves the permissions problem, leaving an error in test_posixpath that I'll investigate.

What's the expectations with the buildbots? Will these tests work there? We could create a branch and run a buildbot test if need be.

It would probably be best to find a way to skip these tests if they would fail with a permissions error.
msg97981 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 22:26
Brian: I applied the draft 18 patch to the latest version of /branches/py3k (77592). I compiled the release x64 build and ran a few tests using the following syntax:

PS C:\Users\jaraco\projects\public\python-core-py3k> .\pcbuild\amd64\python .\lib\test\test_glob.py

I found one failure in test_platform and 6 failures in test_posixpath, but no failures in the other modules you mentioned. Also, the failure in test_posixpath I'm seeing is different in nature from what you failure report indicates.

Can you reconsider if you may have missed some detail of the patch, as I seem to be unable to recreate the bulk of the issues you encountered. It seems Eric and I are getting similar results. I'm attaching the failures output from the tests as I encountered them.
msg97982 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-01-17 22:28
I'm indeed seeing the same test_posixpath errors that Jason reported.
msg97983 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 22:30
Eric: The failures I'm seeing in test_posixpath indicate that realpath isn't working properly. Are you getting the same results?

As for the buildbot issue - I'm unfamiliar with the buildbot configuration. I think it would be worth creating the branch and letting the buildbot attempt the tests and see what things fail.

Let me see if I can track down the realpath and test_platform issues and devise a resolution.
msg97984 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-17 22:49
This new patch (draft 19) addresses the outstanding test failures in test_posixpath.py and test_platform.py (by essentially disabling tests that were previously-disabled but became enabled on Windows by adding symlink support).
msg97988 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-18 04:25
I've confirmed that in fact a security policy permission is required to create a symbolic link, and that by default, that permission is only granted to administrators (see http://en.wikipedia.org/wiki/Symbolic_link#Windows_Vista_symbolic_link). Given this finding, I hope the buildbot can run the symlink tests as administrator.
msg97990 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-01-18 05:39
The buildslaves most definitely will *not* execute any code under administrator privileges; doing so would put the machine under a serious threat.

The tests should be skipped if the privilege is not held; it may be reasonable to grant the privilege to the account the build slave runs under.

I'd appreciate if some piece of text explained how the privilege can be activated, other than invoking "run as administrator".
msg98001 - (view) Author: sorin (sorin) Date: 2010-01-18 11:20
Maybe it's useful to know that Administrator privileges are not required in order be able to create symlinks. You just need a specific permission that by default is assigned only to Administrators.

How to set SeCreateSymbolicLinkPrivilege on Windows Vista or newer:
http://stackoverflow.com/questions/815472/how-do-i-grant-secreatesymboliclink-on-windows-vista-home-edition/2085468#2085468
msg98013 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-18 13:56
When I consider that the buildslaves are probably donated and not designated exclusively for Python testing, it makes good sense that they typically run under a restricted account.

Given that there is a specific permission that can be assigned to the buildslave user, it seems appropriate that the tests that attempt to create symlinks should fail if the user does not have that permission.

Martin, do you still prefer something that wraps tests that call symlink and only executes those tests if the current user context has that permission?
msg98014 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-01-18 14:31
You could use the test skipping functionality present in trunk and beyond. Write a function to test whether the user has the necessary privileges, then use @unittest.skipUnless(has_admin_privs(), "can't test as regular user")
msg98015 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-18 14:35
Great suggestion. I'll do that.
msg98016 - (view) Author: sorin (sorin) Date: 2010-01-18 14:40
BTW, Is there any hope to add this to Python 2.6? - this is the standard on Windows and I see this issue more like a bug resolution than a new feature ;)
msg98017 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-01-18 14:42
No, it won't be backported to 2.6. It's clearly a new feature.
msg98018 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-01-18 14:44
My concern about testing is that we're adding a feature that won't be tested by the buildbots. Although I don't have any suggestions (other than possibly adding the specific permission to the buildbots).

If there is a skip test, it should be dependent on the specific permission required. That is, it shouldn't test if the user is an administrator, it should test if the user has the permission to create links.
msg98019 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-18 14:44
If you want support for symlinks in Python 2.6, see 
http://pypi.python.org/pypi/jaraco.windows . It even has a method to monkey 
patch the os module to provide forward compatibility to the 3.2 functionality.
msg98020 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-18 14:46
Eric: I concur. The function to skip tests will test for the presence of the 
particular permission.
msg98029 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-01-18 20:28
> Given that there is a specific permission that can be assigned to the
> buildslave user, it seems appropriate that the tests that attempt to
> create symlinks should fail if the user does not have that
> permission.

No, the test should *not* fail. A failing test means "the test has
completed, and the outcome was not expected, due to a bug somewhere
(the operating system, Python, or the test case proper)". This is not
the case if the link cannot be created - the resulting behavior is
exactly the correct, and expected one (under the circumstances).

> Martin, do you still prefer something that wraps tests that call
> symlink and only executes those tests if the current user context has
> that permission?

Most definitely. That's what the notion of a "skipped" test is for
(as opposed to a "failed" one).
msg98030 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-01-18 20:33
> If there is a skip test, it should be dependent on the specific permission required.

Terminology: it's a "privilege", not a "permission". Permissions (in
Windows) are stored in ACLs on objects, granted by the owner of the
object. Privileges are held by users, granted by the system
administrator.
msg98063 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-19 16:47
I'm currently struggling with determining if the host process has the appropriate privileges. I'm stuck in that I've enumerated the privileges for an admin account, but the SeCreateSymbolicLink privilege is not present. I guess it's inherited. If you have any suggestions for determining access, please consider posting a response at http://stackoverflow.com/questions/2094663/determine-if-windows-process-has-permission-to-create-symbolic-link .
msg98064 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-01-19 17:33
IMO we could just catch the WindowsError, and skip the test if its winerror attribute is 1314 (=ERROR_PRIVILEGE_NOT_HELD).
msg98310 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-01-26 01:53
Amaury, that was a good suggestion, but I did with Eric's help track down a mechanism to test for the presence of the symlink creation privilege. I prefer to have a proper check rather than to attempt to create one and test for the failure message because it doesn't have the potential to be confounded with other causes. I want to avoid issues such as where is the test symlink created and how is it cleaned up. If there's still desire to go that route after looking at this implementation, I'm not opposed to switching gears and using that technique.

This patch (20) uses ctypes (in the test suite; is that okay?) to determine if the symlink creation privilege is present, falling back to the assumption that it is, and integrates that with the test.support.has_symlink function (which is new in this issue thread).

Eric, can you test this new patch in your limited user environment and report what you find?
msg98709 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-02 03:04
I haven't yet had a chance to look into what caused the failures, but test_tarfile did not pass. This is on Windows 7 x64.


======================================================================
ERROR: test_extract_hardlink (__main__.MiscReadTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib\test\test_tarfile.py", line 295, in test_extract_hardlink
    data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read()
IOError: [Errno 2] No such file or directory: 'd:\\python-dev\\py3k\\@test_2972_
tmp\\ustar/symtype'

======================================================================
ERROR: test_extract_hardlink (__main__.GzipMiscReadTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "lib\test\test_tarfile.py", line 295, in test_extract_hardlink
    data = open(os.path.join(TEMPDIR, "ustar/symtype"), "rb").read()
IOError: [Errno 2] No such file or directory: 'd:\\python-dev\\py3k\\@test_2972_
tmp\\ustar/symtype'
msg98712 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-02 04:06
Most of the guts have already been reviewed, but here are some mainly minor comments on the last patch.

Lib/test/symlink_support.py
- No need to import print_function
- I'd just put the docstrings on one line
- A bunch of if tests are one-lined

Lib/test/test_win_symlink.py
- getwindowsversion now returns named members, so you can just use getwindowsversion().major for example, rather than the tuple.
- Rather than check the Windows version in the setUp, I think it would be cleaner to use the unittest.skipIf decorator on the entire WindowsSymlinkTest class.
- You might want to stack skip decorators to first skip outright if it's not Windows, and then skip if it's not Win 6 or greater -- it gets you out of checking if getwindowsversion actually exists.
- test_remove_directory_link_to_missing_target has some commented out code.

Lib/test/test_posixpath.py
- Lines 365-366 - why check has_symlink() and immediately check it again?

Modules/posixmodule.c
- Line 2740 - "//*** todo: fix this"
- C++ style comments in a few other places (nit picky, I know)
- Line 5117 - win_symlink__doc__ is double spaced and contains an extra slash at line 5121. For consistency it should probably just be single spaced.
msg98727 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-02 12:12
Brian, thanks for the review. I really appreciate it. I'll fix all of the identified issues.

> Lib/test/test_posixpath.py
> - Lines 365-366 - why check has_symlink() and immediately check it
> again?

In the unpatched code, there were two calls that checked for the existence of 'symlink' in the os module. I thought it strange too, but left it assuming it was there for some reason and not wanting to over extend beyond my primary objective. I will rewrite that test to use only one check unless someone posts otherwise.
msg98730 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-02-02 13:08
- When run with patch 20 as non-admin on Windows 7, I get the same test_tarfile errors that Brian gets. I do not get these errors with an unpatched py3k build.

- When run with patch 20 as an admin on Windows 7, I do not get the errors in test_tarfile. However, I do get errors in test_posixpath that I do not get on an unpatched py3k build:
======================================================================
FAIL: test_realpath_basic (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 49
9, in test_realpath_basic
    self.assertEqual(realpath(ABSTFN), ABSTFN+"1")
AssertionError: 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/C:\\opt\\cygwin\\home
\\eric\\python\\py3k/C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp1'
!= 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp1'

======================================================================
FAIL: test_realpath_resolve_before_normalizing (test.test_posixpath.PosixPathTes
t)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 56
0, in test_realpath_resolve_before_normalizing
    self.assertEqual(realpath(ABSTFN + "/link-y/.."), ABSTFN + "/k")
AssertionError: 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/C:\\opt\\cygwin\\home
\\eric\\python\\py3k/@test_3404_tmp/C:\\opt\\cygwin\\home\\eric\\python\\py3k/@t
est_3404_tmp/k' != 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp/k'

======================================================================
FAIL: test_realpath_resolve_first (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 58
3, in test_realpath_resolve_first
    self.assertEqual(realpath(base + "link"), ABSTFN)
AssertionError: 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/C:\\opt\\cygwin\\home
\\eric\\python\\py3k/@test_3404_tmp' != 'C:\\opt\\cygwin\\home\\eric\\python\\py
3k/@test_3404_tmp'

======================================================================
FAIL: test_realpath_resolve_parents (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 53
7, in test_realpath_resolve_parents
    self.assertEqual(realpath("a"), ABSTFN + "/y/a")
AssertionError: 'C:\\opt\\cygwin\\home\\eric\\python\\py3k\\@test_3404_tmp\\k/a'
 != 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp/y/a'

======================================================================
FAIL: test_realpath_symlink_loops (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 50
9, in test_realpath_symlink_loops
    self.assertEqual(realpath(ABSTFN), ABSTFN)
AssertionError: 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/C:\\opt\\cygwin\\home
\\eric\\python\\py3k/C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp' !
= 'C:\\opt\\cygwin\\home\\eric\\python\\py3k/@test_3404_tmp'

======================================================================
FAIL: test_samefile (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 34
3, in test_samefile
    False
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 29
, in assertIs
    self.assertTrue(a is b)
AssertionError: False is not True

======================================================================
FAIL: test_samestat (test.test_posixpath.PosixPathTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 38
4, in test_samestat
    False
  File "C:\opt\cygwin\home\eric\python\py3k\lib\test\test_posixpath.py", line 29
, in assertIs
    self.assertTrue(a is b)
AssertionError: False is not True

----------------------------------------------------------------------
Ran 30 tests in 0.201s

FAILED (failures=7)
test test_posixpath failed -- multiple errors occurred
1 test failed:
    test_posixpath

Even though "cygwin" is in the path, I am running these tests from a cmd.exe (or whatever the built-in shell is called these days) shell. I am not running these tests under cygwin bash.
msg99033 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-08 00:35
Enclosed is patch 21, which addresses the concerns raised by Brian.

Note that I still have work to do resolving the limited user account test failures.

> Brian Curtin <curtin@acm.org> added the comment:
> 
> Most of the guts have already been reviewed, but here are some mainly
> minor comments on the last patch.

Thanks again for the thorough review.

> Lib/test/symlink_support.py
> - No need to import print_function
> - I'd just put the docstrings on one line
> - A bunch of if tests are one-lined

I left `import print_function` in so the script can be run on Python 2.6 without modification.

> Lib/test/test_win_symlink.py
> - getwindowsversion now returns named members, so you can just use
> getwindowsversion().major for example, rather than the tuple.
> - Rather than check the Windows version in the setUp, I think it would
> be cleaner to use the unittest.skipIf decorator on the entire
> WindowsSymlinkTest class.
> - You might want to stack skip decorators to first skip outright if
> it's not Windows, and then skip if it's not Win 6 or greater -- it gets
> you out of checking if getwindowsversion actually exists.
> - test_remove_directory_link_to_missing_target has some commented out
> code.

I tried implementing it using decorators, but I'm not confident that stacking decorators will alleviate the need for checking hasattr(sys, 'getwindowsversion') because the decorators will get run even if the previous decorator returns a skip. If this is possible, please propose a solution. Otherwise, the technique written should work (I'll prove it more with subsequent reports).

I did refactor the tests so there's no longer commented code, but there are now two tests that are skipped and will fail if not skipped. I would like to keep these here to capture where functionality may be improved (though it's not obvious to me that these tests necessarily should pass).

> Modules/posixmodule.c
> - Line 2740 - "//*** todo: fix this"
> - C++ style comments in a few other places (nit picky, I know)
> - Line 5117 - win_symlink__doc__ is double spaced and contains an extra
> slash at line 5121. For consistency it should probably just be single
> spaced.

Done. I removed the TODO. I believe it's an old comment that was already resolved.
msg99064 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-08 19:34
This latest patch (22) does some refactoring in test_posixpath to reduce nesting, limit duplicated code, and skip failing tests on Windows.

The only task now is to address the failing tests in a limited user account.
msg99142 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-09 23:54
This new patch (23) renames support.has_symlink and support.skip_unless_has_symlink to "can_symlink". This more accurately reflects the functionality.
msg99146 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-10 01:40
This latest patch (24) includes a fix for the test_tarfile failure when running on Windows Vista or later with an unprivileged account (without the SE_CREATE_SYMBOLIC_LINK privilege in particular).

I believe this patch now contains no failing tests in the identified Windows environments.
msg99150 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-10 02:59
Patch draft 25 restores a skipped test that got lost in one of the recent
patches.
msg99154 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-10 04:20
With patch #25, I get 6 test failures: test_glob, test_os, test_platform, test_posixpath, test_shutil, and test_tarfile. 

This is interesting because the failures are different depending on how I compile Python. Running in WOW64 (32-bit Python on 64-bit Windows), the tests fail for not having the required privilege. Running a 64-bit Python, the tests fail various asserts (see attached patch25results_python64.txt).

I haven't looked into why the behavior is different in WOW64 mode, but I'll try to take a look in the next day or so.
msg99180 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-10 23:03
> With patch #25, I get 6 test failures: test_glob, test_os,
> test_platform, test_posixpath, test_shutil, and test_tarfile.
> 
> This is interesting because the failures are different depending on how
> I compile Python. Running in WOW64 (32-bit Python on 64-bit Windows),
> the tests fail for not having the required privilege.

I'm unable to reproduce this. I'm using an automated script to checkout, patch, build, and test the code. You can probably use the same script as me; it's available as https://svn.jaraco.com/jaraco/python/incubator/test-python-symlink-patch.py . It should work on your system so long as you have 'patch' and 'svn' in the path and Visual Studio 9.0 in the default location. Would you be willing to try it, so at least we can eliminate the technique as a variable?

When I run the script as guest or admin, the 32-bit regression tests all seem to pass (I occasionally get a transient failure in test_os). The 64-bit ones, however, fail even without applying the patch. I haven't yet figured out why this is. There are plenty of failures in the build, so I was guessing the build is broken.

The fact that it's failing for not having the required privilege indicates to me that the lib/test/symlink_support.py isn't loading properly. Can you try 'from lib.test import symlink_support' and let me know what response you get?

> Running a 64-bit
> Python, the tests fail various asserts (see attached
> patch25results_python64.txt).

These asserts look very much like the ones I was seeing early on before I had addressed symlink artifacts in the tests. Why you would experience different behavior in the different architectures is still unclear.

In the meantime, I'm going to try to see if I can find a case where the import of symlink_support would fail unexpectedly.
msg99187 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-11 01:31
False alarm, the failures are my fault. I had a previous version of symlink_support, and applying patch 25 added the contents of symlink_support to the file again, thus causing an ImportError on that file. Sorry about that.

I removed the file, applied patch 25 again, and the tests pass.
msg99383 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-02-16 03:54
Given the title, I take it os.link should be supported here. However, I don't see an implementation. Is that going to be a part of this issue, or should the title be changed?

In looking at the code and tests I've written up for #7566, I wrote a quick os.link implementation to make sure hard-links would work with that feature, but I don't want to duplicate code if that's going in here.
msg99395 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-02-16 11:46
Let's do just os.symlink for this issue.
msg99525 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-02-18 20:03
At the language summit we okay'd using ctypes in the tests for standard lib modules, specifically for this issue.
msg101975 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-03-31 05:07
Anyone opposed to this being checked in? Other than some style issues which I'll fix on checkin, I believe this is ready to go. I'd like to get it in so I can backport it to 2.7 before the beta on Saturday.
msg101976 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2010-03-31 05:10
I had some style issues at one point, but I haven't looked at it closely recently. I won't have time to look at this before next week, so proceed without me.
msg101977 - (view) Author: sorin (sorin) Date: 2010-03-31 05:14
For me the patch worked. It would be really nice to have it in 2.7 - I really hate Python functions that are not working on Windows.
msg102057 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-04-01 02:03
One last issue to solve before this goes in and I start the backport...test_tarfile.test_extract_hardlink is intermittently failing for me, which was an issue for Eric and I on an earlier version of Jason's patch. Sometimes it fails when run as a part of the whole test suite, and then it'll pass when run by itself. Thoughts, anyone? I've spent some time on it and I'm not sure what I'm missing.
msg102359 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-05 00:51
This latest patch (26) only merges the latest changes from the repo.
msg102387 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-05 17:24
My initial troubleshooting indicated to me that the intermittent test_tarfile problem exists independent of the symlink patch, so it was not relevant to this issue.

I've tried to do some more thorough troubleshooting, and this continues to be my finding, and somewhat consistent with Brian's finding.

I've created issue8317 to track the trouble with test_tarfile.
msg102575 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-07 22:59
While trying to reproduce the transient test_tarfile errors, I found two more tests that appear to be failing when symlinks cannot be created, now skipped by patch 27.
msg102587 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-08 01:40
I've been fighting a failing test in test_platform (when test.support.can_symlink() is True). Turns out the problem is caused by the fact that the Python DLL cannot be resolved when the executable isn't in the same directory (which is the case when launched from a symlink). I've created issue8342 to track this behavior.
msg102630 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-08 17:14
This patch includes a routine that adds the directory of the python executable to the path before attempting to run a symlinked executable (in test_platform).
msg102631 - (view) Author: Martin v. Löwis (loewis) * (Python committer) Date: 2010-04-08 17:20
The patch has now missed the window for 2.7, so backporting it won't be necessary.
msg102640 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-08 19:04
In the last patch, I addressed test_platform running a test under a symlinked Python. I then found the same error resulting from essentially the same code in test_sysconfig. So I refactored those methods into a generator method in test.support. This is patch 29.
msg102658 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-09 00:27
With patch 29, I believe all patch-related test failures are corrected.

The remaining failures in some modules (namely test_tarfile, test_glob, test_mailbox, test_warnings) can be demonstrated to occur in unpatched builds. Since some failures are transient, I created repeat_test, which I used to demonstrate that test_glob, test_tarfile, and test_mailbox will fail on a clean build.

Additionally, I'm including test output for 32- and 64-bit builds on the unpatched build, the patched build running under administrator, and the patched build running under guest.

The test output was generated in an automated fashion to guarantee a clean build. The build process can be found by easy_installing jaraco.develop==1.1.1 and running test-python-symlink-patch.py (VS9, GNU patch, and svn required).
msg102663 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-04-09 01:12
It seems issue7443 discusses the cause of the transient failures.
msg109616 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-07-08 21:43
Committed in r82659.

I'm leaving this open until a few other issues are fleshed out.
1. Document privilege escalation and/or expose some method to do so.
2. Test execution, e.g., buildbots


Once I get a few more things off my plate I should be able to finish setting up #2, the buildbot slave I've got almost up and running. I'd like to safely set it up so that this can be tested there, as none of the other buildbots are likely to run any of these tests.
msg109700 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-07-09 09:34
This has broken all non-Windows buildbots. Can you take a look?
msg109716 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-07-09 11:44
I'm building now and will report back shortly...
msg109717 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-07-09 11:49
Also, GetFinalPathNameByHandle() is called 5 times with VOLUME_NAME_DOS, and once with VOLUME_NAME_NT.  This one looks suspect to me.

[I noticed this because these symbols are not defined with the SDK shipped with VS8.0. I'll propose another patch for this]
msg109720 - (view) Author: Jason R. Coombs (jason.coombs) * (Python committer) Date: 2010-07-09 12:39
Here's a patch to address the posix failures:

- test_posixpath seems to have lost the creation of one test file.
- WindowsError doesn't exist on other platforms, so it can't be caught directly (in tarfile.py). I've written a work-around, but I don't particularly like it (catches all exceptions and tests the name).

There were three other tests that reported BAD for me.

test_os and test_subprocess were reporting bad due to skipped tests. I presume this will not break the buildbots?

test_readline is failing on readline.clear_history because it appears that attribute doesn't exist. I suspect this error is not related to the symlink patch.
msg109725 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-07-09 12:55
Hm, the patch could be more "pythonic". Something like:

symlink_exception = (AttributeError,)
try:
    symlink_exception += (NotImplementedError, WindowsError)
except NameError:
    pass

try:
    ...
except symlink_exception:
    ...
msg109727 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2010-07-09 13:10
> Hm, the patch could be more "pythonic". Something like:
> 
> symlink_exception = (AttributeError,)
> try:
>     symlink_exception += (NotImplementedError, WindowsError)
> except NameError:
>     pass

Probably better as:

symlink_exception = (AttributeError, NotImplementedError)
try:
    symlink_exception += (WindowsError,)
except NameError:
    pass
msg109739 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-07-09 13:56
Committed Jason's patch with Antoine's twist as r82743 after running on Arch Linux. Thanks for catching and looking into this stuff.
msg111156 - (view) Author: Amaury Forgeot d'Arc (amaury.forgeotdarc) * (Python committer) Date: 2010-07-22 08:57
All patches seems already applied. Should we close this issue?
msg111208 - (view) Author: Brian Curtin (brian.curtin) * (Python committer) Date: 2010-07-22 18:46
Closed. I created #9332 for the remaining side issues.
History
Date User Action Args
2010-07-22 18:46:13brian.curtinsetstatus: pending -> closed

messages: + msg111208
2010-07-22 08:57:36amaury.forgeotdarcsetstatus: open -> pending

messages: + msg111156
2010-07-09 13:56:28brian.curtinsetmessages: + msg109739
2010-07-09 13:10:43pitrousetmessages: + msg109727
2010-07-09 12:55:13amaury.forgeotdarcsetmessages: + msg109725
2010-07-09 12:39:45jason.coombssetfiles: - smime.p7s
2010-07-09 12:39:30jason.coombssetfiles: + posix-failures.patch

messages: + msg109720
2010-07-09 11:49:35amaury.forgeotdarcsetmessages: + msg109717
2010-07-09 11:44:31jason.coombssetfiles: + smime.p7s

messages: + msg109716
2010-07-09 09:34:09pitrousetnosy: + pitrou
messages: + msg109700
2010-07-08 21:43:18brian.curtinsetresolution: fixed
messages: + msg109616
stage: patch review -> resolved
2010-04-09 01:12:41jason.coombssetmessages: + msg102663
2010-04-09 00:28:41jason.coombssetfiles: - admin results.zip
2010-04-09 00:28:36jason.coombssetfiles: - guest results.zip
2010-04-09 00:28:28jason.coombssetfiles: + guest results - patch 29.zip
2010-04-09 00:28:17jason.coombssetfiles: + admin results - patch 29.zip
2010-04-09 00:28:07jason.coombssetfiles: + admin results - no patch.zip
2010-04-09 00:27:47jason.coombssetfiles: + repeat_test.py

messages: + msg102658
2010-04-08 19:06:37jason.coombssetfiles: - windows symlink draft 28.patch
2010-04-08 19:06:30jason.coombssetfiles: - windows symlink draft 28.patch
2010-04-08 19:06:24jason.coombssetfiles: - windows symlink draft 27.patch
2010-04-08 19:06:17jason.coombssetfiles: + windows symlink draft 29.patch
2010-04-08 19:04:09jason.coombssetfiles: + windows symlink draft 28.patch

messages: + msg102640
2010-04-08 17:20:37loewissetmessages: + msg102631
2010-04-08 17:14:42jason.coombssetfiles: + windows symlink draft 28.patch

messages: + msg102630
2010-04-08 01:41:32jason.coombssetfiles: - windows symlink draft 26.patch
2010-04-08 01:41:24jason.coombssetfiles: - windows symlink draft 25.patch
2010-04-08 01:40:46jason.coombssetmessages: + msg102587
2010-04-07 22:59:25jason.coombssetfiles: + windows symlink draft 27.patch

messages: + msg102575
2010-04-05 17:24:52jason.coombssetmessages: + msg102387
2010-04-05 00:51:49jason.coombssetfiles: + windows symlink draft 26.patch

messages: + msg102359
2010-04-01 02:03:14brian.curtinsetmessages: + msg102057
2010-03-31 05:14:40sorinsetmessages: + msg101977
2010-03-31 05:10:46eric.smithsetmessages: + msg101976
2010-03-31 05:07:18brian.curtinsetassignee: eric.smith -> brian.curtin
messages: + msg101975
2010-02-18 20:03:37eric.smithsetmessages: + msg99525
2010-02-16 11:46:09jason.coombssetmessages: + msg99395
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.symlink() and os.path.islink() support for Windows
2010-02-16 03:54:45brian.curtinsetnosy: lemburg, loewis, nnorwitz, jafo, amaury.forgeotdarc, jason.coombs, ggenellina, eric.smith, giampaolo.rodola, swarren, r.david.murray, sorin, brian.curtin, asvetlov
messages: + msg99383
components: + Windows
2010-02-11 01:31:46brian.curtinsetmessages: + msg99187
2010-02-10 23:03:55jason.coombssetfiles: + guest results.zip, admin results.zip

messages: + msg99180
2010-02-10 04:20:40brian.curtinsetfiles: + patch25results_python64.txt

messages: + msg99154
2010-02-10 03:00:44jason.coombssetfiles: - smime.p7s
2010-02-10 03:00:37jason.coombssetfiles: - windows symlink draft 24.patch
2010-02-10 03:00:31jason.coombssetfiles: - windows symlink draft 23.patch
2010-02-10 03:00:24jason.coombssetfiles: - windows symlink draft 22.patch
2010-02-10 03:00:15jason.coombssetfiles: - failures.txt
2010-02-10 02:59:30jason.coombssetfiles: + windows symlink draft 25.patch, smime.p7s

messages: + msg99150
2010-02-10 01:40:43jason.coombssetfiles: + windows symlink draft 24.patch

messages: + msg99146
2010-02-09 23:54:36jason.coombssetfiles: + windows symlink draft 23.patch

messages: + msg99142
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-02-08 19:34:54jason.coombssetfiles: - windows symlink draft 21.patch
2010-02-08 19:34:42jason.coombssetfiles: + windows symlink draft 22.patch

messages: + msg99064
2010-02-08 14:13:40jason.coombssetfiles: - windows symlink draft 21.patch
2010-02-08 14:13:32jason.coombssetfiles: + windows symlink draft 21.patch
2010-02-08 14:07:44jason.coombssetfiles: - windows symlink draft 20.patch
2010-02-08 14:07:35jason.coombssetfiles: - windows symlink draft 19.patch
2010-02-08 00:35:47jason.coombssetfiles: + windows symlink draft 21.patch

messages: + msg99033
2010-02-02 13:08:32eric.smithsetmessages: + msg98730
2010-02-02 12:12:18jason.coombssetmessages: + msg98727
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-02-02 04:06:42brian.curtinsetmessages: + msg98712
2010-02-02 03:04:23brian.curtinsetmessages: + msg98709
2010-01-26 01:53:45jason.coombssetfiles: + windows symlink draft 20.patch

messages: + msg98310
2010-01-19 17:33:48amaury.forgeotdarcsetmessages: + msg98064
2010-01-19 17:03:04ggenellinasetnosy: + ggenellina
2010-01-19 16:47:28jason.coombssetmessages: + msg98063
2010-01-18 22:02:30jason.coombssetfiles: - smime.p7s
2010-01-18 22:02:25jason.coombssetfiles: - smime.p7s
2010-01-18 20:33:56loewissetmessages: + msg98030
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-01-18 20:28:31loewissetmessages: + msg98029
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-01-18 14:46:16jason.coombssetfiles: + smime.p7s

messages: + msg98020
2010-01-18 14:44:49jason.coombssetfiles: + smime.p7s

messages: + msg98019
2010-01-18 14:44:34eric.smithsetmessages: + msg98018
2010-01-18 14:42:03eric.smithsetmessages: + msg98017
2010-01-18 14:40:36sorinsetmessages: + msg98016
2010-01-18 14:35:18jason.coombssetmessages: + msg98015
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-01-18 14:31:56brian.curtinsetmessages: + msg98014
2010-01-18 13:56:36jason.coombssetmessages: + msg98013
2010-01-18 11:20:21sorinsetmessages: + msg98001
2010-01-18 05:39:51loewissetmessages: + msg97990
2010-01-18 04:25:24jason.coombssetmessages: + msg97988
2010-01-17 22:49:48jason.coombssetfiles: + windows symlink draft 19.patch

messages: + msg97984
2010-01-17 22:30:46jason.coombssetmessages: + msg97983
2010-01-17 22:30:39jason.coombssetfiles: - windows symlink draft 17.patch
2010-01-17 22:28:53eric.smithsetmessages: + msg97982
2010-01-17 22:26:38jason.coombssetfiles: + failures.txt

messages: + msg97981
2010-01-17 22:16:35eric.smithsetmessages: + msg97980
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2010-01-17 21:44:13jason.coombssetmessages: + msg97979
2010-01-17 21:42:29jason.coombssetmessages: + msg97978
2010-01-17 00:01:09jason.coombssetmessages: + msg97924
2010-01-16 23:59:11brian.curtinsetfiles: + failures.txt

messages: + msg97923
2010-01-16 22:47:09eric.smithsetfiles: + windows symlink draft 18.patch

messages: + msg97916
2010-01-16 22:01:47brian.curtinsetkeywords: + needs review
nosy: + brian.curtin
messages: + msg97913

2010-01-16 11:06:12sorinsetnosy: + sorin
messages: + msg97870
2009-12-23 01:02:07jason.coombssetmessages: + msg96824
2009-12-23 01:00:13jason.coombssetmessages: + msg96823
2009-12-23 00:29:00jason.coombssetfiles: - windows symlink draft 16.patch
2009-12-23 00:28:52jason.coombssetfiles: - windows symlink draft 15.patch
2009-12-22 13:57:22eric.smithsetmessages: + msg96797
2009-12-20 00:14:58jason.coombssetfiles: + windows symlink draft 17.patch

messages: + msg96656
2009-12-18 00:48:15eric.smithsetmessages: + msg96545
2009-12-06 01:34:45asvetlovsetnosy: + asvetlov
messages: + msg96015
2009-11-27 01:40:30jason.coombssetfiles: + windows symlink draft 16.patch

messages: + msg95757
2009-11-17 08:47:47eric.smithsetmessages: + msg95368
2009-10-29 01:00:32jason.coombssetfiles: - windows symlink draft 14.patch
2009-10-29 00:59:13jason.coombssetfiles: + windows symlink draft 15.patch

messages: + msg94643
2009-10-27 19:00:30jason.coombssetfiles: - windows symlink draft 13.patch
2009-10-27 19:00:18jason.coombssetfiles: + windows symlink draft 14.patch

messages: + msg94573
2009-10-26 22:12:04jason.coombssetmessages: + msg94522
2009-10-26 21:49:35jason.coombssetfiles: - windows symlink draft 12.patch
2009-10-26 21:47:02jason.coombssetfiles: + windows symlink draft 13.patch

messages: + msg94517
2009-10-26 21:31:17jason.coombssetfiles: - windows symlink draft 11.patch
2009-10-26 18:22:38jason.coombssetfiles: + windows symlink draft 12.patch

messages: + msg94498
2009-10-26 05:37:30loewissetfiles: - windows symlink draft 10.patch
2009-10-26 05:37:23loewissetfiles: - windows symlink draft 9.patch
2009-10-26 05:37:17loewissetfiles: - windows symlink draft 8.patch
2009-10-26 05:37:12loewissetfiles: - windows symlink draft 7.patch
2009-10-26 05:37:07loewissetfiles: - python-core_rev4275.patch
2009-10-26 05:37:03loewissetfiles: - python-core_rev4274.patch
2009-10-26 05:36:58loewissetfiles: - windows symlink draft 6.patch
2009-10-26 05:36:53loewissetfiles: - windows symlink draft 5.patch
2009-10-26 05:36:48loewissetfiles: - windows symlink draft 4.patch
2009-10-26 05:36:43loewissetfiles: - windows symlink draft 3.patch
2009-10-26 05:36:38loewissetfiles: - windows symlink draft 2.patch
2009-10-26 05:36:28loewissetfiles: - windows symlink draft 1.patch
2009-10-26 01:29:14jason.coombssetfiles: + windows symlink draft 11.patch

messages: + msg94470
2009-10-23 22:08:28jason.coombssetmessages: + msg94395
2009-10-11 01:57:44jason.coombssetfiles: + windows symlink draft 10.patch

messages: + msg93847
2009-09-11 17:39:57jason.coombssetfiles: + windows symlink draft 9.patch

messages: + msg92513
2009-09-11 14:04:04jason.coombssetfiles: + windows symlink draft 8.patch

messages: + msg92509
2009-09-11 00:44:00jason.coombssetfiles: - smime.p7s
2009-09-08 11:19:21jason.coombssetfiles: + smime.p7s

messages: + msg92413
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-09-08 08:57:19amaury.forgeotdarcsetnosy: + amaury.forgeotdarc
messages: + msg92411
2009-09-05 18:07:36jason.coombssetfiles: + windows symlink draft 7.patch

messages: + msg92288
2009-09-05 15:01:53jason.coombssetfiles: + python-core_rev4275.patch

messages: + msg92278
2009-09-05 14:59:42jason.coombssetfiles: + python-core_rev4274.patch

messages: + msg92277
2009-09-02 20:38:39loewissetmessages: + msg92182
2009-09-02 20:18:35jason.coombssetmessages: + msg92178
2009-09-02 18:50:39loewissetmessages: + msg92176
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-09-02 16:07:59eric.smithsetassignee: eric.smith
2009-09-02 15:48:27eric.smithsetnosy: + eric.smith

messages: + msg92171
versions: + Python 3.2, - Python 3.1
2009-08-21 12:12:00jason.coombssetmessages: + msg91820
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-08-21 06:55:02loewissetmessages: + msg91804
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-08-18 15:15:51jason.coombssetmessages: + msg91700
2009-07-18 17:38:57r.david.murraysetmessages: + msg90687
stage: patch review
2009-07-18 17:13:15jason.coombssetmessages: + msg90686
2009-07-18 14:43:36r.david.murraysetnosy: + r.david.murray
messages: + msg90679
2009-07-18 14:03:41jason.coombssetmessages: + msg90677
2009-06-06 21:10:53jason.coombssetfiles: + windows symlink draft 6.patch

messages: + msg89017
2009-06-05 17:29:34jason.coombssetfiles: + windows symlink draft 5.patch

messages: + msg88954
2009-05-31 20:47:36jason.coombssetfiles: + windows symlink draft 4.patch

messages: + msg88609
2009-05-24 17:24:44loewissetmessages: + msg88270
2009-05-24 16:09:51jason.coombssetfiles: - smime.p7s
2009-05-24 16:06:42jason.coombssetfiles: + windows symlink draft 3.patch, smime.p7s

messages: + msg88265
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-05-22 19:58:10loewissetmessages: + msg88213
2009-05-22 04:21:39jason.coombssetfiles: + windows symlink draft 2.patch

messages: + msg88179
2009-05-18 20:29:08loewissetmessages: + msg88050
2009-05-18 12:51:53jason.coombssetfiles: - smime.p7s
2009-05-18 12:51:00jason.coombssetfiles: + windows symlink draft 1.patch
keywords: + patch
messages: + msg88030
2009-05-10 18:14:45loewissetmessages: + msg87534
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-05-10 17:53:43jason.coombssetmessages: + msg87533
2009-05-10 17:52:43jason.coombssetfiles: + smime.p7s

messages: + msg87532
title: Add os.link() and os.symlink() and os.path.islink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-05-10 17:12:44loewissetmessages: + msg87530
2009-05-10 10:37:09jason.coombssetmessages: + msg87519
title: Add os.link() and os.symlink() support for Windows -> Add os.link() and os.symlink() and os.path.islink() support for Windows
2009-05-09 13:38:19loewissetmessages: + msg87496
2009-05-09 12:43:14jason.coombssetmessages: + msg87493
2009-02-24 20:41:38giampaolo.rodolasetnosy: + giampaolo.rodola
2009-02-21 23:18:47pitrousetversions: + Python 3.1, Python 2.7, - Python 2.6
2009-02-19 14:55:12jason.coombssetnosy: + jason.coombs
messages: + msg82476
2007-09-21 23:39:01jafosetmessages: + msg56084
2007-09-21 18:03:08swarrensetmessages: + msg56078
2007-09-21 16:04:03swarrensetmessages: + msg56075
2007-09-21 09:25:47jafosetnosy: + jafo
messages: + msg56073
2007-09-21 09:11:54jafolinkissue478407 superseder
2007-09-21 04:49:44swarrensetnosy: + swarren
messages: + msg56068
2006-10-16 15:21:15lemburgcreate