{"id":26250586,"url":"https://github.com/obriencj/python-livelocals","last_synced_at":"2025-09-03T06:38:10.656Z","repository":{"id":62576424,"uuid":"105078983","full_name":"obriencj/python-livelocals","owner":"obriencj","description":"Living locals and easy frame local variable introspection","archived":false,"fork":false,"pushed_at":"2019-07-05T19:48:00.000Z","size":43,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-09-03T06:38:09.323Z","etag":null,"topics":["python","python2","python3"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/obriencj.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":"2017-09-27T23:17:20.000Z","updated_at":"2019-07-05T19:45:17.000Z","dependencies_parsed_at":"2022-11-03T18:59:03.703Z","dependency_job_id":null,"html_url":"https://github.com/obriencj/python-livelocals","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/obriencj/python-livelocals","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obriencj%2Fpython-livelocals","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obriencj%2Fpython-livelocals/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obriencj%2Fpython-livelocals/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obriencj%2Fpython-livelocals/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obriencj","download_url":"https://codeload.github.com/obriencj/python-livelocals/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obriencj%2Fpython-livelocals/sbom","scorecard":{"id":701137,"data":{"date":"2025-08-11","repo":{"name":"github.com/obriencj/python-livelocals","commit":"20e157ecb8dba87c0e8c911ef0e99e12d3cd71d2"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"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":"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":"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":"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/21 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":"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":"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":"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":"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: GNU Lesser General Public License v3.0: 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":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 12 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-22T05:14:23.740Z","repository_id":62576424,"created_at":"2025-08-22T05:14:23.740Z","updated_at":"2025-08-22T05:14:23.740Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273403950,"owners_count":25099299,"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-09-03T02:00:09.631Z","response_time":76,"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":["python","python2","python3"],"created_at":"2025-03-13T16:19:57.551Z","updated_at":"2025-09-03T06:38:10.628Z","avatar_url":"https://github.com/obriencj.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Overview of python-livelocals\n\n[![Build Status](https://travis-ci.org/obriencj/python-livelocals.svg?branch=master)](https://travis-ci.org/obriencj/python-livelocals)\n\nMapping object that provides an active, living read/write interface\nfor a frame's local fast, free, and cell variables.\n\n`livelocals()` is similar to the builtin `locals()` function, but is\nalways up-to-date, and assigning or deleting values in a LiveLocals\ninstance will also alter the actual variables for the scope in which\nit was created.\n\n[python]: http://python.org \"Python\"\n\n\n## Wait...\n\n\"Doesn't `locals()` already do that?\"\n\nAt the global or module scope, the `locals()` and `globals()`\nfunctions both return the module's underlying `__dict__`. Once you're\ninside of a function however, things change. In a function, the\n`locals()` is just a snapshot view of the frame's fast, free, and cell\nvariables.\n\n\n## Features\n\nA LiveLocals instance (obtained by calling `livelocals()`) can read\nand assign to all of the variables defined or consumed in a scope. It\ncan also clear them.  It will happily function in concert with a\nclosure or a generator, allowing you to alter the lexical bindings at\nruntime.\n\nIt cannot introduce new variables into the scope. It cannot read or\nalter global variables (but `globals()` already lets you do that).\n\n\n## Usage\n\n\n### `livelocals`\n\n```python\ndef working_loop(foo=100, bar=200):\n    baz = True\n    keep_running = True\n\n    while keep_running:\n        phone_home(foo, bar, baz)\n        data = do_important_stuff(foo, bar)\n        livelocals().update(data)\n```\n\nIn the above contrived example, the `data` mapping returned by the\nimaginary `do_important_stuff` call contains new values for the local\nscope of the working loop. Instead of extracting the keys and\nassigning them to the local scope individually, data may contain ANY\nof the local variables for the working loop, and they will be\nreassigned to their new values.\n\nThere's an optional `allow` argument to the `update` method, which\nwill limit the modification of local variable to only those which are\neither it a specified list, or pass a filtering function.\n\n```python\ndef working_loop(foo=100, bar=200):\n    baz = True\n    keep_running = True\n\n    while keep_running:\n        phone_home(foo, bar, baz)\n        data = do_important_stuff(foo, bar)\n        livelocals().update(data, allow=(\"baz\", \"keep_running\"))\n```\n\n\n### `generatorlocals`\n\nThe `generatorlocals` function allows you to access the livelocals of\na running generator function.\n\n```python\ndef working_loop(foo=100, bar=200):\n    tweak = False\n    while True:\n        yield do_important_stuff(foo, bar, tweak)\n\ngen = working_loop()\n\nfor X in gen:\n    if X == \"cheddar cheese\":\n        # special case, the working_loop yielded cheddar cheese!\n        # Better enable tweak mode!\n        generatorlocals(gen)[\"tweak\"] = True\n```\n\n\n### `localvar`\n\nIf you only need access to a single variable by name, the `localvar`\nfunction will provide a simple interface for getting, setting, or\nclearing it.\n\n```python\ndef working_loop(foo=100, bar=200):\n\n    # some distant subsystem might kick off a callback, and we want\n    # to make that value our new bar\n    hook_some_callback(localvar(\"bar\").setvar)\n\n    while bar \u003c 900:\n        do_important_stuff(foo, bar)\n```\n\n\n## Circular Reference\n\nSadly, Python doesn't allow weak references to frame objects. The\nlivelocals and localvar objects therefore have strong references to\nthe particular frame they were invoked from. If that frame also\nhappens to have a lingering reference to the livelocals or localvar\nobjects, then a circular reference exists.\n\nFor example, this will create a circular reference, preventing the\nframe or any of its variables from being deallocated.\n```python\ndef such_leak(data):\n    x = do_something(data)\n    y = more_work(x)\n    l = livelocals()\n    ...\n    return y\n```\n\nThe livelocals instance refers to the frame, and the frame never\ncleared the value of the variable `l` which is a reference to the\nlivelocals. Circular reference!\n\nTo fix this, just make sure to delete any reference to livelocals or\nlocalvar objects.\n```python\ndef fine_dandy(data):\n    x = do_something(data)\n    y = more_work(x)\n    l = livelocals()\n    ...\n    del l\n    return y\n```\n\nThis decrements the livelocals ref count, letting it be deallocated\nright away, which also clears the references it had to the frame, so\nit can be similarly deallocated.\n\nA livelocals instance also has a `clear()` method which will release\ninternal references to the frame, and drop the frame's reference to\nthe livelocals object if one exists.\n\nIn addition, livelocals instances can be used via the context manager\nkeyword `with`, which will call `clear()` when the context exits.\n```python\ndef fine_dandy(data):\n    x = do_something(data)\n    with livelocals() as ll:\n        y = send_locals_elsewhere(ll)\n        ...\n    # ll has been cleared safely\n    return y\n```\n\n\n## Supported Versions\n\nThis has been tested as working on the following versions and\nimplementations of Python\n\n* Python 2.6, 2.7\n* Python 3.4, 3.5, 3.6, 3.7\n\n\n## Contact\n\nauthor: Christopher O'Brien \u003cobriencj@gmail.com\u003e\n\noriginal git repository: \u003chttps://github.com/obriencj/python-livelocals\u003e\n\n\n## License\n\nThis library is free software; you can redistribute it and/or modify\nit under the terms of the GNU Lesser General Public License as\npublished by the Free Software Foundation; either version 3 of the\nLicense, or (at your option) any later version.\n\nThis library is distributed in the hope that it will be useful, but\nWITHOUT ANY WARRANTY; without even the implied warranty of\nMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU\nLesser General Public License for more details.\n\nYou should have received a copy of the GNU Lesser General Public\nLicense along with this library; if not, see\n\u003chttp://www.gnu.org/licenses/\u003e.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobriencj%2Fpython-livelocals","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobriencj%2Fpython-livelocals","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobriencj%2Fpython-livelocals/lists"}