{"id":23387581,"url":"https://github.com/betterbuiltfool/simply_resourceful","last_synced_at":"2026-02-12T06:31:46.748Z","repository":{"id":267615104,"uuid":"898621580","full_name":"BetterBuiltFool/simply_resourceful","owner":"BetterBuiltFool","description":"Simple, lazy loading Python resource management","archived":false,"fork":false,"pushed_at":"2025-01-28T00:02:24.000Z","size":71,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-07-18T06:54:09.252Z","etag":null,"topics":["python-3","python3","resource-management"],"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/BetterBuiltFool.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-12-04T18:10:52.000Z","updated_at":"2025-01-28T00:02:28.000Z","dependencies_parsed_at":"2024-12-11T11:46:11.609Z","dependency_job_id":"eb09419e-9595-4c2d-9b82-497d9a9c7243","html_url":"https://github.com/BetterBuiltFool/simply_resourceful","commit_stats":null,"previous_names":["betterbuiltfool/simply_resourceful"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/BetterBuiltFool/simply_resourceful","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fsimply_resourceful","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fsimply_resourceful/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fsimply_resourceful/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fsimply_resourceful/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/BetterBuiltFool","download_url":"https://codeload.github.com/BetterBuiltFool/simply_resourceful/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/BetterBuiltFool%2Fsimply_resourceful/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273838362,"owners_count":25177162,"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-05T02:00:09.113Z","response_time":402,"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-3","python3","resource-management"],"created_at":"2024-12-22T01:59:14.003Z","updated_at":"2026-02-12T06:31:46.742Z","avatar_url":"https://github.com/BetterBuiltFool.png","language":"Python","readme":"\u003c!-- Improved compatibility of back to top link: See: https://github.com/othneildrew/Best-README-Template/pull/73 --\u003e\n\u003ca id=\"readme-top\"\u003e\u003c/a\u003e\n\u003c!--\n*** Thanks for checking out the Best-README-Template. If you have a suggestion\n*** that would make this better, please fork the repo and create a pull request\n*** or simply open an issue with the tag \"enhancement\".\n*** Don't forget to give the project a star!\n*** Thanks again! Now go create something AMAZING! :D\n--\u003e\n\n\n\n\u003c!-- PROJECT SHIELDS --\u003e\n\u003c!--\n*** I'm using markdown \"reference style\" links for readability.\n*** Reference links are enclosed in brackets [ ] instead of parentheses ( ).\n*** See the bottom of this document for the declaration of the reference variables\n*** for contributors-url, forks-url, etc. This is an optional, concise syntax you may use.\n*** https://www.markdownguide.org/basic-syntax/#reference-style-links\n--\u003e\n[![Contributors][contributors-shield]][contributors-url]\n[![Forks][forks-shield]][forks-url]\n[![Stargazers][stars-shield]][stars-url]\n[![Issues][issues-shield]][issues-url]\n[![MIT License][license-shield]][license-url]\n\u003c!--\n[![LinkedIn][linkedin-shield]][linkedin-url]\n--\u003e\n\n\n\n\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003c!--\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful\"\u003e\n    \u003cimg src=\"images/logo.png\" alt=\"Logo\" width=\"80\" height=\"80\"\u003e\n  \u003c/a\u003e\n--\u003e\n\n\u003ch3 align=\"center\"\u003eSimply Resourceful\u003c/h3\u003e\n\n  \u003cp align=\"center\"\u003e\n    The Simple Resource Manager\n    \u003cbr /\u003e\n    \u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful\"\u003e\u003cstrong\u003eExplore the docs »\u003c/strong\u003e\u003c/a\u003e\n    \u003cbr /\u003e\n    \u003cbr /\u003e\n    \u003c!--\n    \u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful\"\u003eView Demo\u003c/a\u003e\n    ·\n    --\u003e\n    \u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful/issues/new?labels=bug\u0026template=bug-report---.md\"\u003eReport Bug\u003c/a\u003e\n    ·\n    \u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful/issues/new?labels=enhancement\u0026template=feature-request---.md\"\u003eRequest Feature\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/div\u003e\n\n\n\n\u003c!-- TABLE OF CONTENTS --\u003e\n\u003cdetails\u003e\n  \u003csummary\u003eTable of Contents\u003c/summary\u003e\n  \u003col\u003e\n    \u003cli\u003e\n      \u003ca href=\"#about-the-project\"\u003eAbout The Project\u003c/a\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\n      \u003ca href=\"#getting-started\"\u003eGetting Started\u003c/a\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#installation\"\u003eInstallation\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#usage\"\u003eUsage\u003c/a\u003e\u003c/li\u003e\n      \u003cul\u003e\n        \u003cli\u003e\u003ca href=\"#types\"\u003eTypes\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#using-asset-handles\"\u003eUsing Asset Handles\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#importing-resources\"\u003eImporting Resources\u003c/a\u003e\u003c/li\u003e\n        \u003cli\u003e\u003ca href=\"#configuration\"\u003eConfiguration\u003c/a\u003e\u003c/li\u003e\n      \u003c/ul\u003e\n    \u003cli\u003e\u003ca href=\"#roadmap\"\u003eRoadmap\u003c/a\u003e\u003c/li\u003e\n    \u003c!--\u003cli\u003e\u003ca href=\"#contributing\"\u003eContributing\u003c/a\u003e\u003c/li\u003e--\u003e\n    \u003cli\u003e\u003ca href=\"#license\"\u003eLicense\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#contact\"\u003eContact\u003c/a\u003e\u003c/li\u003e\n    \u003cli\u003e\u003ca href=\"#acknowledgments\"\u003eAcknowledgments\u003c/a\u003e\u003c/li\u003e\n  \u003c/ol\u003e\n\u003c/details\u003e\n\n\n\n\u003c!-- ABOUT THE PROJECT --\u003e\n## About The Project\n\n\u003c!--\n[![Product Name Screen Shot][product-screenshot]](https://example.com)\n--\u003e\n\nSimply Resourceful is a simple resource manager, designed to work alongside pygame. It offers deferred loading of resources, as well as a simple way of accessing those resources in your code, making swapping out resources a breeze.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\u003c!-- GETTING STARTED --\u003e\n## Getting Started\n\nSimply Resourceful is written in pure python, with no system dependencies, and should be OS-agnostic.\n\n### Installation\n\nSimply Resourceful can be installed from the [PyPI][pypi-url] using [pip][pip-url]:\n\n```sh\npip install simply_resourceful\n```\n\nand can be imported for use with:\n```python\nimport resourceful\n```\n\nSimply Resourceful has no mandatory dependencies, but has some extra options when Pygame Community Edition is installed.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- USAGE EXAMPLES --\u003e\n## Usage\n\nAssets can often be a heavy burden on memory. The process of loading them from file or downloading them can also be intensive. Having your assets loaded only once, and then reused whenever needed, can help reduce the load. Additionally, instead of loading all assets immediatly, lazy loading allows the load times to be deferred until an asset is needed, and never coming into memory at all if never requested.\n\nResource Managers are created with \n```python\nimport resourceful\n\nMANAGER = resourceful.getResourceManager(\u003ctype\u003e, \"handle\")\n```\n\nWhere ```\u003ctype\u003e``` is the class of resource to be managed.\n\nThis will ensure that a resource manager for the given type and of the given handle exists.\nHandles are optional, but are useful for having resource managers with different loading behavior despite the same resource type, without increasing the complexity of the loader function.\n\nNote that for the rest of the document, 'resource' and 'asset' may be used interchangeably.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n#### Preconfigured Managers\n\nAdditionally, if you have pygame-ce installed, you also gain eccess to two additional methods, resourceful.getImageManager() and resourceful.getSoundManager(). These are preconfigured resource managers for loading images and sounds from disk, respectively. They are not tracked by the Resource Manager, and must be gotten with these methods. These prebuilt managers are designed to take file paths for their resource location data.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Types\n\nResource Managers are generic, and can handle almost any type of data. The type you want the resource manager to handle must be specified before use.\n\n```python\nimport pygame\nimport resourceful\n\nMANAGER = resourceful.getResourceManager(pygame.Surface)\n```\n\nIn this example, a resource manager that handles pygame surfaces will be created or found, if it exists, with a blank handle. This might be useful for storing images loaded into memory in one single place.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Using Asset Handles\n\nResources are referenced by asset handles, which are strings that ascribe common names to their resources. They are used as such:\n```python\n\nsprite.image = image_manager.get(\"Hero\")\n```\n\nThis will check the manager for an asset called \"Hero\", load it if necessary, and supply the sprite with it for display.\n\nIn more complicated use cases, it may be desirable to supply a default value. This may be because the asset handle being requested is coming from elsewhere, and might not be guaranteed to be correct, and something is needed to fill the gap.\n\nThat use case would look something like this:\n```python\n\nsprite.image = image_manager.get(current_hero_pose, hero_blank_sprite)\n```\n\nThis way, if current_hero_pose accidentally refers to an invalid resource, the program will not crash.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Importing Resources\n\nBefore any assets are requested, the resource manager must be made aware of the assets it will manage. This must be done early on in the program, before any manager.get() operations are called.\n```python\n# ---Program set up stuff---\n# Global variables and such, module initialization, whatever.\nmanager.import_asset(\"Hero\", \"path/to/hero.png\")\n```\n\nIn this example, the manager now is aware of an asset called \"Hero\", as well as a path to find it for loading.\n\nLocation data can be anything the loader function can use to generate the asset. Typically, it will be a file location, but could also be a tuple of draw data for drawing surfaces, or data for downloading an asset from a database, or anything else, really.\n\nAssets can also be force-loaded, which is similar to importing, but loads the asset into memory from its location data immediately, no need to have something call get(). This might be useful for assets that are guaranteed to be used immediately.\n\n#### Mass Import\n\nAlternatively, you may also perform a mass import, using\n```python\nmanager.import_directory(\"path/to/asset/folder\")\n```\n\nThis will import everything from the given directory. It has additional options, such as searching subfolders, and filter functions to change filtering, naming, and location data generation. This provides an easier to use way to import many assets, at the cost of control.\n\nBy default, import_directory will import all files regardless of file type, names them based on their file name (and subfolder, if enabled), and gives their file path as their location data.\n\n#### Resource File\n\nIt may be advisable to keep a separate module that contains all of your asset imports. This will collect them all in one place, outside of your main program code.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Configuration\n\n#### Loader Functions\n\nBecause resource managers are generic, they have no inherent knowledge of how to load any given resource. So, a loader function must be supplied.\nFor example:\n```python\ndef image_loader(resource_location: Path | str) -\u003e pygame.Surface:\n    asset = pygame.image.load(resource_location)\n    return asset.convert()\n\n# ---Program set up stuff---\n# Global variables and such, module initialization, whatever.\nmanager.config(loader_helper=image_loader)\nmanager.import_asset(\"Hero\", \"path/to/hero.png\")\n```\n\nThis will load the image from the path, and convert it to be ready for use.\n\nLoader functions only have two requirements:\n1. They must take the same data as is used for location data by the resource manager. That is, if the location data is a path, the loader must take a path.\n2. They must return the same type as the resource manager, or None, indicating a load failure.\nThey can do anything else you'd like, and can be a simple or as complicated as you want. to extend the above example, you could have it check the file extension to determine if convert() is sufficient, or if convert_alpha() would be preferable.\n\nAdditionally, in an async-aware environment, you could have your loader begin a coroutine to download your asset, and return a default asset to tide things over until then, updating the asset upon completion.\n\nFrom there, the resource manager will take over, loading and supplying resources as needed by other parts of the program.\n\n#### Default Assets\n\nA default asset may be provided in the config function, allowing suppression of errors for loading failures by always having an option to fill in any blanks. If get() is called with a default value, it will override the manager-level default asset.\n\nNone is considered a valid default, and should be handled appropriately. Simply Resourceful makes use of a sentinel value called NoDefault to determine that a default value does not exist or shouldn't be used.\n\n```python\nmanager.config(default_asset=some_asset)\n```\n\n#### Preconfigured Options\n\nWith pygame-ce installed, you additionally have access to two preconfigured resource managers, one for images (built around pygame Surfaces), and one for sounds. These both handle loading their respective resources automatically, and require PathLike data for their resource_location data.\n\n\u003c!--\n_For more examples, please refer to the [Documentation](https://example.com)_\n--\u003e\n\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- ROADMAP --\u003e\n## Roadmap\n\n- [ ] Make pickleable for saving and loading resource managers.\n- [ ] Allow for objects to request proxies that don't load the asset until it is called upon.\n    - This may not be possible for all objects.\n- [ ] Make a visual importing tool to generate pickle files for easy imports.\n\n\u003c!--\n- [ ] Feature 2\n- [ ] Feature 3\n    - [ ] Nested Feature\n--\u003e\n\nSee the [open issues](https://github.com/BetterBuiltFool/simply_resourceful/issues) for a full list of proposed features (and known issues).\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- CONTRIBUTING --\u003e\n\u003c!--\n## Contributing\n\nContributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.\n\nIf you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag \"enhancement\".\nDon't forget to give the project a star! Thanks again!\n\n1. Fork the Project\n2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)\n3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)\n4. Push to the Branch (`git push origin feature/AmazingFeature`)\n5. Open a Pull Request\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n### Top contributors:\n\n\u003ca href=\"https://github.com/BetterBuiltFool/simply_resourceful/graphs/contributors\"\u003e\n  \u003cimg src=\"https://contrib.rocks/image?repo=BetterBuiltFool/simply_resourceful\" alt=\"contrib.rocks image\" /\u003e\n\u003c/a\u003e\n--\u003e\n\n\n\n\u003c!-- LICENSE --\u003e\n## License\n\nDistributed under the MIT License. See `LICENSE.txt` for more information.\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- CONTACT --\u003e\n## Contact\n\nBetter Built Fool - betterbuiltfool@gmail.com\n\nBluesky - [@betterbuiltfool.bsky.social](https://bsky.app/profile/betterbuiltfool.bsky.social)\n\u003c!--\n - [@twitter_handle](https://twitter.com/twitter_handle)\n--\u003e\n\nProject Link: [https://github.com/BetterBuiltFool/simply_resourceful](https://github.com/BetterBuiltFool/simply_resourceful)\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n\n\n\n\u003c!-- ACKNOWLEDGMENTS --\u003e\n\u003c!--## Acknowledgments\n\n* []()\n* []()\n* []()\n\n\u003cp align=\"right\"\u003e(\u003ca href=\"#readme-top\"\u003eback to top\u003c/a\u003e)\u003c/p\u003e\n--\u003e\n\n\n\u003c!-- MARKDOWN LINKS \u0026 IMAGES --\u003e\n\u003c!-- https://www.markdownguide.org/basic-syntax/#reference-style-links --\u003e\n[contributors-shield]: https://img.shields.io/github/contributors/BetterBuiltFool/simply_resourceful.svg?style=for-the-badge\n[contributors-url]: https://github.com/BetterBuiltFool/simply_resourceful/graphs/contributors\n[forks-shield]: https://img.shields.io/github/forks/BetterBuiltFool/simply_resourceful.svg?style=for-the-badge\n[forks-url]: https://github.com/BetterBuiltFool/simply_resourceful/network/members\n[stars-shield]: https://img.shields.io/github/stars/BetterBuiltFool/simply_resourceful.svg?style=for-the-badge\n[stars-url]: https://github.com/BetterBuiltFool/simply_resourceful/stargazers\n[issues-shield]: https://img.shields.io/github/issues/BetterBuiltFool/simply_resourceful.svg?style=for-the-badge\n[issues-url]: https://github.com/BetterBuiltFool/simply_resourceful/issues\n[license-shield]: https://img.shields.io/github/license/BetterBuiltFool/simply_resourceful.svg?style=for-the-badge\n[license-url]: https://github.com/BetterBuiltFool/simply_resourceful/blob/main/LICENSE\n[linkedin-shield]: https://img.shields.io/badge/-LinkedIn-black.svg?style=for-the-badge\u0026logo=linkedin\u0026colorB=555\n[linkedin-url]: https://linkedin.com/in/linkedin_username\n[product-screenshot]: images/screenshot.png\n[Next.js]: https://img.shields.io/badge/next.js-000000?style=for-the-badge\u0026logo=nextdotjs\u0026logoColor=white\n[Next-url]: https://nextjs.org/\n[python.org]: https://img.shields.io/badge/python-3670A0?style=for-the-badge\u0026logo=python\u0026logoColor=ffdd54\n[python-url]: https://www.python.org/\n[React.js]: https://img.shields.io/badge/React-20232A?style=for-the-badge\u0026logo=react\u0026logoColor=61DAFB\n[React-url]: https://reactjs.org/\n[Vue.js]: https://img.shields.io/badge/Vue.js-35495E?style=for-the-badge\u0026logo=vuedotjs\u0026logoColor=4FC08D\n[Vue-url]: https://vuejs.org/\n[Angular.io]: https://img.shields.io/badge/Angular-DD0031?style=for-the-badge\u0026logo=angular\u0026logoColor=white\n[Angular-url]: https://angular.io/\n[Svelte.dev]: https://img.shields.io/badge/Svelte-4A4A55?style=for-the-badge\u0026logo=svelte\u0026logoColor=FF3E00\n[Svelte-url]: https://svelte.dev/\n[Laravel.com]: https://img.shields.io/badge/Laravel-FF2D20?style=for-the-badge\u0026logo=laravel\u0026logoColor=white\n[Laravel-url]: https://laravel.com\n[Bootstrap.com]: https://img.shields.io/badge/Bootstrap-563D7C?style=for-the-badge\u0026logo=bootstrap\u0026logoColor=white\n[Bootstrap-url]: https://getbootstrap.com\n[JQuery.com]: https://img.shields.io/badge/jQuery-0769AD?style=for-the-badge\u0026logo=jquery\u0026logoColor=white\n[JQuery-url]: https://jquery.com \n[pypi-url]: https://pypi.org/project/simply_resourceful\n[pip-url]: https://pip.pypa.io/en/stable/","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterbuiltfool%2Fsimply_resourceful","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbetterbuiltfool%2Fsimply_resourceful","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbetterbuiltfool%2Fsimply_resourceful/lists"}