{"id":28003915,"url":"https://github.com/zipfile/fiicha","last_synced_at":"2025-07-05T19:36:38.818Z","repository":{"id":57429306,"uuid":"461579581","full_name":"ZipFile/fiicha","owner":"ZipFile","description":"A minimalistic feature flag implementation with type hints","archived":false,"fork":false,"pushed_at":"2022-02-22T21:44:33.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-06-13T21:44:50.066Z","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":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ZipFile.png","metadata":{"files":{"readme":"README.rst","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":"2022-02-20T18:33:46.000Z","updated_at":"2022-02-20T18:34:12.000Z","dependencies_parsed_at":"2022-08-27T17:01:25.952Z","dependency_job_id":null,"html_url":"https://github.com/ZipFile/fiicha","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ZipFile/fiicha","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZipFile%2Ffiicha","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZipFile%2Ffiicha/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZipFile%2Ffiicha/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZipFile%2Ffiicha/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ZipFile","download_url":"https://codeload.github.com/ZipFile/fiicha/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ZipFile%2Ffiicha/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263795315,"owners_count":23512658,"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","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-05-09T02:33:14.605Z","updated_at":"2025-07-05T19:36:38.753Z","avatar_url":"https://github.com/ZipFile.png","language":"Python","readme":"======\nFiicha\n======\n\nFiicha is minimalistic mypy-friendly feature flag implementation with no\nexternal dependencies.\n\nInstallation\n============\n\n.. code-block:: sh\n\n    pip install fiicha\n\nFor Development\n---------------\n\nClone the repo, change current working dir to the root of the repo and execute:\n\n.. code-block:: sh\n\n    python -m venv env\n    . env/bin/activate\n    pip install -e .[test,lint]\n\nUsage\n=====\n\nBasic\n-----\n\nBasic usage is simple:\n\n1. Sublcass from ``FeatureFlags``\n2. Add ``FeatureFlag`` attributes representing individual feature flags.\n\n.. code-block:: python\n\n    from fiicha import FeatureFlag, FeatureFlags\n\n    class MyProjectFeatureFlags(FeatureFlags):\n        release_x = FeatureFlag(\"Enable features from upcoming release X\")\n        use_new_algorithm = FeatureFlag(\"Use new algorithm for ...\")\n\n    ff = MyProjectFeatureFlags({\"release_x\": True})\n\n    print(ff.release_x)  # True\n    print(ff.use_new_algorithm)  # False\n\n\nIn addition, you kan specify a key defining default state of the feature flags:\n\n.. code-block:: python\n\n    ff = MyProjectFeatureFlags({\"all\": True, \"release_x\": False}, default_key=\"all\")\n\n    print(ff.release_x)  # False\n    print(ff.use_new_algorithm)  # True\n\nClasses subclassed from ``FeatureFlags`` has full type hint support, so\nwhen you are accessing removed or otherwise non-existent feature flags, you\ncan detect it before running tests:\n\n.. code-block:: python\n\n    ff.xxx  # will trigger mypy's attr-defined error\n\n\nUtils\n-----\n\nThe package comes with few util functions to avoid building your own framework\nfor simple use cases.\n\n\nSingle-line Configuration\n~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    from fiicha import parse_feature_flags_string\n\n    flags_string = \"release_x !use_new_algorithm\"  # stored in config\n    ff = MyProjectFeatureFlags(parse_feature_flags_string(flags_string))\n\n    print(ff.release_x)  # True\n    print(ff.use_new_algorithm)  # False\n\nLoad Flags From Environment Variables\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    import os\n    from fiicha import feature_flags_from_environ\n\n    os.environ[\"MYPROJ_FEATURE_RELEASE_X\"] = \"True\"  # can also be 1, t, yes, on\n    os.environ[\"MYPROJ_FEATURE_USE_NEW_ALGORITHM\"] = \"False\"  # can also be 0, f, no, off or empty string\n\n    ff = MyProjectFeatureFlags(feature_flags_from_environ(\"MYPROJ_FEATURE_\"))\n\n    print(ff.release_x)  # True\n    print(ff.use_new_algorithm)  # False\n\nAutomatically Document Your Feature Flags\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n.. code-block:: python\n\n    from fiicha import make_napoleon_doc, make_sphinx_doc\n\n    class GoogleStyleDocFeatureFlags(FeatureFlags, make_doc=make_napoleon_doc):\n        a = FeatureFlag(\"Enable feature A\")\n        b = FeatureFlag(\"Enable feature B\")\n\n    class SphinxStyleDocFeatureFlags(FeatureFlags, make_doc=make_sphinx_doc):\n        x = FeatureFlag(\"Enable feature X\")\n        y = FeatureFlag(\"Enable feature Y\")\n\n    print(GoogleStyleDocFeatureFlags.__doc__)\n    print(SphinxStyleDocFeatureFlags.__doc__)\n\nContext Variable Support\n~~~~~~~~~~~~~~~~~~~~~~~~\n\nYou might want to do A/B testing or otherwise toggle feature flags for\nindividual users without affecting the rest of the system. For such cases,\nthere is ``FeatureFlagsContext`` - a wrapper around ``ContextVar``. It copies\ncurrent feature flags and sets them as new context variable on enter and\nresets them back on exit. This way you will be able to achieve global feature\nflags protection from changes made within context of a request or a task.\n\n.. code-block:: python\n\n    from contextvars import ContextVar\n    from fiicha import FeatureFlag, FeatureFlags, FeatureFlagsContext\n\n    class MyFeatureFlags(FeatureFlags):\n        a = FeatureFlag(\"Enable feature A\")\n        b = FeatureFlag(\"Enable feature B\")\n\n    root = MyFeatureFlags()\n    var: ContextVar[MyFeatureFlags] = ContextVar(\"test\", default=root)\n    ff_ctx = FeatureFlagsContext(var)\n\n    with ff_ctx:\n        ff = var.get()\n        ff.a = True\n\n        assert ff is not root  # is a copy\n\n    assert not root.a  # not changed\n\nAdvanced\n--------\n\nSee ``examples`` subfolder within the repo.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzipfile%2Ffiicha","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzipfile%2Ffiicha","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzipfile%2Ffiicha/lists"}