uproot-custom 2.2.0__tar.gz → 2.3.1__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.
Files changed (101) hide show
  1. uproot_custom-2.3.1/.github/release.yml +16 -0
  2. uproot_custom-2.3.1/.github/workflows/auto-update.yml +49 -0
  3. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/build-wheels.yml +10 -5
  4. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/deploy-docs.yml +6 -5
  5. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/python-publish.yml +1 -1
  6. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/test-package.yml +12 -12
  7. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.gitignore +4 -0
  8. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.pre-commit-config.yaml +2 -2
  9. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/PKG-INFO +22 -15
  10. uproot_custom-2.3.1/README.md +59 -0
  11. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/cpp/CMakeLists.txt +1 -1
  12. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/cpp/include/uproot-custom/uproot-custom.hh +46 -6
  13. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/cpp/share/cmake/uproot-customConfig.cmake +1 -0
  14. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/cpp/src/uproot-custom.cc +206 -53
  15. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/example/override-streamer.md +144 -66
  16. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/example/read-tobjarray.md +127 -51
  17. uproot_custom-2.2.0/docs/tutorial/use-built-in.md → uproot_custom-2.3.1/docs/get-started.md +37 -39
  18. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/index.md +19 -8
  19. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/binary-format.md +1 -1
  20. uproot_custom-2.3.1/docs/reference/reader-backends.md +67 -0
  21. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/version-requirements.md +11 -3
  22. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader/investigate-data.md +461 -0
  23. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader/pipeline.md +448 -0
  24. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader/port-to-cpp.md +371 -0
  25. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader/project-setup.md +74 -0
  26. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader/reader-and-factory.md +417 -0
  27. uproot_custom-2.3.1/docs/tutorial/customize-factory-reader.md +65 -0
  28. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/pyproject.toml +5 -3
  29. uproot_custom-2.3.1/tests/conftest.py +392 -0
  30. uproot_custom-2.3.1/tests/data/test_cstyle_array.root +0 -0
  31. uproot_custom-2.3.1/tests/data/test_pointers.root +0 -0
  32. uproot_custom-2.3.1/tests/data/test_primitive.root +0 -0
  33. uproot_custom-2.3.1/tests/data/test_root_objects.root +0 -0
  34. uproot_custom-2.3.1/tests/data/test_simple_obj.root +0 -0
  35. uproot_custom-2.3.1/tests/data/test_stl_array.root +0 -0
  36. uproot_custom-2.3.1/tests/data/test_stl_complicated.root +0 -0
  37. uproot_custom-2.3.1/tests/data/test_stl_map.root +0 -0
  38. uproot_custom-2.3.1/tests/data/test_stl_map_with_obj.root +0 -0
  39. uproot_custom-2.3.1/tests/data/test_stl_nested.root +0 -0
  40. uproot_custom-2.3.1/tests/data/test_stl_seq_with_obj.root +0 -0
  41. uproot_custom-2.3.1/tests/data/test_stl_sequence.root +0 -0
  42. uproot_custom-2.3.1/tests/data/test_stl_string.root +0 -0
  43. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/CMakeLists.txt +1 -0
  44. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/LinkDef.h +2 -0
  45. uproot_custom-2.3.1/tests/gen-test-data/include/TPointers.hh +38 -0
  46. uproot_custom-2.3.1/tests/gen-test-data/src/main.cc +286 -0
  47. uproot_custom-2.3.1/tests/test_AsCustom.py +14 -0
  48. uproot_custom-2.3.1/tests/test_readers.py +139 -0
  49. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/AsCustom.py +2 -1
  50. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/__init__.py +2 -0
  51. uproot_custom-2.3.1/uproot_custom/_version.py +24 -0
  52. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/cpp.pyi +8 -4
  53. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/factories.py +495 -115
  54. uproot_custom-2.3.1/uproot_custom/readers/_forth.py +1576 -0
  55. uproot_custom-2.3.1/uproot_custom/readers/_numba.py +1348 -0
  56. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/readers/cpp.py +2 -2
  57. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/readers/python.py +250 -64
  58. uproot_custom-2.3.1/uv.lock +3813 -0
  59. uproot_custom-2.2.0/CHANGELOG.md +0 -3
  60. uproot_custom-2.2.0/README.md +0 -53
  61. uproot_custom-2.2.0/docs/reference/reader-backends.md +0 -59
  62. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader/binary-data.md +0 -148
  63. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader/bootstrap.md +0 -336
  64. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader/reader-and-factory.md +0 -402
  65. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader/streamer-info.md +0 -275
  66. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader/template-python-project.md +0 -61
  67. uproot_custom-2.2.0/docs/tutorial/customize-factory-reader.md +0 -33
  68. uproot_custom-2.2.0/tests/conftest.py +0 -328
  69. uproot_custom-2.2.0/tests/gen-test-data/src/main.cc +0 -77
  70. uproot_custom-2.2.0/tests/test-data.root +0 -0
  71. uproot_custom-2.2.0/tests/test_builtin_cpp.py +0 -18
  72. uproot_custom-2.2.0/tests/test_builtin_python.py +0 -20
  73. uproot_custom-2.2.0/uproot_custom/_version.py +0 -34
  74. uproot_custom-2.2.0/uv.lock +0 -2693
  75. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.clang-format +0 -0
  76. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/semantic-pr-titles.yml +0 -0
  77. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/.github/workflows/weekly-build.yml +0 -0
  78. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/LICENSE +0 -0
  79. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/Doxyfile +0 -0
  80. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/conf.py +0 -0
  81. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/api/.gitignore +0 -0
  82. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/api/cpp-api.md +0 -0
  83. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/api/cpp-module.md +0 -0
  84. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/api/uproot-custom-ref.md +0 -0
  85. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/docs/reference/api.md +0 -0
  86. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/README.md +0 -0
  87. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TBasicTypes.hh +0 -0
  88. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TCStyleArray.hh +0 -0
  89. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TComplicatedSTL.hh +0 -0
  90. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TNestedSTL.hh +0 -0
  91. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TRootObjects.hh +0 -0
  92. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLArray.hh +0 -0
  93. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLMap.hh +0 -0
  94. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLMapWithObj.hh +0 -0
  95. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLSeqWithObj.hh +0 -0
  96. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLSequence.hh +0 -0
  97. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSTLString.hh +0 -0
  98. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/tests/gen-test-data/include/TSimpleObject.hh +0 -0
  99. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/readers/__init__.py +0 -0
  100. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/share/cmake/__init__.py +0 -0
  101. {uproot_custom-2.2.0 → uproot_custom-2.3.1}/uproot_custom/utils.py +0 -0
@@ -0,0 +1,16 @@
1
+ changelog:
2
+ categories:
3
+ - title: C++ API Changes
4
+ labels:
5
+ - break cpp
6
+ - title: New Features
7
+ labels:
8
+ - feature
9
+ - title: Bug Fixes, Performance Improvements and Refactors
10
+ labels:
11
+ - bug fix
12
+ - refactor
13
+ - performance
14
+ - title: Other Changes
15
+ labels:
16
+ - '*'
@@ -0,0 +1,49 @@
1
+ name: Update pre-commit and uv lock
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ schedule:
6
+ # update hooks
7
+ - cron: 0 12 1 * *
8
+
9
+ permissions:
10
+ pull-requests: write
11
+ contents: write
12
+
13
+ jobs:
14
+ auto-update:
15
+ runs-on: ubuntu-latest
16
+ steps:
17
+ - uses: actions/checkout@v6
18
+ with:
19
+ fetch-depth: 0
20
+
21
+ - uses: astral-sh/setup-uv@v7
22
+ with:
23
+ python-version: '3.13'
24
+ activate-environment: true
25
+
26
+ - name: Update pre-commit hooks
27
+ run: uvx pre-commit autoupdate
28
+
29
+ - name: Update uv lock
30
+ run: |
31
+ uv lock --upgrade
32
+ uvx pre-commit run --all-files
33
+
34
+ - name: Create Pull Request
35
+ uses: peter-evans/create-pull-request@v8
36
+ id: cpr
37
+ with:
38
+ title: 'chore: auto-update pre-commit hooks and uv lock'
39
+ commit-message: auto-update pre-commit hooks and uv lock
40
+ committer: github-actions[bot] ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
41
+ author: ${{ github.actor }} <${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com>
42
+ branch: auto-update/pre-commit-uv
43
+
44
+ - name: Merge Pull Request
45
+ env:
46
+ GH_TOKEN: ${{ github.token }}
47
+ if: steps.cpr.outputs.pull-request-number != ''
48
+ run: |
49
+ gh pr merge ${{ steps.cpr.outputs.pull-request-number }} --squash --auto --delete-branch
@@ -17,13 +17,18 @@ jobs:
17
17
  os: [ubuntu-latest, windows-latest, macos-latest]
18
18
 
19
19
  steps:
20
- - uses: actions/checkout@v4
20
+ - uses: actions/checkout@v6
21
+
22
+ - uses: actions/setup-python@v6
23
+
24
+ - name: Install cibuildwheel
25
+ run: pip install cibuildwheel==3.4
21
26
 
22
27
  - name: Build wheels
23
- uses: pypa/cibuildwheel@v3.1.3
28
+ run: cibuildwheel --output-dir ./wheelhouse
24
29
 
25
30
  - name: Upload distributions
26
- uses: actions/upload-artifact@v4
31
+ uses: actions/upload-artifact@v7
27
32
  with:
28
33
  name: ci-wheels-${{ matrix.os }}-${{ strategy.job-index }}
29
34
  path: ./wheelhouse/*.whl
@@ -33,12 +38,12 @@ jobs:
33
38
  name: Build source distribution
34
39
  runs-on: ubuntu-latest
35
40
  steps:
36
- - uses: actions/checkout@v4
41
+ - uses: actions/checkout@v6
37
42
 
38
43
  - name: Build sdist
39
44
  run: pipx run build --sdist
40
45
 
41
- - uses: actions/upload-artifact@v4
46
+ - uses: actions/upload-artifact@v7
42
47
  with:
43
48
  name: ci-sdist
44
49
  path: dist/*.tar.gz
@@ -11,24 +11,25 @@ jobs:
11
11
  deploy-docs:
12
12
  runs-on: ubuntu-latest
13
13
  steps:
14
- - uses: actions/checkout@v4
14
+ - uses: actions/checkout@v6
15
15
 
16
- - uses: astral-sh/setup-uv@v5
16
+ - uses: astral-sh/setup-uv@v7
17
17
  with:
18
18
  python-version: '3.13'
19
+ activate-environment: true
19
20
 
20
21
  - name: Install dependencies
21
22
  run: |
22
23
  sudo apt-get update
23
24
  sudo apt-get install -y doxygen
24
- uv sync --group=docs
25
+ uv pip install -e . --group docs
25
26
 
26
27
  - name: Build docs
27
28
  run: |
28
- sphinx-build -b html docs/ build/html
29
+ uv run sphinx-build -b html docs/ build/html
29
30
 
30
31
  - name: Deploy to GitHub Pages
31
- uses: peaceiris/actions-gh-pages@v3
32
+ uses: peaceiris/actions-gh-pages@v4
32
33
  with:
33
34
  github_token: ${{ secrets.GITHUB_TOKEN }}
34
35
  publish_dir: ./build/html
@@ -45,7 +45,7 @@ jobs:
45
45
 
46
46
  steps:
47
47
  - name: Retrieve release distributions
48
- uses: actions/download-artifact@v4
48
+ uses: actions/download-artifact@v8
49
49
  with:
50
50
  path: dist/
51
51
  pattern: ci-*
@@ -16,42 +16,42 @@ jobs:
16
16
  runs-on: ${{ matrix.os }}
17
17
  strategy:
18
18
  matrix:
19
- python-version: ['3.9', '3.10', '3.11', '3.12', '3.13']
19
+ python-version: ['3.9', '3.10', '3.11', '3.12', '3.13', '3.14']
20
20
  os: [ubuntu-latest, macos-latest, windows-latest]
21
21
 
22
22
  steps:
23
- - uses: actions/checkout@v4
23
+ - uses: actions/checkout@v6
24
24
 
25
- - uses: astral-sh/setup-uv@v5
25
+ - uses: astral-sh/setup-uv@v7
26
26
  with:
27
27
  python-version: ${{ matrix.python-version }}
28
+ activate-environment: true
28
29
 
29
30
  - name: Install dependencies
30
31
  run: |
31
- uv lock --upgrade
32
- uv sync --all-extras
32
+ uv pip install -e . --group dev
33
33
 
34
34
  - name: Run pytest
35
35
  run: |
36
- pytest --version
37
- pytest -v tests/
36
+ uv run pytest --version
37
+ uv run pytest -v tests/
38
38
 
39
39
  test-build-docs:
40
40
  runs-on: ubuntu-latest
41
41
  steps:
42
- - uses: actions/checkout@v4
42
+ - uses: actions/checkout@v6
43
43
 
44
- - uses: astral-sh/setup-uv@v5
44
+ - uses: astral-sh/setup-uv@v7
45
45
  with:
46
46
  python-version: '3.13'
47
+ activate-environment: true
47
48
 
48
49
  - name: Install dependencies
49
50
  run: |
50
51
  sudo apt-get update
51
52
  sudo apt-get install -y doxygen
52
- uv lock --upgrade
53
- uv sync --all-extras
53
+ uv pip install -e . --group docs
54
54
 
55
55
  - name: Build docs
56
56
  run: |
57
- sphinx-build -b html docs/ build/html
57
+ uv run sphinx-build -b html docs/ build/html
@@ -206,4 +206,8 @@ marimo/_static/
206
206
  marimo/_lsp/
207
207
  __marimo__/
208
208
 
209
+ # Versioneer
209
210
  _version.py
211
+
212
+ # Claude
213
+ .claude
@@ -23,12 +23,12 @@ repos:
23
23
  - id: trailing-whitespace
24
24
 
25
25
  - repo: https://github.com/psf/black-pre-commit-mirror
26
- rev: 26.1.0
26
+ rev: 26.3.1
27
27
  hooks:
28
28
  - id: black
29
29
 
30
30
  - repo: https://github.com/astral-sh/ruff-pre-commit
31
- rev: v0.14.14
31
+ rev: v0.15.9
32
32
  hooks:
33
33
  - id: ruff-check
34
34
  args: [--fix, --show-fixes]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: uproot-custom
3
- Version: 2.2.0
3
+ Version: 2.3.1
4
4
  Summary: uproot extension for reading custom classes
5
5
  Author-Email: Mingrun Li <mrli@ihep.ac.cn>
6
6
  Classifier: Development Status :: 3 - Alpha
@@ -19,6 +19,7 @@ Classifier: Programming Language :: Python :: 3.10
19
19
  Classifier: Programming Language :: Python :: 3.11
20
20
  Classifier: Programming Language :: Python :: 3.12
21
21
  Classifier: Programming Language :: Python :: 3.13
22
+ Classifier: Programming Language :: Python :: 3.14
22
23
  Classifier: Topic :: Scientific/Engineering
23
24
  Classifier: Topic :: Scientific/Engineering :: Information Analysis
24
25
  Classifier: Topic :: Scientific/Engineering :: Mathematics
@@ -26,7 +27,7 @@ Classifier: Topic :: Scientific/Engineering :: Physics
26
27
  Classifier: Topic :: Software Development
27
28
  Classifier: Topic :: Utilities
28
29
  Project-URL: Homepage, https://github.com/mrzimu/uproot-custom
29
- Requires-Python: <3.14,>=3.9
30
+ Requires-Python: <3.15,>=3.9
30
31
  Requires-Dist: uproot>=5.6.7
31
32
  Requires-Dist: numpy
32
33
  Requires-Dist: awkward>=2.8.0
@@ -36,9 +37,12 @@ Description-Content-Type: text/markdown
36
37
 
37
38
  Uproot-custom is an extension of [Uproot](https://uproot.readthedocs.io/en/latest/basic.html) that provides an enhanced way to read custom classes stored in `TTree`.
38
39
 
40
+ > [!WARNING]
41
+ > Because of earlier mistakes in version management, the `v2.x.x` series should still be treated as a development version rather than a stable release.
42
+
39
43
  ## What uproot-custom can do
40
44
 
41
- Uproot-custom can natively read complicated combinations of nested classes and c-style arrays (e.g. `map<int, map<int, map<int, string>>>`, `vector<TString>[3]`, etc), and memberwisely stored classes. It also exposes a way for users to implement their own readers for custom classes that are not supported by Uproot or uproot-custom built-in readers, so that users can read their custom classes seamlessly.
45
+ Uproot-custom can natively read complicated combinations of nested classes and c-style arrays (e.g. `map<int, map<int, map<int, string>>>`, `vector<TString>[3]`, etc), and memberwisely stored classes. It also exposes a way for users to implement their own readers for custom classes that are not supported by Uproot or uproot-custom built-in readers.
42
46
 
43
47
  ## When to use uproot-custom
44
48
 
@@ -46,23 +50,21 @@ Uproot-custom aims to handle cases that classes are too complex for Uproot to re
46
50
 
47
51
  ## How uproot-custom works
48
52
 
49
- Uproot-custom uses a `reader`/`factory` mechanism to read classes:
53
+ Uproot-custom uses a Reader / Factory mechanism to read classes:
50
54
 
51
55
  ```mermaid
52
56
  flowchart TD
53
57
  subgraph py["Python field"]
54
58
  direction TB
55
- AsCustom --> fac["Factory (Primitive, STLVector, TString, ...)"]
59
+ AsCustom -- Recursively generate --> fac["Factory (Primitive, STLVector, TString, ...)"]
56
60
  fac["Factory (Primitive, STLVector, TString, ...)"] -- Optional --> form(["construct awkward forms"])
57
- fac --> build_reader(["build corresponding C++ reader"])
61
+ fac --> build_reader(["build corresponding reader"])
58
62
  fac --> build_ak(["construct awkward arrays"])
59
63
  end
60
64
 
61
- user_fac["User's Factory"] -. Register .-> fac
62
-
63
- subgraph cpp["C++ field"]
65
+ subgraph reader_field["Reader (Python or C++)"]
64
66
  direction TB
65
- build_reader --> reader["C++ Reader"]
67
+ build_reader --> reader["Reader"]
66
68
  reader --> read_bin(["read binary data"])
67
69
  read_bin --> ret_data(["return data"])
68
70
  end
@@ -71,16 +73,21 @@ flowchart TD
71
73
  raw_data --> build_ak
72
74
  ```
73
75
 
74
- - `reader` is a C++ class that implements the logic to read data from binary buffers.
75
- - `factory` is a Python class that creates, combines `reader`s, and post-processes the data read by `reader`s.
76
+ - `Reader` is a class that implements the logic to read data from binary buffers. It can be written in **Python** (for development and debugging) or **C++** (for production performance).
77
+ - `Factory` is a Python class that creates, combines `Reader`s, and post-processes the data read by `Reader`s.
76
78
 
77
- This machanism is implemented basing on `uproot_custom.AsCustom` interpretation. This makes uproot-custom well compatible with Uproot.
79
+ This mechanism is implemented as `AsCustom` interpretation. This makes uproot-custom well compatible with Uproot.
78
80
 
79
81
  > [!TIP]
80
- > Users can implement their own `factory` and `reader`, register them to uproot-custom. An example of implementing a custom `factory`/`reader` can be found in [the example repository](https://github.com/mrzimu/uproot-custom-example).
82
+ > Users can implement their own Factory and Reader, register them to uproot-custom. Start with a **Python reader** for rapid prototyping, then port the logic to **C++** for production speed. The default reader backend is C++; during development, explicitly set the backend to Python. An example of implementing a custom Factory / Reader can be found in [the example repository](https://github.com/mrzimu/uproot-custom-example).
81
83
 
82
84
  > [!NOTE]
83
- > Uproot-custom does not provide a full reimplementation of `ROOT`'s I/O system. Users are expected to implement their own `factory`/`reader` for their custom classes that built-in factories cannot handle.
85
+ > Uproot-custom does not provide a full reimplementation of `ROOT`'s TTree I/O system. Users are expected to implement their own Factory / Reader for their custom classes that built-in factories cannot handle.
86
+
87
+ ## System Requirements
88
+
89
+ - **C++17 compatible compiler**: Required for building C++ readers and the uproot-custom extension module. The CMake configuration sets `CMAKE_CXX_STANDARD 17`.
90
+ - **Python 3.9+**: Uproot-custom supports Python 3.9 through 3.14.
84
91
 
85
92
  ## Documentation
86
93
 
@@ -0,0 +1,59 @@
1
+ # Introduction
2
+
3
+ Uproot-custom is an extension of [Uproot](https://uproot.readthedocs.io/en/latest/basic.html) that provides an enhanced way to read custom classes stored in `TTree`.
4
+
5
+ > [!WARNING]
6
+ > Because of earlier mistakes in version management, the `v2.x.x` series should still be treated as a development version rather than a stable release.
7
+
8
+ ## What uproot-custom can do
9
+
10
+ Uproot-custom can natively read complicated combinations of nested classes and c-style arrays (e.g. `map<int, map<int, map<int, string>>>`, `vector<TString>[3]`, etc), and memberwisely stored classes. It also exposes a way for users to implement their own readers for custom classes that are not supported by Uproot or uproot-custom built-in readers.
11
+
12
+ ## When to use uproot-custom
13
+
14
+ Uproot-custom aims to handle cases that classes are too complex for Uproot to read, such as when their `Streamer` methods are overridden or some specific data members are not supported by Uproot.
15
+
16
+ ## How uproot-custom works
17
+
18
+ Uproot-custom uses a Reader / Factory mechanism to read classes:
19
+
20
+ ```mermaid
21
+ flowchart TD
22
+ subgraph py["Python field"]
23
+ direction TB
24
+ AsCustom -- Recursively generate --> fac["Factory (Primitive, STLVector, TString, ...)"]
25
+ fac["Factory (Primitive, STLVector, TString, ...)"] -- Optional --> form(["construct awkward forms"])
26
+ fac --> build_reader(["build corresponding reader"])
27
+ fac --> build_ak(["construct awkward arrays"])
28
+ end
29
+
30
+ subgraph reader_field["Reader (Python or C++)"]
31
+ direction TB
32
+ build_reader --> reader["Reader"]
33
+ reader --> read_bin(["read binary data"])
34
+ read_bin --> ret_data(["return data"])
35
+ end
36
+
37
+ ret_data --> raw_data[("tuple, list, numpy arrays, ...")]
38
+ raw_data --> build_ak
39
+ ```
40
+
41
+ - `Reader` is a class that implements the logic to read data from binary buffers. It can be written in **Python** (for development and debugging) or **C++** (for production performance).
42
+ - `Factory` is a Python class that creates, combines `Reader`s, and post-processes the data read by `Reader`s.
43
+
44
+ This mechanism is implemented as `AsCustom` interpretation. This makes uproot-custom well compatible with Uproot.
45
+
46
+ > [!TIP]
47
+ > Users can implement their own Factory and Reader, register them to uproot-custom. Start with a **Python reader** for rapid prototyping, then port the logic to **C++** for production speed. The default reader backend is C++; during development, explicitly set the backend to Python. An example of implementing a custom Factory / Reader can be found in [the example repository](https://github.com/mrzimu/uproot-custom-example).
48
+
49
+ > [!NOTE]
50
+ > Uproot-custom does not provide a full reimplementation of `ROOT`'s TTree I/O system. Users are expected to implement their own Factory / Reader for their custom classes that built-in factories cannot handle.
51
+
52
+ ## System Requirements
53
+
54
+ - **C++17 compatible compiler**: Required for building C++ readers and the uproot-custom extension module. The CMake configuration sets `CMAKE_CXX_STANDARD 17`.
55
+ - **Python 3.9+**: Uproot-custom supports Python 3.9 through 3.14.
56
+
57
+ ## Documentation
58
+
59
+ View the [documentation](https://mrzimu.github.io/uproot-custom/) for more details about customizing your own `reader`/`factory`, the architecture of uproot-custom, and build-only dependencies (e.g., `pybind11` is needed only at build time and should not be present in the runtime environment).
@@ -6,6 +6,7 @@ endif()
6
6
 
7
7
  set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
8
8
  set(PYBIND11_NEWPYTHON ON)
9
+ set(CMAKE_CXX_STANDARD 17)
9
10
 
10
11
  project(${SKBUILD_PROJECT_NAME}
11
12
  VERSION ${SKBUILD_PROJECT_VERSION}
@@ -15,7 +16,6 @@ project(${SKBUILD_PROJECT_NAME}
15
16
  find_package(pybind11 REQUIRED)
16
17
 
17
18
  # Add the uproot-custom module
18
-
19
19
  pybind11_add_module(cpp
20
20
  src/uproot-custom.cc
21
21
  )
@@ -9,9 +9,10 @@
9
9
 
10
10
  #include <cstdint>
11
11
  #include <iostream>
12
+ #include <map>
12
13
  #include <memory>
13
- #include <sstream>
14
14
  #include <string>
15
+ #include <variant>
15
16
 
16
17
  #if defined( _MSC_VER )
17
18
  # include <stdlib.h>
@@ -63,14 +64,26 @@ namespace uproot {
63
64
  << 13 ///< if object ctor succeeded but object should not be used
64
65
  };
65
66
 
67
+ struct RefCls {
68
+ std::string name;
69
+ };
70
+
71
+ struct RefObj {
72
+ int64_t index;
73
+ };
74
+
75
+ using Reference = std::variant<RefCls, RefObj>;
76
+
66
77
  /**
67
78
  * @brief Construct a BinaryBuffer from numpy arrays.
68
79
  * @param data A numpy array of uint8_t containing the raw data.
69
80
  * @param offsets A numpy array of uint32_t containing the offsets for each entry.
70
81
  */
71
- BinaryBuffer( py::array_t<uint8_t> data, py::array_t<uint32_t> offsets )
82
+ BinaryBuffer( py::array_t<uint8_t> data, py::array_t<uint32_t> offsets,
83
+ uint32_t initial_cursor_position )
72
84
  : m_data( static_cast<uint8_t*>( data.request().ptr ) )
73
85
  , m_offsets( static_cast<uint32_t*>( offsets.request().ptr ) )
86
+ , m_initial_cursor_offset( initial_cursor_position )
74
87
  , m_entries( offsets.request().size - 1 )
75
88
  , m_cursor( static_cast<uint8_t*>( data.request().ptr ) ) {}
76
89
 
@@ -249,6 +262,28 @@ namespace uproot {
249
262
  */
250
263
  const uint32_t* get_offsets() const { return m_offsets; }
251
264
 
265
+ /**
266
+ * @brief Get the index object
267
+ *
268
+ * @return const uint32_t
269
+ */
270
+ const uint32_t get_index() const { return m_cursor - m_data; }
271
+
272
+ /**
273
+ * @brief Get the initial cursor offset, which is used for calculating relative
274
+ * offsets.
275
+ *
276
+ * @return const uint32_t
277
+ */
278
+ const uint32_t get_initial_cursor_offset() const { return m_initial_cursor_offset; }
279
+
280
+ /**
281
+ * @brief Get the references map, which is used for pointer reading.
282
+ *
283
+ * @return The references map.
284
+ */
285
+ std::map<uint32_t, Reference>& get_refs() { return m_refs; }
286
+
252
287
  /**
253
288
  * @brief Get the number of entries.
254
289
  */
@@ -265,10 +300,15 @@ namespace uproot {
265
300
  }
266
301
 
267
302
  private:
268
- uint8_t* m_cursor; ///< current cursor position
269
- const uint64_t m_entries; ///< number of entries
270
- const uint8_t* m_data; ///< raw data pointer
271
- const uint32_t* m_offsets; ///< entry offsets pointer
303
+ uint8_t* m_cursor; ///< current cursor position
304
+ const uint64_t m_entries; ///< number of entries
305
+ const uint8_t* m_data; ///< raw data pointer
306
+ const uint32_t* m_offsets; ///< entry offsets pointer
307
+ const uint32_t m_initial_cursor_offset; ///< initial cursor position, used for
308
+ ///< calculating relative offsets
309
+
310
+ std::map<uint32_t, Reference> m_refs; ///< offset -> reference, used for pointer
311
+ ///< reading
272
312
  };
273
313
 
274
314
  /*
@@ -15,5 +15,6 @@ find_package_handle_standard_args(uproot-custom
15
15
  if(uproot-custom_FOUND AND NOT TARGET uproot-custom)
16
16
  add_library(uproot-custom INTERFACE IMPORTED)
17
17
  target_include_directories(uproot-custom INTERFACE ${UPROOT_CUSTOM_INCLUDE_DIR})
18
+ target_compile_features(uproot-custom INTERFACE cxx_std_17)
18
19
  message(DEBUG "[DEBUG] Target uproot-custom created")
19
20
  endif()