python-peps/pep-0235/index.html

252 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="color-scheme" content="light dark">
<title>PEP 235 Import on Case-Insensitive Platforms | peps.python.org</title>
<link rel="shortcut icon" href="../_static/py.png">
<link rel="canonical" href="https://peps.python.org/pep-0235/">
<link rel="stylesheet" href="../_static/style.css" type="text/css">
<link rel="stylesheet" href="../_static/mq.css" type="text/css">
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" media="(prefers-color-scheme: light)" id="pyg-light">
<link rel="stylesheet" href="../_static/pygments_dark.css" type="text/css" media="(prefers-color-scheme: dark)" id="pyg-dark">
<link rel="alternate" type="application/rss+xml" title="Latest PEPs" href="https://peps.python.org/peps.rss">
<meta property="og:title" content='PEP 235 Import on Case-Insensitive Platforms | peps.python.org'>
<meta property="og:description" content="Python Enhancement Proposals (PEPs)">
<meta property="og:type" content="website">
<meta property="og:url" content="https://peps.python.org/pep-0235/">
<meta property="og:site_name" content="Python Enhancement Proposals (PEPs)">
<meta property="og:image" content="https://peps.python.org/_static/og-image.png">
<meta property="og:image:alt" content="Python PEPs">
<meta property="og:image:width" content="200">
<meta property="og:image:height" content="200">
<meta name="description" content="Python Enhancement Proposals (PEPs)">
<meta name="theme-color" content="#3776ab">
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="svg-sun-half" viewBox="0 0 24 24" pointer-events="all">
<title>Following system colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="9"></circle>
<path d="M12 3v18m0-12l4.65-4.65M12 14.3l7.37-7.37M12 19.6l8.85-8.85"></path>
</svg>
</symbol>
<symbol id="svg-moon" viewBox="0 0 24 24" pointer-events="all">
<title>Selected dark colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path stroke="none" d="M0 0h24v24H0z" fill="none"></path>
<path d="M12 3c.132 0 .263 0 .393 0a7.5 7.5 0 0 0 7.92 12.446a9 9 0 1 1 -8.313 -12.454z"></path>
</svg>
</symbol>
<symbol id="svg-sun" viewBox="0 0 24 24" pointer-events="all">
<title>Selected light colour scheme</title>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none"
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="5"></circle>
<line x1="12" y1="1" x2="12" y2="3"></line>
<line x1="12" y1="21" x2="12" y2="23"></line>
<line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line>
<line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line>
<line x1="1" y1="12" x2="3" y2="12"></line>
<line x1="21" y1="12" x2="23" y2="12"></line>
<line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line>
<line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line>
</svg>
</symbol>
</svg>
<script>
document.documentElement.dataset.colour_scheme = localStorage.getItem("colour_scheme") || "auto"
</script>
<section id="pep-page-section">
<header>
<h1>Python Enhancement Proposals</h1>
<ul class="breadcrumbs">
<li><a href="https://www.python.org/" title="The Python Programming Language">Python</a> &raquo; </li>
<li><a href="../pep-0000/">PEP Index</a> &raquo; </li>
<li>PEP 235</li>
</ul>
<button id="colour-scheme-cycler" onClick="setColourScheme(nextColourScheme())">
<svg aria-hidden="true" class="colour-scheme-icon-when-auto"><use href="#svg-sun-half"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-dark"><use href="#svg-moon"></use></svg>
<svg aria-hidden="true" class="colour-scheme-icon-when-light"><use href="#svg-sun"></use></svg>
<span class="visually-hidden">Toggle light / dark / auto colour theme</span>
</button>
</header>
<article>
<section id="pep-content">
<h1 class="page-title">PEP 235 Import on Case-Insensitive Platforms</h1>
<dl class="rfc2822 field-list simple">
<dt class="field-odd">Author<span class="colon">:</span></dt>
<dd class="field-odd">Tim Peters &lt;tim.peters&#32;&#97;t&#32;gmail.com&gt;</dd>
<dt class="field-even">Status<span class="colon">:</span></dt>
<dd class="field-even"><abbr title="Accepted and implementation complete, or no longer active">Final</abbr></dd>
<dt class="field-odd">Type<span class="colon">:</span></dt>
<dd class="field-odd"><abbr title="Normative PEP with a new feature for Python, implementation change for CPython or interoperability standard for the ecosystem">Standards Track</abbr></dd>
<dt class="field-even">Created<span class="colon">:</span></dt>
<dd class="field-even">21-Feb-2001</dd>
<dt class="field-odd">Python-Version<span class="colon">:</span></dt>
<dd class="field-odd">2.1</dd>
<dt class="field-even">Post-History<span class="colon">:</span></dt>
<dd class="field-even">16-Feb-2001</dd>
</dl>
<hr class="docutils" />
<section id="contents">
<details><summary>Table of Contents</summary><ul class="simple">
<li><a class="reference internal" href="#note">Note</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#current-lower-left-semantics">Current Lower-Left Semantics</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
</ul>
</details></section>
<section id="note">
<h2><a class="toc-backref" href="#note" role="doc-backlink">Note</a></h2>
<p>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 cant be put off until 2.2 without also delaying
the Cygwin and MacOS X ports.</p>
</section>
<section id="motivation">
<h2><a class="toc-backref" href="#motivation" role="doc-backlink">Motivation</a></h2>
<p>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 dont insist on
case-sensitive matches:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span> <span class="k">case</span><span class="o">-</span><span class="n">preserving</span> <span class="n">case</span><span class="o">-</span><span class="n">destroying</span>
<span class="o">+-------------------+------------------+</span>
<span class="k">case</span><span class="o">-</span><span class="n">sensitive</span> <span class="o">|</span> <span class="n">most</span> <span class="n">Unix</span> <span class="n">flavors</span> <span class="o">|</span> <span class="n">brrrrrrrrrr</span> <span class="o">|</span>
<span class="o">+-------------------+------------------+</span>
<span class="k">case</span><span class="o">-</span><span class="n">insensitive</span> <span class="o">|</span> <span class="n">Windows</span> <span class="o">|</span> <span class="n">some</span> <span class="n">unfortunate</span> <span class="o">|</span>
<span class="o">|</span> <span class="n">MacOSX</span> <span class="n">HFS</span><span class="o">+</span> <span class="o">|</span> <span class="n">network</span> <span class="n">schemes</span> <span class="o">|</span>
<span class="o">|</span> <span class="n">Cygwin</span> <span class="o">|</span> <span class="o">|</span>
<span class="o">|</span> <span class="o">|</span> <span class="n">OpenVMS</span> <span class="o">|</span>
<span class="o">+-------------------+------------------+</span>
</pre></div>
</div>
<p>In the upper left box, if you create “fiLe” its stored as “fiLe”,
and only <code class="docutils literal notranslate"><span class="pre">open(&quot;fiLe&quot;)</span></code> will open it (<code class="docutils literal notranslate"><span class="pre">open(&quot;file&quot;)</span></code> will not, nor
will the 14 other variations on that theme).</p>
<p>In the lower right box, if you create “fiLe”, theres no telling
what its stored as but most likely as “FILE” and any of the
16 obvious variations on <code class="docutils literal notranslate"><span class="pre">open(&quot;FilE&quot;)</span></code> will open it.</p>
<p>The lower left box is a mix: creating “fiLe” stores “fiLe” in the
platform directory, but you dont have to match case when opening
it; any of the 16 obvious variations on <code class="docutils literal notranslate"><span class="pre">open(&quot;FILe&quot;)</span></code> work.</p>
<p>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 <code class="docutils literal notranslate"><span class="pre">open()</span></code> requires a case-sensitive match. In
practice, you should always code as if matches were
case-sensitive, else your program wont be portable.</p>
<p>Whats proposed is to change the semantics of Python “import”
statements, and there <em>only</em> in the lower left box.</p>
</section>
<section id="current-lower-left-semantics">
<h2><a class="toc-backref" href="#current-lower-left-semantics" role="doc-backlink">Current Lower-Left Semantics</a></h2>
<p>Support for MacOSX HFS+, and for Cygwin, is new in 2.1, so nothing
is changing there. Whats changing is Windows behavior. Here are
the current rules for import on Windows:</p>
<ol class="arabic">
<li>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, <code class="docutils literal notranslate"><span class="pre">FiLe.py</span></code> and <code class="docutils literal notranslate"><span class="pre">file.py</span></code> on
<code class="docutils literal notranslate"><span class="pre">sys.path</span></code>, and do<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">file</span>
</pre></div>
</div>
<p>then if Python finds <code class="docutils literal notranslate"><span class="pre">FiLe.py</span></code> first, it raises a <code class="docutils literal notranslate"><span class="pre">NameError</span></code>.
It does <em>not</em> go on to find <code class="docutils literal notranslate"><span class="pre">file.py</span></code>; indeed, its impossible to
import any but the first case-insensitive match on <code class="docutils literal notranslate"><span class="pre">sys.path</span></code>,
and then only if case matches exactly in the first
case-insensitive match.</p>
</li>
<li>An ugly exception: if the first case-insensitive match on
<code class="docutils literal notranslate"><span class="pre">sys.path</span></code> is for a file whose name is entirely in upper case
(<code class="docutils literal notranslate"><span class="pre">FILE.PY</span></code> or <code class="docutils literal notranslate"><span class="pre">FILE.PYC</span></code> or <code class="docutils literal notranslate"><span class="pre">FILE.PYO</span></code>), 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.</li>
<li>And another exception: if the environment variable <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code>
exists, Python silently grabs the first case-insensitive match
of any kind.</li>
</ol>
<p>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 <em>or</em> Windows
users. Nevertheless, theyve worked fine for years, and in
isolation theres no compelling reason to change them.</p>
<p>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 didnt complain they had patches of their
own pending to do this, but the reviewer for those balked).</p>
<p>At a higher level, we want to keep Python consistent, by following
the same rules on <em>all</em> platforms with case-preserving
case-insensitive filesystems.</p>
</section>
<section id="proposed-semantics">
<h2><a class="toc-backref" href="#proposed-semantics" role="doc-backlink">Proposed Semantics</a></h2>
<p>The proposed new semantics for the lower left box:</p>
<ol class="upperalpha simple">
<li>If the <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code> environment variable exists, same as
before: silently accept the first case-insensitive match of any
kind; raise <code class="docutils literal notranslate"><span class="pre">ImportError</span></code> if none found.</li>
<li>Else search <code class="docutils literal notranslate"><span class="pre">sys.path</span></code> for the first case-sensitive match; raise
<code class="docutils literal notranslate"><span class="pre">ImportError</span></code> if none found.</li>
</ol>
<p>#B is the same rule as is used on Unix, so this will improve
cross-platform portability. Thats 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
cant 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 <code class="docutils literal notranslate"><span class="pre">NameError</span></code> or
<code class="docutils literal notranslate"><span class="pre">ImportError</span></code>, in which latter case it still will, or in which
former case will continue searching, and either succeed or blow up
with an <code class="docutils literal notranslate"><span class="pre">ImportError</span></code>.</p>
<p>#A is needed to cater to case-destroying filesystems mounted on Windows,
and <em>may</em> also be used by people so enamored of “natural” Windows
behavior that theyre willing to set an environment variable to
get it. I dont intend to implement #A for Unix too, but thats
just because Im not clear on how I <em>could</em> do so efficiently (Im
not going to slow imports under Unix just for theoretical purity).</p>
<p>The potential damage is here: #2 (matching on <code class="docutils literal notranslate"><span class="pre">ALLCAPS.PY</span></code>) is
proposed to be dropped. Case-destroying filesystems are a
vanishing breed, and support for them is ugly. Were already
supporting (and will continue to support) <code class="docutils literal notranslate"><span class="pre">PYTHONCASEOK</span></code> for their
benefit, but they dont deserve multiple hacks in 2001.</p>
</section>
</section>
<hr class="docutils" />
<p>Source: <a class="reference external" href="https://github.com/python/peps/blob/main/peps/pep-0235.rst">https://github.com/python/peps/blob/main/peps/pep-0235.rst</a></p>
<p>Last modified: <a class="reference external" href="https://github.com/python/peps/commits/main/peps/pep-0235.rst">2023-09-09 17:39:29 GMT</a></p>
</article>
<nav id="pep-sidebar">
<h2>Contents</h2>
<ul>
<li><a class="reference internal" href="#note">Note</a></li>
<li><a class="reference internal" href="#motivation">Motivation</a></li>
<li><a class="reference internal" href="#current-lower-left-semantics">Current Lower-Left Semantics</a></li>
<li><a class="reference internal" href="#proposed-semantics">Proposed Semantics</a></li>
</ul>
<br>
<a id="source" href="https://github.com/python/peps/blob/main/peps/pep-0235.rst">Page Source (GitHub)</a>
</nav>
</section>
<script src="../_static/colour_scheme.js"></script>
<script src="../_static/wrap_tables.js"></script>
<script src="../_static/sticky_banner.js"></script>
</body>
</html>