diff options
author | Michał Górny <mgorny@gentoo.org> | 2022-10-14 11:52:28 +0200 |
---|---|---|
committer | Michał Górny <mgorny@gentoo.org> | 2022-10-14 11:52:28 +0200 |
commit | 34789dd7a883e62e91cc0c77cb484e10422eb7b8 (patch) | |
tree | 0fb84e5cf291689f596f05e703f2264295183961 /guide/porting.html | |
parent | Rebuild with Sphinx 5.2.3 (diff) | |
download | python-34789dd7a883e62e91cc0c77cb484e10422eb7b8.tar.gz python-34789dd7a883e62e91cc0c77cb484e10422eb7b8.tar.bz2 python-34789dd7a883e62e91cc0c77cb484e10422eb7b8.zip |
Update Guide to bac402d
Signed-off-by: Michał Górny <mgorny@gentoo.org>
Diffstat (limited to 'guide/porting.html')
-rw-r--r-- | guide/porting.html | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/guide/porting.html b/guide/porting.html index 0a9c78d..c1750e3 100644 --- a/guide/porting.html +++ b/guide/porting.html @@ -337,6 +337,130 @@ are provided for the purpose.</p> <code class="docutils literal notranslate"><span class="pre">python-X.Y-embed</span></code> first and fall back to <code class="docutils literal notranslate"><span class="pre">python-X.Y</span></code>.</p> </section> </section> +<section id="replacing-the-toml-package"> +<h2>Replacing the toml package<a class="headerlink" href="#replacing-the-toml-package" title="Permalink to this heading">¶</a></h2> +<p>The old <a class="reference external" href="https://pypi.org/project/toml/">toml</a> package is no longer maintained. It was last released +in November 2020 and it was never updated to implement TOML 1.0. +The recommended alternatives are:</p> +<ul class="simple"> +<li><p>the built-in <a class="reference external" href="https://docs.python.org/3.11/library/tomllib.html">tomllib</a> module (since Python 3.11) with fallback to +<a class="reference external" href="https://pypi.org/project/tomli/">tomli</a> package for reading TOML files</p></li> +<li><p>the <a class="reference external" href="https://pypi.org/project/tomli-w/">tomli-w</a> package for writing TOML files</p></li> +<li><p>the <a class="reference external" href="https://pypi.org/project/tomlkit/">tomlkit</a> package for editing already existing TOML files +while preserving style</p></li> +</ul> +<section id="porting-to-tomllib-tomli-without-toml-fallback"> +<h3>Porting to tomllib/tomli without toml fallback<a class="headerlink" href="#porting-to-tomllib-tomli-without-toml-fallback" title="Permalink to this heading">¶</a></h3> +<p>Using a combination of <a class="reference external" href="https://docs.python.org/3.11/library/tomllib.html">tomllib</a> and <a class="reference external" href="https://pypi.org/project/tomli/">tomli</a> is the recommended approach +for packages that only read TOML files, or both read and write them +but do not need to preserve style. The tomllib module is available +since Python 3.11, while tomli versions providing a compatible API +are compatible with Python 3.6 and newer.</p> +<p>The key differences between <a class="reference external" href="https://pypi.org/project/toml/">toml</a> and tomllib/tomli are:</p> +<ul class="simple"> +<li><p>the <code class="docutils literal notranslate"><span class="pre">load()</span></code> function accepts only a file object open for reading +in binary mode whereas toml expects a path or a file object open +for reading in text mode</p></li> +<li><p>the exception raised for invalid input is named <code class="docutils literal notranslate"><span class="pre">TOMLDecodeError</span></code> +where it is named <code class="docutils literal notranslate"><span class="pre">TomlDecodeError</span></code> in toml</p></li> +</ul> +<p>For example, the following code:</p> +<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">toml</span> + +<span class="k">try</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="n">toml</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="s2">"in1.toml"</span><span class="p">)</span> +<span class="k">except</span> <span class="n">toml</span><span class="o">.</span><span class="n">TomlDecodeError</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="kc">None</span> + +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"in2.toml"</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">d2</span> <span class="o">=</span> <span class="n">toml</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + +<span class="n">d3</span> <span class="o">=</span> <span class="n">toml</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="s1">'test = "foo"</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> +</pre></div> +</div> +<p>would normally be written as:</p> +<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span> + +<span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span> <span class="o">>=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span> + <span class="kn">import</span> <span class="nn">tomllib</span> +<span class="k">else</span><span class="p">:</span> + <span class="kn">import</span> <span class="nn">tomli</span> <span class="k">as</span> <span class="nn">tomllib</span> + +<span class="k">try</span><span class="p">:</span> + <span class="c1"># tomllib does not accept paths</span> + <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"in1.toml"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> +<span class="c1"># the exception uses uppercase "TOML"</span> +<span class="k">except</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">TOMLDecodeError</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="kc">None</span> + +<span class="c1"># the file must be open in binary mode</span> +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"in2.toml"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">d2</span> <span class="o">=</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + +<span class="n">d3</span> <span class="o">=</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="s1">'test = "foo"</span><span class="se">\n</span><span class="s1">'</span><span class="p">)</span> +</pre></div> +</div> +</section> +<section id="porting-to-tomllib-tomli-with-toml-fallback"> +<h3>Porting to tomllib/tomli with toml fallback<a class="headerlink" href="#porting-to-tomllib-tomli-with-toml-fallback" title="Permalink to this heading">¶</a></h3> +<p>If upstream insists on preserving compatibility with EOL versions +of Python, it is possible to use a combination of <a class="reference external" href="https://docs.python.org/3.11/library/tomllib.html">tomllib</a>, <a class="reference external" href="https://pypi.org/project/tomli/">tomli</a> +and <a class="reference external" href="https://pypi.org/project/toml/">toml</a>. Unfortunately, the incompatibilites in API need to be taken +into consideration.</p> +<p>For example, a backwards compatible code for loading a TOML file could +look like the following:</p> +<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">sys</span> + +<span class="k">try</span><span class="p">:</span> + <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">version_info</span> <span class="o">>=</span> <span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">11</span><span class="p">):</span> + <span class="kn">import</span> <span class="nn">tomllib</span> + <span class="k">else</span><span class="p">:</span> + <span class="kn">import</span> <span class="nn">tomli</span> <span class="k">as</span> <span class="nn">tomllib</span> + + <span class="k">try</span><span class="p">:</span> + <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"in1.toml"</span><span class="p">,</span> <span class="s2">"rb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">except</span> <span class="n">tomllib</span><span class="o">.</span><span class="n">TOMLDecodeError</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="kc">None</span> +<span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span> + <span class="kn">import</span> <span class="nn">toml</span> + + <span class="k">try</span><span class="p">:</span> + <span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"in1.toml"</span><span class="p">,</span> <span class="s2">"r"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="n">toml</span><span class="o">.</span><span class="n">load</span><span class="p">(</span><span class="n">f</span><span class="p">)</span> + <span class="k">except</span> <span class="n">toml</span><span class="o">.</span><span class="n">TomlDecodeError</span><span class="p">:</span> + <span class="n">d1</span> <span class="o">=</span> <span class="kc">None</span> +</pre></div> +</div> +</section> +<section id="porting-to-tomli-w"> +<h3>Porting to tomli-w<a class="headerlink" href="#porting-to-tomli-w" title="Permalink to this heading">¶</a></h3> +<p><a class="reference external" href="https://pypi.org/project/tomli-w/">tomli-w</a> provides a minimal module for dumping TOML files.</p> +<p>The key differences between <a class="reference external" href="https://pypi.org/project/toml/">toml</a> and tomli-w are:</p> +<ul class="simple"> +<li><p>the <code class="docutils literal notranslate"><span class="pre">dump()</span></code> function takes a file object open for writing in binary +mode whereas toml expected a file object open for writing in text mode</p></li> +<li><p>providing a custom encoder instance is not supported</p></li> +</ul> +<p>For example, the following code:</p> +<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">toml</span> + +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"out.toml"</span><span class="p">,</span> <span class="s2">"w"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">toml</span><span class="o">.</span><span class="n">dump</span><span class="p">({</span><span class="s2">"test"</span><span class="p">:</span> <span class="s2">"data"</span><span class="p">},</span> <span class="n">f</span><span class="p">)</span> +</pre></div> +</div> +<p>would be replaced by:</p> +<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">tomli_w</span> + +<span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s2">"out.toml"</span><span class="p">,</span> <span class="s2">"wb"</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span> + <span class="n">tomli_w</span><span class="o">.</span><span class="n">dump</span><span class="p">({</span><span class="s2">"test"</span><span class="p">:</span> <span class="s2">"data"</span><span class="p">},</span> <span class="n">f</span><span class="p">)</span> +</pre></div> +</div> +<p>Note that when both reading and writing TOML files is necessary, two +modules need to be imported and used separately rather than one.</p> +</section> +</section> </section> @@ -380,6 +504,7 @@ are provided for the purpose.</p> <li class="toctree-l2"><a class="reference internal" href="#python-3-10">Python 3.10</a></li> <li class="toctree-l2"><a class="reference internal" href="#python-3-9">Python 3.9</a></li> <li class="toctree-l2"><a class="reference internal" href="#python-3-8">Python 3.8</a></li> +<li class="toctree-l2"><a class="reference internal" href="#replacing-the-toml-package">Replacing the toml package</a></li> </ul> </li> <li class="toctree-l1"><a class="reference internal" href="migration.html">Migration guides</a></li> |