{"id":18084945,"url":"https://github.com/jwodder/iterpath","last_synced_at":"2025-06-21T05:02:20.093Z","repository":{"id":39031629,"uuid":"338902606","full_name":"jwodder/iterpath","owner":"jwodder","description":"Iterate through a file tree","archived":false,"fork":false,"pushed_at":"2025-01-23T14:37:35.000Z","size":76,"stargazers_count":3,"open_issues_count":15,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-06-16T13:05:31.459Z","etag":null,"topics":["available-on-pypi","directories","directory-tree","direntry","file-tree","files","find","path","pathlib","python","walk"],"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/jwodder.png","metadata":{"files":{"readme":"README.rst","changelog":"CHANGELOG.md","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":"2021-02-14T21:09:51.000Z","updated_at":"2025-01-23T14:37:38.000Z","dependencies_parsed_at":"2023-01-31T01:55:13.122Z","dependency_job_id":"c54d0a80-7cba-4753-9453-cb24507b6294","html_url":"https://github.com/jwodder/iterpath","commit_stats":{"total_commits":74,"total_committers":1,"mean_commits":74.0,"dds":0.0,"last_synced_commit":"db3e986f248b3bfb2373fec734fdcd061c5e34b1"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/jwodder/iterpath","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fiterpath","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fiterpath/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fiterpath/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fiterpath/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jwodder","download_url":"https://codeload.github.com/jwodder/iterpath/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jwodder%2Fiterpath/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261065242,"owners_count":23104761,"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":["available-on-pypi","directories","directory-tree","direntry","file-tree","files","find","path","pathlib","python","walk"],"created_at":"2024-10-31T15:08:44.665Z","updated_at":"2025-06-21T05:02:15.080Z","avatar_url":"https://github.com/jwodder.png","language":"Python","readme":"|repostatus| |ci-status| |coverage| |pyversions| |license|\n\n.. |repostatus| image:: https://www.repostatus.org/badges/latest/active.svg\n    :target: https://www.repostatus.org/#active\n    :alt: Project Status: Active — The project has reached a stable, usable\n          state and is being actively developed.\n\n.. |ci-status| image:: https://github.com/jwodder/iterpath/actions/workflows/test.yml/badge.svg\n    :target: https://github.com/jwodder/iterpath/actions/workflows/test.yml\n    :alt: CI Status\n\n.. |coverage| image:: https://codecov.io/gh/jwodder/iterpath/branch/master/graph/badge.svg\n    :target: https://codecov.io/gh/jwodder/iterpath\n\n.. |pyversions| image:: https://img.shields.io/pypi/pyversions/iterpath.svg\n    :target: https://pypi.org/project/iterpath/\n\n.. |license| image:: https://img.shields.io/github/license/jwodder/iterpath.svg\n    :target: https://opensource.org/licenses/MIT\n    :alt: MIT License\n\n`GitHub \u003chttps://github.com/jwodder/iterpath\u003e`_\n| `PyPI \u003chttps://pypi.org/project/iterpath/\u003e`_\n| `Issues \u003chttps://github.com/jwodder/iterpath/issues\u003e`_\n| `Changelog \u003chttps://github.com/jwodder/iterpath/blob/master/CHANGELOG.md\u003e`_\n\n``iterpath`` lets you iterate over a file tree as a single iterator of\n``pathlib.Path`` objects, eliminating the need to combine lists returned by\n``os.walk()`` or recursively call ``Path.iterdir()`` or ``os.scandir()``.\nBesides the standard ``os.walk()`` options, the library also includes options\nfor sorting \u0026 filtering entries.\n\n\nInstallation\n============\n``iterpath`` requires Python 3.8 or higher.  Just use `pip\n\u003chttps://pip.pypa.io\u003e`_ for Python 3 (You have pip, right?) to install it::\n\n    python3 -m pip install iterpath\n\n\nExample\n=======\n\nIterate over this library's source repository, skipping the ``.git`` and\n``test/data`` folders:\n\n\u003e\u003e\u003e import os.path\n\u003e\u003e\u003e from iterpath import iterpath\n\u003e\u003e\u003e def filterer(dir_entry):\n...     if dir_entry.name == \".git\":\n...         return False\n...     elif dir_entry.path == os.path.join(\".\", \"test\", \"data\"):\n...         return False\n...     else:\n...         return True\n...\n\u003e\u003e\u003e with iterpath(\".\", sort=True, filter_dirs=filterer) as ip:\n...     for p in ip:\n...         print(p)\n...\n.github\n.github/workflows\n.github/workflows/test.yml\n.gitignore\nLICENSE\nMANIFEST.in\nREADME.rst\nTODO.md\npyproject.toml\nsetup.cfg\nsrc\nsrc/iterpath\nsrc/iterpath/__init__.py\nsrc/iterpath/__pycache__\nsrc/iterpath/__pycache__/__init__.cpython-39.pyc\nsrc/iterpath/py.typed\ntest\ntest/test_iterpath.py\ntox.ini\n\n\nAPI\n===\n\nThe ``iterpath`` module provides a single function, also named ``iterpath``:\n\n.. code:: python\n\n    iterpath(dirpath: AnyStr | os.PathLike[AnyStr] = os.curdir, **kwargs) -\u003e Iterpath[AnyStr]\n\nIterate through the file tree rooted at the directory ``dirpath`` (by default,\nthe current directory) in depth-first order, yielding the files \u0026 directories\nwithin as ``pathlib.Path`` instances.\n\nThe return value is both an iterator and a context manager.  In order to ensure\nthat the internal ``os.scandir()`` iterators are closed properly, either call\nthe ``close()`` method when done or else use it as a context manager like so::\n\n    with iterpath(...) as ip:\n        for path in ip:\n            ...\n\nIf ``return_relative`` is true, the generated ``Path`` objects will be relative\nto ``dirpath``.  If ``return_relative`` is false (the default) and ``dirpath``\nis an absolute path, the generated ``Path`` objects will be absolute;\notherwise, if ``dirpath`` is a relative path, the ``Path`` objects will be\nrelative and will have ``dirpath`` as a prefix.\n\nNote that, although ``iterpath()`` yields ``pathlib.Path`` objects, it operates\ninternally on ``os.DirEntry`` objects, and so any function supplied as the\n``sort_key`` parameter or as a filter/exclude parameter must accept\n``os.DirEntry`` instances.\n\nKeyword arguments:\n\n``dirs: bool = True``\n    Whether to include directories in the output\n\n``topdown: bool = True``\n    Whether to yield each directory before (``True``) or after (``False``) its\n    contents\n\n``include_root: bool = False``\n    Whether to include the ``dirpath`` argument passed to ``iterpath()`` in the\n    output\n\n``followlinks: bool = False``\n    Whether to treat a symlink to a directory as a directory\n\n``return_relative: bool = False``\n    If true, the generated paths will be relative to ``dirpath``\n\n``onerror: Optional[Callable[[OSError], Any]] = None``\n    Specify a function to be called whenever an ``OSError`` is encountered\n    while iterating over a directory.  If the function reraises the exception,\n    ``iterpath()`` aborts; otherwise, it continues with the next directory.  By\n    default, ``OSError`` exceptions are ignored.\n\n``sort: bool = False``\n    Sort the entries in each directory.  When ``False``, entries are yielded in\n    the order returned by ``os.scandir()``.  When ``True``, entries are sorted,\n    by default, by filename in ascending order, but this can be changed via the\n    ``sort_key`` and ``sort_reverse`` arguments.\n\n``sort_key: Optional[Callable[[os.DirEntry[AnyStr]], _typeshed.SupportsLessThan]] = None``\n    Specify a custom key function for sorting directory entries.  Only has an\n    effect when ``sort`` is ``True``.\n\n``sort_reverse: bool = False``\n    Sort directory entries in reverse order.  Only has an effect when ``sort``\n    is ``True``.\n\n``filter: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all files \u0026 directories encountered;\n    only those for which the predicate returns a true value will be yielded\n    (and, for directories, descended into).\n\n    If ``filter`` is specified, it is an error to also specify ``filter_dirs``\n    or ``filter_files``.\n\n``filter_dirs: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all directories encountered; only\n    those for which the predicate returns a true value will be yielded \u0026\n    descended into\n\n``filter_files: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all files encountered; only those for\n    which the predicate returns a true value will be yielded\n\n``exclude: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all files \u0026 directories encountered;\n    only those for which the predicate returns a false value will be yielded\n    (and, for directories, descended into).\n\n    If ``exclude`` is specified, it is an error to also specify ``exclude_dirs``\n    or ``exclude_files``.\n\n``exclude_dirs: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all directories encountered; only\n    those for which the predicate returns a false value will be yielded \u0026\n    descended into\n\n``exclude_files: Optional[Callable[[os.DirEntry[AnyStr]], Any]] = None``\n    Specify a predicate to be applied to all files encountered; only those for\n    which the predicate returns a false value will be yielded\n\nIf both ``filter`` and ``exclude`` are set, a given entry will only be included\nif ``filter`` returns true and ``exclude`` returns false (that is, exclusions\ntake priority over inclusions), and likewise for the directory- and\nfile-specific arguments.\n\n**Warnings:**\n\n- If ``dirpath`` is a relative path, changing the working directory while\n  ``iterpath()`` is in progress will lead to errors, or at least inaccurate\n  results.\n\n- Setting ``followlinks`` to ``True`` can result in infinite recursion if a\n  symlink points to a parent directory of itself.\n\nSelectors\n---------\n\n*New in version 0.3.0*\n\n``iterpath`` also provides a selection of \"selector\" classes \u0026 constants for\neasy construction of ``filter`` and ``exclude`` arguments.  Selectors are\ncallables that return true for ``DirEntry``'s whose (base) names match given\ncriteria.\n\nSelectors can even be combined using the ``|`` operator:\n\n.. code:: python\n\n    # This only returns entries whose names end in \".txt\" or equal \"foo.png\" or\n    # \".hidden\":\n    iterpath(\n        dirpath,\n        filter=SelectGlob(\"*.txt\") | SelectNames(\"foo.png\", \".hidden\")\n    )\n\n    # Exclude all dot-directories and VCS directories:\n    iterpath(dirpath, exclude_dirs=SELECT_DOTS | SELECT_VCS_DIRS)\n\nThe selectors:\n\n.. code:: python\n\n    class SelectNames(*names: AnyStr, case_sensitive: bool = True)\n\nSelects ``DirEntry``'s whose names are one of ``names``.  If ``case_sensitive``\nis ``False``, the check is performed case-insensitively.\n\n.. code:: python\n\n    class SelectGlob(pattern: AnyStr)\n\nSelects ``DirEntry``'s whose names match the given fileglob pattern\n\n.. code:: python\n\n    class SelectRegex(pattern: AnyStr | re.Pattern[AnyStr])\n\nSelects ``DirEntry``'s whose names match (using ``re.search()``) the given\nregular expression\n\n.. code:: python\n\n    SELECT_DOTS\n\nSelects ``DirEntry``'s whose names begin with a period\n\n.. code:: python\n\n    SELECT_VCS\n\nSelects ``DirEntry``'s matched by either ``SELECT_VCS_DIRS`` or\n``SELECT_VCS_FILES`` (see below)\n\n.. code:: python\n\n    SELECT_VCS_DIRS\n\nSelects the following names of version-control directories: ``.git``, ``.hg``,\n``_darcs``, ``.bzr``, ``.svn``, ``_svn``, ``CVS``, ``RCS``\n\n.. code:: python\n\n    SELECT_VCS_FILES\n\nSelects the following names of version-control-specific files:\n``.gitattributes``, ``.gitignore``, ``.gitmodules``, ``.mailmap``,\n``.hgignore``, ``.hgsigs``, ``.hgtags``, ``.binaries``, ``.boring``,\n``.bzrignore``, and all nonempty filenames that end in ``,v``\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fiterpath","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjwodder%2Fiterpath","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjwodder%2Fiterpath/lists"}