{"id":37403642,"url":"https://github.com/oslokommune/okdata-sdk-python","last_synced_at":"2026-01-23T10:53:22.483Z","repository":{"id":39706539,"uuid":"222710116","full_name":"oslokommune/okdata-sdk-python","owner":"oslokommune","description":"Python SDK for Origo Dataplatform","archived":false,"fork":false,"pushed_at":"2026-01-13T07:51:27.000Z","size":394,"stargazers_count":4,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"main","last_synced_at":"2026-01-16T17:24:00.694Z","etag":null,"topics":["dataplatform"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oslokommune.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-11-19T14:05:05.000Z","updated_at":"2026-01-13T07:51:29.000Z","dependencies_parsed_at":"2024-10-28T13:54:31.826Z","dependency_job_id":"5d58eeb3-75c3-4a08-acc8-d0d7103dfa82","html_url":"https://github.com/oslokommune/okdata-sdk-python","commit_stats":{"total_commits":249,"total_committers":17,"mean_commits":"14.647058823529411","dds":0.7429718875502008,"last_synced_commit":"2494fdaf7f14c2f2e85b698bf27f8cc319a26a0c"},"previous_names":["oslokommune/origo-sdk-python"],"tags_count":61,"template":false,"template_full_name":null,"purl":"pkg:github/oslokommune/okdata-sdk-python","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokdata-sdk-python","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokdata-sdk-python/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokdata-sdk-python/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokdata-sdk-python/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oslokommune","download_url":"https://codeload.github.com/oslokommune/okdata-sdk-python/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oslokommune%2Fokdata-sdk-python/sbom","scorecard":{"id":713701,"data":{"date":"2025-08-11","repo":{"name":"github.com/oslokommune/okdata-sdk-python","commit":"d9b42afa420a4e0d54b161d92b4ef96a97bd7988"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":5.9,"checks":[{"name":"Maintained","score":4,"reason":"5 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 4","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":8,"reason":"dependency not pinned by hash detected -- score normalized to 8","details":["Warn: pipCommand not pinned by hash: .github/workflows/continous-integration.yml:23","Info:   6 out of   6 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Code-Review","score":6,"reason":"Found 5/8 approved changesets -- score normalized to 6","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Info: jobLevel 'actions' permission set to 'read': .github/workflows/codeql-analysis.yml:17","Info: jobLevel 'contents' permission set to 'read': .github/workflows/codeql-analysis.yml:18","Info: jobLevel 'actions' permission set to 'read': .github/workflows/labeler.yml:10","Info: jobLevel 'contents' permission set to 'read': .github/workflows/labeler.yml:11","Warn: no topLevel permission defined: .github/workflows/codeql-analysis.yml:1","Warn: no topLevel permission defined: .github/workflows/continous-integration.yml:1","Warn: no topLevel permission defined: .github/workflows/labeler.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"SAST","score":7,"reason":"SAST tool detected but not run on all commits","details":["Info: SAST configuration detected: CodeQL","Warn: 5 commits out of 27 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-22T08:53:08.893Z","repository_id":39706539,"created_at":"2025-08-22T08:53:08.893Z","updated_at":"2025-08-22T08:53:08.893Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28689076,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T05:48:07.525Z","status":"ssl_error","status_checked_at":"2026-01-23T05:48:07.129Z","response_time":59,"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":["dataplatform"],"created_at":"2026-01-16T05:48:31.239Z","updated_at":"2026-01-23T10:53:22.447Z","avatar_url":"https://github.com/oslokommune.png","language":"Python","readme":"[![PyPI](https://img.shields.io/pypi/v/okdata-sdk)](https://pypi.org/project/okdata-sdk/)\n\n# `okdata-sdk`: Python SDK for Origo Dataplatform\n\n[`okdata-sdk`](https://pypi.org/project/okdata-sdk/) is on PyPI: `pip install okdata-sdk`\n\n# Configuration\n\nWhen calling any classes interacting with the Origo Dataplatform API and there are no Config params passed to the constructor, a config object will be\nautomaticly created for you based on environment variables\n\n\n### Environment variables\nDefault, will pick up configuration from current environment.\nThe credentials is resolved automatically if you do not set a specific Auth config, in the following order:\n\n1. _Client Credentials_: If you have added client_id / client_secret to the config. Or if you use the\nenvironment variable equivalent: `OKDATA_CLIENT_ID` / `OKDATA_CLIENT_SECRET`.\n2. _Username And Password_:  If you have added username / password to the config. Or if you use the\nenvironment variable equivalent: `OKDATA_USERNAME` / `OKDATA_PASSWORD`.\n```\n# keycloak user\nexport OKDATA_USERNAME=my-user\n\n# keycloak password for OKDATA_USERNAME\nexport OKDATA_PASSWORD=my-password\n\n# keycloak client\nexport OKDATA_CLIENT_ID=my-machine-client\n\n# keycloak secret for OKDATA_CLIENT_ID\nexport OKDATA_CLIENT_SECRET=some-generated-secure-string\n\n\n# overrides default environment (dev), but will be trumped by --env=\u003cenvironment\u003e on the commandline\nexport OKDATA_ENVIRONMENT=dev|prod\n\n# If you are sending events and have been assigned a API key\nexport OKDATA_API_KEY=your-api-key\n```\n\n### Getting Credentials:\n`username/password ` are synced with Oslo municipalities Active Directory so any user with an association can\nuse their personal account to access the SDK.\n\nFor `client credentials` please contact the data platform team. `dataplattform[at]oslo.kommune.no`\n\n### TODO: Named profiles\nIf environment variables are not available, the system will try to load from a default profile: Located in ~/.okdata/configuration\n\n# Usage\n\nTable of contents:\n- [Upload data](#upload-data)\n- [Download data](#download-data)\n- [Creating datasets with versions and editions](#creating-datasets-with-versions-and-editions)\n- [Updating dataset metadata](#updating-dataset-metadata)\n\n## Upload data\n\nWhen uploading data you need to refer to an existing dataset that you own, a version and an edition.\nIf these are non existent then you can create them yourself. This can be achieved [using the sdk](#creating-datasets-with-versions-and-editions),\nor you can use our [command line interface](https://github.com/oslokommune/okdata-cli).\n\n\n```python\nfrom okdata.sdk.data.upload import Upload\nfrom okdata.sdk.config import Config\n\nokdata_config = Config()\n\n# If necessary you can override default values\nokdata_config.config[\"cacheCredentials\"] = False\n\ndata_uploader = Upload(config=okdata_config)\n\n# Upload file 'data.json' to dataset-id/version/edition\ndataset_id = \"my-dataset-id\"\nversion = \"my-version\"  # example value: 1\nedition = \"my-edition\"  # example value: 20200618T114038\n\nfilename = \"/path-to-file/data.json\"\n\n# Note! filename must be pointing to an existing file on your disk\nupload_response = data_uploader.upload(filename, dataset_id, version, edition)\nprint(upload_response)\n# {\n#     \"result\": True,\n#     \"trace_id\": \"my-dataset-id-54a3c78e-86a3-4631-8f28-0252fe1c7c13\"\n# }\n```\n\nThe `trace_id` returned by the upload method can be used to \"trace\" the steps involved in the upload process:\n\n```python\nfrom okdata.sdk.status import Status\n...\nstatus = Status(config=okdata_config)\ntrace_events = status.get_status(trace_id)\nprint(trace_events)\n# [\n#     {\n#         \"trace_id\": \"my-dataset-1a2bc345-6789-1234-567d-8912ef34a567\",\n#         \"trace_status\": \"STARTED\",\n#         \"trace_event_id\": \"1a2b3cd4-eef5-6aa7-bccd-e889912334f5\",\n#         \"trace_event_status\": \"OK\",\n#         \"component\": \"data-uploader\",\n#         ...\n#     },\n#     {\n#         \"trace_id\": \"my-dataset-1a2bc345-6789-1234-567d-8912ef34a567\",\n#         \"trace_status\": \"CONTINUE\",\n#         ...\n#     },\n#     {\n#         \"trace_id\": \"my-dataset-1a2bc345-6789-1234-567d-8912ef34a567\",\n#         \"trace_event_id\": \"1aa2b345-678c-9de1-f2a3-4566bcd78912\",\n#         \"trace_status\": \"FINISHED\",\n#         \"trace_event_status\": \"OK\",\n#         ...\n#     }\n# ]\n```\n\n## Download data\n\nTo download data you need to refer to a dataset that you have access to. This\ncould be a public dataset, a restricted dataset you've been given access to, or\na dataset that you own yourself. If the dataset is public, [authenticating\nyourself](#environment-variables) is not necessary.\n\nYou will also need to refer to the specific version and edition of the dataset\nthat you want to download. If this is your own dataset, make sure to create a\n[version and edition](#creating-datasets-with-versions-and-editions) before\nattempting to download it.\n\n```python\nfrom okdata.sdk.data.download import Download\nfrom okdata.sdk.config import Config\n\nokdata_config = Config(env=\"dev\")\n\n# If necessary you can override default config values\nokdata_config.config[\"cacheCredentials\"] = False\n\ndata_downloader = Download(config=okdata_config)\n\ndataset_id = \"your-dataset-id\"\nversion = \"1\"\nedition = \"latest\"\n\n# Downloading a file\nres1 = data_downloader.download(dataset_id, version, edition, \"my/preferred/output/path\")\nprint(res1)\n# {\n#     \"downloaded_files\": [\"my/preferred/output/path/file_name.csv\"]\n# }\n```\n\n## Creating datasets with versions and editions\n```python\nfrom okdata.sdk.data.dataset import Dataset\nfrom okdata.sdk.config import Config\n\nokdata_config = Config()\n\n# If necessary you can override default values\nokdata_config.config[\"cacheCredentials\"] = False\n\n# Create a new dataset\ndataset = Dataset(config=okdata_config)\n\ndataset_metadata = {\n    \"title\": \"Precise Descriptive Title\",\n    \"description\": \"Describe your dataset here\",\n    \"keywords\": [\"some-keyword\"],\n    \"accessRights\": \"public\",\n    \"objective\": \"Exemplify how to create a new dataset\",\n    \"contactPoint\": {\n        \"name\": \"Your name\",\n        \"email\": \"your_email@domain.com\",\n        \"phone\": \"999555111\"\n    },\n    \"publisher\": \"name of organization or person responsible for publishing the data\"\n}\n\nnew_dataset = dataset.create_dataset(data=dataset_metadata)\n\n# new_dataset:\n# { 'Id': 'precise-descriptive-title',\n#   'Type': 'Dataset',\n#   '_links': {'self': {'href': '/datasets/precise-descriptive-title'}},\n#   'accessRights': 'public',\n#   'contactPoint': { 'email': 'your_email@domain.com',\n#                     'name': 'Your name',\n#                     'phone': '999555111'},\n#   'description': 'Describe your dataset here',\n#   'keywords': ['some-keyword'],\n#   'objective': 'Exemplify how to create a new dataset',\n#   'publisher': 'name of organization or person responsible for publishing the '\n#                'data',\n#   'title': 'Precise Descriptive Title'}\n\n\n# create version for new dataset:\nversion_data = {\"version\": \"1\"}\nnew_version = dataset.create_version(new_dataset[\"Id\"], data=version_data)\n\n# new_version:\n# { 'Id': 'precise-descriptive-title/1',\n#   'Type': 'Version',\n#   '_links': { 'self': { 'href': '/datasets/precise-descriptive-title/versions/1'}},\n#   'version': '1'}\n\n# create edition for new_dataset/new_version:\nimport datetime\n\n# Note! edition-field must be ISO 8601 with utc offset\nedition_data = {\n    \"edition\": str(datetime.datetime.utcnow().replace(tzinfo=datetime.timezone.utc).isoformat()),\n    \"description\": \"My edition description\",\n    \"startTime\": \"2019-01-01\",\n    \"endTime\": \"2019-12-31\"\n}\nnew_edition = dataset.create_edition(new_dataset[\"Id\"], new_version[\"version\"], data=edition_data)\n\n# new_edition\n# { 'Id': 'precise-descriptive-title/1/20200115T130439',\n#   'Type': 'Edition',\n#   '_links': { 'self': { 'href': '/datasets/precise-descriptive-title/versions/1/editions/20200115T130439'}},\n#   'description': 'My edition description',\n#   'edition': '2020-01-15T13:04:39.041778+00:00',\n#   'endTime': '2019-12-31',\n#   'startTime': '2019-01-01'}\n```\n\n## Updating dataset metadata\n\nSimilarly to creating datasets, metadata for any given dataset, version etc., can also be\n**updated** by using the methods listed below. These methods accept an updated version of\nthe JSON document posted when creating the same resource:\n\n```py\ndataset.update_dataset(datasetid, data={ ... })\ndataset.update_version(datasetid, versionid, data={ ... })\ndataset.update_edition(datasetid, versionid, editionid, data={ ... })\ndataset.update_distribution(datasetid, versionid, editionid, distributionid, data={ ... })\n\n# Example: Update dataset metadata\ndataset.update_dataset(\n    datasetid=\"precise-descriptive-title\",\n    data={\n        \"title\": \"Precise Descriptive Title\",\n        \"description\": \"Describe your dataset here\",\n        \"keywords\": [\"some-keyword\", \"another-keyword\"], # Add another keyword\n        \"accessRights\": \"public\",\n        \"license\": \"http://data.norge.no/nlod/\", # Add licensing information\n        \"objective\": \"Exemplify how to update an existing dataset\", # Update objective text\n        \"contactPoint\": {\n            \"name\": \"Your name\",\n            \"email\": \"your_email@domain.com\",\n            \"phone\": \"999555111\"\n        },\n        \"publisher\": \"name of organization or person responsible for publishing the data\"\n    }\n)\n```\n\nThe `update_dataset` method also supports an optional `partial` keyword,\nenabling partial updates when true:\n\n```py\ndataset.update_dataset(\n    \"my-dataset-id\", {\"description\": \"Only update description\"}, partial=True\n)\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foslokommune%2Fokdata-sdk-python","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foslokommune%2Fokdata-sdk-python","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foslokommune%2Fokdata-sdk-python/lists"}