mercurial/thirdparty/tomli/README.md
changeset 50761 2c34c9b61a4f
equal deleted inserted replaced
50760:b584dae08774 50761:2c34c9b61a4f
       
     1 [![Build Status](https://github.com/hukkin/tomli/workflows/Tests/badge.svg?branch=master)](https://github.com/hukkin/tomli/actions?query=workflow%3ATests+branch%3Amaster+event%3Apush)
       
     2 [![codecov.io](https://codecov.io/gh/hukkin/tomli/branch/master/graph/badge.svg)](https://codecov.io/gh/hukkin/tomli)
       
     3 [![PyPI version](https://img.shields.io/pypi/v/tomli)](https://pypi.org/project/tomli)
       
     4 
       
     5 # Tomli
       
     6 
       
     7 > A lil' TOML parser
       
     8 
       
     9 **Table of Contents**  *generated with [mdformat-toc](https://github.com/hukkin/mdformat-toc)*
       
    10 
       
    11 <!-- mdformat-toc start --slug=github --maxlevel=6 --minlevel=2 -->
       
    12 
       
    13 - [Intro](#intro)
       
    14 - [Installation](#installation)
       
    15 - [Usage](#usage)
       
    16   - [Parse a TOML string](#parse-a-toml-string)
       
    17   - [Parse a TOML file](#parse-a-toml-file)
       
    18   - [Handle invalid TOML](#handle-invalid-toml)
       
    19   - [Construct `decimal.Decimal`s from TOML floats](#construct-decimaldecimals-from-toml-floats)
       
    20 - [FAQ](#faq)
       
    21   - [Why this parser?](#why-this-parser)
       
    22   - [Is comment preserving round-trip parsing supported?](#is-comment-preserving-round-trip-parsing-supported)
       
    23   - [Is there a `dumps`, `write` or `encode` function?](#is-there-a-dumps-write-or-encode-function)
       
    24   - [How do TOML types map into Python types?](#how-do-toml-types-map-into-python-types)
       
    25 - [Performance](#performance)
       
    26 
       
    27 <!-- mdformat-toc end -->
       
    28 
       
    29 ## Intro<a name="intro"></a>
       
    30 
       
    31 Tomli is a Python library for parsing [TOML](https://toml.io).
       
    32 Tomli is fully compatible with [TOML v1.0.0](https://toml.io/en/v1.0.0).
       
    33 
       
    34 ## Installation<a name="installation"></a>
       
    35 
       
    36 ```bash
       
    37 pip install tomli
       
    38 ```
       
    39 
       
    40 ## Usage<a name="usage"></a>
       
    41 
       
    42 ### Parse a TOML string<a name="parse-a-toml-string"></a>
       
    43 
       
    44 ```python
       
    45 import tomli
       
    46 
       
    47 toml_str = """
       
    48            gretzky = 99
       
    49 
       
    50            [kurri]
       
    51            jari = 17
       
    52            """
       
    53 
       
    54 toml_dict = tomli.loads(toml_str)
       
    55 assert toml_dict == {"gretzky": 99, "kurri": {"jari": 17}}
       
    56 ```
       
    57 
       
    58 ### Parse a TOML file<a name="parse-a-toml-file"></a>
       
    59 
       
    60 ```python
       
    61 import tomli
       
    62 
       
    63 with open("path_to_file/conf.toml", "rb") as f:
       
    64     toml_dict = tomli.load(f)
       
    65 ```
       
    66 
       
    67 The file must be opened in binary mode (with the `"rb"` flag).
       
    68 Binary mode will enforce decoding the file as UTF-8 with universal newlines disabled,
       
    69 both of which are required to correctly parse TOML.
       
    70 Support for text file objects is deprecated for removal in the next major release.
       
    71 
       
    72 ### Handle invalid TOML<a name="handle-invalid-toml"></a>
       
    73 
       
    74 ```python
       
    75 import tomli
       
    76 
       
    77 try:
       
    78     toml_dict = tomli.loads("]] this is invalid TOML [[")
       
    79 except tomli.TOMLDecodeError:
       
    80     print("Yep, definitely not valid.")
       
    81 ```
       
    82 
       
    83 Note that while the `TOMLDecodeError` type is public API, error messages of raised instances of it are not.
       
    84 Error messages should not be assumed to stay constant across Tomli versions.
       
    85 
       
    86 ### Construct `decimal.Decimal`s from TOML floats<a name="construct-decimaldecimals-from-toml-floats"></a>
       
    87 
       
    88 ```python
       
    89 from decimal import Decimal
       
    90 import tomli
       
    91 
       
    92 toml_dict = tomli.loads("precision-matters = 0.982492", parse_float=Decimal)
       
    93 assert toml_dict["precision-matters"] == Decimal("0.982492")
       
    94 ```
       
    95 
       
    96 Note that `decimal.Decimal` can be replaced with another callable that converts a TOML float from string to a Python type.
       
    97 The `decimal.Decimal` is, however, a practical choice for use cases where float inaccuracies can not be tolerated.
       
    98 
       
    99 Illegal types include `dict`, `list`, and anything that has the `append` attribute.
       
   100 Parsing floats into an illegal type results in undefined behavior.
       
   101 
       
   102 ## FAQ<a name="faq"></a>
       
   103 
       
   104 ### Why this parser?<a name="why-this-parser"></a>
       
   105 
       
   106 - it's lil'
       
   107 - pure Python with zero dependencies
       
   108 - the fastest pure Python parser [\*](#performance):
       
   109   15x as fast as [tomlkit](https://pypi.org/project/tomlkit/),
       
   110   2.4x as fast as [toml](https://pypi.org/project/toml/)
       
   111 - outputs [basic data types](#how-do-toml-types-map-into-python-types) only
       
   112 - 100% spec compliant: passes all tests in
       
   113   [a test set](https://github.com/toml-lang/compliance/pull/8)
       
   114   soon to be merged to the official
       
   115   [compliance tests for TOML](https://github.com/toml-lang/compliance)
       
   116   repository
       
   117 - thoroughly tested: 100% branch coverage
       
   118 
       
   119 ### Is comment preserving round-trip parsing supported?<a name="is-comment-preserving-round-trip-parsing-supported"></a>
       
   120 
       
   121 No.
       
   122 
       
   123 The `tomli.loads` function returns a plain `dict` that is populated with builtin types and types from the standard library only.
       
   124 Preserving comments requires a custom type to be returned so will not be supported,
       
   125 at least not by the `tomli.loads` and `tomli.load` functions.
       
   126 
       
   127 Look into [TOML Kit](https://github.com/sdispater/tomlkit) if preservation of style is what you need.
       
   128 
       
   129 ### Is there a `dumps`, `write` or `encode` function?<a name="is-there-a-dumps-write-or-encode-function"></a>
       
   130 
       
   131 [Tomli-W](https://github.com/hukkin/tomli-w) is the write-only counterpart of Tomli, providing `dump` and `dumps` functions.
       
   132 
       
   133 The core library does not include write capability, as most TOML use cases are read-only, and Tomli intends to be minimal.
       
   134 
       
   135 ### How do TOML types map into Python types?<a name="how-do-toml-types-map-into-python-types"></a>
       
   136 
       
   137 | TOML type        | Python type         | Details                                                      |
       
   138 | ---------------- | ------------------- | ------------------------------------------------------------ |
       
   139 | Document Root    | `dict`              |                                                              |
       
   140 | Key              | `str`               |                                                              |
       
   141 | String           | `str`               |                                                              |
       
   142 | Integer          | `int`               |                                                              |
       
   143 | Float            | `float`             |                                                              |
       
   144 | Boolean          | `bool`              |                                                              |
       
   145 | Offset Date-Time | `datetime.datetime` | `tzinfo` attribute set to an instance of `datetime.timezone` |
       
   146 | Local Date-Time  | `datetime.datetime` | `tzinfo` attribute set to `None`                             |
       
   147 | Local Date       | `datetime.date`     |                                                              |
       
   148 | Local Time       | `datetime.time`     |                                                              |
       
   149 | Array            | `list`              |                                                              |
       
   150 | Table            | `dict`              |                                                              |
       
   151 | Inline Table     | `dict`              |                                                              |
       
   152 
       
   153 ## Performance<a name="performance"></a>
       
   154 
       
   155 The `benchmark/` folder in this repository contains a performance benchmark for comparing the various Python TOML parsers.
       
   156 The benchmark can be run with `tox -e benchmark-pypi`.
       
   157 Running the benchmark on my personal computer output the following:
       
   158 
       
   159 ```console
       
   160 foo@bar:~/dev/tomli$ tox -e benchmark-pypi
       
   161 benchmark-pypi installed: attrs==19.3.0,click==7.1.2,pytomlpp==1.0.2,qtoml==0.3.0,rtoml==0.7.0,toml==0.10.2,tomli==1.1.0,tomlkit==0.7.2
       
   162 benchmark-pypi run-test-pre: PYTHONHASHSEED='2658546909'
       
   163 benchmark-pypi run-test: commands[0] | python -c 'import datetime; print(datetime.date.today())'
       
   164 2021-07-23
       
   165 benchmark-pypi run-test: commands[1] | python --version
       
   166 Python 3.8.10
       
   167 benchmark-pypi run-test: commands[2] | python benchmark/run.py
       
   168 Parsing data.toml 5000 times:
       
   169 ------------------------------------------------------
       
   170     parser |  exec time | performance (more is better)
       
   171 -----------+------------+-----------------------------
       
   172      rtoml |    0.901 s | baseline (100%)
       
   173   pytomlpp |     1.08 s | 83.15%
       
   174      tomli |     3.89 s | 23.15%
       
   175       toml |     9.36 s | 9.63%
       
   176      qtoml |     11.5 s | 7.82%
       
   177    tomlkit |     56.8 s | 1.59%
       
   178 ```
       
   179 
       
   180 The parsers are ordered from fastest to slowest, using the fastest parser as baseline.
       
   181 Tomli performed the best out of all pure Python TOML parsers,
       
   182 losing only to pytomlpp (wraps C++) and rtoml (wraps Rust).