{"id":16199863,"url":"https://github.com/banesullivan/scooby","last_synced_at":"2025-04-12T23:42:35.285Z","repository":{"id":40062414,"uuid":"193755261","full_name":"banesullivan/scooby","owner":"banesullivan","description":"🐶  🕵️   Great Dane turned Python environment detective","archived":false,"fork":false,"pushed_at":"2025-01-20T21:48:22.000Z","size":541,"stargazers_count":49,"open_issues_count":9,"forks_count":13,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-12T23:42:30.287Z","etag":null,"topics":["bug-reporting","python","python-versions","reproducibility","system-information"],"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/banesullivan.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}},"created_at":"2019-06-25T17:40:56.000Z","updated_at":"2025-04-09T11:40:02.000Z","dependencies_parsed_at":"2025-02-12T16:10:10.309Z","dependency_job_id":"dd156ab9-490e-4106-8ba5-3a771b7c5870","html_url":"https://github.com/banesullivan/scooby","commit_stats":{"total_commits":199,"total_committers":14,"mean_commits":"14.214285714285714","dds":0.4723618090452262,"last_synced_commit":"b373f384b132fd573a8723009a7c365a436509a9"},"previous_names":[],"tags_count":36,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banesullivan%2Fscooby","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banesullivan%2Fscooby/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banesullivan%2Fscooby/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/banesullivan%2Fscooby/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/banesullivan","download_url":"https://codeload.github.com/banesullivan/scooby/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248647256,"owners_count":21139081,"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":["bug-reporting","python","python-versions","reproducibility","system-information"],"created_at":"2024-10-10T09:28:31.906Z","updated_at":"2025-04-12T23:42:35.266Z","avatar_url":"https://github.com/banesullivan.png","language":"Python","readme":"# 🐶🕵️ Scooby\n\n[![Downloads](https://img.shields.io/pypi/dm/scooby.svg?label=PyPI%20downloads)](https://pypi.org/project/scooby/)\n[![Tests](https://github.com/banesullivan/scooby/actions/workflows/pythonpackage.yml/badge.svg)](https://github.com/banesullivan/scooby/actions/workflows/pythonpackage.yml)\n[![PyPI Status](https://img.shields.io/pypi/v/scooby.svg?logo=python\u0026logoColor=white)](https://pypi.org/project/scooby/)\n[![Conda Status](https://img.shields.io/conda/vn/conda-forge/scooby.svg)](https://anaconda.org/conda-forge/scooby)\n[![codecov](https://codecov.io/gh/banesullivan/scooby/branch/main/graph/badge.svg?token=eJqZ700tqH)](https://codecov.io/gh/banesullivan/scooby)\n\n*Great Dane turned Python environment detective*\n\nThis is a lightweight tool for easily reporting your Python environment's\npackage versions and hardware resources.\n\n\nInstall from [PyPI](https://pypi.org/project/scooby/)\n\n```bash\npip install scooby\n```\n\nor from [conda-forge](https://anaconda.org/conda-forge/scooby/)\n\n```bash\nconda install -c conda-forge scooby\n```\n\n![Jupyter Notebook Formatting](https://github.com/banesullivan/scooby/raw/main/assets/jupyter.png)\n\nScooby has HTML formatting for Jupyter notebooks and rich text formatting for\njust about every other environment. We designed this module to be lightweight\nsuch that it could easily be added as a dependency to Python projects for\nenvironment reporting when debugging. Simply add scooby to your dependencies\nand implement a function to have scooby report on the aspects of the\nenvironment you care most about.\n\nIf scooby is unable to detect aspects of an environment that you'd like to\nknow, please share this with us as a feature requests or pull requests.\n\nThe scooby reporting is derived from the versioning-scripts created by [Dieter\nWerthmüller](https://github.com/prisae) for\n[empymod](https://empymod.github.io), [emg3d](https://empymod.github.io), and\nthe [SimPEG](https://github.com/simpeg/) framework. It was heavily inspired by\n`ipynbtools.py` from [qutip](https://github.com/qutip) and\n[`watermark.py`](https://github.com/rasbt/watermark). This package has been\naltered to create a lightweight implementation so that it can easily be used as\nan environment reporting tool in any Python library with minimal impact.\n\n## Usage\n\n### Generating Reports\n\nReports are rendered as html-tables in Jupyter notebooks as shown in the\nscreenshot above, and otherwise as plain text lists. If you do not output the\n`Report` object either at the end of a notebook cell or it is generated\nsomewhere in a vanilla Python script, you may have to print the `Report`\nobject: `print(scooby.Report())`, but note that this will only output the plain\ntext representation of the script.\n\n```py\n\u003e\u003e\u003e import scooby\n\u003e\u003e\u003e scooby.Report()\n```\n```\n--------------------------------------------------------------------------------\n  Date: Wed Feb 12 15:35:43 2020 W. Europe Standard Time\n\n                OS : Windows\n            CPU(s) : 16\n           Machine : AMD64\n      Architecture : 64bit\n               RAM : 31.9 GiB\n       Environment : IPython\n\n  Python 3.7.6 | packaged by conda-forge | (default, Jan  7 2020, 21:48:41)\n  [MSC v.1916 64 bit (AMD64)]\n\n             numpy : 1.18.1\n             scipy : 1.3.1\n           IPython : 7.12.0\n        matplotlib : 3.0.3\n            scooby : 0.5.0\n\n  Intel(R) Math Kernel Library Version 2019.0.4 Product Build 20190411 for\n  Intel(R) 64 architecture applications\n--------------------------------------------------------------------------------\n```\n\nFor all the Scooby-Doo fans out there, `doo` is an alias for `Report` so you\ncan oh-so satisfyingly do:\n\n```py\n\u003e\u003e\u003e import scooby\n\u003e\u003e\u003e scooby.doo()\n```\n```\n--------------------------------------------------------------------------------\n  Date: Thu Nov 25 09:47:50 2021 MST\n\n                OS : Darwin\n            CPU(s) : 12\n           Machine : x86_64\n      Architecture : 64bit\n               RAM : 32.0 GiB\n       Environment : Python\n       File system : apfs\n\n  Python 3.8.12 | packaged by conda-forge | (default, Oct 12 2021, 21:50:38)\n  [Clang 11.1.0 ]\n\n             numpy : 1.21.4\n             scipy : 1.7.3\n           IPython : 7.29.0\n        matplotlib : 3.5.0\n            scooby : 0.5.8\n--------------------------------------------------------------------------------\n```\n\nOr better yet:\n\n```py\nfrom scooby import doo as doobiedoo\n```\n\nOn top of the default (optional) packages you can provide additional packages,\neither as strings or give already imported packages:\n```py\n\u003e\u003e\u003e import pyvista\n\u003e\u003e\u003e import scooby\n\u003e\u003e\u003e scooby.Report(additional=[pyvista, 'vtk', 'no_version', 'does_not_exist'])\n```\n```\n--------------------------------------------------------------------------------\n  Date: Wed Feb 12 16:15:15 2020 W. Europe Standard Time\n\n                OS : Windows\n            CPU(s) : 16\n           Machine : AMD64\n      Architecture : 64bit\n               RAM : 31.9 GiB\n       Environment : IPython\n\n  Python 3.7.6 | packaged by conda-forge | (default, Jan  7 2020, 21:48:41)\n  [MSC v.1916 64 bit (AMD64)]\n\n           pyvista : 0.23.1\n               vtk : 8.1.2\n        no_version : Version unknown\n    does_not_exist : Could not import\n             numpy : 1.18.1\n             scipy : 1.3.1\n           IPython : 7.12.0\n        matplotlib : 3.0.3\n            scooby : 0.5.0\n\n  Intel(R) Math Kernel Library Version 2019.0.4 Product Build 20190411 for\n  Intel(R) 64 architecture applications\n--------------------------------------------------------------------------------\n```\n\nFurthermore, scooby reports if a package could not be imported or if the\nversion of a package could not be determined.\n\nOther useful parameters are\n\n- `ncol`: number of columns in the html-table;\n- `text_width`: text width of the plain-text version;\n- `sort`: list is sorted alphabetically if True.\n\nBesides `additional` there are two more lists, `core` and `optional`, which\ncan be used to provide package names. However, they are mostly useful for\npackage maintainers wanting to use scooby to create their reporting system\n(see below).\n\n\n### Implementing scooby in your project\n\nYou can easily generate a custom `Report` instance using scooby within your\nproject:\n\n```py\nclass Report(scooby.Report):\n    def __init__(self, additional=None, ncol=3, text_width=80, sort=False):\n        \"\"\"Initiate a scooby.Report instance.\"\"\"\n\n        # Mandatory packages.\n        core = ['yourpackage', 'your_core_packages', 'e.g.', 'numpy', 'scooby']\n\n        # Optional packages.\n        optional = ['your_optional_packages', 'e.g.', 'matplotlib']\n\n        scooby.Report.__init__(self, additional=additional, core=core,\n                               optional=optional, ncol=ncol,\n                               text_width=text_width, sort=sort)\n```\n\nThis makes it particularly easy for a user of your project to quickly generate\na report on all of the relevant package versions and environment details when\nsubmitting a bug.\n\n```py\n\u003e\u003e\u003e import your_package\n\u003e\u003e\u003e your_package.Report()\n```\n\nThe packages on the `core`-list are the mandatory ones for your project, while\nthe `optional`-list can be used for optional packages. Keep the\n`additional`-list free to allow your users to add packages to the list.\n\n#### Implementing as a soft dependency\n\nIf you would like to implement scooby, but are hesitant to add another\ndependency to your package, here is an easy way how you can use scooby as a\nsoft dependency. Instead of `import scooby` use the following snippet:\n\n```py\n# Make scooby a soft dependency:\ntry:\n    from scooby import Report as ScoobyReport\nexcept ImportError:\n    class ScoobyReport:\n        def __init__(self, *args, **kwargs):\n            message = (\n                '\\n  *ERROR*: `Report` requires `scooby`.'\n                '\\n           Install it via `pip install scooby` or'\n                '\\n           `conda install -c conda-forge scooby`.\\n'\n            )\n            raise ImportError(message)\n```\n\nand then create your own `Report` class same as above,\n\n```py\nclass Report(ScoobyReport):\n    def __init__(self, additional=None, ncol=3, text_width=80, sort=False):\n        \"\"\"Initiate a scooby.Report instance.\"\"\"\n\n        # Mandatory packages.\n        core = ['yourpackage', 'your_core_packages', 'e.g.', 'numpy', 'scooby']\n\n        # Optional packages.\n        optional = ['your_optional_packages', 'e.g.', 'matplotlib']\n\n        scooby.Report.__init__(self, additional=additional, core=core,\n                               optional=optional, ncol=ncol,\n                               text_width=text_width, sort=sort)\n\n```\nIf a user has scooby installed, all works as expected. If scooby is not\ninstalled, it will raise the following exception:\n\n```py\n\u003e\u003e\u003e import your_package\n\u003e\u003e\u003e your_package.Report()\n\n  *ERROR*: `Report` requires `scooby`\n           Install it via `pip install scooby` or\n           `conda install -c conda-forge scooby`.\n```\n\n### Autogenerate Reports for any Packages\n\nScooby can automatically generate a Report for any package and its\ndistribution requirements with the `AutoReport` class:\n\n```py\n\u003e\u003e\u003e import scooby\n\u003e\u003e\u003e scooby.AutoReport('matplotlib')\n```\n```\n--------------------------------------------------------------------------------\n  Date: Fri Oct 20 16:49:34 2023 PDT\n\n                OS : Darwin\n            CPU(s) : 8\n           Machine : arm64\n      Architecture : 64bit\n               RAM : 16.0 GiB\n       Environment : Python\n       File system : apfs\n\n  Python 3.11.3 | packaged by conda-forge | (main, Apr  6 2023, 08:58:31)\n  [Clang 14.0.6 ]\n\n        matplotlib : 3.7.1\n         contourpy : 1.0.7\n            cycler : 0.11.0\n         fonttools : 4.39.4\n        kiwisolver : 1.4.4\n             numpy : 1.24.3\n         packaging : 23.1\n            pillow : 9.5.0\n         pyparsing : 3.0.9\n   python-dateutil : 2.8.2\n--------------------------------------------------------------------------------\n```\n\n### Solving Mysteries\n\nAre you struggling with the mystery of whether or not code is being executed in\nIPython, Jupyter, or normal Python? Try using some of scooby's investigative\nfunctions to solve these kinds of mysteries:\n\n```py\nimport scooby\n\nif scooby.in_ipykernel():\n    # Do Jupyter/IPyKernel stuff\nelif scooby.in_ipython():\n    # Do IPython stuff\nelse:\n    # Do normal, boring Python stuff\n```\n\n### How does scooby get version numbers?\n\nA couple of locations are checked, and we are happy to implement more if\nneeded, just open an issue!\n\nCurrently, it looks in the following places:\n- `__version__`\n- `version`\n- lookup `VERSION_ATTRIBUTES` in the scooby knowledge base\n- lookup `VERSION_METHODS` in the scooby knowledge base\n\n`VERSION_ATTRIBUTES` is a dictionary of attributes for known python packages\nwith a non-standard place for the version. You can add other known places via:\n\n```py\nscooby.knowledge.VERSION_ATTRIBUTES['a_module'] = 'Awesome_version_location'\n```\n\nSimilarly, `VERSION_METHODS` is a dictionary for methods to retrieve the\nversion, and you can similarly add your methods which will get the version\nof a package.\n\n### Using scooby to get version information.\n\nIf you are only interested in the version of a single package then you can use\nscooby as well. A few examples:\n\n```py\n\u003e\u003e\u003e import scooby, numpy\n\u003e\u003e\u003e scooby.get_version(numpy)\n('numpy', '1.16.4')\n\u003e\u003e\u003e scooby.get_version('no_version')\n('no_version', 'Version unknown')\n\u003e\u003e\u003e scooby.get_version('does_not_exist')\n('does_not_exist', 'Could not import')\n```\n\nNote that modules can be provided as already loaded ones or as strings.\n\n\n### Tracking Imports in a Session\n\nScooby has the ability to track all imported modules during a Python session\nsuch that *any* imported, non-standard lib package that is used in the session\nis reported by a `TrackedReport`. For instance, start a session by importing\nscooby and enabling tracking with the `track_imports()` function.\nThen *all* subsequent packages that are imported during the session will be\ntracked and scooby can report their versions.\nOnce you are ready to generate a `Report`, instantiate a `TrackedReport` object.\n\nIn the following example, we import a constant from `scipy` which will report\nthe versions of `scipy` and `numpy` as both packages are loaded in the session\n(note that `numpy` is internally loaded by `scipy`).\n\n```py\n\u003e\u003e\u003e import scooby\n\u003e\u003e\u003e scooby.track_imports()\n\n\u003e\u003e\u003e from scipy.constants import mu_0 # a float value\n\n\u003e\u003e\u003e scooby.TrackedReport()\n```\n```\n--------------------------------------------------------------------------------\n  Date: Thu Apr 16 15:33:11 2020 MDT\n\n                OS : Linux\n            CPU(s) : 8\n           Machine : x86_64\n      Architecture : 64bit\n               RAM : 62.7 GiB\n       Environment : IPython\n\n  Python 3.7.7 (default, Mar 10 2020, 15:16:38)  [GCC 7.5.0]\n\n            scooby : 0.5.2\n             numpy : 1.18.1\n             scipy : 1.4.1\n--------------------------------------------------------------------------------\n```\n\n## Command-Line Interface\n\nScooby comes with a command-line interface. Simply typing\n\n```bash\nscooby\n```\n\nin a terminal will display the default report. You can also use the CLI to show\nthe scooby Report of another package if that package has implemented a Report\nclass as suggested above, using `packagename.Report()`.\n\nAs an example, to print the report of pyvista you can run\n\n```bash\nscooby -r pyvista\n```\n\nwhich will show the Report implemented in PyVista.\n\nThe CLI can also generate a report based on the dependencies of a package's\ndistribution where that package hasn't implemented a Report class. For example,\nwe can generate a Report for `matplotlib` and its dependencies:\n\n```bash\n$ scooby -r matplotlib\n--------------------------------------------------------------------------------\n  Date: Fri Oct 20 17:03:45 2023 PDT\n\n                 OS : Darwin\n             CPU(s) : 8\n            Machine : arm64\n       Architecture : 64bit\n                RAM : 16.0 GiB\n        Environment : Python\n        File system : apfs\n\n  Python 3.11.3 | packaged by conda-forge | (main, Apr  6 2023, 08:58:31)\n  [Clang 14.0.6 ]\n\n         matplotlib : 3.7.1\n          contourpy : 1.0.7\n             cycler : 0.11.0\n          fonttools : 4.39.4\n         kiwisolver : 1.4.4\n              numpy : 1.24.3\n          packaging : 23.1\n             pillow : 9.5.0\n          pyparsing : 3.0.9\n    python-dateutil : 2.8.2\nimportlib-resources : 5.12.0\n--------------------------------------------------------------------------------\n```\n\nSimply type\n\n```bash\nscooby --help\n```\n\nto see all the possibilities.\n\n## Optional Requirements\n\nThe following is a list of optional requirements and their purpose:\n\n- `psutil`: report total RAM in GiB\n- `mkl-services`: report Intel(R) Math Kernel Library version\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbanesullivan%2Fscooby","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbanesullivan%2Fscooby","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbanesullivan%2Fscooby/lists"}