%global _empty_manifest_terminate_build 0 Name: python-scantree Version: 0.0.1 Release: 1 Summary: Flexible recursive directory iterator: scandir meets glob("**", recursive=True) License: MIT URL: https://github.com/andhus/scantree Source0: https://mirrors.nju.edu.cn/pypi/web/packages/35/0a/8709b1516110e7b5e1ef796426d8e3fcdb96d83a0cc2639a3d559df1b7c7/scantree-0.0.1.tar.gz BuildArch: noarch %description [![Build Status](https://travis-ci.com/andhus/scantree.svg?branch=master)](https://travis-ci.com/andhus/scantree) [![codecov](https://codecov.io/gh/andhus/scantree/branch/master/graph/badge.svg)](https://codecov.io/gh/andhus/scantree) # scantree Recursive directory iterator supporting: - flexible filtering including wildcard path matching - in memory representation of file-tree (for repeated access) - efficient access to directory entry properties (`posix.DirEntry` interface) extended with real path and path relative to the recursion root directory - detection and handling of cyclic symlinks ## Installation ```commandline pip install scantree ``` ## Usage See source code for full documentation, some generic examples below. Get matching file paths: ```python from scantree import scantree, RecursionFilter tree = scantree('/path/to/dir', RecursionFilter(match=['*.txt'])) print([path.relative for path in tree.filepaths()]) print([path.real for path in tree.filepaths()]) ``` ``` ['d1/d2/file3.txt', 'd1/file2.txt', 'file1.txt'] ['/path/to/other_dir/file3.txt', '/path/to/dir/d1/file2.txt', '/path/to/dir/file1.txt'] ``` Access metadata of directory entries in file tree: ```python d2 = tree.directories[0].directories[0] print(type(d2)) print(d2.path.absolute) print(d2.path.real) print(d2.path.is_symlink()) print(d2.files[0].relative) ``` ``` scantree._node.DirNode /path/to/dir/d1/d2 /path/to/other_dir True d1/d2/file3.txt ``` Aggregate information by operating on tree: ```python hello_count = tree.apply( file_apply=lambda path: sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]), dir_apply=lambda dir_: sum(dir_.entries), ) print(hello_count) ``` ``` 3 ``` ```python hello_count_tree = tree.apply( file_apply=lambda path: { 'name': path.name, 'count': sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]) }, dir_apply=lambda dir_: { 'name': dir_.path.name, 'count': sum(e['count'] for e in dir_.entries), 'sub_counts': [e for e in dir_.entries] }, ) from pprint import pprint pprint(hello_count_tree) ``` ``` {'count': 3, 'name': 'dir', 'sub_counts': [{'count': 2, 'name': 'file1.txt'}, {'count': 1, 'name': 'd1', 'sub_counts': [{'count': 1, 'name': 'file2.txt'}, {'count': 0, 'name': 'd2', 'sub_counts': [{'count': 0, 'name': 'file3.txt'}]}]}]} ``` Flexible filtering: ```python without_hidden_files = scantree('.', RecursionFilter(match=['*', '!.*'])) without_palindrome_linked_dirs = scantree( '.', lambda paths: [ p for p in paths if not ( p.is_dir() and p.is_symlink() and p.name == p.name[::-1] ) ] ) ``` Comparison: ```python tree = scandir('path/to/dir') # make some operations on filesystem, make sure file tree is the same: assert tree == scandir('path/to/dir') # tree contains absolute/real path info: import shutil shutil.copytree('path/to/dir', 'path/to/other_dir') new_tree = scandir('path/to/other_dir') assert tree != new_tree assert ( [p.relative for p in tree.leafpaths()] == [p.relative for p in new_tree.leafpaths()] ) ``` Inspect symlinks: ```python from scantree import CyclicLinkedDir file_links = [] dir_links = [] cyclic_links = [] def file_apply(path): if path.is_symlink(): file_links.append(path) def dir_apply(dir_node): if dir_node.path.is_symlink(): dir_links.append(dir_node.path) if isinstance(dir_node, CyclicLinkedDir): cyclic_links.append((dir_node.path, dir_node.target_path)) scantree('.', file_apply=file_apply, dir_apply=dir_apply) ``` %package -n python3-scantree Summary: Flexible recursive directory iterator: scandir meets glob("**", recursive=True) Provides: python-scantree BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-scantree [![Build Status](https://travis-ci.com/andhus/scantree.svg?branch=master)](https://travis-ci.com/andhus/scantree) [![codecov](https://codecov.io/gh/andhus/scantree/branch/master/graph/badge.svg)](https://codecov.io/gh/andhus/scantree) # scantree Recursive directory iterator supporting: - flexible filtering including wildcard path matching - in memory representation of file-tree (for repeated access) - efficient access to directory entry properties (`posix.DirEntry` interface) extended with real path and path relative to the recursion root directory - detection and handling of cyclic symlinks ## Installation ```commandline pip install scantree ``` ## Usage See source code for full documentation, some generic examples below. Get matching file paths: ```python from scantree import scantree, RecursionFilter tree = scantree('/path/to/dir', RecursionFilter(match=['*.txt'])) print([path.relative for path in tree.filepaths()]) print([path.real for path in tree.filepaths()]) ``` ``` ['d1/d2/file3.txt', 'd1/file2.txt', 'file1.txt'] ['/path/to/other_dir/file3.txt', '/path/to/dir/d1/file2.txt', '/path/to/dir/file1.txt'] ``` Access metadata of directory entries in file tree: ```python d2 = tree.directories[0].directories[0] print(type(d2)) print(d2.path.absolute) print(d2.path.real) print(d2.path.is_symlink()) print(d2.files[0].relative) ``` ``` scantree._node.DirNode /path/to/dir/d1/d2 /path/to/other_dir True d1/d2/file3.txt ``` Aggregate information by operating on tree: ```python hello_count = tree.apply( file_apply=lambda path: sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]), dir_apply=lambda dir_: sum(dir_.entries), ) print(hello_count) ``` ``` 3 ``` ```python hello_count_tree = tree.apply( file_apply=lambda path: { 'name': path.name, 'count': sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]) }, dir_apply=lambda dir_: { 'name': dir_.path.name, 'count': sum(e['count'] for e in dir_.entries), 'sub_counts': [e for e in dir_.entries] }, ) from pprint import pprint pprint(hello_count_tree) ``` ``` {'count': 3, 'name': 'dir', 'sub_counts': [{'count': 2, 'name': 'file1.txt'}, {'count': 1, 'name': 'd1', 'sub_counts': [{'count': 1, 'name': 'file2.txt'}, {'count': 0, 'name': 'd2', 'sub_counts': [{'count': 0, 'name': 'file3.txt'}]}]}]} ``` Flexible filtering: ```python without_hidden_files = scantree('.', RecursionFilter(match=['*', '!.*'])) without_palindrome_linked_dirs = scantree( '.', lambda paths: [ p for p in paths if not ( p.is_dir() and p.is_symlink() and p.name == p.name[::-1] ) ] ) ``` Comparison: ```python tree = scandir('path/to/dir') # make some operations on filesystem, make sure file tree is the same: assert tree == scandir('path/to/dir') # tree contains absolute/real path info: import shutil shutil.copytree('path/to/dir', 'path/to/other_dir') new_tree = scandir('path/to/other_dir') assert tree != new_tree assert ( [p.relative for p in tree.leafpaths()] == [p.relative for p in new_tree.leafpaths()] ) ``` Inspect symlinks: ```python from scantree import CyclicLinkedDir file_links = [] dir_links = [] cyclic_links = [] def file_apply(path): if path.is_symlink(): file_links.append(path) def dir_apply(dir_node): if dir_node.path.is_symlink(): dir_links.append(dir_node.path) if isinstance(dir_node, CyclicLinkedDir): cyclic_links.append((dir_node.path, dir_node.target_path)) scantree('.', file_apply=file_apply, dir_apply=dir_apply) ``` %package help Summary: Development documents and examples for scantree Provides: python3-scantree-doc %description help [![Build Status](https://travis-ci.com/andhus/scantree.svg?branch=master)](https://travis-ci.com/andhus/scantree) [![codecov](https://codecov.io/gh/andhus/scantree/branch/master/graph/badge.svg)](https://codecov.io/gh/andhus/scantree) # scantree Recursive directory iterator supporting: - flexible filtering including wildcard path matching - in memory representation of file-tree (for repeated access) - efficient access to directory entry properties (`posix.DirEntry` interface) extended with real path and path relative to the recursion root directory - detection and handling of cyclic symlinks ## Installation ```commandline pip install scantree ``` ## Usage See source code for full documentation, some generic examples below. Get matching file paths: ```python from scantree import scantree, RecursionFilter tree = scantree('/path/to/dir', RecursionFilter(match=['*.txt'])) print([path.relative for path in tree.filepaths()]) print([path.real for path in tree.filepaths()]) ``` ``` ['d1/d2/file3.txt', 'd1/file2.txt', 'file1.txt'] ['/path/to/other_dir/file3.txt', '/path/to/dir/d1/file2.txt', '/path/to/dir/file1.txt'] ``` Access metadata of directory entries in file tree: ```python d2 = tree.directories[0].directories[0] print(type(d2)) print(d2.path.absolute) print(d2.path.real) print(d2.path.is_symlink()) print(d2.files[0].relative) ``` ``` scantree._node.DirNode /path/to/dir/d1/d2 /path/to/other_dir True d1/d2/file3.txt ``` Aggregate information by operating on tree: ```python hello_count = tree.apply( file_apply=lambda path: sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]), dir_apply=lambda dir_: sum(dir_.entries), ) print(hello_count) ``` ``` 3 ``` ```python hello_count_tree = tree.apply( file_apply=lambda path: { 'name': path.name, 'count': sum([ w.lower() == 'hello' for w in path.as_pathlib().read_text().split() ]) }, dir_apply=lambda dir_: { 'name': dir_.path.name, 'count': sum(e['count'] for e in dir_.entries), 'sub_counts': [e for e in dir_.entries] }, ) from pprint import pprint pprint(hello_count_tree) ``` ``` {'count': 3, 'name': 'dir', 'sub_counts': [{'count': 2, 'name': 'file1.txt'}, {'count': 1, 'name': 'd1', 'sub_counts': [{'count': 1, 'name': 'file2.txt'}, {'count': 0, 'name': 'd2', 'sub_counts': [{'count': 0, 'name': 'file3.txt'}]}]}]} ``` Flexible filtering: ```python without_hidden_files = scantree('.', RecursionFilter(match=['*', '!.*'])) without_palindrome_linked_dirs = scantree( '.', lambda paths: [ p for p in paths if not ( p.is_dir() and p.is_symlink() and p.name == p.name[::-1] ) ] ) ``` Comparison: ```python tree = scandir('path/to/dir') # make some operations on filesystem, make sure file tree is the same: assert tree == scandir('path/to/dir') # tree contains absolute/real path info: import shutil shutil.copytree('path/to/dir', 'path/to/other_dir') new_tree = scandir('path/to/other_dir') assert tree != new_tree assert ( [p.relative for p in tree.leafpaths()] == [p.relative for p in new_tree.leafpaths()] ) ``` Inspect symlinks: ```python from scantree import CyclicLinkedDir file_links = [] dir_links = [] cyclic_links = [] def file_apply(path): if path.is_symlink(): file_links.append(path) def dir_apply(dir_node): if dir_node.path.is_symlink(): dir_links.append(dir_node.path) if isinstance(dir_node, CyclicLinkedDir): cyclic_links.append((dir_node.path, dir_node.target_path)) scantree('.', file_apply=file_apply, dir_apply=dir_apply) ``` %prep %autosetup -n scantree-0.0.1 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "/%h/%f\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "/%h/%f\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "/%h/%f.gz\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-scantree -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Sun Apr 23 2023 Python_Bot - 0.0.1-1 - Package Spec generated