labapi 1.0.3__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 (148) hide show
  1. labapi-1.0.3/.github/ISSUE_TEMPLATE/bug_report.yml +110 -0
  2. labapi-1.0.3/.github/ISSUE_TEMPLATE/config.yml +8 -0
  3. labapi-1.0.3/.github/ISSUE_TEMPLATE/feature_request.yml +50 -0
  4. labapi-1.0.3/.github/workflows/docs.yml +29 -0
  5. labapi-1.0.3/.github/workflows/format.yml +13 -0
  6. labapi-1.0.3/.github/workflows/integration_tests.yml +43 -0
  7. labapi-1.0.3/.github/workflows/lint.yml +13 -0
  8. labapi-1.0.3/.github/workflows/publish.yml +40 -0
  9. labapi-1.0.3/.github/workflows/python_check.yml +47 -0
  10. labapi-1.0.3/.github/workflows/typecheck.yml +19 -0
  11. labapi-1.0.3/.github/workflows/unit_tests.yml +12 -0
  12. labapi-1.0.3/.gitignore +55 -0
  13. labapi-1.0.3/.mockenv +10 -0
  14. labapi-1.0.3/.pre-commit-config.yaml +27 -0
  15. labapi-1.0.3/.zenodo.json +20 -0
  16. labapi-1.0.3/CLAUDE.md +73 -0
  17. labapi-1.0.3/CONTRIBUTING.md +70 -0
  18. labapi-1.0.3/LICENSE +121 -0
  19. labapi-1.0.3/PKG-INFO +210 -0
  20. labapi-1.0.3/README.md +172 -0
  21. labapi-1.0.3/conftest.py +391 -0
  22. labapi-1.0.3/docs/Makefile +20 -0
  23. labapi-1.0.3/docs/make.bat +35 -0
  24. labapi-1.0.3/docs/source/_static/.gitkeep +1 -0
  25. labapi-1.0.3/docs/source/_templates/custom-class-template.rst +32 -0
  26. labapi-1.0.3/docs/source/_templates/custom-module-template.rst +68 -0
  27. labapi-1.0.3/docs/source/conf.py +66 -0
  28. labapi-1.0.3/docs/source/examples/csv_table.rst +174 -0
  29. labapi-1.0.3/docs/source/examples/folder_download.rst +153 -0
  30. labapi-1.0.3/docs/source/examples/index.rst +81 -0
  31. labapi-1.0.3/docs/source/examples/json_sync.rst +95 -0
  32. labapi-1.0.3/docs/source/faq.rst +123 -0
  33. labapi-1.0.3/docs/source/guide/api_calls.rst +136 -0
  34. labapi-1.0.3/docs/source/guide/architecture.rst +257 -0
  35. labapi-1.0.3/docs/source/guide/auth.rst +186 -0
  36. labapi-1.0.3/docs/source/guide/clearing_cache.rst +175 -0
  37. labapi-1.0.3/docs/source/guide/contributing.rst +158 -0
  38. labapi-1.0.3/docs/source/guide/entries.rst +165 -0
  39. labapi-1.0.3/docs/source/guide/exceptions.rst +61 -0
  40. labapi-1.0.3/docs/source/guide/index.rst +38 -0
  41. labapi-1.0.3/docs/source/guide/index_access.rst +89 -0
  42. labapi-1.0.3/docs/source/guide/integration_design.rst +59 -0
  43. labapi-1.0.3/docs/source/guide/json_entries.rst +63 -0
  44. labapi-1.0.3/docs/source/guide/limitations.rst +105 -0
  45. labapi-1.0.3/docs/source/guide/paths.rst +250 -0
  46. labapi-1.0.3/docs/source/index.rst +60 -0
  47. labapi-1.0.3/docs/source/quick_start/copying.rst +117 -0
  48. labapi-1.0.3/docs/source/quick_start/creating_pages.rst +113 -0
  49. labapi-1.0.3/docs/source/quick_start/deleting.rst +75 -0
  50. labapi-1.0.3/docs/source/quick_start/first_calls.rst +211 -0
  51. labapi-1.0.3/docs/source/quick_start/index.rst +37 -0
  52. labapi-1.0.3/docs/source/quick_start/installation.rst +123 -0
  53. labapi-1.0.3/docs/source/quick_start/navigating.rst +180 -0
  54. labapi-1.0.3/docs/source/quick_start/tutorial.rst +91 -0
  55. labapi-1.0.3/docs/source/quick_start/uploading_files.rst +76 -0
  56. labapi-1.0.3/docs/source/quick_start/writing_rich_text.rst +114 -0
  57. labapi-1.0.3/docs/source/reference/index.rst +24 -0
  58. labapi-1.0.3/examples/csv_table/README.md +58 -0
  59. labapi-1.0.3/examples/csv_table/csv_table.py +299 -0
  60. labapi-1.0.3/examples/csv_table/pyproject.toml +10 -0
  61. labapi-1.0.3/examples/csv_table/sample_data.csv +5 -0
  62. labapi-1.0.3/examples/folder_download/README.md +60 -0
  63. labapi-1.0.3/examples/folder_download/folder_download.py +224 -0
  64. labapi-1.0.3/examples/folder_download/populate_notebook.py +102 -0
  65. labapi-1.0.3/examples/folder_download/pyproject.toml +9 -0
  66. labapi-1.0.3/examples/json_sync/README.md +55 -0
  67. labapi-1.0.3/examples/json_sync/json_sync.py +212 -0
  68. labapi-1.0.3/examples/json_sync/pyproject.toml +9 -0
  69. labapi-1.0.3/examples/json_sync/sample_data/config.json +8 -0
  70. labapi-1.0.3/examples/json_sync/sample_data/results.json +6 -0
  71. labapi-1.0.3/examples/model_logging/README.md +41 -0
  72. labapi-1.0.3/examples/model_logging/model_logger.py +142 -0
  73. labapi-1.0.3/examples/model_logging/pyproject.toml +9 -0
  74. labapi-1.0.3/examples/model_logging/run_test.py +48 -0
  75. labapi-1.0.3/examples/model_logging/test_data/dummy_figure.png +0 -0
  76. labapi-1.0.3/examples/model_logging/test_data/metrics.json +7 -0
  77. labapi-1.0.3/examples/model_logging/test_data/results.csv +6 -0
  78. labapi-1.0.3/examples/notebook_logging/.gitignore +2 -0
  79. labapi-1.0.3/examples/notebook_logging/README.md +87 -0
  80. labapi-1.0.3/examples/notebook_logging/example.ipynb +171 -0
  81. labapi-1.0.3/examples/notebook_logging/notebook_logger.py +340 -0
  82. labapi-1.0.3/examples/notebook_logging/pyproject.toml +11 -0
  83. labapi-1.0.3/pyproject.toml +157 -0
  84. labapi-1.0.3/pyrightconfig.json +14 -0
  85. labapi-1.0.3/setup.cfg +4 -0
  86. labapi-1.0.3/src/labapi/__init__.py +77 -0
  87. labapi-1.0.3/src/labapi/client.py +835 -0
  88. labapi-1.0.3/src/labapi/entry/__init__.py +28 -0
  89. labapi-1.0.3/src/labapi/entry/attachment.py +191 -0
  90. labapi-1.0.3/src/labapi/entry/collection.py +209 -0
  91. labapi-1.0.3/src/labapi/entry/comment.py +15 -0
  92. labapi-1.0.3/src/labapi/entry/entries/__init__.py +22 -0
  93. labapi-1.0.3/src/labapi/entry/entries/attachment.py +148 -0
  94. labapi-1.0.3/src/labapi/entry/entries/base.py +139 -0
  95. labapi-1.0.3/src/labapi/entry/entries/text.py +69 -0
  96. labapi-1.0.3/src/labapi/entry/entries/unknown.py +41 -0
  97. labapi-1.0.3/src/labapi/entry/entries/widget.py +29 -0
  98. labapi-1.0.3/src/labapi/exceptions.py +80 -0
  99. labapi-1.0.3/src/labapi/py.typed +1 -0
  100. labapi-1.0.3/src/labapi/tree/__init__.py +21 -0
  101. labapi-1.0.3/src/labapi/tree/collection.py +163 -0
  102. labapi-1.0.3/src/labapi/tree/directory.py +57 -0
  103. labapi-1.0.3/src/labapi/tree/mixins.py +852 -0
  104. labapi-1.0.3/src/labapi/tree/notebook.py +69 -0
  105. labapi-1.0.3/src/labapi/tree/page.py +218 -0
  106. labapi-1.0.3/src/labapi/user.py +146 -0
  107. labapi-1.0.3/src/labapi/util/__init__.py +45 -0
  108. labapi-1.0.3/src/labapi/util/browser.py +125 -0
  109. labapi-1.0.3/src/labapi/util/extract.py +124 -0
  110. labapi-1.0.3/src/labapi/util/path.py +367 -0
  111. labapi-1.0.3/src/labapi/util/types.py +76 -0
  112. labapi-1.0.3/src/labapi.egg-info/PKG-INFO +210 -0
  113. labapi-1.0.3/src/labapi.egg-info/SOURCES.txt +146 -0
  114. labapi-1.0.3/src/labapi.egg-info/dependency_links.txt +1 -0
  115. labapi-1.0.3/src/labapi.egg-info/requires.txt +10 -0
  116. labapi-1.0.3/src/labapi.egg-info/top_level.txt +1 -0
  117. labapi-1.0.3/tests/__init__.py +1 -0
  118. labapi-1.0.3/tests/conftest.py +43 -0
  119. labapi-1.0.3/tests/entry/__init__.py +1 -0
  120. labapi-1.0.3/tests/entry/entries/__init__.py +1 -0
  121. labapi-1.0.3/tests/entry/entries/test_attachment.py +173 -0
  122. labapi-1.0.3/tests/entry/entries/test_base.py +66 -0
  123. labapi-1.0.3/tests/entry/entries/test_text.py +115 -0
  124. labapi-1.0.3/tests/entry/entries/test_widget.py +49 -0
  125. labapi-1.0.3/tests/entry/test_attachment.py +179 -0
  126. labapi-1.0.3/tests/entry/test_collection.py +456 -0
  127. labapi-1.0.3/tests/examples/__init__.py +1 -0
  128. labapi-1.0.3/tests/examples/test_csv_table.py +153 -0
  129. labapi-1.0.3/tests/examples/test_folder_download.py +89 -0
  130. labapi-1.0.3/tests/examples/test_json_sync.py +149 -0
  131. labapi-1.0.3/tests/test_browser.py +175 -0
  132. labapi-1.0.3/tests/test_client.py +880 -0
  133. labapi-1.0.3/tests/test_entry.json +3 -0
  134. labapi-1.0.3/tests/test_integration.py +376 -0
  135. labapi-1.0.3/tests/test_user.py +139 -0
  136. labapi-1.0.3/tests/tree/__init__.py +1 -0
  137. labapi-1.0.3/tests/tree/test_collection.py +241 -0
  138. labapi-1.0.3/tests/tree/test_directory.py +121 -0
  139. labapi-1.0.3/tests/tree/test_mixins.py +752 -0
  140. labapi-1.0.3/tests/tree/test_notebook.py +47 -0
  141. labapi-1.0.3/tests/tree/test_page.py +376 -0
  142. labapi-1.0.3/tests/util/__init__.py +1 -0
  143. labapi-1.0.3/tests/util/test_behavior.py +23 -0
  144. labapi-1.0.3/tests/util/test_extract.py +298 -0
  145. labapi-1.0.3/tests/util/test_index.py +21 -0
  146. labapi-1.0.3/tests/util/test_notebookinit.py +49 -0
  147. labapi-1.0.3/tests/util/test_path.py +143 -0
  148. labapi-1.0.3/uv.lock +1683 -0
@@ -0,0 +1,110 @@
1
+ name: Bug report
2
+ description: Report a reproducible problem in labapi.
3
+ title: "[Bug]: "
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to report a problem.
9
+
10
+ Please redact API credentials, auth keys, notebook content, and any other sensitive data before submitting.
11
+ - type: textarea
12
+ id: summary
13
+ attributes:
14
+ label: Summary
15
+ description: A short description of the problem and the impact it has on your workflow.
16
+ placeholder: default_authenticate() raises an exception after opening the browser callback flow.
17
+ validations:
18
+ required: true
19
+ - type: input
20
+ id: labapi-version
21
+ attributes:
22
+ label: labapi version
23
+ description: The package version you are using, or the commit/branch name if installed from source.
24
+ placeholder: 0.1.0, main, or a git commit SHA
25
+ validations:
26
+ required: true
27
+ - type: dropdown
28
+ id: python-version
29
+ attributes:
30
+ label: Python version
31
+ description: Which Python version reproduces the issue?
32
+ options:
33
+ - "3.12"
34
+ - "3.13"
35
+ - Other
36
+ validations:
37
+ required: true
38
+ - type: dropdown
39
+ id: install-profile
40
+ attributes:
41
+ label: Install profile
42
+ description: Which install path most closely matches your environment?
43
+ options:
44
+ - Installed from source with `uv sync`
45
+ - `pip install labapi`
46
+ - `pip install 'labapi[dotenv]'`
47
+ - `pip install 'labapi[builtin-auth]'`
48
+ - `pip install 'labapi[dotenv,builtin-auth]'`
49
+ - Other
50
+ validations:
51
+ required: true
52
+ - type: textarea
53
+ id: environment
54
+ attributes:
55
+ label: Environment
56
+ description: Include your OS, shell, and any other environment details that matter.
57
+ placeholder: |
58
+ Windows 11
59
+ PowerShell 7
60
+ API_URL=https://api.labarchives.com
61
+ Running behind a VPN
62
+ validations:
63
+ required: true
64
+ - type: textarea
65
+ id: steps
66
+ attributes:
67
+ label: Steps to reproduce
68
+ description: Share the smallest sequence of steps that reproduces the issue.
69
+ placeholder: |
70
+ 1. Create a client with `Client()`
71
+ 2. Call `default_authenticate()`
72
+ 3. Complete the browser auth flow
73
+ 4. Observe the exception
74
+ validations:
75
+ required: true
76
+ - type: textarea
77
+ id: expected
78
+ attributes:
79
+ label: Expected behavior
80
+ placeholder: The client should authenticate and return the current user object.
81
+ validations:
82
+ required: true
83
+ - type: textarea
84
+ id: actual
85
+ attributes:
86
+ label: Actual behavior
87
+ placeholder: The browser flow completes, but the callback server times out after 60 seconds.
88
+ validations:
89
+ required: true
90
+ - type: textarea
91
+ id: repro
92
+ attributes:
93
+ label: Minimal reproducible example
94
+ description: If possible, share a small script that reproduces the problem.
95
+ render: python
96
+ - type: textarea
97
+ id: logs
98
+ attributes:
99
+ label: Traceback or logs
100
+ description: Paste any error output, traceback, or debug logs that may help.
101
+ render: shell
102
+ - type: checkboxes
103
+ id: checks
104
+ attributes:
105
+ label: Checks
106
+ options:
107
+ - label: I searched the existing issues before opening this report.
108
+ required: true
109
+ - label: I redacted secrets and sensitive notebook data from the details above.
110
+ required: true
@@ -0,0 +1,8 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Usage and setup docs
4
+ url: https://github.com/nimh-dsst/labapi/tree/main/docs/source
5
+ about: Start here for installation, authentication, quick-start, and FAQ guidance.
6
+ - name: Contributing guide
7
+ url: https://github.com/nimh-dsst/labapi/blob/main/CONTRIBUTING.md
8
+ about: Review local setup, testing commands, and code-quality expectations for contributions.
@@ -0,0 +1,50 @@
1
+ name: Feature request
2
+ description: Suggest an improvement to the library, docs, or developer workflow.
3
+ title: "[Feature]: "
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for suggesting an improvement to labapi.
9
+
10
+ Clear examples of the workflow you want to support make it much easier to evaluate the request.
11
+ - type: textarea
12
+ id: problem
13
+ attributes:
14
+ label: Problem to solve
15
+ description: What are you trying to do, and what is hard or missing today?
16
+ placeholder: I need a simpler way to authenticate in a headless CI job without wiring my own callback server.
17
+ validations:
18
+ required: true
19
+ - type: textarea
20
+ id: proposal
21
+ attributes:
22
+ label: Proposed solution
23
+ description: Describe the API, behavior, or docs change you would like to see.
24
+ placeholder: Add a helper that exchanges a one-time auth token for a session using environment variables.
25
+ validations:
26
+ required: true
27
+ - type: textarea
28
+ id: alternatives
29
+ attributes:
30
+ label: Alternatives considered
31
+ description: Share any workarounds, adjacent APIs, or alternative approaches you have tried.
32
+ placeholder: Today I build the auth URL myself and parse the callback in a separate script.
33
+ - type: textarea
34
+ id: examples
35
+ attributes:
36
+ label: Example usage
37
+ description: If helpful, sketch the code or command-line flow you want.
38
+ render: python
39
+ - type: textarea
40
+ id: context
41
+ attributes:
42
+ label: Additional context
43
+ description: Add links, screenshots, docs references, or other details that would help.
44
+ - type: checkboxes
45
+ id: checks
46
+ attributes:
47
+ label: Checks
48
+ options:
49
+ - label: I searched the existing issues before opening this request.
50
+ required: true
@@ -0,0 +1,29 @@
1
+ name: Docs
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ docs:
9
+ name: Docs build
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v5
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v7
18
+ with:
19
+ enable-cache: true
20
+ version: "latest"
21
+
22
+ - name: Set up Python
23
+ run: uv python install 3.13
24
+
25
+ - name: Install dependencies
26
+ run: uv sync --all-groups
27
+
28
+ - name: Build Sphinx docs
29
+ run: uv run sphinx-build -b html docs/source docs/_build
@@ -0,0 +1,13 @@
1
+ name: Ruff Format
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ format:
9
+ uses: ./.github/workflows/python_check.yml
10
+ with:
11
+ job_name: Ruff format
12
+ command: uv run ruff format --check .
13
+ python_versions: '["3.13"]'
@@ -0,0 +1,43 @@
1
+ name: Integration Test Suite
2
+
3
+ on:
4
+ workflow_dispatch:
5
+ inputs:
6
+ la_key:
7
+ description: LabArchives Authentication Token
8
+ required: true
9
+ type: string
10
+ la_email:
11
+ description: LabArchives Authentication la_email
12
+ required: true
13
+ type: string
14
+
15
+ jobs:
16
+ build:
17
+ runs-on: ubuntu-latest
18
+
19
+ steps:
20
+ - name: Checkout code
21
+ uses: actions/checkout@v5
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v7
25
+ with:
26
+ enable-cache: true
27
+ version: "latest"
28
+
29
+ - name: Set up Python
30
+ run: uv python install 3.13
31
+
32
+ - name: Install dependencies
33
+ run: uv sync --all-groups
34
+
35
+ - name: Run tests with pytest
36
+ env:
37
+ API_URL: ${{ secrets.API_URL }}
38
+ ACCESS_KEYID: ${{ secrets.AKID }}
39
+ ACCESS_PWD: ${{ secrets.AKPASS }}
40
+ AUTH_KEY: ${{ github.event.inputs.la_key }}
41
+ AUTH_EMAIL: ${{ github.event.inputs.la_email }}
42
+ NOTEBOOK: ${{ secrets.NOTEBOOK }}
43
+ run: uv run pytest tests/test_integration.py
@@ -0,0 +1,13 @@
1
+ name: Ruff Lint
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ lint:
9
+ uses: ./.github/workflows/python_check.yml
10
+ with:
11
+ job_name: Ruff lint
12
+ command: uv run ruff check .
13
+ python_versions: '["3.13"]'
@@ -0,0 +1,40 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+
9
+ permissions:
10
+ contents: read
11
+ id-token: write
12
+
13
+ jobs:
14
+ publish:
15
+ name: Publish to PyPI
16
+ runs-on: ubuntu-latest
17
+ environment:
18
+ name: pypi
19
+ url: https://pypi.org/project/labapi/
20
+
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v5
24
+ with:
25
+ fetch-depth: 0
26
+
27
+ - name: Install uv
28
+ uses: astral-sh/setup-uv@v7
29
+ with:
30
+ enable-cache: true
31
+ version: "latest"
32
+
33
+ - name: Set up Python
34
+ run: uv python install 3.13
35
+
36
+ - name: Build distributions
37
+ run: uv build --python 3.13 --clear --no-build-logs
38
+
39
+ - name: Publish to PyPI
40
+ run: uv publish --trusted-publishing always
@@ -0,0 +1,47 @@
1
+ name: Python Check
2
+
3
+ on:
4
+ workflow_call:
5
+ inputs:
6
+ job_name:
7
+ required: true
8
+ type: string
9
+ command:
10
+ required: true
11
+ type: string
12
+ append_python_version_arg:
13
+ required: false
14
+ type: boolean
15
+ default: false
16
+ python_versions:
17
+ required: false
18
+ type: string
19
+ default: '["3.12", "3.13"]'
20
+
21
+ jobs:
22
+ check:
23
+ name: ${{ inputs.job_name }} (Python ${{ matrix.python-version }})
24
+ runs-on: ubuntu-latest
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ python-version: ${{ fromJSON(inputs.python_versions) }}
29
+
30
+ steps:
31
+ - name: Checkout code
32
+ uses: actions/checkout@v5
33
+
34
+ - name: Install uv
35
+ uses: astral-sh/setup-uv@v7
36
+ with:
37
+ enable-cache: true
38
+ version: "latest"
39
+
40
+ - name: Set up Python
41
+ run: uv python install ${{ matrix.python-version }}
42
+
43
+ - name: Install dependencies
44
+ run: uv sync --all-groups
45
+
46
+ - name: Run check
47
+ run: ${{ inputs.command }}${{ inputs.append_python_version_arg && format(' --python-version {0}', matrix.python-version) || '' }}
@@ -0,0 +1,19 @@
1
+ name: Type Check
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ pyright:
9
+ uses: ./.github/workflows/python_check.yml
10
+ with:
11
+ job_name: Pyright
12
+ command: uv run pyright
13
+
14
+ ty:
15
+ uses: ./.github/workflows/python_check.yml
16
+ with:
17
+ job_name: ty
18
+ command: uv run ty check
19
+ append_python_version_arg: true
@@ -0,0 +1,12 @@
1
+ name: Unit Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ unit-tests:
9
+ uses: ./.github/workflows/python_check.yml
10
+ with:
11
+ job_name: Unit tests
12
+ command: uv run pytest
@@ -0,0 +1,55 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ tests/__pycache__
7
+ wheels/
8
+ *.egg-info
9
+
10
+ # Virtual environments
11
+ .venv
12
+
13
+ .env
14
+ .python-version
15
+ .ruff_cache/
16
+ .mypy_cache/
17
+
18
+
19
+ # Coverage reports
20
+ .coverage
21
+
22
+ # IDE files
23
+ .vscode/
24
+ .idea/
25
+ *.iml
26
+ .idea
27
+
28
+
29
+ .claude/
30
+ .notes
31
+ .environment-*
32
+ .mcp.json
33
+
34
+ # Sandbox stub files (empty placeholders created by Claude Code's sandbox)
35
+ .gitconfig
36
+ .gitmodules
37
+ .zprofile
38
+ .zshrc
39
+ .bashrc
40
+ .bash_profile
41
+ .profile
42
+ .ripgreprc
43
+ HEAD
44
+ config
45
+ hooks
46
+ objects
47
+ refs
48
+
49
+ docs/build/
50
+ docs/_build/
51
+ docs/source/reference/generated/
52
+
53
+
54
+ .ipynb-checkpoints
55
+ .tmpdocs
labapi-1.0.3/.mockenv ADDED
@@ -0,0 +1,10 @@
1
+ # LabArchives API Client credentials
2
+ API_URL=https://api.labarchives.com
3
+ ACCESS_KEYID=your_access_key_id_here
4
+ ACCESS_PWD=your_access_password_here
5
+
6
+ # Integration test settings
7
+ AUTH_EMAIL=your_email@example.com
8
+ AUTH_KEY=your_auth_key_here
9
+ AUTH_INTERACTIVE=false
10
+ NOTEBOOK=My Test Notebook
@@ -0,0 +1,27 @@
1
+ repos:
2
+ - repo: local
3
+ hooks:
4
+ - id: pyright-check
5
+ name: Run Pyright
6
+ entry: uv
7
+ args: [run, pyright]
8
+ language: system
9
+ pass_filenames: false
10
+ always_run: true
11
+ - id: pytest-check
12
+ name: Run Pytest (pre-push)
13
+ entry: uv
14
+ args: [run, pytest, --no-cov]
15
+ language: system
16
+ pass_filenames: false
17
+ always_run: true
18
+ stages: [pre-push]
19
+ - repo: https://github.com/astral-sh/ruff-pre-commit
20
+ # Ruff version.
21
+ rev: v0.14.11
22
+ hooks:
23
+ # Run the linter.
24
+ - id: ruff-check
25
+ args: [ --fix ]
26
+ # Run the formatter.
27
+ - id: ruff-format
@@ -0,0 +1,20 @@
1
+ {
2
+ "title": "labapi",
3
+ "description": "Python client for the LabArchives API",
4
+ "creators": [
5
+ {
6
+ "name": "Li, Christoph",
7
+ "affiliation": "National Institute of Mental Health",
8
+ "orcid": "0009-0009-4624-2578"
9
+ },
10
+ {
11
+ "name": "Lawrimore, Josh",
12
+ "affiliation": "National Institute of Mental Health",
13
+ "orcid": "0000-0003-2301-9073"
14
+ }
15
+ ],
16
+ "keywords": ["Electronic Lab Notebook", "ELN", "LabArchives", "API"],
17
+ "license": "CC0-1.0",
18
+ "access_right": "open",
19
+ "upload_type": "software"
20
+ }
labapi-1.0.3/CLAUDE.md ADDED
@@ -0,0 +1,73 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ **Important:** Check `.environment-setup` if it exists - it contains host-specific instructions (e.g., using Nix instead of uv).
6
+
7
+ ## Project Overview
8
+
9
+ `labapi` is a Python client library for the LabArchives API, providing an object-oriented interface for managing notebooks, folders, pages, and entries. The LabArchives API uses XML, and requests are signed with HMAC-SHA512.
10
+
11
+ ## Build & Development Commands
12
+
13
+ ```bash
14
+ # Setup (using uv)
15
+ uv sync
16
+ source .venv/bin/activate
17
+
18
+ # Run all tests with coverage
19
+ pytest
20
+
21
+ # Run specific test file
22
+ pytest tests/test_unit.py
23
+ pytest tests/test_integration.py # requires LA_KEY and LA_EMAIL env vars
24
+
25
+ # Lint and format
26
+ ruff check .
27
+ ruff format .
28
+ ruff check --fix . # auto-fix linting issues
29
+ ```
30
+
31
+ ## Architecture
32
+
33
+ The codebase follows a hierarchical tree structure mirroring LabArchives organization:
34
+
35
+ **Core modules:**
36
+ - `src/labapi/client.py` - Main API client with HMAC-SHA512 request signing, authentication flows (`generate_auth_url`, `login_authcode`), and `api_get`/`api_post` methods
37
+ - `src/labapi/user.py` - Authenticated user session; provides access to notebooks via `user.notebooks`
38
+ - `src/labapi/tree/` - Hierarchical data model: `Notebook` → `NotebookDirectory` → `NotebookPage`
39
+ - `src/labapi/entry/` - Entry types on pages: `TextEntry`, `HeaderEntry`, `PlainTextEntry`, `AttachmentEntry`, `WidgetEntry`
40
+ - `src/labapi/util/extract.py` - XML extraction helpers (`extract_etree`, `to_bool`, `_flatten_dict`)
41
+ - `src/labapi/util/index.py` - Indexing enum for accessing items by ID or name: `notebook[Index.Id:"some_id"]` or `notebook[Index.Name:"some_name"]`
42
+
43
+ **Entry point pattern:**
44
+ ```python
45
+ from labapi import Client
46
+ client = Client(base_url, akid, password) # or Client() to load from .env
47
+ auth_url = client.generate_auth_url(redirect_url)
48
+ user = client.login_authcode(user_email, auth_code)
49
+ notebooks = user.notebooks
50
+ ```
51
+
52
+ ## Development Conventions
53
+
54
+ - **Type hinting:** All new code must be fully type-hinted
55
+ - **XML handling:** Use `lxml` for all XML parsing; use helpers in `src/labapi/util/extract.py`
56
+ - **Testing:** Prefer unit tests with `MockClient` (in `tests/test_unit.py`) over integration tests to avoid hitting the live API
57
+ - **Error handling:** API errors are raised as `RuntimeError` (future: type these more specifically)
58
+
59
+ ## Environment Variables
60
+
61
+ The `Client` class auto-loads from a `.env` file via `python-dotenv` when credentials aren't passed directly. Create a `.env` file (gitignored) with:
62
+
63
+ ```bash
64
+ API_URL=https://api.labarchives.com # optional, this is the default
65
+ ACCESS_KEYID=your_akid # required
66
+ ACCESS_PWD=your_password # required
67
+ ```
68
+
69
+ **Other environment variables:**
70
+ - `LA_KEY`, `LA_EMAIL` - Required for integration tests
71
+ - `LA_AUTH_BROWSER` - Browser for OAuth flows (chrome, firefox, edge)
72
+ - `AUTH_INTERACTIVE` - Enable interactive authentication mode
73
+ - `NOTEBOOK` - Target notebook name for testing
@@ -0,0 +1,70 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ uv sync --all-groups
7
+ pre-commit install --hook-type pre-commit --hook-type pre-push
8
+ ```
9
+
10
+ ## Running Tests
11
+
12
+ Unit tests run entirely offline using `MockClient`:
13
+
14
+ ```bash
15
+ uv run pytest
16
+ ```
17
+
18
+ Integration tests are opt-in and require live API credentials in `.env` or the environment:
19
+
20
+ ```bash
21
+ # Required
22
+ ACCESS_KEYID=your_akid
23
+ ACCESS_PWD=your_password
24
+ API_URL=https://api.labarchives.com
25
+
26
+ # Required for non-interactive login used by tests/test_integration.py
27
+ AUTH_EMAIL=your@email.com
28
+ AUTH_KEY=your_auth_key
29
+
30
+ # Optional: use the browser callback flow instead
31
+ # AUTH_INTERACTIVE=true
32
+ ```
33
+
34
+ ```bash
35
+ uv run pytest --integration tests/test_integration.py
36
+ ```
37
+
38
+ `Client()` only auto-loads `API_URL`, `ACCESS_KEYID`, and `ACCESS_PWD`; `AUTH_EMAIL` and `AUTH_KEY` are test-fixture conventions used by the integration suite.
39
+
40
+ ## Code Style
41
+
42
+ Ruff handles linting, formatting, and branch-complexity checks. Pyright handles type checking. After installing both hook types:
43
+
44
+ - `ruff-check`, `ruff-format`, and `pyright-check` run on `pre-commit`
45
+ - `pytest-check` runs `uv run pytest --no-cov` on `pre-push`
46
+
47
+ Manual equivalents:
48
+
49
+ ```bash
50
+ uv run ruff check --fix . # lint
51
+ uv run ruff format . # format
52
+ uv run pyright # typecheck
53
+ uv run radon cc src tests -s -a # complexity report
54
+ uv run pytest --no-cov # pre-push test gate
55
+ ```
56
+
57
+ ## Type Annotations
58
+
59
+ Run type checking locally with:
60
+
61
+ ```bash
62
+ uv run pyright
63
+ ```
64
+
65
+ All new code must be fully type-annotated. Key conventions:
66
+
67
+ - `from __future__ import annotations` in every module
68
+ - `override` on all method overrides
69
+ - `TYPE_CHECKING` guards to avoid circular imports
70
+ - Generics where they give callers concrete return types (e.g. `Entry[Attachment]`)