{"id":34113794,"url":"https://github.com/cs3org/cs3-python-client","last_synced_at":"2026-04-01T20:22:48.076Z","repository":{"id":247746979,"uuid":"826182563","full_name":"cs3org/cs3-python-client","owner":"cs3org","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-03T08:52:25.000Z","size":138,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-03-28T00:39:48.777Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/cs3org.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-09T08:22:28.000Z","updated_at":"2026-03-03T08:52:23.000Z","dependencies_parsed_at":"2024-08-02T10:32:12.407Z","dependency_job_id":"18d4aa54-2ad7-4f84-9b9d-a62375f5aad5","html_url":"https://github.com/cs3org/cs3-python-client","commit_stats":null,"previous_names":["cernbox/cs3-python-client"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/cs3org/cs3-python-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs3org%2Fcs3-python-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs3org%2Fcs3-python-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs3org%2Fcs3-python-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs3org%2Fcs3-python-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cs3org","download_url":"https://codeload.github.com/cs3org/cs3-python-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cs3org%2Fcs3-python-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31291536,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-01T13:12:26.723Z","status":"ssl_error","status_checked_at":"2026-04-01T13:12:25.102Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-12-14T19:19:30.292Z","updated_at":"2026-04-01T20:22:48.057Z","avatar_url":"https://github.com/cs3org.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CS3Client\n\n`CS3Client` is a Python client for interacting with the CS3 (Cloud Sync\u0026Share Storage) [APIs](https://github.com/cs3org/cs3apis). It allows users to seamlessly communicate with cloud storage services that support CS3 protocols, enabling file management, data transfer, and other cloud-based operations.\n\n## Table of Contents\n\n- [Features](#features)\n- [Installation](#installation)\n- [Usage](#usage)\n- [Configuration](#configuration)\n- [Examples](#examples)\n- [Documentation](#documentation)\n- [License](#license)\n\n\n## Features\n\n- Simple and easy-to-use API client for CS3 services.\n- Support for common file operations (read, write, delete, rename, ...).\n- Support for common lock operations (set lock, get lock, unlock, ...).\n- Support for common share operations (create share, update share, delete share, ...).\n- Support for common user operations (get user, find users, get user groups, ...).\n- support for common group operations (get group, find group, has member, ...).\n- Support for restoring files through checkpoints (restore file version, list checkpoints).\n- Support for applications (open in app, list app providers).\n- Authentication and authorization handling.\n- Cross-platform compatibility.\n- Detailed error handling and logging.\n\n## Installation\n\nTo install `cs3client`, you need to have Python 3.7+ installed. You can install the package via `pip`:\n\n```bash\npip install cs3client\n```\nAlternatively, you can clone this repository and install manually:\n```bash\ngit clone git@github.com:cs3org/cs3-python-client.git\ncd cs3-python-client\npip install . \n```\n\n\n## Configuration\n\n`CS3Client` can be configured by passing specific parameters when initializing the client through a ConfigParser instance.\n\n### Parameters:\n\n#### Required\n- `host`\n\n#### Optional (parameter - default)\n- `chunk_size` - 4194384\n- `grpc_timeout` - 10\n- `http_timeout` - 10\n- `tus_enabled` - False\n- `ssl_enabled` - False\n- `ssl_client_cert` - None\n- `ssl_client_key` - None\n- `ssl_ca_cert` - None\n- `auth_client_id` - None\n- `auth_login_type` - \"basic\"\n- `lock_by_setting_attr` - False\n- `lock_not_impl` - False\n- `lock_expiration` - 1800\n\n#### Example configuration\n```yaml\n[cs3client]\n\n# Required\nhost = localhost:19000\n# Optional, defaults to 4194304\nchunk_size = 4194304\n# Optional, defaults to 10\ngrpc_timeout = 10\n# Optional, defaults to 10\nhttp_timeout = 10\n\n# Optional, defaults to True\ntus_enabled = False\n\n# Optional, defaults to True\nssl_enabled = False\n# Optional, defaults to True\nssl_verify = False\n# Optional, defaults to an empty string\nssl_client_cert = test_client_cert\n# Optional, defaults to an empty string\nssl_client_key = test_client_key\n# Optional, defaults to an empty string\nssl_ca_cert = test_ca_cert\n\n# Optinal, defaults to an empty string\nauth_client_id = einstein\n# Optional (can also be set when instansiating the class)\nauth_client_secret = relativity\n# Optional, defaults to basic\nauth_login_type = basic\n\n# Optional, defaults to False\nlock_by_setting_attr = False\n# Optional, defaults to False\nlock_not_impl = False\n# Optional, defaults to 1800\nlock_expiration = 1800\n\n\n```\n\n## Usage\n\nTo 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/`. \n\n### Initilization and Authentication\n```python\nimport logging\nimport configparser\nfrom cs3client.cs3client import CS3Client\nfrom cs3client.auth import Auth\n\nconfig = configparser.ConfigParser()\nwith open(\"default.conf\") as fdef:\n    config.read_file(fdef)\nlog = logging.getLogger(__name__)\n\nclient = CS3Client(config, \"cs3client\", log)\nauth = Auth(client)\n# Set the client id (can also be set in the config)\nauth.set_client_id(\"\u003cyour_client_id_here\u003e\")\n# Set client secret (can also be set in config)\nauth.set_client_secret(\"\u003cyour_client_secret_here\u003e\")\n# Checks if token is expired if not return ('x-access-token', \u003ctoken\u003e)\n# if expired, request a new token from reva\nauth_token = auth.get_token()\n\n# OR if you already have a reva token\n# Checks if token is expired if not return (x-access-token', \u003ctoken\u003e)\n# if expired, throws an AuthenticationException (so you can refresh your reva token)\ntoken = \"\u003cyour_reva_token\u003e\"\nauth_token = Auth.check_token(token)\n\n```\n\n### File Example\n```python\n# mkdir\ndirectory_resource = Resource(abs_path=f\"/eos/user/r/rwelande/test_directory\")\nres = client.file.make_dir(auth.get_token(), directory_resource)\n\n# touchfile\ntouch_resource = Resource(abs_path=\"/eos/user/r/rwelande/touch_file.txt\")\nres = client.file.touch_file(auth.get_token(), touch_resource)\n\n# setxattr\nresource = Resource(abs_path=\"/eos/user/r/rwelande/text_file.txt\")\nres = client.file.set_xattr(auth.get_token(), resource, \"iop.wopi.lastwritetime\", str(1720696124))\n\n# rmxattr\nres = client.file.remove_xattr(auth.get_token(), resource, \"iop.wopi.lastwritetime\")\n\n# stat\nres = client.file.stat(auth.get_token(), resource)\n\n# removefile\nres = client.file.remove_file(auth.get_token(), touch_resource)\n\n# rename\nrename_resource = Resource(abs_path=\"/eos/user/r/rwelande/rename_file.txt\")\nres = client.file.rename_file(auth.get_token(), resource, rename_resource)\n\n# writefile\ncontent = b\"Hello World\"\nsize = len(content)\nres = client.file.write_file(auth.get_token(), rename_resource, content, size)\n\n# listdir\nlist_directory_resource = Resource(abs_path=\"/eos/user/r/rwelande\")\nres = client.file.list_dir(auth.get_token(), list_directory_resource)\n\n\n# readfile\nfile_res = client.file.read_file(auth.get_token(), rename_resource)\n```\n### Lock Example\n```python\n\nWEBDAV_LOCK_PREFIX = 'opaquelocktoken:797356a8-0500-4ceb-a8a0-c94c8cde7eba'\n\n\ndef encode_lock(lock):\n    '''Generates the lock payload for the storage given the raw metadata'''\n    if lock:\n        return WEBDAV_LOCK_PREFIX + ' ' + b64encode(lock.encode()).decode()\n    return None\n\nresource = Resource(abs_path=\"/eos/user/r/rwelande/lock_test.txt\")\n\n# Set lock\nclient.file.set_lock(auth_token, resource, app_name=\"a\", lock_id=encode_lock(\"some_lock\"))\n\n# Get lock\nres = client.file.get_lock(auth_token, resource)\nif res is not None:\n    lock_id = res[\"lock_id\"]\n    print(res)\n\n# Unlock\nres = client.file.unlock(auth_token, resource, app_name=\"a\", lock_id=lock_id)\n\n# Refresh lock\nclient.file.set_lock(auth_token, resource, app_name=\"a\", lock_id=encode_lock(\"some_lock\"))\nres = client.file.refresh_lock(\n    auth_token, resource, app_name=\"a\", lock_id=encode_lock(\"new_lock\"), existing_lock_id=lock_id\n)\n\nif res is not None:\n    print(res)\n\nres = client.file.get_lock(auth_token, resource)\nif res is not None:\n    print(res)\n\n```\n\n### Share Example\n```python\n# Create share #\nresource = Resource(abs_path=\"/eos/user/r/\u003csome_username\u003e/text.txt\")\nresource_info = client.file.stat(auth.get_token(), resource)\nuser = client.user.get_user_by_claim(\"username\", \"\u003csome_username\u003e\")\nres = client.share.create_share(auth.get_token(), resource_info, user.id.opaque_id, user.id.idp, \"EDITOR\", \"USER\")\n\n# List existing shares #\nfilter_list = []\nfilter = client.share.create_share_filter(resource_id=resource_info.id, filter_type=\"TYPE_RESOURCE_ID\")\nfilter_list.append(filter)\nfilter = client.share.create_share_filter(share_state=\"SHARE_STATE_PENDING\", filter_type=\"TYPE_STATE\")\nfilter_list.append(filter)\nres, _ = client.share.list_existing_shares(auth.get_token(), )\n\n# Get share #\nshare_id = \"58\"\nres = client.share.get_share(auth.get_token(), opaque_id=share_id)\n\n# update share #\nres = client.share.update_share(auth.get_token(), opaque_id=share_id, role=\"VIEWER\")\n\n# remove share #\nres = client.share.remove_share(auth.get_token(), opaque_id=share_id)\n\n# List existing received shares #\nfilter_list = []\nfilter = client.share.create_share_filter(share_state=\"SHARE_STATE_ACCEPTED\", filter_type=\"TYPE_STATE\")\nfilter_list.append(filter)\nres, _ = client.share.list_received_existing_shares(auth.get_token())\n\n# get received share #\nreceived_share = client.share.get_received_share(auth.get_token(), opaque_id=share_id)\n\n# update recieved share #\nres = client.share.update_received_share(auth.get_token(), received_share=received_share, state=\"SHARE_STATE_ACCEPTED\")\n\n# create public share #\nres = client.share.create_public_share(auth.get_token(), resource_info, role=\"VIEWER\")\n\n# list existing public shares #\nfilter_list = []\nfilter = client.share.create_public_share_filter(resource_id=resource_info.id, filter_type=\"TYPE_RESOURCE_ID\")\nfilter_list.append(filter)\nres, _ = client.share.list_existing_public_shares(filter_list=filter_list)\n\nres = client.share.get_public_share(auth.get_token(), opaque_id=share_id, sign=True)\n# OR token = \"\u003ctoken\u003e\"\n# res = client.share.get_public_share(token=token, sign=True)\n\n# update public share #\nres = client.share.update_public_share(auth.get_token(), type=\"TYPE_PASSWORD\", token=token, role=\"VIEWER\", password=\"hello\")\n\n# remove public share #\nres = client.share.remove_public_share(auth.get_token(), token=token)\n\n```\n\n### User Example\n```python\n# find_user\nres = client.user.find_users(auth.get_token(), \"rwel\")\n\n# get_user\nres = client.user.get_user(\"https://auth.cern.ch/auth/realms/cern\", \"asdoiqwe\")\n\n# get_user_groups\nres = client.user.get_user_groups(\"https://auth.cern.ch/auth/realms/cern\", \"rwelande\")\n\n# get_user_by_claim (mail)\nres = client.user.get_user_by_claim(\"mail\", \"rasmus.oscar.welander@cern.ch\")\n\n# get_user_by_claim (username)\nres = client.user.get_user_by_claim(\"username\", \"rwelande\")\n\n```\n\n### Group example\n```python\n# get_group_by_claim (username)\nres = client.group.get_group_by_claim(client.auth.get_token(), \"username\", \"rwelande\")\n\n# get_group\nres = client.group.get_group(client.auth.get_token(), \"https://auth.cern.ch/auth/realms/cern\", \"asdoiqwe\")\n\n# has_member\nres = client.group.has_member(client.auth.get_token(), \"somegroup\", \"rwelande\", \"https://auth.cern.ch/auth/realms/cern\")\n\n# get_members\nres = client.group.get_members(client.auth.get_token(), \"somegroup\", \"https://auth.cern.ch/auth/realms/cern\")\n\n# find_groups\nres = client.group.find_groups(client.auth.get_token(), \"rwel\")\n```\n\n### App Example\n```python\n# list_app_providers\nres = client.app.list_app_providers(auth.get_token())\n\n# open_in_app\nresource = Resource(abs_path=\"/eos/user/r/rwelande/collabora.odt\")\nres = client.app.open_in_app(auth.get_token(), resource)\n```\n\n### Checkpoint Example\n```python\n# list file versions\nresource = Resource(abs_path=\"/eos/user/r/rwelande/test.md\")\nres = client.checkpoint.list_file_versions(auth.get_token(), resource)\n\n# restore file version\nres = client.checkpoint.restore_file_version(auth.get_token(), resource, \"1722936250.0569fa2f\")\n```\n\n## Documentation\nThe documentation can be generated using sphinx\n\n```bash\npip install sphinx\ncd docs\nmake html\n```\n\n## Unit tests\n\n```bash\npytest --cov-report term --cov=serc tests/\n```\n\n## License\n\nThis project is licensed under the Apache 2.0 License. See the LICENSE file for more details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcs3org%2Fcs3-python-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcs3org%2Fcs3-python-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcs3org%2Fcs3-python-client/lists"}