Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up| PEP: 235 | |
| Title: Import on Case-Insensitive Platforms | |
| Version: $Revision$ | |
| Last-Modified: $Date$ | |
| Author: Tim Peters <tim.peters@gmail.com> | |
| Status: Final | |
| Type: Standards Track | |
| Content-Type: text/x-rst | |
| Created: | |
| Python-Version: 2.1 | |
| Post-History: 16 February 2001 | |
| Note | |
| ==== | |
| This is essentially a retroactive PEP: the issue came up too late | |
| in the 2.1 release process to solicit wide opinion before deciding | |
| what to do, and can't be put off until 2.2 without also delaying | |
| the Cygwin and MacOS X ports. | |
| Motivation | |
| ========== | |
| File systems vary across platforms in whether or not they preserve | |
| the case of filenames, and in whether or not the platform C | |
| library file-opening functions do or don't insist on | |
| case-sensitive matches:: | |
| case-preserving case-destroying | |
| +-------------------+------------------+ | |
| case-sensitive | most Unix flavors | brrrrrrrrrr | | |
| +-------------------+------------------+ | |
| case-insensitive | Windows | some unfortunate | | |
| | MacOSX HFS+ | network schemes | | |
| | Cygwin | | | |
| | | OpenVMS | | |
| +-------------------+------------------+ | |
| In the upper left box, if you create "fiLe" it's stored as "fiLe", | |
| and only ``open("fiLe")`` will open it (``open("file")`` will not, nor | |
| will the 14 other variations on that theme). | |
| In the lower right box, if you create "fiLe", there's no telling | |
| what it's stored as -- but most likely as "FILE" -- and any of the | |
| 16 obvious variations on ``open("FilE")`` will open it. | |
| The lower left box is a mix: creating "fiLe" stores "fiLe" in the | |
| platform directory, but you don't have to match case when opening | |
| it; any of the 16 obvious variations on ``open("FILe")`` work. | |
| NONE OF THAT IS CHANGING! Python will continue to follow platform | |
| conventions w.r.t. whether case is preserved when creating a file, | |
| and w.r.t. whether ``open()`` requires a case-sensitive match. In | |
| practice, you should always code as if matches were | |
| case-sensitive, else your program won't be portable. | |
| What's proposed is to change the semantics of Python "import" | |
| statements, and there *only* in the lower left box. | |
| Current Lower-Left Semantics | |
| ============================ | |
| Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing | |
| is changing there. What's changing is Windows behavior. Here are | |
| the current rules for import on Windows: | |
| 1. Despite that the filesystem is case-insensitive, Python insists | |
| on a case-sensitive match. But not in the way the upper left | |
| box works: if you have two files, ``FiLe.py`` and ``file.py`` on | |
| ``sys.path``, and do :: | |
| import file | |
| then if Python finds ``FiLe.py`` first, it raises a ``NameError``. | |
| It does *not* go on to find ``file.py``; indeed, it's impossible to | |
| import any but the first case-insensitive match on ``sys.path``, | |
| and then only if case matches exactly in the first | |
| case-insensitive match. | |
| 2. An ugly exception: if the first case-insensitive match on | |
| ``sys.path`` is for a file whose name is entirely in upper case | |
| (``FILE.PY`` or ``FILE.PYC`` or ``FILE.PYO``), then the import silently | |
| grabs that, no matter what mixture of case was used in the | |
| import statement. This is apparently to cater to miserable old | |
| filesystems that really fit in the lower right box. But this | |
| exception is unique to Windows, for reasons that may or may not | |
| exist. | |
| 3. And another exception: if the environment variable ``PYTHONCASEOK`` | |
| exists, Python silently grabs the first case-insensitive match | |
| of any kind. | |
| So these Windows rules are pretty complicated, and neither match | |
| the Unix rules nor provide semantics natural for the native | |
| filesystem. That makes them hard to explain to Unix *or* Windows | |
| users. Nevertheless, they've worked fine for years, and in | |
| isolation there's no compelling reason to change them. | |
| However, that was before the MacOSX HFS+ and Cygwin ports arrived. | |
| They also have case-preserving case-insensitive filesystems, but | |
| the people doing the ports despised the Windows rules. Indeed, a | |
| patch to make HFS+ act like Unix for imports got past a reviewer | |
| and into the code base, which incidentally made Cygwin also act | |
| like Unix (but this met the unbounded approval of the Cygwin | |
| folks, so they sure didn't complain -- they had patches of their | |
| own pending to do this, but the reviewer for those balked). | |
| At a higher level, we want to keep Python consistent, by following | |
| the same rules on *all* platforms with case-preserving | |
| case-insensitive filesystems. | |
| Proposed Semantics | |
| ================== | |
| The proposed new semantics for the lower left box: | |
| A. If the ``PYTHONCASEOK`` environment variable exists, same as | |
| before: silently accept the first case-insensitive match of any | |
| kind; raise ``ImportError`` if none found. | |
| B. Else search ``sys.path`` for the first case-sensitive match; raise | |
| ``ImportError`` if none found. | |
| #B is the same rule as is used on Unix, so this will improve cross- | |
| platform portability. That's good. #B is also the rule the Mac | |
| and Cygwin folks want (and wanted enough to implement themselves, | |
| multiple times, which is a powerful argument in PythonLand). It | |
| can't cause any existing non-exceptional Windows import to fail, | |
| because any existing non-exceptional Windows import finds a | |
| case-sensitive match first in the path -- and it still will. An | |
| exceptional Windows import currently blows up with a ``NameError`` or | |
| ``ImportError``, in which latter case it still will, or in which | |
| former case will continue searching, and either succeed or blow up | |
| with an ``ImportError``. | |
| #A is needed to cater to case-destroying filesystems mounted on Windows, | |
| and *may* also be used by people so enamored of "natural" Windows | |
| behavior that they're willing to set an environment variable to | |
| get it. I don't intend to implement #A for Unix too, but that's | |
| just because I'm not clear on how I *could* do so efficiently (I'm | |
| not going to slow imports under Unix just for theoretical purity). | |
| The potential damage is here: #2 (matching on ``ALLCAPS.PY``) is | |
| proposed to be dropped. Case-destroying filesystems are a | |
| vanishing breed, and support for them is ugly. We're already | |
| supporting (and will continue to support) ``PYTHONCASEOK`` for their | |
| benefit, but they don't deserve multiple hacks in 2001. | |
| .. | |
| Local Variables: | |
| mode: indented-text | |
| indent-tabs-mode: nil | |
| End: |