{"id":22371315,"url":"https://github.com/abstract-x/xcept","last_synced_at":"2025-08-19T05:13:00.698Z","repository":{"id":62589813,"uuid":"436805104","full_name":"Abstract-X/xcept","owner":"Abstract-X","description":"A Python package for the convenience of creating exceptions.","archived":false,"fork":false,"pushed_at":"2022-07-31T09:35:38.000Z","size":51,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-30T21:30:10.040Z","etag":null,"topics":["exceptions","python"],"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/Abstract-X.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}},"created_at":"2021-12-10T00:49:17.000Z","updated_at":"2023-04-09T21:15:58.000Z","dependencies_parsed_at":"2022-11-03T17:56:05.353Z","dependency_job_id":null,"html_url":"https://github.com/Abstract-X/xcept","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/Abstract-X/xcept","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abstract-X%2Fxcept","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abstract-X%2Fxcept/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abstract-X%2Fxcept/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abstract-X%2Fxcept/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Abstract-X","download_url":"https://codeload.github.com/Abstract-X/xcept/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Abstract-X%2Fxcept/sbom","scorecard":{"id":8058,"data":{"date":"2025-08-11","repo":{"name":"github.com/Abstract-X/xcept","commit":"7e722bee566f6704f6d8bcb55c8a0d1b2018237b"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"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":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","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":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"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":"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":"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"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":"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":"Vulnerabilities","score":8,"reason":"2 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2022-42969","Warn: Project is vulnerable to: GHSA-jfmj-5v4g-7637"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-14T13:59:35.455Z","repository_id":62589813,"created_at":"2025-08-14T13:59:35.455Z","updated_at":"2025-08-14T13:59:35.455Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271103202,"owners_count":24699646,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-19T02:00:09.176Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["exceptions","python"],"created_at":"2024-12-04T20:18:51.291Z","updated_at":"2025-08-19T05:13:00.677Z","avatar_url":"https://github.com/Abstract-X.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# xcept\n\n[![PyPI version](https://badge.fury.io/py/xcept.svg)](https://badge.fury.io/py/xcept)\n[![Python](https://img.shields.io/badge/python-3.7%2B-blue)](https://www.python.org)\n[![GitHub license](https://img.shields.io/github/license/Abstract-X/xcept)](https://github.com/Abstract-X/xcept/blob/main/LICENSE)\n\n`xcept` is a Python package for the convenience of creating exceptions.\n\n---\n\n### Installation\n\n```commandline\npip install xcept\n```\n\n---\n\n### Usage\n\n#### Built-in `Exception`\n\nUsually exceptions are created like this:\n\n```python3\nclass Error(Exception):  # Base error class of your application or library\n    pass\n\n\nclass FooError(Error):  # Concrete error class\n    pass\n\n\nclass BarError(Error):  # Concrete error class\n    pass\n```\n\nIt looks pretty simple.\nLet's try to create exceptions with arguments:\n\n```python3\nclass Error(Exception):\n\n    def __init__(self, message: str):\n        self.message = message\n\n    def __str__(self):\n        return self.message\n\n\nclass FooError(Error):\n\n    def __init__(self, message: str, a: str):\n        super().__init__(message=message)\n        self.a = a\n\n\nclass BarError(Error):\n\n    def __init__(self, message: str, b: str, c: int):\n        super().__init__(message=message)\n        self.b = b\n        self.c = c\n```\n\nIn the simplest case we have to use `super` each time to initialize a new exception. And we also pass an already prepared message.  \nThis does not allow us from getting a modified message when the attributes change:\n\n```python3\n\u003e\u003e\u003e a = \"value\"\n\u003e\u003e\u003e error = FooError(f\"Error (a='{a}')!\", a)\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.FooError: Error (a='value')!\n\u003e\u003e\u003e \n\u003e\u003e\u003e error.a = \"new_value\"\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.FooError: Error (a='value')!\n```\n\n#### xcept `Exception_`\n\nThe idea of `xcept` is based on use of `dataclasses`:\n\n```python3\nfrom dataclasses import dataclass\n\nfrom xcept import Exception_\n\n\n@dataclass\nclass Error(Exception_):\n    pass\n\n\n@dataclass\nclass FooError(Error):\n    a: str\n\n\n@dataclass\nclass BarError(Error):\n    b: str\n    c: int\n```\n\nThe first argument is always a message template with replacement fields:\n\n```python3\n\u003e\u003e\u003e error = FooError(\"Error ({a=})!\", a=\"value\")\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.FooError: Error (a='value')!\n\u003e\u003e\u003e\n\u003e\u003e\u003e error.a = \"new_value\"\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.FooError: Error (a='new_value')!\n```\n\nFormat syntax is presented here:  \nhttps://docs.python.org/3.7/library/string.html#format-string-syntax  \n**Note:** Only keyword replacement fields are supported.  \n**Note:** Additionally, there is an expression with the `=`. It allows you to set a value along with a name:\n```python3\n\u003e\u003e\u003e error = FooError(\"{a}\", a=\"a_value\")\n\u003e\u003e\u003e print(error)\na_value\n\u003e\u003e\u003e\n\u003e\u003e\u003e error = FooError(\"{a=}\", a=\"a_value\")\n\u003e\u003e\u003e print(error)\na='a_value'\n```\n\nIf a message template does not contain all replacement fields and all replacement fields is required, the `MissingFieldWarning` occurs:\n\n```python3\n\u003e\u003e\u003e error = FooError(\"Error!\", a=\"value\")\n\u003cinput\u003e:1: MissingFieldWarning: No the replacement field 'a' in the template 'Error!' (FooError)!\n\u003e\u003e\u003e\n\u003e\u003e\u003e error = BarError(\"Error ({b=})!\", b=\"value\", c=\"value\")\n\u003cinput\u003e:1: MissingFieldWarning: No the replacement field 'c' in the template 'Error ({b=})!' (BarError)!\n\u003e\u003e\u003e\n\u003e\u003e\u003e error = BarError(\"Error!\", b=\"value\", c=\"value\")\n\u003cinput\u003e:1: MissingFieldWarning: No the replacement fields 'b', 'c' in the template 'Error!' (BarError)!\n```\n\nIf for some reason you don't need to include all attributes in a message, define `ALL_REPLACEMENT_FIELDS_IS_REQUIRED = False` (default `True`) to disable checks and warnings:\n\n```python3\n\u003e\u003e\u003e @dataclass\n... class SomeError(Exception_):\n...     ALL_REPLACEMENT_FIELDS_IS_REQUIRED = False\n...     a: str\n...     b: str\n...\n\u003e\u003e\u003e error = SomeError(\"Error ({a=})!\", a=\"a_value\", b=\"b_value\")\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.SomeError: Error (a='a_value')!\n```\n\nIf a message template contains unknown replacement fields, the `UnknownFieldWarning` occurs and the value is set to `\u003cUNKNOWN\u003e`:\n\n```python3\n\u003e\u003e\u003e error = FooError(\"Error ({a=}, {b=}, {c=})!\", a=\"a_value\")\n\u003cinput\u003e:1: UnknownFieldWarning: Unknown the replacement fields 'b', 'c' in the template 'Error ({a=}, {b=}, {c=})!' (FooError)!\n\u003e\u003e\u003e raise error\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.FooError: Error (a='a_value', b=\u003cUNKNOWN\u003e, c=\u003cUNKNOWN\u003e)!\n```\n\nIf there is no a message template and all replacement fields is required, the `MissingTemplateWarning` occurs:\n\n```python3\n\u003e\u003e\u003e @dataclass\n... class SomeError(Exception_):\n...     pass\n...\n\u003e\u003e\u003e error = SomeError(None)  # Message template is None\n\u003cinput\u003e:1: MissingTemplateWarning: No a template (SomeError)!\n```\n\nYou can set a default message template:\n\n```python3\n\u003e\u003e\u003e @dataclass\n... class SomeError(Exception_):\n...     DEFAULT_TEMPLATE = \"Default message template ({a=})!\"\n...     a: str\n...\n\u003e\u003e\u003e raise SomeError(None, a=\"a_value\")  # Message template is None\nTraceback (most recent call last):\n  File \"\u003cinput\u003e\", line 1\n__main__.SomeError: Default message template (a='a_value')!\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabstract-x%2Fxcept","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabstract-x%2Fxcept","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabstract-x%2Fxcept/lists"}