Skip to content

Commit 4e539b2

Browse files
authored
Merge pull request #7 from cs3org/dev
Adapted tokens to be external, CI now builds and installs the package, and unit tests are now using the installed package.
2 parents afe7044 + 8c016f1 commit 4e539b2

36 files changed

+1368
-806
lines changed

.github/workflows/ci-tests.yml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This workflow will install Python dependencies, run tests and lint with a single version of Python
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
33

4-
name: Linting and unit tests
4+
name: Lint, Build and Test
55
on:
66
push:
77
branches: [ "main" ]
@@ -15,10 +15,10 @@ jobs:
1515
- name: Checkout
1616
uses: actions/checkout@v4
1717

18-
- name: Set up Python 3.12
18+
- name: Set up Python 3.9
1919
uses: actions/setup-python@v3
2020
with:
21-
python-version: "3.12"
21+
python-version: "3.9"
2222

2323
- name: Install dependencies
2424
run: |
@@ -32,8 +32,11 @@ jobs:
3232
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
3333
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide, we further relax this
3434
flake8 . --count --exit-zero --max-complexity=30 --max-line-length=130 --statistics
35-
35+
- name: Build
36+
run: |
37+
pip install build
38+
python -m build
3639
- name: Test with pytest
3740
run: |
3841
if [ -f tests/requirements.txt ]; then pip install -r tests/requirements.txt; fi
39-
pytest --cov-report term --cov=src tests/
42+
pytest --cov-report term --cov=cs3client tests/

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,9 @@ dmypy.json
157157
# Cython debug symbols
158158
cython_debug/
159159

160+
# MacOS
161+
.DS_Store
162+
160163
# PyCharm
161164
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
162165
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore

README.md

Lines changed: 99 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,7 @@ Alternatively, you can clone this repository and install manually:
3737
```bash
3838
git clone [email protected]:cs3org/cs3-python-client.git
3939
cd cs3-python-client
40-
pip install -e .
41-
export PYTHONPATH="path/to/cs3-python-client/:$PYTHONPATH"
40+
pip install .
4241
```
4342

4443

@@ -89,12 +88,14 @@ ssl_verify = False
8988
# Optional, defaults to an empty string
9089
ssl_client_cert = test_client_cert
9190
# Optional, defaults to an empty string
92-
ssl_client_key = test_client_key
91+
ssl_client_key = test_client_key
9392
# Optional, defaults to an empty string
94-
ssl_ca_cert = test_ca_cert
93+
ssl_ca_cert = test_ca_cert
9594

9695
# Optinal, defaults to an empty string
9796
auth_client_id = einstein
97+
# Optional (can also be set when instansiating the class)
98+
auth_client_secret = relativity
9899
# Optional, defaults to basic
99100
auth_login_type = basic
100101

@@ -112,129 +113,180 @@ lock_expiration = 1800
112113

113114
To use `cs3client`, you first need to import and configure it. Here's a simple example of how to set up and start using the client. For configuration see [Configuration](#configuration). For more in depth examples see `cs3-python-client/examples/`.
114115

115-
### Initilization
116+
### Initilization and Authentication
116117
```python
117118
import logging
118119
import configparser
119-
from cs3client import CS3Client
120-
from cs3resource import Resource
120+
from cs3client.cs3client import CS3Client
121+
from cs3client.auth import Auth
121122

122123
config = configparser.ConfigParser()
123124
with open("default.conf") as fdef:
124125
config.read_file(fdef)
125-
126126
log = logging.getLogger(__name__)
127127

128128
client = CS3Client(config, "cs3client", log)
129-
# client.auth.set_token("<your_token_here>")
130-
# OR
131-
client.auth.set_client_secret("<your_client_secret_here>")
129+
auth = Auth(client)
130+
# Set the client id (can also be set in the config)
131+
auth.set_client_id("<your_client_id_here>")
132+
# Set client secret (can also be set in config)
133+
auth.set_client_secret("<your_client_secret_here>")
134+
# Checks if token is expired if not return ('x-access-token', <token>)
135+
# if expired, request a new token from reva
136+
auth_token = auth.get_token()
137+
138+
# OR if you already have a reva token
139+
# Checks if token is expired if not return (x-access-token', <token>)
140+
# if expired, throws an AuthenticationException (so you can refresh your reva token)
141+
token = "<your_reva_token>"
142+
auth_token = Auth.check_token(token)
143+
132144
```
133145

134146
### File Example
135147
```python
136148
# mkdir
137-
directory_resource = Resource.from_file_ref_and_endpoint(f"/eos/user/r/rwelande/test_directory")
138-
res = client.file.make_dir(directory_resource)
149+
directory_resource = Resource(abs_path=f"/eos/user/r/rwelande/test_directory")
150+
res = client.file.make_dir(auth.get_token(), directory_resource)
139151

140152
# touchfile
141-
touch_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/touch_file.txt")
142-
res = client.file.touch_file(touch_resource)
153+
touch_resource = Resource(abs_path="/eos/user/r/rwelande/touch_file.txt")
154+
res = client.file.touch_file(auth.get_token(), touch_resource)
143155

144156
# setxattr
145-
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/text_file.txt")
146-
res = client.file.set_xattr(resource, "iop.wopi.lastwritetime", str(1720696124))
157+
resource = Resource(abs_path="/eos/user/r/rwelande/text_file.txt")
158+
res = client.file.set_xattr(auth.get_token(), resource, "iop.wopi.lastwritetime", str(1720696124))
147159

148160
# rmxattr
149-
res = client.file.remove_xattr(resource, "iop.wopi.lastwritetime")
161+
res = client.file.remove_xattr(auth.get_token(), resource, "iop.wopi.lastwritetime")
150162

151163
# stat
152-
res = client.file.stat(resource)
164+
res = client.file.stat(auth.get_token(), resource)
153165

154166
# removefile
155-
res = client.file.remove_file(touch_resource)
167+
res = client.file.remove_file(auth.get_token(), touch_resource)
156168

157169
# rename
158-
rename_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/rename_file.txt")
159-
res = client.file.rename_file(resource, rename_resource)
170+
rename_resource = Resource(abs_path="/eos/user/r/rwelande/rename_file.txt")
171+
res = client.file.rename_file(auth.get_token(), resource, rename_resource)
160172

161173
# writefile
162174
content = b"Hello World"
163175
size = len(content)
164-
res = client.file.write_file(rename_resource, content, size)
176+
res = client.file.write_file(auth.get_token(), rename_resource, content, size)
165177

166178
# listdir
167-
list_directory_resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande")
168-
res = client.file.list_dir(list_directory_resource)
179+
list_directory_resource = Resource(abs_path="/eos/user/r/rwelande")
180+
res = client.file.list_dir(auth.get_token(), list_directory_resource)
169181

170182

171183
# readfile
172-
file_res = client.file.read_file(rename_resource)
184+
file_res = client.file.read_file(auth.get_token(), rename_resource)
185+
```
186+
### Lock Example
187+
```python
188+
189+
WEBDAV_LOCK_PREFIX = 'opaquelocktoken:797356a8-0500-4ceb-a8a0-c94c8cde7eba'
190+
191+
192+
def encode_lock(lock):
193+
'''Generates the lock payload for the storage given the raw metadata'''
194+
if lock:
195+
return WEBDAV_LOCK_PREFIX + ' ' + b64encode(lock.encode()).decode()
196+
return None
197+
198+
resource = Resource(abs_path="/eos/user/r/rwelande/lock_test.txt")
199+
200+
# Set lock
201+
client.file.set_lock(auth_token, resource, app_name="a", lock_id=encode_lock("some_lock"))
202+
203+
# Get lock
204+
res = client.file.get_lock(auth_token, resource)
205+
if res is not None:
206+
lock_id = res["lock_id"]
207+
print(res)
208+
209+
# Unlock
210+
res = client.file.unlock(auth_token, resource, app_name="a", lock_id=lock_id)
211+
212+
# Refresh lock
213+
client.file.set_lock(auth_token, resource, app_name="a", lock_id=encode_lock("some_lock"))
214+
res = client.file.refresh_lock(
215+
auth_token, resource, app_name="a", lock_id=encode_lock("new_lock"), existing_lock_id=lock_id
216+
)
217+
218+
if res is not None:
219+
print(res)
220+
221+
res = client.file.get_lock(auth_token, resource)
222+
if res is not None:
223+
print(res)
224+
173225
```
174226

175227
### Share Example
176228
```python
177229
# Create share #
178-
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/<some_username>/text.txt")
179-
resource_info = client.file.stat(resource)
230+
resource = Resource(abs_path="/eos/user/r/<some_username>/text.txt")
231+
resource_info = client.file.stat(auth.get_token(), resource)
180232
user = client.user.get_user_by_claim("username", "<some_username>")
181-
res = client.share.create_share(resource_info, user.id.opaque_id, user.id.idp, "EDITOR", "USER")
233+
res = client.share.create_share(auth.get_token(), resource_info, user.id.opaque_id, user.id.idp, "EDITOR", "USER")
182234

183235
# List existing shares #
184236
filter_list = []
185237
filter = client.share.create_share_filter(resource_id=resource_info.id, filter_type="TYPE_RESOURCE_ID")
186238
filter_list.append(filter)
187239
filter = client.share.create_share_filter(share_state="SHARE_STATE_PENDING", filter_type="TYPE_STATE")
188240
filter_list.append(filter)
189-
res, _ = client.share.list_existing_shares()
241+
res, _ = client.share.list_existing_shares(auth.get_token(), )
190242

191243
# Get share #
192244
share_id = "58"
193-
res = client.share.get_share(opaque_id=share_id)
245+
res = client.share.get_share(auth.get_token(), opaque_id=share_id)
194246

195247
# update share #
196-
res = client.share.update_share(opaque_id=share_id, role="VIEWER")
248+
res = client.share.update_share(auth.get_token(), opaque_id=share_id, role="VIEWER")
197249

198250
# remove share #
199-
res = client.share.remove_share(opaque_id=share_id)
251+
res = client.share.remove_share(auth.get_token(), opaque_id=share_id)
200252

201253
# List existing received shares #
202254
filter_list = []
203255
filter = client.share.create_share_filter(share_state="SHARE_STATE_ACCEPTED", filter_type="TYPE_STATE")
204256
filter_list.append(filter)
205-
res, _ = client.share.list_received_existing_shares()
257+
res, _ = client.share.list_received_existing_shares(auth.get_token())
206258

207259
# get received share #
208-
received_share = client.share.get_received_share(opaque_id=share_id)
260+
received_share = client.share.get_received_share(auth.get_token(), opaque_id=share_id)
209261

210262
# update recieved share #
211-
res = client.share.update_received_share(received_share=received_share, state="SHARE_STATE_ACCEPTED")
263+
res = client.share.update_received_share(auth.get_token(), received_share=received_share, state="SHARE_STATE_ACCEPTED")
212264

213265
# create public share #
214-
res = client.share.create_public_share(resource_info, role="VIEWER")
266+
res = client.share.create_public_share(auth.get_token(), resource_info, role="VIEWER")
215267

216268
# list existing public shares #
217269
filter_list = []
218270
filter = client.share.create_public_share_filter(resource_id=resource_info.id, filter_type="TYPE_RESOURCE_ID")
219271
filter_list.append(filter)
220272
res, _ = client.share.list_existing_public_shares(filter_list=filter_list)
221273

222-
res = client.share.get_public_share(opaque_id=share_id, sign=True)
274+
res = client.share.get_public_share(auth.get_token(), opaque_id=share_id, sign=True)
223275
# OR token = "<token>"
224276
# res = client.share.get_public_share(token=token, sign=True)
225277

226278
# update public share #
227-
res = client.share.update_public_share(type="TYPE_PASSWORD", token=token, role="VIEWER", password="hello")
279+
res = client.share.update_public_share(auth.get_token(), type="TYPE_PASSWORD", token=token, role="VIEWER", password="hello")
228280

229281
# remove public share #
230-
res = client.share.remove_public_share(token=token)
282+
res = client.share.remove_public_share(auth.get_token(), token=token)
231283

232284
```
233285

234286
### User Example
235287
```python
236288
# find_user
237-
res = client.user.find_users("rwel")
289+
res = client.user.find_users(auth.get_token(), "rwel")
238290

239291
# get_user
240292
res = client.user.get_user("https://auth.cern.ch/auth/realms/cern", "asdoiqwe")
@@ -253,21 +305,21 @@ res = client.user.get_user_by_claim("username", "rwelande")
253305
### App Example
254306
```python
255307
# list_app_providers
256-
res = client.app.list_app_providers()
308+
res = client.app.list_app_providers(auth.get_token())
257309

258310
# open_in_app
259-
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/collabora.odt")
260-
res = client.app.open_in_app(resource)
311+
resource = Resource(abs_path="/eos/user/r/rwelande/collabora.odt")
312+
res = client.app.open_in_app(auth.get_token(), resource)
261313
```
262314

263315
### Checkpoint Example
264316
```python
265317
# list file versions
266-
resource = Resource.from_file_ref_and_endpoint("/eos/user/r/rwelande/test.md")
267-
res = client.checkpoint.list_file_versions(resource)
318+
resource = Resource(abs_path="/eos/user/r/rwelande/test.md")
319+
res = client.checkpoint.list_file_versions(auth.get_token(), resource)
268320

269321
# restore file version
270-
res = client.checkpoint.restore_file_version(resource, "1722936250.0569fa2f")
322+
res = client.checkpoint.restore_file_version(auth.get_token(), resource, "1722936250.0569fa2f")
271323
```
272324

273325
## Documentation
File renamed without changes.

0 commit comments

Comments
 (0)