Skip to content

Commit 970d1bc

Browse files
authored
update toml++ to v2.4.0 (#55)
other small changes: - removed dependency on some of toml++'s internal macros - updated benchmark script to show relative speedup/slowdown factor - updated README with new benchmark data - updated `tloptional` - made use of `tloptional` over `std::optional` switched based on a configurable `#define` - added an explicit .clang-format config
1 parent f9d7c41 commit 970d1bc

File tree

11 files changed

+239
-70
lines changed

11 files changed

+239
-70
lines changed

.clang-format

+166
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
---
2+
Language: Cpp
3+
# BasedOnStyle: LLVM
4+
AccessModifierOffset: -2
5+
AlignAfterOpenBracket: Align
6+
AlignConsecutiveMacros: None
7+
AlignConsecutiveAssignments: None
8+
AlignConsecutiveBitFields: None
9+
AlignConsecutiveDeclarations: None
10+
AlignEscapedNewlines: Right
11+
AlignOperands: Align
12+
AlignTrailingComments: true
13+
AllowAllArgumentsOnNextLine: true
14+
AllowAllConstructorInitializersOnNextLine: true
15+
AllowAllParametersOfDeclarationOnNextLine: true
16+
AllowShortEnumsOnASingleLine: true
17+
AllowShortBlocksOnASingleLine: Never
18+
AllowShortCaseLabelsOnASingleLine: false
19+
AllowShortFunctionsOnASingleLine: All
20+
AllowShortLambdasOnASingleLine: All
21+
AllowShortIfStatementsOnASingleLine: Never
22+
AllowShortLoopsOnASingleLine: false
23+
AlwaysBreakAfterDefinitionReturnType: None
24+
AlwaysBreakAfterReturnType: None
25+
AlwaysBreakBeforeMultilineStrings: false
26+
AlwaysBreakTemplateDeclarations: MultiLine
27+
AttributeMacros:
28+
- __capability
29+
BinPackArguments: true
30+
BinPackParameters: true
31+
BraceWrapping:
32+
AfterCaseLabel: false
33+
AfterClass: false
34+
AfterControlStatement: Never
35+
AfterEnum: false
36+
AfterFunction: false
37+
AfterNamespace: false
38+
AfterObjCDeclaration: false
39+
AfterStruct: false
40+
AfterUnion: false
41+
AfterExternBlock: false
42+
BeforeCatch: false
43+
BeforeElse: false
44+
BeforeLambdaBody: false
45+
BeforeWhile: false
46+
IndentBraces: false
47+
SplitEmptyFunction: true
48+
SplitEmptyRecord: true
49+
SplitEmptyNamespace: true
50+
BreakBeforeBinaryOperators: None
51+
BreakBeforeConceptDeclarations: true
52+
BreakBeforeBraces: Attach
53+
BreakBeforeInheritanceComma: false
54+
BreakInheritanceList: BeforeColon
55+
BreakBeforeTernaryOperators: true
56+
BreakConstructorInitializersBeforeComma: false
57+
BreakConstructorInitializers: BeforeColon
58+
BreakAfterJavaFieldAnnotations: false
59+
BreakStringLiterals: true
60+
ColumnLimit: 80
61+
CommentPragmas: '^ IWYU pragma:'
62+
CompactNamespaces: false
63+
ConstructorInitializerAllOnOneLineOrOnePerLine: false
64+
ConstructorInitializerIndentWidth: 4
65+
ContinuationIndentWidth: 4
66+
Cpp11BracedListStyle: true
67+
DeriveLineEnding: true
68+
DerivePointerAlignment: false
69+
DisableFormat: false
70+
EmptyLineBeforeAccessModifier: LogicalBlock
71+
ExperimentalAutoDetectBinPacking: false
72+
FixNamespaceComments: true
73+
ForEachMacros:
74+
- foreach
75+
- Q_FOREACH
76+
- BOOST_FOREACH
77+
StatementAttributeLikeMacros:
78+
- Q_EMIT
79+
IncludeBlocks: Preserve
80+
IncludeCategories:
81+
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
82+
Priority: 2
83+
SortPriority: 0
84+
CaseSensitive: false
85+
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
86+
Priority: 3
87+
SortPriority: 0
88+
CaseSensitive: false
89+
- Regex: '.*'
90+
Priority: 1
91+
SortPriority: 0
92+
CaseSensitive: false
93+
IncludeIsMainRegex: '(Test)?$'
94+
IncludeIsMainSourceRegex: ''
95+
IndentCaseLabels: false
96+
IndentCaseBlocks: false
97+
IndentGotoLabels: true
98+
IndentPPDirectives: None
99+
IndentExternBlock: AfterExternBlock
100+
IndentRequires: false
101+
IndentWidth: 2
102+
IndentWrappedFunctionNames: false
103+
InsertTrailingCommas: None
104+
JavaScriptQuotes: Leave
105+
JavaScriptWrapImports: true
106+
KeepEmptyLinesAtTheStartOfBlocks: true
107+
MacroBlockBegin: ''
108+
MacroBlockEnd: ''
109+
MaxEmptyLinesToKeep: 1
110+
NamespaceIndentation: None
111+
ObjCBinPackProtocolList: Auto
112+
ObjCBlockIndentWidth: 2
113+
ObjCBreakBeforeNestedBlockParam: true
114+
ObjCSpaceAfterProperty: false
115+
ObjCSpaceBeforeProtocolList: true
116+
PenaltyBreakAssignment: 2
117+
PenaltyBreakBeforeFirstCallParameter: 19
118+
PenaltyBreakComment: 300
119+
PenaltyBreakFirstLessLess: 120
120+
PenaltyBreakString: 1000
121+
PenaltyBreakTemplateDeclaration: 10
122+
PenaltyExcessCharacter: 1000000
123+
PenaltyReturnTypeOnItsOwnLine: 60
124+
PenaltyIndentedWhitespace: 0
125+
PointerAlignment: Right
126+
ReflowComments: true
127+
SortIncludes: false
128+
SortJavaStaticImport: Before
129+
SortUsingDeclarations: true
130+
SpaceAfterCStyleCast: false
131+
SpaceAfterLogicalNot: false
132+
SpaceAfterTemplateKeyword: true
133+
SpaceBeforeAssignmentOperators: true
134+
SpaceBeforeCaseColon: false
135+
SpaceBeforeCpp11BracedList: false
136+
SpaceBeforeCtorInitializerColon: true
137+
SpaceBeforeInheritanceColon: true
138+
SpaceBeforeParens: ControlStatements
139+
SpaceAroundPointerQualifiers: Default
140+
SpaceBeforeRangeBasedForLoopColon: true
141+
SpaceInEmptyBlock: false
142+
SpaceInEmptyParentheses: false
143+
SpacesBeforeTrailingComments: 1
144+
SpacesInAngles: false
145+
SpacesInConditionalStatement: false
146+
SpacesInContainerLiterals: true
147+
SpacesInCStyleCastParentheses: false
148+
SpacesInParentheses: false
149+
SpacesInSquareBrackets: false
150+
SpaceBeforeSquareBrackets: false
151+
BitFieldColonSpacing: Both
152+
Standard: Latest
153+
StatementMacros:
154+
- Q_UNUSED
155+
- QT_REQUIRE_VERSION
156+
TabWidth: 8
157+
UseCRLF: false
158+
UseTab: Never
159+
WhitespaceSensitiveMacros:
160+
- STRINGIZE
161+
- PP_STRINGIZE
162+
- BOOST_PP_STRINGIZE
163+
- NS_SWIFT_NAME
164+
- CF_SWIFT_NAME
165+
...
166+

.github/workflows/wheels.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,10 @@ jobs:
6969

7070
steps:
7171
- uses: actions/checkout@v2
72-
- uses: DoozyX/clang-format-lint-action@v0.5
72+
- uses: DoozyX/clang-format-lint-action@v0.12
7373
with:
7474
source: "./include ./src"
75+
clangFormatVersion: 12
7576

7677
publish:
7778
runs-on: ubuntu-latest

README.md

+9-20
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
[![Conda Status](https://anaconda.org/dorafmon/pytomlpp/badges/version.svg)](https://anaconda.org/dorafmon/pytomlpp)
55
[![PyPI version](https://badge.fury.io/py/pytomlpp.svg)](https://badge.fury.io/py/pytomlpp)
66

7-
This is an unofficial python wrapper for `toml++` (https://marzer.github.io/tomlplusplus/).
7+
This is an python wrapper for `toml++` (https://marzer.github.io/tomlplusplus/).
88

99
Some points you may want to know before use:
10-
* Using `toml++` means that this module is fully compatible with TOML [v1.0.0-rc.3](https://toml.io/en/v1.0.0-rc.3).
10+
* Using `toml++` means that this module is fully compatible with TOML [v1.0.0](https://toml.io/en/v1.0.0).
1111
* We convert toml structure to native python data structures (dict/list etc.) when parsing, this is more inline with what `json` module does.
1212
* The binding is using [pybind11](https://github.com/pybind/pybind11).
1313
* The project is tested using [toml-test](https://github.com/BurntSushi/toml-test) and [pytest](https://github.com/pytest-dev/pytest).
@@ -29,27 +29,16 @@ Out[6]: '"你好" = "world"'
2929
```
3030

3131
# Why bother?
32-
There are some exisitng python TOML parser on the market but from my experience they are all purely implemented in python which is a bit slow.
32+
There are some existing python TOML parsers on the market but from my experience they are implemented purely in python which is a bit slow.
3333

3434
```
35-
In [1]: import pytomlpp
36-
37-
In [2]: import toml
38-
39-
In [3]: def run_parser(parser_func, toml_string):
40-
...: for i in range(1000):
41-
...: parser_func(toml_string)
42-
...:
43-
44-
In [4]: %timeit run_parser(pytomlpp.loads, toml_string)
45-
310 ms ± 56.7 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
46-
47-
In [5]: %timeit run_parser(toml.loads, toml_string)
48-
3.5 s ± 162 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
49-
50-
In [6]: pytomlpp.lib_version
51-
Out[6]: '1.3.2'
35+
Parsing data.toml 5000 times:
36+
pytomlpp: 0.662 s
37+
toml: 5.277 s (7.9x slower)
38+
qtoml: 8.020 s (12.1x slower)
39+
tomlkit: 32.898 s (49.6x slower)
5240
```
41+
Test it for yourself using [the benchmark script](benchmark/run.py).
5342

5443
# Installing
5544

benchmark/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pytomlpp
12
toml
23
tomlkit
34
qtoml

benchmark/run.py

+26-10
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,32 @@
44
import qtoml
55
import timeit
66

7-
def benchmark(name, func, number=5000):
7+
def benchmark(name, run_count, func, compare_to=None):
88
print(f'{name:>10}: Running...', end='', flush=True)
9-
res = str(timeit.timeit(func, number=number)).split('.')
10-
print('\b'*10 + f'{res[0]:>3}.{res[1]} s')
9+
time_taken = timeit.timeit(func, number=run_count)
10+
res = str(time_taken).split('.')
11+
print('\b'*10, end='')
12+
print(f'{res[0]:>4}.{res[1][:3]} s', end='')
13+
if compare_to is not None:
14+
delta = time_taken / compare_to
15+
relation = 'slower'
16+
if delta < 1.0:
17+
delta = 1.0 / delta
18+
relation = 'faster'
19+
delta = int(delta * 10.0) / 10.0
20+
print(f' ({delta}x {relation})', end='')
21+
print('')
22+
return time_taken
1123

12-
test_data = ''
13-
with open('data.toml', 'r', encoding='utf-8') as f:
14-
test_data = f.read()
24+
def run(run_count = 5000):
25+
test_data = ''
26+
with open('data.toml', 'r', encoding='utf-8') as f:
27+
test_data = f.read()
28+
print(f'Parsing data.toml {run_count} times:')
29+
baseline = benchmark('pytomlpp', run_count, lambda: pytomlpp.loads(test_data))
30+
benchmark('toml', run_count, lambda: toml.loads(test_data), compare_to=baseline)
31+
benchmark('qtoml', run_count, lambda: qtoml.loads(test_data), compare_to=baseline)
32+
benchmark('tomlkit', run_count, lambda: tomlkit.parse(test_data), compare_to=baseline)
1533

16-
benchmark('pytomlpp', lambda: pytomlpp.loads(test_data))
17-
benchmark('toml', lambda: toml.loads(test_data))
18-
benchmark('qtoml', lambda: qtoml.loads(test_data))
19-
benchmark('tomlkit', lambda: tomlkit.parse(test_data))
34+
if __name__ == '__main__':
35+
run()

include/pytomlpp/pytomlpp.hpp

+16-9
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
#pragma once
22

3+
// pytomlpp config
4+
#ifndef PYTOMLPP_USE_TL_OPTIONAL
5+
#ifdef __APPLE__
6+
#define PYTOMLPP_USE_TL_OPTIONAL 1
7+
#else
8+
#define PYTOMLPP_USE_TL_OPTIONAL 0
9+
#endif
10+
#endif // PYTOMLPP_USE_TL_OPTIONAL
11+
#ifndef PYTOMLPP_PROFILING
12+
#define PYTOMLPP_PROFILING 0 // see a profiling summary on shutdown
13+
#endif
14+
315
// toml++ config
4-
#define TOML_OPTIONAL_TYPE tl::optional
516
#define TOML_WINDOWS_COMPAT 0
617
#define TOML_LARGE_FILES 1
718
#define TOML_HEADER_ONLY 0
8-
#define TOML_UNDEF_MACROS 0 // leaves some toml++'s macros for us to use
919
#ifdef __APPLE__
1020
#define TOML_INT_CHARCONV 0
1121
#endif
12-
13-
// pytomlpp config
14-
#ifndef PYTOMLPP_PROFILING
15-
#define PYTOMLPP_PROFILING 0 // see a profiling summary on shutdown
22+
#if PYTOMLPP_USE_TL_OPTIONAL
23+
#define TOML_OPTIONAL_TYPE tl::optional
1624
#endif
1725

1826
// common includes
19-
#include <tomlplusplus/include/toml++/toml_preprocessor.h>
20-
TOML_DISABLE_WARNINGS
27+
#if PYTOMLPP_USE_TL_OPTIONAL
2128
#include <optional.hpp>
29+
#endif
2230
#include <pybind11/pybind11.h>
2331
#include <sstream>
2432
#include <tomlplusplus/include/toml++/toml.h>
25-
TOML_ENABLE_WARNINGS
2633

2734
// namespace and type forward declarations
2835
namespace py = pybind11;

src/encoding_decoding.cpp

-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
11
#include <pytomlpp/pytomlpp.hpp>
2-
3-
TOML_DISABLE_WARNINGS
42
#include <pybind11/stl.h>
5-
TOML_ENABLE_WARNINGS
63

74
namespace pytomlpp {
85
py::list toml_array_to_py_list(toml::array &&a) {

src/pytomlpp.cpp

-2
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@
22

33
#include <pytomlpp/pytomlpp.hpp>
44
#if PYTOMLPP_PROFILING
5-
TOML_DISABLE_WARNINGS
65
#include <chrono>
76
#include <iomanip>
87
#include <pybind11/iostream.h>
9-
TOML_ENABLE_WARNINGS
108
#endif // PYTOMLPP_PROFILING
119

1210
namespace {

src/type_casters.cpp

-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
#include <pytomlpp/pytomlpp.hpp>
2-
3-
TOML_DISABLE_WARNINGS
4-
//#include <pybind11/chrono.h>
52
#include <datetime.h>
6-
TOML_ENABLE_WARNINGS
73

84
namespace {
95
void lazy_init_py_date_time() noexcept {

0 commit comments

Comments
 (0)