pygixml 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pygixml-0.1.0/.github/workflows/wheels.yml +123 -0
- pygixml-0.1.0/.gitignore +39 -0
- pygixml-0.1.0/.gitmodules +3 -0
- pygixml-0.1.0/CMakeLists.txt +55 -0
- pygixml-0.1.0/LICENSE +24 -0
- pygixml-0.1.0/PKG-INFO +162 -0
- pygixml-0.1.0/README.md +139 -0
- pygixml-0.1.0/benchmarks/benchmark_parsing.py +220 -0
- pygixml-0.1.0/benchmarks/clean_visualization.py +196 -0
- pygixml-0.1.0/benchmarks/results/benchmark_results.csv +46 -0
- pygixml-0.1.0/benchmarks/results/performance_comparison.svg +2902 -0
- pygixml-0.1.0/examples/basic_usage.py +128 -0
- pygixml-0.1.0/pyproject.toml +63 -0
- pygixml-0.1.0/src/pygixml/__init__.py +22 -0
- pygixml-0.1.0/src/pygixml/pygixml.pyx +256 -0
- pygixml-0.1.0/src/third_party/pugixml/.codecov.yml +7 -0
- pygixml-0.1.0/src/third_party/pugixml/.gitattributes +1 -0
- pygixml-0.1.0/src/third_party/pugixml/.github/ISSUE_TEMPLATE/bug_report.md +8 -0
- pygixml-0.1.0/src/third_party/pugixml/.github/ISSUE_TEMPLATE/config.yml +5 -0
- pygixml-0.1.0/src/third_party/pugixml/.github/ISSUE_TEMPLATE/feature_request.md +8 -0
- pygixml-0.1.0/src/third_party/pugixml/.github/workflows/build.yml +76 -0
- pygixml-0.1.0/src/third_party/pugixml/.github/workflows/cifuzz.yml +24 -0
- pygixml-0.1.0/src/third_party/pugixml/.gitignore +5 -0
- pygixml-0.1.0/src/third_party/pugixml/CMakeLists.txt +309 -0
- pygixml-0.1.0/src/third_party/pugixml/LICENSE.md +24 -0
- pygixml-0.1.0/src/third_party/pugixml/README.md +81 -0
- pygixml-0.1.0/src/third_party/pugixml/SECURITY.md +9 -0
- pygixml-0.1.0/src/third_party/pugixml/appveyor.yml +37 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/config.adoc +7 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/dom_tree.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_link1.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_link2.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_pch1.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_pch2.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_pch3.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2005_pch4.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2010_link1.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/images/vs2010_link2.png +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/manual.adoc +3283 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/manual.html +6279 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/quickstart.adoc +287 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/quickstart.html +1106 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/character.xml +8 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/custom_memory_management.cpp +27 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/include.cpp +64 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/load_error_handling.cpp +33 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/load_file.cpp +16 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/load_memory.cpp +66 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/load_options.cpp +30 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/load_stream.cpp +97 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/modify_add.cpp +29 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/modify_base.cpp +43 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/modify_remove.cpp +27 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_custom_writer.cpp +116 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_declaration.cpp +27 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_file.cpp +17 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_options.cpp +48 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_stream.cpp +18 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/save_subtree.cpp +26 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/text.cpp +35 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/transitions.xml +7 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/traverse_base.cpp +51 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/traverse_iter.cpp +27 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/traverse_predicate.cpp +48 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/traverse_rangefor.cpp +32 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/traverse_walker.cpp +35 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/tree.xml +12 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/weekly-shift_jis.xml +78 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/weekly-utf-16.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/weekly-utf-8.xml +78 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/xgconsole.xml +12 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/xpath_error.cpp +43 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/xpath_query.cpp +36 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/xpath_select.cpp +28 -0
- pygixml-0.1.0/src/third_party/pugixml/docs/samples/xpath_variables.cpp +38 -0
- pygixml-0.1.0/src/third_party/pugixml/readme.txt +50 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/archive.py +54 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/cocoapods_push.sh +4 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/natvis/pugixml.natvis +77 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/natvis/pugixml_compact.natvis +506 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/nuget/pugixml.nuspec +20 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/nuget_build.ps1 +70 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/premake4.lua +92 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml-config.cmake.in +12 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml.pc.in +11 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml.podspec +14 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml.xcodeproj/project.pbxproj +212 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_airplay.mkf +13 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_codeblocks.cbp +44 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_codelite.project +56 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_dll.rc +45 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2005.vcproj +343 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2005_static.vcproj +343 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2008.vcproj +339 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2008_static.vcproj +339 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2010.vcxproj +191 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2010_static.vcxproj +191 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2013.vcxproj +199 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2013_static.vcxproj +199 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2015.vcxproj +172 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2015_static.vcxproj +176 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2017.vcxproj +172 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2017_static.vcxproj +176 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2019.vcxproj +176 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2019_static.vcxproj +180 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2022.vcxproj +176 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/pugixml_vs2022_static.vcxproj +180 -0
- pygixml-0.1.0/src/third_party/pugixml/scripts/sbom.cdx.json +47 -0
- pygixml-0.1.0/src/third_party/pugixml/src/pugiconfig.hpp +78 -0
- pygixml-0.1.0/src/third_party/pugixml/src/pugixml.cpp +13557 -0
- pygixml-0.1.0/src/third_party/pugixml/src/pugixml.hpp +1583 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/allocator.cpp +175 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/allocator.hpp +10 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/autotest-appveyor.ps1 +89 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/cmake-appveyor.ps1 +57 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/empty.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/large.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/latintest_latin1.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/latintest_utf8.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/multiline.xml +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/small.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/truncation.xml +19 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_be.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_be_bom.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_be_clean.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_be_nodecl.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_le.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_le_bom.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_le_clean.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf16_le_nodecl.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_be.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_be_bom.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_be_clean.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_be_nodecl.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_le.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_le_bom.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_le_clean.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf32_le_nodecl.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf8.xml +87 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf8_bom.xml +87 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf8_clean.xml +84 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data/utftest_utf8_nodecl.xml +86 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data//321/202/320/265/321/201/321/202.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/basic.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/doctype.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/refs.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/types.xml +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/utf16.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_parse/utf32.xml +0 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_xpath/basic.xpath +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_xpath/functions.xpath +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_xpath/math.xpath +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_xpath/path.xpath +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/data_fuzz_xpath/predicate.xpath +1 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/fuzz_parse.cpp +14 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/fuzz_parse.dict +72 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/fuzz_setup.sh +11 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/fuzz_xpath.cpp +46 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/fuzz_xpath.dict +72 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/helpers.hpp +114 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/main.cpp +218 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test.cpp +220 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test.hpp +175 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_compact.cpp +150 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_deprecated.cpp +25 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_document.cpp +1884 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_dom_modify.cpp +2039 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_dom_text.cpp +596 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_dom_traverse.cpp +1478 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_guard.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_iosfwd_1.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_iosfwd_2.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_iostream_1.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_iostream_2.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_only_1.cpp +21 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_only_2.cpp +21 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_string_1.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_string_2.cpp +3 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_header_string_iostream.cpp +5 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_memory.cpp +303 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_parse.cpp +1463 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_parse_doctype.cpp +366 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_unicode.cpp +153 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_version.cpp +5 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_write.cpp +733 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath.cpp +815 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_api.cpp +646 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_functions.cpp +844 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_operators.cpp +566 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_parse.cpp +416 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_paths.cpp +783 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_paths_abbrev_w3c.cpp +219 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_paths_w3c.cpp +312 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_variables.cpp +673 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_xalan_1.cpp +411 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_xalan_2.cpp +417 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_xalan_3.cpp +321 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_xalan_4.cpp +300 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/test_xpath_xalan_5.cpp +295 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/writer_string.cpp +79 -0
- pygixml-0.1.0/src/third_party/pugixml/tests/writer_string.hpp +27 -0
- pygixml-0.1.0/tests/test_advanced.py +225 -0
- pygixml-0.1.0/tests/test_basic.py +165 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
name: PYTHON_BUILD_TEST_DEPLOY
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
pull_request:
|
|
6
|
+
push:
|
|
7
|
+
branches:
|
|
8
|
+
- master
|
|
9
|
+
tags:
|
|
10
|
+
- "v*"
|
|
11
|
+
|
|
12
|
+
env:
|
|
13
|
+
FORCE_COLOR: 3
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: github.workflow-${{ github.workflow }}-${{ github.ref }}
|
|
17
|
+
cancel-in-progress: true
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
contents: write
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build_sdist:
|
|
24
|
+
name: Build SDist
|
|
25
|
+
runs-on: ubuntu-latest
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
with:
|
|
29
|
+
submodules: true
|
|
30
|
+
|
|
31
|
+
- uses: actions/setup-python@v4
|
|
32
|
+
with:
|
|
33
|
+
python-version: "3.x"
|
|
34
|
+
|
|
35
|
+
- name: Install build dependencies
|
|
36
|
+
run: pip install build twine
|
|
37
|
+
|
|
38
|
+
- name: Build SDist
|
|
39
|
+
run: python -m build --sdist
|
|
40
|
+
|
|
41
|
+
- name: Check metadata
|
|
42
|
+
run: twine check dist/*
|
|
43
|
+
|
|
44
|
+
- uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
path: dist/*.tar.gz
|
|
47
|
+
overwrite: true
|
|
48
|
+
|
|
49
|
+
build_wheels:
|
|
50
|
+
name: Wheels on ${{ matrix.os }}
|
|
51
|
+
runs-on: ${{ matrix.os }}
|
|
52
|
+
strategy:
|
|
53
|
+
fail-fast: true
|
|
54
|
+
matrix:
|
|
55
|
+
os: [ubuntu-latest, windows-latest]
|
|
56
|
+
|
|
57
|
+
steps:
|
|
58
|
+
- uses: actions/checkout@v4
|
|
59
|
+
with:
|
|
60
|
+
submodules: true
|
|
61
|
+
|
|
62
|
+
- name: Build wheels
|
|
63
|
+
uses: pypa/cibuildwheel@v2.16.5
|
|
64
|
+
env:
|
|
65
|
+
# Disable building PyPy wheels on all platforms
|
|
66
|
+
CIBW_SKIP: pp*
|
|
67
|
+
# Build for all supported Python versions
|
|
68
|
+
CIBW_BUILD_VERBOSITY: 1
|
|
69
|
+
|
|
70
|
+
- name: Verify clean directory
|
|
71
|
+
run: git diff --exit-code
|
|
72
|
+
shell: bash
|
|
73
|
+
|
|
74
|
+
- uses: actions/upload-artifact@v4
|
|
75
|
+
with:
|
|
76
|
+
name: wheelhouse-${{ matrix.os }}
|
|
77
|
+
path: wheelhouse/*.whl
|
|
78
|
+
overwrite: false
|
|
79
|
+
|
|
80
|
+
release:
|
|
81
|
+
name: Release Assets and Upload to PyPI
|
|
82
|
+
needs: [build_wheels, build_sdist]
|
|
83
|
+
runs-on: ubuntu-latest
|
|
84
|
+
if: github.event_name == 'push' && (github.ref == 'refs/heads/master' || startsWith(github.ref, 'refs/tags/'))
|
|
85
|
+
|
|
86
|
+
steps:
|
|
87
|
+
# Determine release type
|
|
88
|
+
- name: Determine release type
|
|
89
|
+
id: release_type
|
|
90
|
+
run: |
|
|
91
|
+
if [[ "${{ github.ref }}" =~ ^refs/tags/v.*$ ]]; then
|
|
92
|
+
echo "RELEASE_NAME=${GITHUB_REF#refs/tags/}" >> $GITHUB_ENV
|
|
93
|
+
echo "IS_TAG=true" >> $GITHUB_ENV
|
|
94
|
+
else
|
|
95
|
+
echo "RELEASE_NAME=__beta__" >> $GITHUB_ENV
|
|
96
|
+
echo "IS_TAG=false" >> $GITHUB_ENV
|
|
97
|
+
fi
|
|
98
|
+
shell: bash
|
|
99
|
+
|
|
100
|
+
- uses: actions/download-artifact@v4
|
|
101
|
+
with:
|
|
102
|
+
path: dist
|
|
103
|
+
merge-multiple: true
|
|
104
|
+
|
|
105
|
+
- name: List dist directory
|
|
106
|
+
run: ls -la dist/
|
|
107
|
+
|
|
108
|
+
- name: Create or update release
|
|
109
|
+
id: create_release
|
|
110
|
+
uses: softprops/action-gh-release@v2
|
|
111
|
+
with:
|
|
112
|
+
tag_name: ${{ env.RELEASE_NAME }}
|
|
113
|
+
name: ${{ env.RELEASE_NAME }}
|
|
114
|
+
draft: false
|
|
115
|
+
prerelease: ${{ env.IS_TAG }} == 'false'
|
|
116
|
+
files: dist/*
|
|
117
|
+
token: ${{ secrets.GITHUB_TOKEN }}
|
|
118
|
+
|
|
119
|
+
- name: Publishing to PyPi
|
|
120
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
121
|
+
if: ${{ env.IS_TAG }} == 'true'
|
|
122
|
+
with:
|
|
123
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
pygixml-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Build directories
|
|
2
|
+
build/
|
|
3
|
+
dist/
|
|
4
|
+
*.egg-info/
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.pyc
|
|
7
|
+
*.pyo
|
|
8
|
+
*.pyd
|
|
9
|
+
*.so
|
|
10
|
+
|
|
11
|
+
# CMake
|
|
12
|
+
CMakeCache.txt
|
|
13
|
+
CMakeFiles/
|
|
14
|
+
cmake_install.cmake
|
|
15
|
+
Makefile
|
|
16
|
+
*.cmake
|
|
17
|
+
|
|
18
|
+
# Development
|
|
19
|
+
*.swp
|
|
20
|
+
*.swo
|
|
21
|
+
*~
|
|
22
|
+
.DS_Store
|
|
23
|
+
|
|
24
|
+
# Python
|
|
25
|
+
.pytest_cache/
|
|
26
|
+
.coverage
|
|
27
|
+
htmlcov/
|
|
28
|
+
|
|
29
|
+
# IDE
|
|
30
|
+
.vscode/
|
|
31
|
+
.idea/
|
|
32
|
+
*.sublime-*
|
|
33
|
+
|
|
34
|
+
# Temporary files
|
|
35
|
+
*.tmp
|
|
36
|
+
*.temp
|
|
37
|
+
|
|
38
|
+
# Documentation
|
|
39
|
+
docs/_build/
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15)
|
|
2
|
+
project(pygixml)
|
|
3
|
+
|
|
4
|
+
# Set C++ standard
|
|
5
|
+
set(CMAKE_CXX_STANDARD 11)
|
|
6
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
7
|
+
|
|
8
|
+
# Optimize for performance
|
|
9
|
+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
|
|
10
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -DNDEBUG")
|
|
11
|
+
else()
|
|
12
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
|
|
13
|
+
endif()
|
|
14
|
+
|
|
15
|
+
# Additional optimization flags for GCC/Clang
|
|
16
|
+
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
|
17
|
+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native -fomit-frame-pointer -fno-stack-protector")
|
|
18
|
+
endif()
|
|
19
|
+
|
|
20
|
+
# Set build type to Release for better performance
|
|
21
|
+
if(NOT CMAKE_BUILD_TYPE)
|
|
22
|
+
set(CMAKE_BUILD_TYPE Release)
|
|
23
|
+
endif()
|
|
24
|
+
|
|
25
|
+
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
|
26
|
+
|
|
27
|
+
# Find Python and Cython
|
|
28
|
+
find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)
|
|
29
|
+
find_package(Cython MODULE REQUIRED VERSION 3.0)
|
|
30
|
+
include(UseCython)
|
|
31
|
+
|
|
32
|
+
# Add pugixml
|
|
33
|
+
add_subdirectory(src/third_party/pugixml)
|
|
34
|
+
|
|
35
|
+
# Set Python module output directory
|
|
36
|
+
set(PYTHON_MODULE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/pygixml)
|
|
37
|
+
|
|
38
|
+
# Transpile Cython to C++
|
|
39
|
+
cython_transpile(src/pygixml/pygixml.pyx LANGUAGE CXX OUTPUT_VARIABLE pygixml_cpp_file)
|
|
40
|
+
|
|
41
|
+
# Create the Python extension module
|
|
42
|
+
python_add_library(pygixml MODULE "${pygixml_cpp_file}" WITH_SOABI)
|
|
43
|
+
|
|
44
|
+
# Link pugixml to our module
|
|
45
|
+
target_link_libraries(pygixml PRIVATE pugixml)
|
|
46
|
+
|
|
47
|
+
# Include directories
|
|
48
|
+
target_include_directories(pygixml PRIVATE
|
|
49
|
+
${CMAKE_CURRENT_SOURCE_DIR}/src/third_party/pugixml/src
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
# Install the module
|
|
53
|
+
install(TARGETS pygixml
|
|
54
|
+
DESTINATION .
|
|
55
|
+
)
|
pygixml-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Mohammad Raziei
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
1. The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
2. **STAR REQUIREMENT**: To use this software, you must star the project on GitHub:
|
|
16
|
+
https://github.com/MohammadRaziei/pygixml
|
|
17
|
+
|
|
18
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
19
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
20
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
21
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
22
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
23
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
24
|
+
SOFTWARE.
|
pygixml-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: pygixml
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python wrapper for pugixml using Cython - Please star the project on GitHub to use!
|
|
5
|
+
Keywords: xml,pugixml,cython,wrapper
|
|
6
|
+
Author-Email: Mohammad Raziei <mohammadraziei1375@gmail.com>
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Provides-Extra: test
|
|
19
|
+
Requires-Dist: pytest>=7.0.0; extra == "test"
|
|
20
|
+
Requires-Dist: pytest-xdist>=3.0.0; extra == "test"
|
|
21
|
+
Requires-Dist: pytest-timeout>=2.0.0; extra == "test"
|
|
22
|
+
Description-Content-Type: text/markdown
|
|
23
|
+
|
|
24
|
+
# pygixml
|
|
25
|
+
|
|
26
|
+
[](https://www.python.org/)
|
|
27
|
+
[](https://opensource.org/licenses/MIT)
|
|
28
|
+
[](https://github.com/MohammadRaziei/pygixml/actions)
|
|
29
|
+
[](https://github.com/MohammadRaziei/pygixml)
|
|
30
|
+
|
|
31
|
+
A high-performance Python wrapper for [pugixml](https://pugixml.org/) using Cython, providing fast XML parsing and manipulation capabilities.
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## 🚀 Performance
|
|
36
|
+
|
|
37
|
+
pygixml delivers exceptional performance compared to other XML libraries:
|
|
38
|
+
|
|
39
|
+
### Performance Comparison (5000 XML elements)
|
|
40
|
+
|
|
41
|
+
| Library | Parsing Time | Speedup vs ElementTree |
|
|
42
|
+
|---------|--------------|------------------------|
|
|
43
|
+
| **pygixml** | 0.00077s | **15.9x faster** |
|
|
44
|
+
| **lxml** | 0.00407s | 3.0x faster |
|
|
45
|
+
| **ElementTree** | 0.01220s | 1.0x (baseline) |
|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
### Key Performance Highlights
|
|
50
|
+
|
|
51
|
+
- **15.9x faster** than Python's ElementTree for XML parsing
|
|
52
|
+
- **5.3x faster** than lxml for XML parsing
|
|
53
|
+
- **Memory efficient** - uses pugixml's optimized C++ memory management
|
|
54
|
+
- **Scalable performance** - maintains speed advantage across different XML sizes
|
|
55
|
+
|
|
56
|
+
## Installation
|
|
57
|
+
|
|
58
|
+
### From Pypi repositoey
|
|
59
|
+
```bash
|
|
60
|
+
pip install pygixml
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### From Source
|
|
64
|
+
```bash
|
|
65
|
+
git clone --recurse-submodules https://github.com/MohammadRaziei/pygixml.git
|
|
66
|
+
pip install ./pygixml
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Development Installation
|
|
70
|
+
```bash
|
|
71
|
+
pip install ./pygixml[test]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Quick SWtart
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
import pygixml
|
|
78
|
+
|
|
79
|
+
# Parse XML from string
|
|
80
|
+
xml_string = """
|
|
81
|
+
<library>
|
|
82
|
+
<book id="1">
|
|
83
|
+
<title>The Great Gatsby</title>
|
|
84
|
+
<author>F. Scott Fitzgerald</author>
|
|
85
|
+
<year>1925</year>
|
|
86
|
+
</book>
|
|
87
|
+
</library>
|
|
88
|
+
"""
|
|
89
|
+
|
|
90
|
+
doc = pygixml.parse_string(xml_string)
|
|
91
|
+
root = doc.first_child()
|
|
92
|
+
|
|
93
|
+
# Access elements
|
|
94
|
+
book = root.first_child()
|
|
95
|
+
title = book.child("title")
|
|
96
|
+
print(f"Title: {title.child_value()}") # Output: Title: The Great Gatsby
|
|
97
|
+
|
|
98
|
+
# Create new XML
|
|
99
|
+
doc = pygixml.XMLDocument()
|
|
100
|
+
root = doc.append_child("catalog")
|
|
101
|
+
product = root.append_child("product")
|
|
102
|
+
product.append_child("name").set_value("Laptop")
|
|
103
|
+
product.append_child("price").set_value("999.99")
|
|
104
|
+
|
|
105
|
+
# Save to file
|
|
106
|
+
doc.save_file("output.xml")
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## API Overview
|
|
110
|
+
|
|
111
|
+
### Core Classes
|
|
112
|
+
|
|
113
|
+
- **XMLDocument**: Create, parse, save XML documents
|
|
114
|
+
- **XMLNode**: Navigate and manipulate XML nodes
|
|
115
|
+
- **XMLAttribute**: Handle XML attributes
|
|
116
|
+
|
|
117
|
+
### Key Methods
|
|
118
|
+
|
|
119
|
+
- `parse_string(xml_string)` - Parse XML from string
|
|
120
|
+
- `parse_file(file_path)` - Parse XML from file
|
|
121
|
+
- `save_file(file_path)` - Save XML to file
|
|
122
|
+
- `append_child(name)` - Add child node
|
|
123
|
+
- `child(name)` - Get child by name
|
|
124
|
+
- `child_value()` - Get node value
|
|
125
|
+
- `attribute(name)` - Get attribute
|
|
126
|
+
|
|
127
|
+
## Benchmarks
|
|
128
|
+
|
|
129
|
+
Run performance comparisons:
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
# Run complete benchmark suite
|
|
133
|
+
python benchmarks/clean_visualization.py
|
|
134
|
+
|
|
135
|
+
# View results
|
|
136
|
+
cat benchmarks/results/benchmark_results.csv
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The benchmark suite compares pygixml against:
|
|
140
|
+
- **lxml** - Industry-standard C-based parser
|
|
141
|
+
- **xml.etree.ElementTree** - Python standard library
|
|
142
|
+
|
|
143
|
+
**Benchmark Files:**
|
|
144
|
+
- `benchmarks/clean_visualization.py` - Main benchmark runner
|
|
145
|
+
- `benchmarks/benchmark_parsing.py` - Core benchmark logic
|
|
146
|
+
- `benchmarks/results/` - Generated CSV data and SVG charts
|
|
147
|
+
|
|
148
|
+
## License
|
|
149
|
+
|
|
150
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
151
|
+
|
|
152
|
+
**To use this library, you must star the project on GitHub!**
|
|
153
|
+
|
|
154
|
+
This helps support the development and shows appreciation for the work. Please star the repository before using the library:
|
|
155
|
+
|
|
156
|
+
👉 **[Star pygixml on GitHub](https://github.com/MohammadRaziei/pygixml)**
|
|
157
|
+
|
|
158
|
+
## Acknowledgments
|
|
159
|
+
|
|
160
|
+
- [pugixml](https://pugixml.org/) - Fast and lightweight C++ XML processing library
|
|
161
|
+
- [Cython](https://cython.org/) - C extensions for Python
|
|
162
|
+
- [scikit-build](https://scikit-build.readthedocs.io/) - Modern Python build system
|
pygixml-0.1.0/README.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# pygixml
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://github.com/MohammadRaziei/pygixml/actions)
|
|
6
|
+
[](https://github.com/MohammadRaziei/pygixml)
|
|
7
|
+
|
|
8
|
+
A high-performance Python wrapper for [pugixml](https://pugixml.org/) using Cython, providing fast XML parsing and manipulation capabilities.
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
## 🚀 Performance
|
|
13
|
+
|
|
14
|
+
pygixml delivers exceptional performance compared to other XML libraries:
|
|
15
|
+
|
|
16
|
+
### Performance Comparison (5000 XML elements)
|
|
17
|
+
|
|
18
|
+
| Library | Parsing Time | Speedup vs ElementTree |
|
|
19
|
+
|---------|--------------|------------------------|
|
|
20
|
+
| **pygixml** | 0.00077s | **15.9x faster** |
|
|
21
|
+
| **lxml** | 0.00407s | 3.0x faster |
|
|
22
|
+
| **ElementTree** | 0.01220s | 1.0x (baseline) |
|
|
23
|
+
|
|
24
|
+

|
|
25
|
+
|
|
26
|
+
### Key Performance Highlights
|
|
27
|
+
|
|
28
|
+
- **15.9x faster** than Python's ElementTree for XML parsing
|
|
29
|
+
- **5.3x faster** than lxml for XML parsing
|
|
30
|
+
- **Memory efficient** - uses pugixml's optimized C++ memory management
|
|
31
|
+
- **Scalable performance** - maintains speed advantage across different XML sizes
|
|
32
|
+
|
|
33
|
+
## Installation
|
|
34
|
+
|
|
35
|
+
### From Pypi repositoey
|
|
36
|
+
```bash
|
|
37
|
+
pip install pygixml
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### From Source
|
|
41
|
+
```bash
|
|
42
|
+
git clone --recurse-submodules https://github.com/MohammadRaziei/pygixml.git
|
|
43
|
+
pip install ./pygixml
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Development Installation
|
|
47
|
+
```bash
|
|
48
|
+
pip install ./pygixml[test]
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Quick SWtart
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
import pygixml
|
|
55
|
+
|
|
56
|
+
# Parse XML from string
|
|
57
|
+
xml_string = """
|
|
58
|
+
<library>
|
|
59
|
+
<book id="1">
|
|
60
|
+
<title>The Great Gatsby</title>
|
|
61
|
+
<author>F. Scott Fitzgerald</author>
|
|
62
|
+
<year>1925</year>
|
|
63
|
+
</book>
|
|
64
|
+
</library>
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
doc = pygixml.parse_string(xml_string)
|
|
68
|
+
root = doc.first_child()
|
|
69
|
+
|
|
70
|
+
# Access elements
|
|
71
|
+
book = root.first_child()
|
|
72
|
+
title = book.child("title")
|
|
73
|
+
print(f"Title: {title.child_value()}") # Output: Title: The Great Gatsby
|
|
74
|
+
|
|
75
|
+
# Create new XML
|
|
76
|
+
doc = pygixml.XMLDocument()
|
|
77
|
+
root = doc.append_child("catalog")
|
|
78
|
+
product = root.append_child("product")
|
|
79
|
+
product.append_child("name").set_value("Laptop")
|
|
80
|
+
product.append_child("price").set_value("999.99")
|
|
81
|
+
|
|
82
|
+
# Save to file
|
|
83
|
+
doc.save_file("output.xml")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## API Overview
|
|
87
|
+
|
|
88
|
+
### Core Classes
|
|
89
|
+
|
|
90
|
+
- **XMLDocument**: Create, parse, save XML documents
|
|
91
|
+
- **XMLNode**: Navigate and manipulate XML nodes
|
|
92
|
+
- **XMLAttribute**: Handle XML attributes
|
|
93
|
+
|
|
94
|
+
### Key Methods
|
|
95
|
+
|
|
96
|
+
- `parse_string(xml_string)` - Parse XML from string
|
|
97
|
+
- `parse_file(file_path)` - Parse XML from file
|
|
98
|
+
- `save_file(file_path)` - Save XML to file
|
|
99
|
+
- `append_child(name)` - Add child node
|
|
100
|
+
- `child(name)` - Get child by name
|
|
101
|
+
- `child_value()` - Get node value
|
|
102
|
+
- `attribute(name)` - Get attribute
|
|
103
|
+
|
|
104
|
+
## Benchmarks
|
|
105
|
+
|
|
106
|
+
Run performance comparisons:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
# Run complete benchmark suite
|
|
110
|
+
python benchmarks/clean_visualization.py
|
|
111
|
+
|
|
112
|
+
# View results
|
|
113
|
+
cat benchmarks/results/benchmark_results.csv
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
The benchmark suite compares pygixml against:
|
|
117
|
+
- **lxml** - Industry-standard C-based parser
|
|
118
|
+
- **xml.etree.ElementTree** - Python standard library
|
|
119
|
+
|
|
120
|
+
**Benchmark Files:**
|
|
121
|
+
- `benchmarks/clean_visualization.py` - Main benchmark runner
|
|
122
|
+
- `benchmarks/benchmark_parsing.py` - Core benchmark logic
|
|
123
|
+
- `benchmarks/results/` - Generated CSV data and SVG charts
|
|
124
|
+
|
|
125
|
+
## License
|
|
126
|
+
|
|
127
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
128
|
+
|
|
129
|
+
**To use this library, you must star the project on GitHub!**
|
|
130
|
+
|
|
131
|
+
This helps support the development and shows appreciation for the work. Please star the repository before using the library:
|
|
132
|
+
|
|
133
|
+
👉 **[Star pygixml on GitHub](https://github.com/MohammadRaziei/pygixml)**
|
|
134
|
+
|
|
135
|
+
## Acknowledgments
|
|
136
|
+
|
|
137
|
+
- [pugixml](https://pugixml.org/) - Fast and lightweight C++ XML processing library
|
|
138
|
+
- [Cython](https://cython.org/) - C extensions for Python
|
|
139
|
+
- [scikit-build](https://scikit-build.readthedocs.io/) - Modern Python build system
|