{"id":15297441,"url":"https://github.com/xion/recursely","last_synced_at":"2025-03-25T13:15:04.054Z","repository":{"id":8020598,"uuid":"9429548","full_name":"Xion/recursely","owner":"Xion","description":"Recursive importer for Python packages","archived":false,"fork":false,"pushed_at":"2015-03-26T01:18:46.000Z","size":276,"stargazers_count":0,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-25T13:15:00.807Z","etag":null,"topics":["import","python2"],"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/Xion.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":"2013-04-14T13:45:08.000Z","updated_at":"2015-03-26T01:18:46.000Z","dependencies_parsed_at":"2022-08-06T01:15:28.433Z","dependency_job_id":null,"html_url":"https://github.com/Xion/recursely","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xion%2Frecursely","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xion%2Frecursely/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xion%2Frecursely/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Xion%2Frecursely/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Xion","download_url":"https://codeload.github.com/Xion/recursely/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245467615,"owners_count":20620216,"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":["import","python2"],"created_at":"2024-09-30T19:17:35.348Z","updated_at":"2025-03-25T13:15:04.025Z","avatar_url":"https://github.com/Xion.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"recursely\n=========\n\nRecursive importer for Python submodules and subpackages\n\n.. image:: https://secure.travis-ci.org/Xion/recursely.png\n   :alt: Build Status\n   :target: http://travis-ci.org/Xion/recursely\n\n\nWhy?\n~~~~\n\nNowadays, there are quite a few popular frameworks that use\nmodern Python features - like decorators - to organize code.\nThis keeps it concise and  `DRY \u003chttp://en.wikipedia.org/wiki/Don%27t_Repeat_Yourself\u003e`_.\nbut presents a challenge when it comes to tying everything together.\n\nAs an example, if you use a web framework such as `Flask \u003chttp://flask.pocoo.org\u003e`_,\nyou typically don't have a central place in code that maps URL patterns\nto request handlers. Instead, you define your handlers like this::\n\n    @app.route('/')\n    def hello():\n        return \"Hello world!\"\n\nand it makes them available automatically.\n\nHowever, once you start putting them into different modules,\nyou need to ensure they are all actually *imported*.\nThe way it's typically done borders on\n`circular imports \u003chttp://flask.pocoo.org/docs/patterns/packages/\u003e`_\nand requires either repetition or some *ad-hoc* hacks.\n\nNote that same issues may arise when using an ORM library,\ndeveloping a plugin system, and so on.\n\n\nWhat?\n~~~~~\n\n*recursely* sets to deal with those issues in a more standarized, systemic way.\n\nThe idea is to avoid putting any explicit or implicit ``import submodule``\nstatements in package's `__init__.py`. file They introduce dependencies that\njust shouldn't be there, and only narrowly avoid circular imports by their\nsole placement at the bottom, rather than the top of the file.\n\nInstead of those fragile ``import``\\ s, with *recursely* you can just say::\n\n    __recursive__ = True\n\nand put this line anywhere in the file, even at the very top.\nIn fact, I recommend placing it right after module's docstring.\n\nThere's of course some setup involved, but it's quite trivial. You only\nneed to install *recursely*::\n\n    import recursely\n    recursely.install()\n\nat some early stage of your program's initialization, before all the imports.\nPutting this on top of your main package's `\\_\\_init\\_\\_.py` should be enough\nin vast majority of cases.\n\n\nHow?\n~~~~\n\nSo, what's the trick?... *recursely* uses a simple **import hook** to inspect\nevery imported module and check for the presence of ``__recursive__`` directive.\nIf it's found, its submodules and subpackages are imported automatically,\nand this proceeds further to their submodules and subpackages, and so on.\n\nBut aren't import hooks Deep Magic™?\n------------------------------------\n\nActually, the only real problem with import hooks is their composability:\nmaking several hooks works together and not stomp on each other.\nThat's why *recursely* goes to great lengths to ensure that\nits catch-all hook is always invoked as the *last* one.\nThis allows other, specialized hooks - like the one handling\n`flask.ext pseudopackage \u003chttp://flask.pocoo.org/docs/extensiondev/\u003e`_\n- to operate without any issue on imports they are designed to intercept.\n\n\nWhere?\n~~~~~~\n\n*recursely* is available from PyPI::\n\n    $ pip install recursely\n\nLicense is BSD. Contributions are welcome!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxion%2Frecursely","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxion%2Frecursely","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxion%2Frecursely/lists"}