{"id":40577814,"url":"https://github.com/edaniszewski/bison","last_synced_at":"2026-01-21T02:30:27.312Z","repository":{"id":30234079,"uuid":"124340265","full_name":"edaniszewski/bison","owner":"edaniszewski","description":"Python application configuration","archived":false,"fork":false,"pushed_at":"2022-05-03T07:49:04.000Z","size":65,"stargazers_count":16,"open_issues_count":2,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-01-03T15:54:48.697Z","etag":null,"topics":["application-configuration","configuration","python","python3","yaml"],"latest_commit_sha":null,"homepage":null,"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/edaniszewski.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":"2018-03-08T05:13:03.000Z","updated_at":"2025-08-13T14:08:53.000Z","dependencies_parsed_at":"2022-07-27T15:15:25.480Z","dependency_job_id":null,"html_url":"https://github.com/edaniszewski/bison","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/edaniszewski/bison","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edaniszewski%2Fbison","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edaniszewski%2Fbison/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edaniszewski%2Fbison/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edaniszewski%2Fbison/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/edaniszewski","download_url":"https://codeload.github.com/edaniszewski/bison/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/edaniszewski%2Fbison/sbom","scorecard":{"id":365983,"data":{"date":"2025-08-11","repo":{"name":"github.com/edaniszewski/bison","commit":"d6d3a6bc0f641e80a1fae544e3cceb31960f4bc7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"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":"Code-Review","score":0,"reason":"Found 0/19 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":"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":"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":"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":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yaml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/edaniszewski/bison/lint.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/lint.yaml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/edaniszewski/bison/lint.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/edaniszewski/bison/test.yaml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yaml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/edaniszewski/bison/test.yaml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/lint.yaml:18","Warn: pipCommand not pinned by hash: .github/workflows/lint.yaml:19","Warn: pipCommand not pinned by hash: .github/workflows/test.yaml:22","Warn: pipCommand not pinned by hash: .github/workflows/test.yaml:23","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   4 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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/lint.yaml:1","Warn: no topLevel permission defined: .github/workflows/test.yaml: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":"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":"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":"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":"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":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 16 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-18T11:51:17.565Z","repository_id":30234079,"created_at":"2025-08-18T11:51:17.565Z","updated_at":"2025-08-18T11:51:17.565Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28623204,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-20T23:49:58.628Z","status":"online","status_checked_at":"2026-01-21T02:00:08.227Z","response_time":86,"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":["application-configuration","configuration","python","python3","yaml"],"created_at":"2026-01-21T02:30:23.635Z","updated_at":"2026-01-21T02:30:27.307Z","avatar_url":"https://github.com/edaniszewski.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://pypi.python.org/pypi/bison\"\u003e\u003cimg src=\"https://img.shields.io/pypi/v/bison.svg\"\u003e\u003c/a\u003e\n    \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/github/license/edaniszewski/bison.svg\"\u003e\u003c/a\u003e\n        \n\u003ch1 align=\"center\"\u003ebison\u003c/h1\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003ePython application configuration\u003c/p\u003e\n\n\n## What is Bison?\nBison is a configuration solution for Python applications that aims to be simple\nand intuitive. It supports:\n* reading from YAML config files\n* reading from environment variables\n* setting explicit values\n* setting defaults\n* configuration validation\n* configuration access/manipulation with dot notation\n\nInstead of implementing custom configuration reading and parsing, you can use\nBison to handle it for you.\n\nBison was inspired by [Viper][viper] and the lack of good\napplication configuration solutions for Python (at least, in my opinion). Documentation\nfor Bison can be found on [ReadtheDocs][docs]\n\nBison uses the following precedence order. Each item in the list takes precedence\nover the item below it.\n- override (e.g. calling `Bison.set()`)\n- environment\n- config file\n- defaults\n\n## Installation\nBison can be installed with `pip`\n```\npip install bison\n```\nor with `pipenv`\n```\npipenv install bison\n```\n\n## Using Bison\n### Creating a configuration Scheme\nA configuration scheme is not required by Bison, but having one allows you to set default\nvalues for configuration fields as well as do configuration validation. It is pretty easy\nto create a new Scheme:\n\n```python\nscheme = bison.Scheme()\n```\n\nA Scheme is really just a container for configuration options, so without any options, a\nScheme is somewhat useless.\n\n#### Configuration Options\nThere are currently three types of configuration options:\n- `bison.Option`\n- `bison.DictOption`\n- `bison.ListOption`\n\nTheir intended functionality should be mostly obvious from their names. An `Option` represents\na singular value in a configuration. A `DictOption` represents a dictionary or mapping of values\nin a configuration. A `ListOption` represents a list of values in a configuration.\n\nSee the [documentation][docs] for more on how options can be configured.\n\nAny number of options can be added to a Scheme, but as a simple example we can define a Scheme\nwhich expects a key \"log\", and a key \"count\".\n\n```python\nscheme = bison.Scheme(\n    bison.Option('log'),\n    bison.Option('count'),\n)\n```\n\n#### Configuration Validation\nValidation operates based on the constraints set on the options. Above, there are no\nconstraints (other than the need for those keys to exist), so any value for \"log\" and\n\"count\" will pass validation.\n\nAn option can be constrained in different ways by using its keyword arguments. For example,\nto ensure the value for \"count\" is an integer,\n```python\nbison.Option('count', field_type=int)\n```\n\nOr, to restrict the values to a set of choices\n```python\nbison.Option('log', choices=['debug', 'info', 'warn', 'error'])\n```\n\nThe [documentation][docs] goes into more detail about other validation settings.\n\n#### Setting Defaults\nIf a default value is not set on an option, it is considered required. In these cases,\nif the key specified by that value is not present in the parse configuration, it will\ncause a validation failure.\n\nIf a default value is set, then the absence of that field in the configuration will not\ncause a validation failure.\n\n```python\nbison.Option('log', default='info')\n```\n\n### Configuring Bison\nOnce you have a Scheme to use (if you'd like to), it will need to be passed to a Bison\nobject to manage the config building. \n\n```python\nscheme = bison.Scheme()\nconfig = bison.Bison(scheme)\n```\n\nThere are a few options that can be set on the Bison object to change how it\nsearches for and builds the unified configuration. \n\nFor reading configuration files\n```python\nconfig.config_name = 'config'  # name of the config file (no extension)\nconfig.add_config_paths(       # paths to look in for the config file\n    '.',\n    '/tmp/app'\n)\nconfig.config_format = bison.YAML # the config format to use\n```\n\nFor reading environment variables\n```python\nconfig.env_prefix = \"MY_APP\"  # the prefix to use for environment variables\nconfig.auto_env = True  #  automatically bind all options to env variables based on their key\n```\n\n### Building the unified config\nOnce the scheme has been set (if using) and Bison has been configured, the only thing\nleft to do is to read in all the config sources and parse them into a unified config.\nThis is done simply with\n```python\nconfig.parse()\n```\n\n### Example\nBelow is a complete example for parsing a hypothetical application configuration which\nis described by the following YAML config.\n```yaml\nlog: debug\nport: 5000\nsettings:\n  requests:\n    timeout: 3\nbackends:\n  - host: 10.1.2.3\n    port: 5001\n  - host: 10.1.2.4\n    port: 5013\n  - host: 10.1.2.5\n    port: 5044\n```\n\n```python\nimport bison\n\n# the scheme for the configuration. this allows us to set defaults\n# and validate configuration data\nconfig_scheme = bison.Scheme(\n    bison.Option('log', default='info', choices=['debug', 'info', 'warn', 'error']),\n    bison.Option('port', field_type=int),\n    bison.DictOption('settings', scheme=bison.Scheme(\n        bison.DictOption('requests', scheme=bison.Scheme(\n            bison.Option('timeout', field_type=int)\n        ))\n    )),\n    bison.ListOption('backends', member_scheme=bison.Scheme(\n        bison.Option('host', field_type=str),\n        bison.Option('port', field_type=int)\n    ))\n)\n\n# create a new Bison instance to store and manage configuration data\nconfig = bison.Bison(scheme=config_scheme)\n\n# set the config file name to 'app' (default is 'config') and set the\n# search paths to '.' and '/tmp/app/config'\nconfig.config_name = 'app'\nconfig.add_config_paths('.', '/tmp/app/config')\n\n# set the environment variable prefix and enable auto-env\nconfig.env_prefix = 'MY_APP'\nconfig.auto_env = True\n\n# finally, parse the config sources to build the unified configuration\nconfig.parse()\n```\n\nSee the [example](example) directory for this example along with demonstrations\nof how to access configuration data.\n\n## Future Work\nThere is more that can be done to improve Bison and expand its functionality. If\nyou wish to contribute, open a pull request. If you have questions or feature requests,\nopen an issue. Below are some high level ideas for future improvements:\n\n* Support additional configuration formats (JSON, TOML, ...)\n* Versioned configurations\n\n\n[docs]: http://readthedocs\n[viper]: https://github.com/spf13/viper","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedaniszewski%2Fbison","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fedaniszewski%2Fbison","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fedaniszewski%2Fbison/lists"}