summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'guide/porting.html')
-rw-r--r--guide/porting.html125
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">&quot;in1.toml&quot;</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">&quot;in2.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</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">&#39;test = &quot;foo&quot;</span><span class="se">\n</span><span class="s1">&#39;</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">&gt;=</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">&quot;in1.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</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 &quot;TOML&quot;</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">&quot;in2.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</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">&#39;test = &quot;foo&quot;</span><span class="se">\n</span><span class="s1">&#39;</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">&gt;=</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">&quot;in1.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;rb&quot;</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">&quot;in1.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;r&quot;</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">&quot;out.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;w&quot;</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">&quot;test&quot;</span><span class="p">:</span> <span class="s2">&quot;data&quot;</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">&quot;out.toml&quot;</span><span class="p">,</span> <span class="s2">&quot;wb&quot;</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">&quot;test&quot;</span><span class="p">:</span> <span class="s2">&quot;data&quot;</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>