kadi-apy-helper 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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Adam Reupert
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
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,135 @@
1
+ Metadata-Version: 2.4
2
+ Name: kadi-apy-helper
3
+ Version: 0.1.0
4
+ Summary: Contains a set of functions and helper scripts to ease the usage and interaction with Kadi4mat through the Kadi-APY / Kadi CLI manager.
5
+ Keywords: kadi,kadi4mat,kadi-apy
6
+ Author: Adam Reupert
7
+ Author-email: Adam Reupert <adam.reupert@kit.edu>
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.14
12
+ Classifier: Operating System :: OS Independent
13
+ Requires-Dist: kadi-apy>=0.51.0
14
+ Requires-Python: >=3.14
15
+ Description-Content-Type: text/markdown
16
+
17
+ # Kadi-APY Helper
18
+
19
+ A lightweight Python package for simplified management of users, groups, collections, and records in **Kadi4Mat** based on `kadi-apy`.
20
+
21
+ ## Installation
22
+
23
+ Install the package in your project via `uv`:
24
+
25
+ ```bash
26
+ uv add kadi-apy-helper
27
+ ```
28
+
29
+ Alternatively, you can install the package traditionally via `pip`:
30
+
31
+ ```bash
32
+ pip install kadi-apy-helper
33
+ ```
34
+
35
+ ## Setup (One-Time)
36
+
37
+ Before you can access Kadi4Mat, the local configuration file must be created with your instance URL (host) and your Personal Access Token (PAT):
38
+
39
+ ```python
40
+ from kadi_apy_helper import setup_kadi_apy
41
+
42
+ setup_kadi_apy(
43
+ host_info="https://your-institution.edu",
44
+ pat_token="YOUR_PERSONAL_ACCESS_TOKEN"
45
+ )
46
+ ```
47
+
48
+ ## Quickstart & Usage
49
+
50
+ ### 1. Load and Manage Elements
51
+
52
+ Use `create_kadi_elements()` to set up a structured dictionary for your loaded objects:
53
+
54
+ ```python
55
+ from kadi_apy_helper import (
56
+ create_kadi_elements,
57
+ load_users,
58
+ load_groups,
59
+ load_records,
60
+ load_collections,
61
+ print_loaded_elements,
62
+ )
63
+
64
+ # Initialize empty structure for elements
65
+ elements = create_kadi_elements()
66
+
67
+ # Load existing elements from Kadi4mat by their identifiers
68
+ load_users(user_ids=["jdoe"], kadi_elements=elements)
69
+ load_groups(group_ids=["research_group_xy"], kadi_elements=elements)
70
+ load_collections(collection_ids=["project-2026"], kadi_elements=elements)
71
+ load_records(record_ids=["measurement-series-01"], kadi_elements=elements)
72
+
73
+ # Print loaded elements clearly
74
+ print_loaded_elements(elements)
75
+ ```
76
+
77
+ ### 2. Create New Groups, Collections, and Records
78
+
79
+ ```python
80
+ from kadi_apy_helper import add_group, add_collection, add_record
81
+
82
+ # Create a new group
83
+ group = add_group(
84
+ identifier="new-group",
85
+ title="My Research Group",
86
+ description="Description of the group",
87
+ users=[("jdoe", "member")]
88
+ )
89
+
90
+ # Create a new collection
91
+ collection = add_collection(
92
+ identifier="new-collection",
93
+ title="Measurement Campaign 2026",
94
+ description="All datasets of the measurement campaign",
95
+ add_tags=["experiment", "2026"]
96
+ )
97
+
98
+ # Create a new record and upload files
99
+ record = add_record(
100
+ identifier="measurement-001",
101
+ title="First Test Run",
102
+ record_type="dataset",
103
+ description="Raw data of the first test run",
104
+ add_tags=["raw-data"],
105
+ fileloc=["./data/measurement.csv"],
106
+ filedesc=["Measurement data as CSV"],
107
+ collection_link=[collection.id]
108
+ )
109
+ ```
110
+
111
+ ### 3. Use a Custom `KadiManager` Instance (Optional)
112
+
113
+ By default, all functions use the locally stored configuration file (`~/.kadi-apy.cfg`). If you want to work with multiple Kadi4Mat instances in parallel, you can pass your own `KadiManager` instance to any function:
114
+
115
+ ```python
116
+ from kadi_apy import KadiManager
117
+ from kadi_apy_helper import add_group
118
+
119
+ custom_manager = KadiManager(
120
+ host="https://demo-kadi4mat.iam.kit.edu/",
121
+ pat="ANOTHER_TOKEN"
122
+ )
123
+
124
+ add_group(
125
+ identifier="test-group",
126
+ title="Test Group",
127
+ description="Created via custom manager",
128
+ manager=custom_manager
129
+ )
130
+ ```
131
+
132
+ ## Requirements
133
+
134
+ * Python >= 3.14
135
+ * kadi-apy >= 0.51.0
@@ -0,0 +1,119 @@
1
+ # Kadi-APY Helper
2
+
3
+ A lightweight Python package for simplified management of users, groups, collections, and records in **Kadi4Mat** based on `kadi-apy`.
4
+
5
+ ## Installation
6
+
7
+ Install the package in your project via `uv`:
8
+
9
+ ```bash
10
+ uv add kadi-apy-helper
11
+ ```
12
+
13
+ Alternatively, you can install the package traditionally via `pip`:
14
+
15
+ ```bash
16
+ pip install kadi-apy-helper
17
+ ```
18
+
19
+ ## Setup (One-Time)
20
+
21
+ Before you can access Kadi4Mat, the local configuration file must be created with your instance URL (host) and your Personal Access Token (PAT):
22
+
23
+ ```python
24
+ from kadi_apy_helper import setup_kadi_apy
25
+
26
+ setup_kadi_apy(
27
+ host_info="https://your-institution.edu",
28
+ pat_token="YOUR_PERSONAL_ACCESS_TOKEN"
29
+ )
30
+ ```
31
+
32
+ ## Quickstart & Usage
33
+
34
+ ### 1. Load and Manage Elements
35
+
36
+ Use `create_kadi_elements()` to set up a structured dictionary for your loaded objects:
37
+
38
+ ```python
39
+ from kadi_apy_helper import (
40
+ create_kadi_elements,
41
+ load_users,
42
+ load_groups,
43
+ load_records,
44
+ load_collections,
45
+ print_loaded_elements,
46
+ )
47
+
48
+ # Initialize empty structure for elements
49
+ elements = create_kadi_elements()
50
+
51
+ # Load existing elements from Kadi4mat by their identifiers
52
+ load_users(user_ids=["jdoe"], kadi_elements=elements)
53
+ load_groups(group_ids=["research_group_xy"], kadi_elements=elements)
54
+ load_collections(collection_ids=["project-2026"], kadi_elements=elements)
55
+ load_records(record_ids=["measurement-series-01"], kadi_elements=elements)
56
+
57
+ # Print loaded elements clearly
58
+ print_loaded_elements(elements)
59
+ ```
60
+
61
+ ### 2. Create New Groups, Collections, and Records
62
+
63
+ ```python
64
+ from kadi_apy_helper import add_group, add_collection, add_record
65
+
66
+ # Create a new group
67
+ group = add_group(
68
+ identifier="new-group",
69
+ title="My Research Group",
70
+ description="Description of the group",
71
+ users=[("jdoe", "member")]
72
+ )
73
+
74
+ # Create a new collection
75
+ collection = add_collection(
76
+ identifier="new-collection",
77
+ title="Measurement Campaign 2026",
78
+ description="All datasets of the measurement campaign",
79
+ add_tags=["experiment", "2026"]
80
+ )
81
+
82
+ # Create a new record and upload files
83
+ record = add_record(
84
+ identifier="measurement-001",
85
+ title="First Test Run",
86
+ record_type="dataset",
87
+ description="Raw data of the first test run",
88
+ add_tags=["raw-data"],
89
+ fileloc=["./data/measurement.csv"],
90
+ filedesc=["Measurement data as CSV"],
91
+ collection_link=[collection.id]
92
+ )
93
+ ```
94
+
95
+ ### 3. Use a Custom `KadiManager` Instance (Optional)
96
+
97
+ By default, all functions use the locally stored configuration file (`~/.kadi-apy.cfg`). If you want to work with multiple Kadi4Mat instances in parallel, you can pass your own `KadiManager` instance to any function:
98
+
99
+ ```python
100
+ from kadi_apy import KadiManager
101
+ from kadi_apy_helper import add_group
102
+
103
+ custom_manager = KadiManager(
104
+ host="https://demo-kadi4mat.iam.kit.edu/",
105
+ pat="ANOTHER_TOKEN"
106
+ )
107
+
108
+ add_group(
109
+ identifier="test-group",
110
+ title="Test Group",
111
+ description="Created via custom manager",
112
+ manager=custom_manager
113
+ )
114
+ ```
115
+
116
+ ## Requirements
117
+
118
+ * Python >= 3.14
119
+ * kadi-apy >= 0.51.0
@@ -0,0 +1,27 @@
1
+ [project]
2
+ name = "kadi-apy-helper"
3
+ version = "0.1.0"
4
+ description = "Contains a set of functions and helper scripts to ease the usage and interaction with Kadi4mat through the Kadi-APY / Kadi CLI manager."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ requires-python = ">=3.14"
9
+ dependencies = ["kadi-apy>=0.51.0"]
10
+ keywords = [
11
+ "kadi",
12
+ "kadi4mat",
13
+ "kadi-apy",
14
+ ]
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.14",
18
+ "Operating System :: OS Independent",
19
+ ]
20
+
21
+ [[project.authors]]
22
+ name = "Adam Reupert"
23
+ email = "adam.reupert@kit.edu"
24
+
25
+ [build-system]
26
+ requires = ["uv_build>=0.13.7,<0.14.0"]
27
+ build-backend = "uv_build"
@@ -0,0 +1,24 @@
1
+ [project]
2
+ name = "kadi-apy-helper"
3
+ version = "0.1.0"
4
+ description = "Contains a set of functions and helper scripts to ease the usage and interaction with Kadi4mat through the Kadi-APY / Kadi CLI manager."
5
+ readme = "README.md"
6
+ license = "MIT"
7
+ license-files = ["LICENSE"]
8
+ authors = [
9
+ { name = "Adam Reupert", email = "adam.reupert@kit.edu" }
10
+ ]
11
+ requires-python = ">=3.14"
12
+ dependencies = [
13
+ "kadi-apy>=0.51.0",
14
+ ]
15
+ keywords = ["kadi", "kadi4mat", "kadi-apy"]
16
+ classifiers = [
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.14",
19
+ "Operating System :: OS Independent",
20
+ ]
21
+
22
+ [build-system]
23
+ requires = ["uv_build>=0.13.7,<0.14.0"]
24
+ build-backend = "uv_build"
@@ -0,0 +1,25 @@
1
+ from .main import (
2
+ setup_kadi_apy,
3
+ create_kadi_elements,
4
+ add_collection,
5
+ add_group,
6
+ add_record,
7
+ load_users,
8
+ load_groups,
9
+ load_collections,
10
+ load_records,
11
+ print_loaded_elements,
12
+ )
13
+
14
+ __all__ = [
15
+ "setup_kadi_apy",
16
+ "create_kadi_elements",
17
+ "add_collection",
18
+ "add_group",
19
+ "add_record",
20
+ "load_users",
21
+ "load_groups",
22
+ "load_collections",
23
+ "load_records",
24
+ "print_loaded_elements",
25
+ ]
@@ -0,0 +1,191 @@
1
+ import subprocess
2
+ from typing import Optional
3
+ from kadi_apy import KadiManager
4
+ from kadi_apy.lib.resources.groups import Group
5
+ from kadi_apy.lib.resources.records import Record
6
+ from kadi_apy.lib.resources.collections import Collection
7
+
8
+
9
+ def _get_manager(manager: Optional[KadiManager] = None) -> KadiManager:
10
+ return manager if manager is not None else KadiManager()
11
+
12
+
13
+ def setup_kadi_apy(host_info: str, pat_token: str) -> None:
14
+ subprocess.run(['kadi-apy', 'config', 'create'], encoding="utf-8")
15
+ subprocess.run(['kadi-apy', 'config', 'set-host'], input=host_info + "\n", encoding="utf-8")
16
+ subprocess.run(['kadi-apy', 'config', 'set-pat'], input=pat_token, encoding="utf-8")
17
+ subprocess.run(['kadi-apy', 'config', 'get-kadi-info'], encoding="utf-8")
18
+
19
+ def create_kadi_elements() -> dict[str, dict]:
20
+ return {
21
+ "users": {},
22
+ "groups": {},
23
+ "collections": {},
24
+ "records": {},
25
+ }
26
+
27
+
28
+ def add_group(
29
+ identifier: str,
30
+ title: str,
31
+ description: str,
32
+ users: Optional[list] = None,
33
+ manager: Optional[KadiManager] = None
34
+ ) -> Group:
35
+ mgr = _get_manager(manager)
36
+ group = mgr.group(create_kadi_elementsidentifier=identifier, title=title, create=True)
37
+ group.edit(description=description)
38
+ if users:
39
+ for i in users:
40
+ group.add_user(i[0], permission_new=i[1])
41
+ print("Sample group created/updated successfully.")
42
+ return group
43
+
44
+
45
+ def add_record(
46
+ identifier: str,
47
+ title: str,
48
+ record_type: str,
49
+ description: Optional[str] = None,
50
+ add_tags: Optional[list] = None,
51
+ remove_tags: Optional[list] = None,
52
+ fileloc: Optional[list] = None,
53
+ filedesc: Optional[list] = None,
54
+ metadata: Optional[list] = None,
55
+ collection_link: Optional[list] = None,
56
+ record_link: Optional[list] = None,
57
+ users: Optional[list] = None,
58
+ groups: Optional[list] = None,
59
+ manager: Optional[KadiManager] = None
60
+ ) -> Record:
61
+ mgr = _get_manager(manager)
62
+ record = mgr.record(identifier=identifier, title=title, create=True)
63
+ record.edit(type=record_type, description=description)
64
+ if add_tags:
65
+ for i in add_tags:
66
+ record.add_tag(i)
67
+ if remove_tags:
68
+ for i in remove_tags:
69
+ record.remove_tag(i)
70
+ if fileloc and filedesc:
71
+ for file_number, loc in enumerate(fileloc):
72
+ print(f"Upload {filedesc[file_number]} from {loc}")
73
+ record.upload_file(loc, file_description=filedesc[file_number])
74
+ if metadata:
75
+ record.add_metadata(metadata, force=True)
76
+ if collection_link:
77
+ for i in collection_link:
78
+ record.add_collection_link(i)
79
+ if record_link:
80
+ for i in record_link:
81
+ i[0].link_record(record, name=i[1])
82
+ if users:
83
+ for i in users:
84
+ record.add_user(i[0], permission_new=i[1])
85
+ if groups:
86
+ for i in groups:
87
+ record.add_group_role(i[0], permission_new=i[1])
88
+ return record
89
+
90
+
91
+ def add_collection(
92
+ identifier: str,
93
+ title: str,
94
+ description: str,
95
+ add_tags: Optional[list] = None,
96
+ remove_tags: Optional[list] = None,
97
+ users: Optional[list] = None,
98
+ groups: Optional[list] = None,
99
+ manager: Optional[KadiManager] = None
100
+ ) -> Collection:
101
+ mgr = _get_manager(manager)
102
+ collection = mgr.collection(identifier=identifier, title=title, create=True)
103
+ collection.edit(description=description)
104
+
105
+ if add_tags:
106
+ for i in add_tags:
107
+ collection.add_tag(i)
108
+ if remove_tags:
109
+ for i in remove_tags:
110
+ collection.remove_tag(i)
111
+ if users:
112
+ for i in users:
113
+ collection.add_user(i)
114
+ if groups:
115
+ for i in groups:
116
+ collection.add_group_role(i[0], permission_new=i[1])
117
+ print("Sample collection created/updated successfully.")
118
+ return collection
119
+
120
+
121
+ def load_users(
122
+ user_ids: list,
123
+ kadi_elements: Optional[dict] = None,
124
+ manager: Optional[KadiManager] = None
125
+ ) -> dict:
126
+ mgr = _get_manager(manager)
127
+ user_dict: dict = {}
128
+ for identifier in user_ids:
129
+ user_obj = mgr.user(username=identifier, identity_type="ldap")
130
+ user_dict[identifier] = user_obj.id
131
+ if kadi_elements is not None:
132
+ kadi_elements.setdefault("users", {})[identifier] = user_obj
133
+ return user_dict
134
+
135
+
136
+ def load_groups(
137
+ group_ids: list,
138
+ kadi_elements: Optional[dict] = None,
139
+ manager: Optional[KadiManager] = None
140
+ ) -> dict:
141
+ mgr = _get_manager(manager)
142
+ group_dict: dict = {}
143
+ for identifier in group_ids:
144
+ group_obj = mgr.group(identifier=identifier)
145
+ group_dict[identifier] = group_obj.id
146
+ if kadi_elements is not None:
147
+ kadi_elements.setdefault("groups", {})[identifier] = group_obj
148
+ return group_dict
149
+
150
+
151
+ def load_records(
152
+ record_ids: list,
153
+ kadi_elements: Optional[dict] = None,
154
+ manager: Optional[KadiManager] = None
155
+ ) -> dict:
156
+ mgr = _get_manager(manager)
157
+ record_dict: dict = {}
158
+ for identifier in record_ids:
159
+ record_obj = mgr.record(identifier=identifier)
160
+ record_dict[identifier] = record_obj.id
161
+ if kadi_elements is not None:
162
+ kadi_elements.setdefault("records", {})[identifier] = record_obj
163
+ return record_dict
164
+
165
+
166
+ def load_collections(
167
+ collection_ids: list,
168
+ kadi_elements: Optional[dict] = None,
169
+ manager: Optional[KadiManager] = None
170
+ ) -> dict:
171
+ mgr = _get_manager(manager)
172
+ collection_dict: dict = {}
173
+ for identifier in collection_ids:
174
+ collection_obj = mgr.collection(identifier=identifier)
175
+ collection_dict[identifier] = collection_obj.id
176
+ if kadi_elements is not None:
177
+ kadi_elements.setdefault("collections", {})[identifier] = collection_obj
178
+ return collection_dict
179
+
180
+
181
+ def print_loaded_elements(kadi_elements: dict) -> None:
182
+ for category, label in [
183
+ ("users", "User:"),
184
+ ("groups", "Groups:"),
185
+ ("records", "Records:"),
186
+ ("collections", "Collections:")
187
+ ]:
188
+ print(label)
189
+ for identifier, obj in kadi_elements.get(category, {}).items():
190
+ print(f"{obj.id}: {identifier}")
191
+ print("")