├── docs
├── exampledir
│ ├── Vogel.txt
│ ├── jowly.pdf
│ ├── monkish.txt
│ ├── scrooge
│ │ ├── light.pdf
│ │ ├── reliquary.pdf
│ │ └── paycheck
│ │ │ └── electrophoresis.txt
│ └── pedantic
│ │ └── cataclysmic.txt
├── templates
│ ├── credits.mako
│ ├── head.mako
│ ├── logo.mako
│ ├── _lunr_search.inc.mako
│ ├── config.mako
│ ├── text.mako
│ ├── search.mako
│ ├── pdf.mako
│ ├── css.mako
│ └── html.mako
├── seedir
│ ├── errors.html
│ └── printing.html
└── gettingstarted.md
├── MANIFEST.in
├── seedir
├── __version__.py
├── errors.py
├── __init__.py
├── __main__.py
├── printing.py
├── realdir.py
└── folderstructure.py
├── .gitattributes
├── img
├── pun.jpg
├── seedir_diagram.png
└── seedir_diagram.pptx
├── pdoc_command.txt
├── tests
├── __init__.py
├── print_examples.py
└── test_seedir.py
├── stackoverflow.txt
├── .gitignore
├── pyproject.toml
├── .github
└── workflows
│ ├── deploy_pypi.yml
│ ├── deploy_testpypi.yml
│ └── test.yml
├── LICENSE
├── setup.py
├── README.md
├── CONTRIBUTING.md
└── CHANGELOG.md
/docs/exampledir/Vogel.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/exampledir/jowly.pdf:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/exampledir/monkish.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/templates/credits.mako:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/templates/head.mako:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/templates/logo.mako:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/exampledir/scrooge/light.pdf:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include seedir/words.txt
--------------------------------------------------------------------------------
/docs/exampledir/scrooge/reliquary.pdf:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/seedir/__version__.py:
--------------------------------------------------------------------------------
1 | version='0.5.1'
--------------------------------------------------------------------------------
/docs/exampledir/pedantic/cataclysmic.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/exampledir/scrooge/paycheck/electrophoresis.txt:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * linguist-vendored
2 | *.py linguist-vendored=false
3 |
--------------------------------------------------------------------------------
/img/pun.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/earnestt1234/seedir/HEAD/img/pun.jpg
--------------------------------------------------------------------------------
/pdoc_command.txt:
--------------------------------------------------------------------------------
1 | pdoc --html -o docs --template-dir docs/templates seedir --force
--------------------------------------------------------------------------------
/img/seedir_diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/earnestt1234/seedir/HEAD/img/seedir_diagram.png
--------------------------------------------------------------------------------
/img/seedir_diagram.pptx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/earnestt1234/seedir/HEAD/img/seedir_diagram.pptx
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Sep 7 11:53:42 2020
4 |
5 | @author: earne
6 | """
7 |
--------------------------------------------------------------------------------
/seedir/errors.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Custom exceptions for seedir.
4 |
5 | """
6 |
7 | # NOTE: SeedirError removed for 0.4.0
8 |
9 | # class SeedirError(Exception):
10 | # """Class for representing errors from module `seedir.realdir`"""
11 |
12 | class FakedirError(Exception):
13 | """Class for handling errors from module `seedir.fakedir`"""
14 |
--------------------------------------------------------------------------------
/stackoverflow.txt:
--------------------------------------------------------------------------------
1 | Stack Overflow posts which either inspired or helped solve issues with seedir:
2 |
3 | posts about printing tree structures in Python: https://stackoverflow.com/q/9727673/13386979
4 | posts about printing tree structures in general: https://stackoverflow.com/q/19699059/13386979
5 | recursively adding to a string: https://stackoverflow.com/a/44335113/13386979
6 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #testing script
2 | seedir/seedir_testing.py
3 | seedirpackagetesting.py
4 |
5 | # Compiled python modules.
6 | *.pyc
7 | seedir/__pycache__
8 |
9 | # Setuptools distribution folder.
10 | /dist/
11 | /build/
12 |
13 | # Python egg metadata, regenerated from source files by setuptools.
14 | /*.egg-info
15 |
16 | # Mac specific editing files
17 | .DS_Store
18 | **/.DS_Store
19 |
20 | .ipynb_checkpoints
21 | */.ipynb_checkpoints/*
22 |
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = ["setuptools"]
3 | build-backend = "setuptools.build_meta"
4 |
5 | [project]
6 | name = "seedir"
7 | description = "Package for creating, editing, and reading folder tree diagrams."
8 | dependencies = [
9 | "natsort"
10 | ]
11 | dynamic = ["version"]
12 | authors =[
13 | {name = "Tom Earnest", email = "earnestt1234@gmail.com"}
14 | ]
15 | readme = "README.md"
16 | license = {text = "MIT"}
17 |
18 | [project.optional-dependencies]
19 | emoji = ["emoji"]
20 |
21 | [project.urls]
22 | Homepage = "https://github.com/earnestt1234/seedir"
23 |
24 | [project.scripts]
25 | seedir = "seedir.__main__:main"
--------------------------------------------------------------------------------
/.github/workflows/deploy_pypi.yml:
--------------------------------------------------------------------------------
1 | # DERIVED FROM: https://realpython.com/github-actions-python
2 |
3 | # human readable name (shows up on Github)
4 | name: Deploy code to PyPI.
5 |
6 | on:
7 | release:
8 | types: [published]
9 | workflow_call:
10 | workflow_dispatch:
11 |
12 | jobs:
13 | publish:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - name: Set up Python
18 | uses: actions/setup-python@v5
19 | with:
20 | python-version: "3.13"
21 |
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | python -m pip install build
26 |
27 | - name: Build package
28 | run: python -m build
29 |
30 | - name: Upload to PyPI
31 | uses: pypa/gh-action-pypi-publish@release/v1
32 | with:
33 | user: __token__
34 | password: ${{ secrets.PYPI_API_TOKEN }}
--------------------------------------------------------------------------------
/.github/workflows/deploy_testpypi.yml:
--------------------------------------------------------------------------------
1 | # DERIVED FROM: https://realpython.com/github-actions-python
2 |
3 | # human readable name (shows up on Github)
4 | name: Deploy code to TestPyPI.
5 |
6 | on:
7 | release:
8 | types: [published]
9 | workflow_call:
10 | workflow_dispatch:
11 |
12 | jobs:
13 | publish:
14 | runs-on: ubuntu-latest
15 | steps:
16 | - uses: actions/checkout@v4
17 | - name: Set up Python
18 | uses: actions/setup-python@v5
19 | with:
20 | python-version: "3.13"
21 |
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | python -m pip install build
26 |
27 | - name: Build package
28 | run: python -m build
29 |
30 | - name: Upload to PyPI
31 | uses: pypa/gh-action-pypi-publish@release/v1
32 | with:
33 | user: __token__
34 | password: ${{ secrets.TESTPYPI_API_TOKEN }}
35 | repository-url: https://test.pypi.org/legacy/
--------------------------------------------------------------------------------
/seedir/__init__.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | [seedir](https://github.com/earnestt1234/seedir) is a Python package for
4 | creating, editing, and reading folder tree diagrams.
5 |
6 | The general logic of seedir is based on representing directories in 3
7 | different forms: real directories on a computer, text diagrams of directories,
8 | and "fake directories" (manipulable Python folder objects). seedir provides
9 | tools for going in between these formats.
10 |
11 | .. include:: ../docs/gettingstarted.md
12 |
13 | ## Cheatsheet
14 |
15 | 
16 |
17 | """
18 |
19 | #imports for package namespace
20 | from .realdir import seedir
21 |
22 | from .fakedir import (fakedir,
23 | fakedir_fromstring,
24 | populate,
25 | randomdir,)
26 |
27 | from .fakedir import FakeDir
28 | from .fakedir import FakeFile
29 |
30 | from .printing import (get_styleargs,
31 | STYLE_DICT,)
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2020 Tom Earnest
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | """
4 | Setup for seedir.
5 |
6 | @author: Tom Earnest
7 | """
8 |
9 | from os import path
10 |
11 | from setuptools import setup
12 |
13 | # read the contents of your README file
14 | this_directory = path.abspath(path.dirname(__file__))
15 | with open(path.join(this_directory, 'README.md'), encoding='utf-8') as f:
16 | long_description = f.read()
17 |
18 | # read version
19 | with open(path.join(this_directory, 'seedir', '__version__.py'), encoding='utf-8') as f:
20 | version = f.read().split('=')[1].strip('\'"\n')
21 |
22 | setup(name='seedir',
23 | version=version,
24 | description='Package for creating, editing, and reading folder tree diagrams.',
25 | url='https://github.com/earnestt1234/seedir',
26 | author='Tom Earnest',
27 | author_email='earnestt1234@gmail.com',
28 | license='MIT',
29 | packages=['seedir'],
30 | install_requires=['natsort'],
31 | extras_require={'emoji': ['emoji']},
32 | include_package_data=True,
33 | zip_safe=False,
34 | long_description=long_description,
35 | long_description_content_type='text/markdown',
36 | entry_points = {
37 | 'console_scripts': ['seedir=seedir.__main__:main'],
38 | })
39 |
--------------------------------------------------------------------------------
/.github/workflows/test.yml:
--------------------------------------------------------------------------------
1 | name: Run unit tests
2 |
3 | # defines when testing job is run
4 | on:
5 | push:
6 | branches:
7 | - main
8 | - dev
9 | pull_request:
10 | branches:
11 | - main
12 | - dev
13 | workflow_call:
14 | workflow_dispatch:
15 |
16 | # Defines the tasks to be completed
17 | jobs:
18 |
19 | testing:
20 | runs-on: ubuntu-latest
21 | continue-on-error: true
22 | strategy:
23 | matrix:
24 | python-version: ["3.10", "3.11", "3.12", "3.13"]
25 |
26 | steps:
27 | - uses: actions/checkout@v4 # checkout the github branch
28 |
29 | # Sets up Python, accesising the matrix defined above
30 | # to get a specific Python version
31 | # adding name here allows Python version to be documented
32 | - name: Set up Python ${{ matrix.python-version }}
33 | uses: actions/setup-python@v5
34 | with:
35 | python-version: ${{ matrix.python-version }}
36 | cache: "pip"
37 |
38 | # Installs the code to be tested, and pytest
39 | - name: Install dependencies
40 | run: |
41 | python -m pip install --upgrade pip
42 | python -m pip install .
43 | python -m pip install pytest
44 |
45 | # Runs pytest
46 | - name: Run Pytest
47 | run: pytest
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # seedir
2 | A Python package for creating, editing, and reading folder tree diagrams.
3 |
4 | 
5 |
6 | *Photo by [Adam Kring](https://unsplash.com/@adamkring).*
7 |
8 |
9 | ```python
10 | >>> import seedir as sd
11 | >>> sd.seedir(style='lines', itemlimit=10, depthlimit=2, exclude_folders='.git')
12 | seedir/
13 | ├─.gitattributes
14 | ├─.gitignore
15 | ├─.ipynb_checkpoints/
16 | │ └─examples-checkpoint.ipynb
17 | ├─build/
18 | │ ├─bdist.win-amd64/
19 | │ └─lib/
20 | ├─CHANGELOG.md
21 | ├─dist/
22 | │ └─seedir-0.1.4-py3-none-any.whl
23 | ├─docs/
24 | │ ├─exampledir/
25 | │ ├─gettingstarted.md
26 | │ ├─seedir/
27 | │ └─templates/
28 | ├─img/
29 | │ ├─pun.jpg
30 | │ ├─seedir_diagram.png
31 | │ └─seedir_diagram.pptx
32 | ├─LICENSE
33 | └─MANIFEST.in
34 |
35 | ```
36 |
37 | ## Installation
38 |
39 | Available with [`pip`](https://pypi.org/project/seedir/):
40 |
41 | ```
42 | pip install seedir
43 | ```
44 |
45 | To make use of the 'emoji' style, install [emoji](https://pypi.org/project/emoji/) (`pip install emoji`) or use `pip install seedir[emoji]`.
46 |
47 | ## Usage
48 |
49 | See the [API documentation](https://earnestt1234.github.io/seedir/seedir/index.html) (generated with [pdoc3](https://pdoc3.github.io/pdoc/)).
50 |
51 | ## License
52 |
53 | Open source under MIT.
54 |
55 |
--------------------------------------------------------------------------------
/tests/print_examples.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Unit tests for seedir.
4 |
5 | Previously written for unittests, and updated for pytest.
6 |
7 | Test methods MUST start with "test"
8 | """
9 |
10 | import os
11 |
12 | import seedir as sd
13 |
14 | # realdir for testing on
15 | testdir = os.path.dirname(os.path.abspath(__file__))
16 |
17 | # ---- Test cases
18 |
19 | print('\n--------------------'
20 | '\n\nTesting seedir.seedir() against {}\n\n'
21 | '--------------------'
22 | '\n'.format(testdir))
23 |
24 | print('Basic seedir (depthlimit=2, itemlimit=10):\n')
25 | sd.seedir(testdir, depthlimit=2, itemlimit=10)
26 |
27 | print('\nDifferent Styles (depthlimit=1, itemlimit=5):')
28 | for style in sd.STYLE_DICT.keys():
29 | print('\n{}:\n'.format(style))
30 | sd.seedir(testdir, style=style, depthlimit=1, itemlimit=5)
31 |
32 | print('\nCustom Styles (depthlimit=1, itemlimit=5):')
33 | sd.seedir(testdir, depthlimit=1, itemlimit=5, space='>>',
34 | split='>>', extend='II', final='->',
35 | folderstart='Folder: ', filestart='File: ')
36 |
37 | print('\nDifferent Indents (depthlimit=1, itemlimit=5):')
38 | for i in list(range(3)) + [8]:
39 | print('\nindent={}:\n'.format(str(i)))
40 | sd.seedir(testdir, depthlimit=1, itemlimit=5, indent=i)
41 |
42 | print('\nItems Beyond Limit (depthlimit=1, itemlimit=1, beyond="content")')
43 | sd.seedir(testdir, itemlimit=1, beyond='content')
44 |
45 |
46 |
--------------------------------------------------------------------------------
/docs/templates/_lunr_search.inc.mako:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
21 |
51 |
--------------------------------------------------------------------------------
/docs/templates/config.mako:
--------------------------------------------------------------------------------
1 | <%!
2 | # Template configuration. Copy over in your template directory
3 | # (used with `--template-dir`) and adapt as necessary.
4 | # Note, defaults are loaded from this distribution file, so your
5 | # config.mako only needs to contain values you want overridden.
6 | # You can also run pdoc with `--config KEY=VALUE` to override
7 | # individual values.
8 |
9 | html_lang = 'en'
10 | show_inherited_members = False
11 | extract_module_toc_into_sidebar = True
12 | list_class_variables_in_index = True
13 | sort_identifiers = True
14 | show_type_annotations = True
15 |
16 | # Show collapsed source code block next to each item.
17 | # Disabling this can improve rendering speed of large modules.
18 | show_source_code = True
19 |
20 | # If set, format links to objects in online source code repository
21 | # according to this template. Supported keywords for interpolation
22 | # are: commit, path, start_line, end_line.
23 | #git_link_template = 'https://github.com/USER/PROJECT/blob/{commit}/{path}#L{start_line}-L{end_line}'
24 | #git_link_template = 'https://gitlab.com/USER/PROJECT/blob/{commit}/{path}#L{start_line}-L{end_line}'
25 | #git_link_template = 'https://bitbucket.org/USER/PROJECT/src/{commit}/{path}#lines-{start_line}:{end_line}'
26 | #git_link_template = 'https://CGIT_HOSTNAME/PROJECT/tree/{path}?id={commit}#n{start-line}'
27 | git_link_template = None
28 |
29 | # A prefix to use for every HTML hyperlink in the generated documentation.
30 | # No prefix results in all links being relative.
31 | link_prefix = ''
32 |
33 | # Enable syntax highlighting for code/source blocks by including Highlight.js
34 | syntax_highlighting = True
35 |
36 | # Set the style keyword such as 'atom-one-light' or 'github-gist'
37 | # Options: https://github.com/highlightjs/highlight.js/tree/master/src/styles
38 | # Demo: https://highlightjs.org/static/demo/
39 | hljs_style = 'github'
40 |
41 | # If set, insert Google Analytics tracking code. Value is GA
42 | # tracking id (UA-XXXXXX-Y).
43 | google_analytics = ''
44 |
45 | # If set, insert Google Custom Search search bar widget above the sidebar index.
46 | # The whitespace-separated tokens represent arbitrary extra queries (at least one
47 | # must match) passed to regular Google search. Example:
48 | #google_search_query = 'inurl:github.com/USER/PROJECT site:PROJECT.github.io site:PROJECT.website'
49 | google_search_query = ''
50 |
51 | # Enable offline search using Lunr.js. For explanation of 'fuzziness' parameter, which is
52 | # added to every query word, see: https://lunrjs.com/guides/searching.html#fuzzy-matches
53 | # If 'index_docstrings' is False, a shorter index is built, indexing only
54 | # the full object reference names.
55 | #lunr_search = {'fuzziness': 1, 'index_docstrings': True}
56 | lunr_search = None
57 |
58 | # If set, render LaTeX math syntax within \(...\) (inline equations),
59 | # or within \[...\] or $$...$$ or `.. math::` (block equations)
60 | # as nicely-formatted math formulas using MathJax.
61 | # Note: in Python docstrings, either all backslashes need to be escaped (\\)
62 | # or you need to use raw r-strings.
63 | latex_math = False
64 | %>
65 |
--------------------------------------------------------------------------------
/docs/templates/text.mako:
--------------------------------------------------------------------------------
1 | ## Define mini-templates for each portion of the doco.
2 |
3 | <%!
4 | def indent(s, spaces=4):
5 | new = s.replace('\n', '\n' + ' ' * spaces)
6 | return ' ' * spaces + new.strip()
7 | %>
8 |
9 | <%def name="deflist(s)">:${indent(s)[1:]}%def>
10 |
11 | <%def name="h3(s)">### ${s}
12 | %def>
13 |
14 | <%def name="function(func)" buffered="True">
15 | <%
16 | returns = show_type_annotations and func.return_annotation() or ''
17 | if returns:
18 | returns = ' \N{non-breaking hyphen}> ' + returns
19 | %>
20 | `${func.name}(${", ".join(func.params(annotate=show_type_annotations))})${returns}`
21 | ${func.docstring | deflist}
22 | %def>
23 |
24 | <%def name="variable(var)" buffered="True">
25 | <%
26 | annot = show_type_annotations and var.type_annotation() or ''
27 | if annot:
28 | annot = ': ' + annot
29 | %>
30 | `${var.name}${annot}`
31 | ${var.docstring | deflist}
32 | %def>
33 |
34 | <%def name="class_(cls)" buffered="True">
35 | `${cls.name}(${", ".join(cls.params(annotate=show_type_annotations))})`
36 | ${cls.docstring | deflist}
37 | <%
38 | class_vars = cls.class_variables(show_inherited_members, sort=sort_identifiers)
39 | static_methods = cls.functions(show_inherited_members, sort=sort_identifiers)
40 | inst_vars = cls.instance_variables(show_inherited_members, sort=sort_identifiers)
41 | methods = cls.methods(show_inherited_members, sort=sort_identifiers)
42 | mro = cls.mro()
43 | subclasses = cls.subclasses()
44 | %>
45 | % if mro:
46 | ${h3('Ancestors (in MRO)')}
47 | % for c in mro:
48 | * ${c.refname}
49 | % endfor
50 |
51 | % endif
52 | % if subclasses:
53 | ${h3('Descendants')}
54 | % for c in subclasses:
55 | * ${c.refname}
56 | % endfor
57 |
58 | % endif
59 | % if class_vars:
60 | ${h3('Class variables')}
61 | % for v in class_vars:
62 | ${variable(v) | indent}
63 |
64 | % endfor
65 | % endif
66 | % if static_methods:
67 | ${h3('Static methods')}
68 | % for f in static_methods:
69 | ${function(f) | indent}
70 |
71 | % endfor
72 | % endif
73 | % if inst_vars:
74 | ${h3('Instance variables')}
75 | % for v in inst_vars:
76 | ${variable(v) | indent}
77 |
78 | % endfor
79 | % endif
80 | % if methods:
81 | ${h3('Methods')}
82 | % for m in methods:
83 | ${function(m) | indent}
84 |
85 | % endfor
86 | % endif
87 | %def>
88 |
89 | ## Start the output logic for an entire module.
90 |
91 | <%
92 | variables = module.variables(sort=sort_identifiers)
93 | classes = module.classes(sort=sort_identifiers)
94 | functions = module.functions(sort=sort_identifiers)
95 | submodules = module.submodules()
96 | heading = 'Namespace' if module.is_namespace else 'Module'
97 | %>
98 |
99 | ${heading} ${module.name}
100 | =${'=' * (len(module.name) + len(heading))}
101 | ${module.docstring}
102 |
103 |
104 | % if submodules:
105 | Sub-modules
106 | -----------
107 | % for m in submodules:
108 | * ${m.name}
109 | % endfor
110 | % endif
111 |
112 | % if variables:
113 | Variables
114 | ---------
115 | % for v in variables:
116 | ${variable(v)}
117 |
118 | % endfor
119 | % endif
120 |
121 | % if functions:
122 | Functions
123 | ---------
124 | % for f in functions:
125 | ${function(f)}
126 |
127 | % endfor
128 | % endif
129 |
130 | % if classes:
131 | Classes
132 | -------
133 | % for c in classes:
134 | ${class_(c)}
135 |
136 | % endfor
137 | % endif
138 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 |
2 | # Contributing to seedir
3 |
4 | This document describes ways that you can contribute to seedir, progressing in increasing levels of involvement.
5 |
6 | ## Use it
7 |
8 | Simply using this package is helpful! It is rewarding for me to see more people using it, and makes me want to keep working on it. Having the code be used in more real world settings is great for detecting use cases and missing features. Maybe you are already using it if you are reading this... but if not, please give it a try.
9 |
10 | ## Share it
11 |
12 | If you liked seedir or found it useful, sharing it with others is a good way to help the package grow. Moreover, the package maintainer is basically just me - so sharing the project may be helpful for growing a maintenance community and fostering stable development in the long term.
13 |
14 | ## Report a bug / request a feature
15 |
16 | Please use the [issues page](https://github.com/earnestt1234/seedir/issues) to formally log any sort of suggestion to improve the package. This can be a bug report, a feature request, documentation improvements, etc. These are extremely helpful as they can give me a sense of what people are actually doing with the package, and what its drawbacks are.
17 |
18 | Note that proposed changes will be implemented at the discretion of the maintainers.
19 |
20 | There currently is no formal structure needed for posting an issue. But some general guidelines:
21 |
22 | - If sharing a bug, include a minimally reproducible example - something that I will be able to demonstrate and debug on my own machine.
23 | - Please share code where possible (as plaintext, not as pictures)
24 | - Please be courteous : )
25 |
26 | ## Contribute code
27 |
28 | We welcome anyone who wants to contribute code to seedir! Expanding the maintainers would be great for the longterm stability of the package.
29 |
30 | This has not happened much so far, so the guidelines may evolve over time. But the general steps should be:
31 |
32 | 1. Open an issue (or comment on an existing issue) indicating the changes you plan to implement. Discuss with a maintainer to agree on a general course of action for the proposed changes.
33 | 2. [Fork the seedir repository](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo), and make sure you have the most up-to-date changes from the `dev` branch.
34 | 3. Create a branch stemming from the `dev` branch. Name it whatever you like, but ideally something related to the feature/bug you plan to tackle.
35 | 4. Implement your changes, making one or more commits to your created branch. **Note:** We currently do not have an opposition to generative AI tools (e.g. ChatGPT, Claude, Copilot, etc) being used for aiding with seedir development. But we ask that you inform us if you have used AI tools for any code slated to be contributed to the seedir codebase.
36 | 5. Run the test suite to make sure they still pass. Add any additional tests needed to cover your changes - or edit existing tests if they are no longer valid following your changes.
37 | 6. Add to the [`CHANGELOG.md`](https://github.com/earnestt1234/seedir/blob/master/CHANGELOG.md) to document any changes that occurred. You can add a header for "DEV" rather than assigning them to a specific version.
38 | 7. Create a pull request into the main branch, with a brief summary of what you did.
39 | 8. A maintainer should then approve your changes and merge them into `dev`, which will then be merged into `master` at the next version release.
40 |
41 | Please raise an issue if these steps are unclear or seem incorrect. If you are more familiar with this process and have suggestions, please let us know!
42 |
43 |
--------------------------------------------------------------------------------
/seedir/__main__.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 |
4 | import argparse
5 | import os
6 |
7 | from .realdir import seedir
8 |
9 | helptxt = """
10 | Help for the seedir CLI. Function for printing a folder tree
11 | structure, similar to UNIX `tree`. Directs all arguments to `seedir.seedir()`.
12 |
13 | Note that this has been revamped for version v0.3.1. Specifically, parsing
14 | was moved from getopts to argparse. Options should now all explicitly
15 | reference parameters of `seedir.seedir()`.
16 |
17 | Not all seedir arguments are accepted, namely ones which expect Python
18 | callables and ones which alter the style. The latter may be added
19 | in a future version.
20 |
21 | Options (short/long):
22 |
23 | -b / --beyond BEYOND
24 | Way to represent items past the depthlimit or itemlimit.
25 | Options are 'content', 'ellipsis', or explicit string starting
26 | with an underscore. Not set by default.
27 |
28 | -d / --depthlimit DEPTHLIMIT
29 | Integer limit on depth of folders to enter. Default: None
30 |
31 | -f / --first FIRST
32 | Sort the directory so that either files or folders appear first.
33 | Options are "folders" or "files".
34 |
35 | -h / --help
36 | Show this message and exit.
37 |
38 | -i / --itemlimit ITEMLIMIT
39 | Integer limit on the number of items to include per directory.
40 | Default: None
41 |
42 | -p / --path PATH
43 | Dir to see. Default: current directory (os.getcwd())
44 |
45 | -r / --sort_reverse
46 | Reverse the sort.
47 |
48 | -s / --sort
49 | Sort the contents of each directory by name.
50 |
51 | -t / --indent INDENT
52 | Amount to indent. Default: 2
53 |
54 | -y / --style STYLE
55 | seedir style to use. Default: "lines"
56 |
57 | Options (long only):
58 |
59 | --include_folders, --include_files, --exclude_folders, --exclude_files ...
60 | Folder / file names to include or exclude. Not set by default. Pass
61 | multiple items as space-separated values.
62 |
63 | --regex
64 | Interpret include/exclude folder/file arguments as Python regex.
65 | """
66 |
67 | def parse():
68 |
69 | """Parse command line arguments with argparse."""
70 |
71 | parser = argparse.ArgumentParser(add_help=False)
72 |
73 | parser.add_argument('-b', '--beyond', default=None)
74 | parser.add_argument('-d', '--depthlimit', default=None, type=int)
75 | parser.add_argument('-f', '--first', default=None)
76 | parser.add_argument('-h', '--help', action='store_true')
77 | parser.add_argument('-i', '--itemlimit', default=None, type=int)
78 | parser.add_argument('-p', '--path', default=os.getcwd())
79 | parser.add_argument('-r', '--sort_reverse', action='store_true')
80 | parser.add_argument('-s', '--sort', action='store_true')
81 | parser.add_argument('-t', '--indent', default=2, type=int)
82 | parser.add_argument('-y', '--style', default='lines')
83 |
84 | parser.add_argument('--include_folders', default=None, nargs='+')
85 | parser.add_argument('--exclude_folders', default=None, nargs='+')
86 | parser.add_argument('--include_files', default=None, nargs='+')
87 | parser.add_argument('--exclude_files', default=None, nargs='+')
88 | parser.add_argument('--regex', action='store_true')
89 |
90 | return parser.parse_args()
91 |
92 | def main():
93 |
94 | """Parses arguments and passes them to `seedir.seedir()`"""
95 |
96 | args = parse()
97 | if args.help:
98 | print(helptxt)
99 | return
100 |
101 | kwargs = vars(args)
102 | del kwargs['help']
103 | seedir(**kwargs)
104 |
105 | if __name__ == '__main__':
106 | main()
107 |
108 |
--------------------------------------------------------------------------------
/seedir/printing.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | General module of resources and helpers for printing and making folder trees
4 | in seedir.
5 |
6 | """
7 |
8 | __pdoc__ = {'is_match': False,
9 | 'format_indent': False,
10 | 'words': False}
11 |
12 |
13 |
14 | import copy
15 | import os
16 | import re
17 |
18 |
19 | STYLE_DICT = {
20 | 'lines': {'split':'├─',
21 | 'extend':'│ ',
22 | 'space':' ',
23 | 'final':'└─',
24 | 'folderstart':'',
25 | 'filestart':'',
26 | 'folderend': '/',
27 | 'fileend': ''},
28 | 'dash': {'split':'|-',
29 | 'extend':'| ',
30 | 'space':' ',
31 | 'final':'|-',
32 | 'folderstart':'',
33 | 'filestart':'',
34 | 'folderend': '/',
35 | 'fileend': ''},
36 | 'spaces':{'split':' ',
37 | 'extend':' ',
38 | 'space':' ',
39 | 'final':' ',
40 | 'folderstart':'',
41 | 'filestart':'',
42 | 'folderend': '/',
43 | 'fileend': ''},
44 | 'plus': {'split':'+-',
45 | 'extend':'| ',
46 | 'space':' ',
47 | 'final':'+-',
48 | 'folderstart':'',
49 | 'filestart':'',
50 | 'folderend': '/',
51 | 'fileend': ''},
52 | 'arrow': {'split':' ',
53 | 'extend':' ',
54 | 'space':' ',
55 | 'final':' ',
56 | 'folderstart':'>',
57 | 'filestart':'>',
58 | 'folderend': '/',
59 | 'fileend': ''}
60 | }
61 | '''"Tokens" used to create folder trees in different styles'''
62 |
63 | try:
64 | import emoji
65 | STYLE_DICT["emoji"] = {
66 | 'split':'├─',
67 | 'extend':'│ ',
68 | 'space':' ',
69 | 'final':'└─',
70 | 'folderstart':emoji.emojize(':file_folder:' + ' '),
71 | 'filestart':emoji.emojize(':page_facing_up:' + ' '),
72 | 'folderend': '/',
73 | 'fileend': ''
74 | }
75 | except ImportError:
76 | pass
77 |
78 |
79 | filepath = os.path.dirname(os.path.abspath(__file__))
80 | wordpath = os.path.join(filepath, 'words.txt')
81 | with open(wordpath, 'r') as wordfile:
82 | words = [line.strip() for line in wordfile.readlines()]
83 | """List of dictionary words for seedir.fakedir.randomdir()"""
84 |
85 | # functions
86 |
87 | def is_match(pattern, string, regex=True):
88 | '''Function for matching strings using either regular expression
89 | or literal interpretation.'''
90 | if regex:
91 | return bool(re.search(pattern, string))
92 | else:
93 | return pattern == string
94 |
95 | def get_styleargs(style):
96 | '''
97 | Return the string tokens associated with different styles for printing
98 | folder trees with `seedir.realdir.seedir()`.
99 |
100 | Parameters
101 | ----------
102 | style : str
103 | Style name. Current options are `'lines'`, `'spaces'`, `'arrow'`,
104 | `'plus'`, `'dash'`, or `'emoji'`.
105 |
106 | Raises
107 | ------
108 | ValueError
109 | Style not recognized.
110 |
111 | ImportError
112 | 'emoji' style requested but emoji package not installed.
113 |
114 | Returns
115 | -------
116 | dict
117 | Dictionary of tokens for the given style.
118 |
119 | '''
120 | if style not in STYLE_DICT and style == 'emoji':
121 | error_text = 'style "emoji" requires "emoji" to be installed'
122 | error_text += ' (pip install emoji) '
123 | raise ImportError(error_text)
124 | elif style not in STYLE_DICT:
125 | error_text = 'style "{}" not recognized, must be '.format(style)
126 | error_text += 'lines, spaces, arrow, plus, dash, or emoji'
127 | raise ValueError(error_text)
128 | else:
129 | return copy.deepcopy(STYLE_DICT[style])
130 |
131 | def format_indent(style_dict, indent=2):
132 | '''
133 | Format the indent of style tokens, from seedir.STYLE_DICT or returned
134 | by seedir.get_styleargs().
135 |
136 | Note that as of v0.3.1, the dictionary is modified in place,
137 | rather than a new copy being created.
138 |
139 | Parameters
140 | ----------
141 | style_dict : dict
142 | Dictionary of style tokens.
143 | indent : int, optional
144 | Number of spaces to indent. The default is 2. With 0, all tokens
145 | become the null string. With 1, all tokens are only the first
146 | character. With 2, the style tokens are returned unedited. When >2,
147 | the final character of each token (excep the file/folder start/end tokens)
148 | are extened n - indent times, to give a string whose
149 | length is equal to indent.
150 |
151 | Returns
152 | -------
153 | output : dict
154 | New dictionary of edited tokens.
155 |
156 | '''
157 | indentable = ['split', 'extend', 'space', 'final']
158 | if indent < 0 or not isinstance(indent, int):
159 | raise ValueError('indent must be a non-negative integer')
160 | elif indent == 0:
161 | for key in indentable:
162 | style_dict[key] = ''
163 | elif indent == 1:
164 | for key in indentable:
165 | style_dict[key] = style_dict[key][0]
166 | elif indent > 2:
167 | extension = indent - 2
168 | for key in indentable:
169 | val = style_dict[key]
170 | style_dict[key] = val + val[-1] * extension
171 |
172 | return None
173 |
--------------------------------------------------------------------------------
/docs/templates/search.mako:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Search
7 |
8 |
9 |
28 |
29 |
30 |
31 |
34 |
35 |
36 |
class FakedirError(Exception):
65 | """Class for handling errors from module `seedir.fakedir`"""
66 |
67 |
Ancestors
68 |
69 |
builtins.Exception
70 |
builtins.BaseException
71 |
72 |
73 |
74 |
75 |
76 |
96 |
97 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | This document will serve as a record for past and future changes to seedir. It is being retroactively added after the version [0.2.0](https://github.com/earnestt1234/seedir/releases/tag/v0.2.0) release (so notes for prior releases will be less detailed).
4 |
5 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6 |
7 | ## [0.5.1](https://github.com/earnestt1234/seedir/releases/tag/v0.5.1)
8 |
9 | ### Added
10 |
11 | - GitHub workflows for testing the code (on pushes and pulls to `main` and `dev`) and for uploading to PyPI (on new release).
12 | - Created a pyproject.toml
13 | - Add CONTRIBUTING.md for instructions on how to contribute to the project
14 |
15 | ### Changed
16 |
17 | - `seedir.fakedir.fakedir_fromstring` has been refactored. The logic is essentially the same, but there have been some simplifications and more comments have been added.
18 |
19 | ## [0.5.0](https://github.com/earnestt1234/seedir/releases/tag/v0.5.0)
20 |
21 | ### Added
22 |
23 | - The `itemlimit` now accepts a 2-tuple as an argument, indicating a separate limit for folders and files (respectively).
24 | - Added two parameters for handling errors when trying to list the children of a directory:
25 | - `acceptable_listdir_errors`: One or more error types (`Exceptions`) which are ignored when occurring during a directory listing call. E.g., a permissions error.
26 | - `denied_string`: String to add to follow directory entries for which the error was triggered.
27 | - More test cases added
28 |
29 | ### Changed
30 |
31 | - The main algorithm for folder tree traversal has been refactored.
32 | - The unit tests are now structured for pytest.
33 | - `seedir.folderstructure.FolderStructure` is now an abstract class that cannot be directly instantiated. The functions that previously needed to be provided as arguments for the constructor must now be implemented as part of a subclass (see [getting started for an example](https://earnestt1234.github.io/seedir/seedir/index.html#getting-started))
34 |
35 | ### Deprecated
36 |
37 | - `slash` is now totally deprecated; use `folderend` instead.
38 |
39 | ## [0.4.2](https://github.com/earnestt1234/seedir/releases/tag/v0.4.2)
40 |
41 | ### Changed
42 |
43 | - Syntax for accessing the CLI is updated. Now, you can do `seedir` or `python -m seedir`; `seedir.command_line` is renamed to enable this change.
44 |
45 | ## [0.4.0](https://github.com/earnestt1234/seedir/releases/tag/v0.4.0)
46 |
47 | ### Added
48 |
49 | - pathlib Path objects now accepted by `sd.seedir()`. All other arguments apply as normal; arguments accepting callables (`mask` and `formatter`) will see pathlib objects.
50 |
51 | ### Changed
52 |
53 | - [emoji is now an optional dependency](https://github.com/earnestt1234/seedir/issues/12). It can be installed with `pip install seedir[emoji]`. An error is raised if the emoji style is requested without emoji installed.
54 | - Reorganization of `folderstructure.py` and the `FolderStructure` class
55 | - `folderstructurehelpers.py` has been removed. Most of the functions implemented there have become methods of `FolderStucture`.
56 | - FolderStructure has been made more user-friendly, and can now be initialized with less functions.
57 | - There are no longer separate "real dir"/"fake dir" functions for handing item filtering/sorting.
58 |
59 | - Item inclusion is now prioritized above exclusion for include/exclude folders/files. The order of precedence now is mask (1), inclusion (2), exclusion (3). The code in this function was generally rewritten to be more concise (`FolderStructure._filter_items()`).
60 | - The `~` in paths is now resolved, as well as `.` and `..`
61 | - More examples in the getting started readme.
62 |
63 | ### Fixed
64 |
65 | - Typos in documentation
66 | - Removal of IPYNB checkpoints
67 |
68 | ### Removed
69 |
70 | - The `SeedirError` has been removed. All uses have been replaced with more appropriate errors, mainly `ValueError` or `TypeError`
71 |
72 | ## [0.3.1](https://github.com/earnestt1234/seedir/releases/tag/v0.3.1)
73 |
74 | ### Added
75 | - Additional functionality to the `formatter` parameter: can now dynamically set other seedir arguments as well as styling ones
76 | - Added a `sticky_formatter` parameter for causing the formatter changes to continue through sub-directories.
77 | - Additional test cases for `formatter`
78 | - Add `folderend` & `fileend` tokens for setting characters at end of line. Default styles have been updated to include these.
79 | - Additional documentation, specifically for `formatter` but also some smaller tweaks
80 |
81 | ### Changed
82 | - The CLI was revamped, now using argparse instead of getopts. More seedir options were added.
83 | - The `seedir.printing.format_indent()` method now modifies dictionaries in place, rather than creating a new one
84 | - the `FakeDir.realize()` method no longer creates a reference to unused file variable
85 |
86 | ### Fixed
87 | - Fix the words.txt file not being closed after opening 🤦
88 |
89 | ### Deprecated
90 |
91 | - `slash` is on warning for removal after addition of `folderend`.
92 |
93 | ## [0.3.0](https://github.com/earnestt1234/seedir/releases/tag/v0.3.0) - 2021-12-20
94 |
95 | ### Added
96 |
97 | - [`formatter` parameter](https://github.com/earnestt1234/seedir/issues/4) for more customizable diagrams
98 | - FakeDir methods for creating files/folders now return references to the objects created
99 | - A `copy()` method for FakeDirs
100 | - A `siblings()` method for FakeDirs
101 |
102 | ### Changed
103 |
104 | - Documentation updates
105 | - Added code blocks to examples in docstrings
106 | - replaced the "cheatsheet.png" image in the Getting Started section with a markdown link
107 | - remove broken link to `FolderStructure` class in `seedir.realdir` module
108 | - fixed some examples in docstrings and readmes
109 | - in getting started, redo examples to omit empty folders (which are omitted by GitHub)
110 | - replace `'\s'` with `' '` in `seedir.fakedir.fakedir_fromstring()`
111 | - [Remove .DS_Store files](https://github.com/earnestt1234/seedir/pull/5) (thanks @[timweissenfels](https://github.com/timweissenfels))
112 | - Reverted API doc style back to pdoc3 default
113 |
114 | ### Fixed
115 |
116 | - remove [call to `copy` method](https://github.com/earnestt1234/seedir/blob/09fbed86a356fa9b01588546e1e7dbda15812b49/seedir/fakedir.py#L417) in `Fakedir.delete()`, which prevented non-list arguments
117 | - the `walk_apply` method is now applied to the calling folder, rather than just children
118 |
119 | ## [0.2.0](https://github.com/earnestt1234/seedir/releases/tag/v0.2.0) - 2021-05-21
120 |
121 | ### Added
122 |
123 | - a new `folderstructure.py` module was added containing a single folder tree construction algorithm. This module is called for both real directories (`seedir.realdir.seedir()`) and fake directories (`seedir.fakedir.Fakedir.seedir()`). The code was also refactored to be less convoluted and more readable (and also more correct for some fringe cases)
124 | - using `depthlimit=0` with a `beyond` string now produces just the root folder (this was incorrect before)
125 | - with `beyond='content'`, empty folders are only shown when the `depthlimit` is crossed
126 | - trailing separators or slashes no longer cause the name of the root folder to be empty
127 | - A `folderstructurehelpers.py` module was also added to support the main folder structure algorithm.
128 | - More unit tests were added.
129 | - `name` parameter added to `seedir.fakedir.randomdir`
130 | - Convert some arguments to `bool` or `int` in the command line tool
131 |
132 | ### Changed
133 |
134 | - The documentation was overhauled:
135 | - The Jupyter Notebook examples file was removed, in favor of a `gettingstarted.md` file which is included in the main page of the API docs.
136 | - The getting started README as well as the `seedir.fakedir` module are now `doctest`-able.
137 | - New style added to the API docs.
138 | - `seedir.seedir` module has been renamed to `seedir.realdir` to avoid some of my confusions
139 | - added an `exampledir` to the `docs` folder for some examples
140 | - Some changes to `seedir.fakedir.fakedir_fromstring` to handle some more failed cases.
141 | - `words`, `FakeItem` removed from package namespace
142 |
143 | ## [0.1.4](https://github.com/earnestt1234/seedir/releases/tag/v0.1.4) - 2021-03-01
144 |
145 | ### Added
146 |
147 | - Documentation was updated to include code formatting and within-package hyperlinks (thanks to pdoc)
148 |
149 | ### Changed
150 |
151 | - the variable name of the output of `seedir.seedir()` and `seedir.fakedir()` was renamed from `rfs` to `s`
152 |
153 | ## [0.1.3](https://github.com/earnestt1234/seedir/releases/tag/v0.1.3) - 2020-12-31
154 |
155 | ### Changed
156 |
157 | - Code block examples added to docstrings, following [this issue](https://github.com/earnestt1234/seedir/issues/3)
158 |
159 | ## [0.1.2](https://github.com/earnestt1234/seedir/releases/tag/v0.1.2) - 2020-11-28
160 |
161 | ### Added
162 |
163 | - [new `mask` parameter](https://github.com/earnestt1234/seedir/issues/1) for functionally filtering items, used by `seedir.seedir`, `seedir.FakeDir.seedir`, and `seedir.fakedir`
164 | - test cases for the `mask` parameter
165 |
166 | ### Changed
167 |
168 | - Updated examples notebook
169 | - Updated documentation
170 |
171 | ## [0.1.1](https://github.com/earnestt1234/seedir/releases/tag/v0.1.1) - 2020-11-20
172 |
173 | Initial public release of seedir 🎉
--------------------------------------------------------------------------------
/docs/templates/css.mako:
--------------------------------------------------------------------------------
1 | <%!
2 | from pdoc.html_helpers import minify_css
3 | %>
4 |
5 | <%def name="mobile()" filter="minify_css">
6 | :root {
7 | --highlight-color: #fe9;
8 | }
9 | .flex {
10 | display: flex !important;
11 | }
12 |
13 | body {
14 | line-height: 1.5em;
15 | }
16 |
17 | #content {
18 | padding: 20px;
19 | }
20 |
21 | #sidebar {
22 | padding: 30px;
23 | overflow: hidden;
24 | }
25 | #sidebar > *:last-child {
26 | margin-bottom: 2cm;
27 | }
28 |
29 | % if lunr_search is not None:
30 | #lunr-search {
31 | width: 100%;
32 | font-size: 1em;
33 | padding: 6px 9px 5px 9px;
34 | border: 1px solid silver;
35 | }
36 | % endif
37 |
38 | .http-server-breadcrumbs {
39 | font-size: 130%;
40 | margin: 0 0 15px 0;
41 | }
42 |
43 | #footer {
44 | font-size: .75em;
45 | padding: 5px 30px;
46 | border-top: 1px solid #ddd;
47 | text-align: right;
48 | }
49 | #footer p {
50 | margin: 0 0 0 1em;
51 | display: inline-block;
52 | }
53 | #footer p:last-child {
54 | margin-right: 30px;
55 | }
56 |
57 | h1, h2, h3, h4, h5 {
58 | font-weight: 300;
59 | }
60 | h1 {
61 | font-size: 2.5em;
62 | line-height: 1.1em;
63 | }
64 | h2 {
65 | font-size: 1.75em;
66 | margin: 1em 0 .50em 0;
67 | }
68 | h3 {
69 | font-size: 1.4em;
70 | margin: 25px 0 10px 0;
71 | }
72 | h4 {
73 | margin: 0;
74 | font-size: 105%;
75 | }
76 | h1:target,
77 | h2:target,
78 | h3:target,
79 | h4:target,
80 | h5:target,
81 | h6:target {
82 | background: var(--highlight-color);
83 | padding: .2em 0;
84 | }
85 |
86 | a {
87 | color: #058;
88 | text-decoration: none;
89 | transition: color .3s ease-in-out;
90 | }
91 | a:hover {
92 | color: #e82;
93 | }
94 |
95 | .title code {
96 | font-weight: bold;
97 | }
98 | h2[id^="header-"] {
99 | margin-top: 2em;
100 | }
101 | .ident {
102 | color: #900;
103 | }
104 |
105 | pre code {
106 | background: #f8f8f8;
107 | font-size: .8em;
108 | line-height: 1.15em;
109 | }
110 | code {
111 | background: #f2f2f1;
112 | padding: 1px 4px;
113 | overflow-wrap: break-word;
114 | }
115 | h1 code { background: transparent }
116 |
117 | pre {
118 | background: #f8f8f8;
119 | border: 0;
120 | border-top: 1px solid #ccc;
121 | border-bottom: 1px solid #ccc;
122 | margin: 1em 0;
123 | padding: 1ex;
124 | }
125 |
126 | #http-server-module-list {
127 | display: flex;
128 | flex-flow: column;
129 | }
130 | #http-server-module-list div {
131 | display: flex;
132 | }
133 | #http-server-module-list dt {
134 | min-width: 10%;
135 | }
136 | #http-server-module-list p {
137 | margin-top: 0;
138 | }
139 |
140 | .toc ul,
141 | #index {
142 | list-style-type: none;
143 | margin: 0;
144 | padding: 0;
145 | }
146 | #index code {
147 | background: transparent;
148 | }
149 | #index h3 {
150 | border-bottom: 1px solid #ddd;
151 | }
152 | #index ul {
153 | padding: 0;
154 | }
155 | #index h4 {
156 | margin-top: .6em;
157 | font-weight: bold;
158 | }
159 | /* Make TOC lists have 2+ columns when viewport is wide enough.
160 | Assuming ~20-character identifiers and ~30% wide sidebar. */
161 | @media (min-width: 200ex) { #index .two-column { column-count: 2 } }
162 | @media (min-width: 300ex) { #index .two-column { column-count: 3 } }
163 |
164 | dl {
165 | margin-bottom: 2em;
166 | }
167 | dl dl:last-child {
168 | margin-bottom: 4em;
169 | }
170 | dd {
171 | margin: 0 0 1em 3em;
172 | }
173 | #header-classes + dl > dd {
174 | margin-bottom: 3em;
175 | }
176 | dd dd {
177 | margin-left: 2em;
178 | }
179 | dd p {
180 | margin: 10px 0;
181 | }
182 | .name {
183 | background: #eee;
184 | font-weight: bold;
185 | font-size: .85em;
186 | padding: 5px 10px;
187 | display: inline-block;
188 | min-width: 40%;
189 | }
190 | .name:hover {
191 | background: #e0e0e0;
192 | }
193 | dt:target .name {
194 | background: var(--highlight-color);
195 | }
196 | .name > span:first-child {
197 | white-space: nowrap;
198 | }
199 | .name.class > span:nth-child(2) {
200 | margin-left: .4em;
201 | }
202 | .inherited {
203 | color: #999;
204 | border-left: 5px solid #eee;
205 | padding-left: 1em;
206 | }
207 | .inheritance em {
208 | font-style: normal;
209 | font-weight: bold;
210 | }
211 |
212 | /* Docstrings titles, e.g. in numpydoc format */
213 | .desc h2 {
214 | font-weight: 400;
215 | font-size: 1.25em;
216 | }
217 | .desc h3 {
218 | font-size: 1em;
219 | }
220 | .desc dt code {
221 | background: inherit; /* Don't grey-back parameters */
222 | }
223 |
224 | .source summary,
225 | .git-link-div {
226 | color: #666;
227 | text-align: right;
228 | font-weight: 400;
229 | font-size: .8em;
230 | text-transform: uppercase;
231 | }
232 | .source summary > * {
233 | white-space: nowrap;
234 | cursor: pointer;
235 | }
236 | .git-link {
237 | color: inherit;
238 | margin-left: 1em;
239 | }
240 | .source pre {
241 | max-height: 500px;
242 | overflow: auto;
243 | margin: 0;
244 | }
245 | .source pre code {
246 | font-size: 12px;
247 | overflow: visible;
248 | }
249 | .hlist {
250 | list-style: none;
251 | }
252 | .hlist li {
253 | display: inline;
254 | }
255 | .hlist li:after {
256 | content: ',\2002';
257 | }
258 | .hlist li:last-child:after {
259 | content: none;
260 | }
261 | .hlist .hlist {
262 | display: inline;
263 | padding-left: 1em;
264 | }
265 |
266 | img {
267 | max-width: 100%;
268 | }
269 | td {
270 | padding: 0 .5em;
271 | }
272 |
273 | .admonition {
274 | padding: .1em .5em;
275 | margin-bottom: 1em;
276 | }
277 | .admonition-title {
278 | font-weight: bold;
279 | }
280 | .admonition.note,
281 | .admonition.info,
282 | .admonition.important {
283 | background: #aef;
284 | }
285 | .admonition.todo,
286 | .admonition.versionadded,
287 | .admonition.tip,
288 | .admonition.hint {
289 | background: #dfd;
290 | }
291 | .admonition.warning,
292 | .admonition.versionchanged,
293 | .admonition.deprecated {
294 | background: #fd4;
295 | }
296 | .admonition.error,
297 | .admonition.danger,
298 | .admonition.caution {
299 | background: lightpink;
300 | }
301 | %def>
302 |
303 | <%def name="desktop()" filter="minify_css">
304 | @media screen and (min-width: 700px) {
305 | #sidebar {
306 | width: 30%;
307 | height: 100vh;
308 | overflow: auto;
309 | position: sticky;
310 | top: 0;
311 | }
312 | #content {
313 | width: 70%;
314 | max-width: 100ch;
315 | padding: 3em 4em;
316 | border-left: 1px solid #ddd;
317 | }
318 | pre code {
319 | font-size: 1em;
320 | }
321 | .item .name {
322 | font-size: 1em;
323 | }
324 | main {
325 | display: flex;
326 | flex-direction: row-reverse;
327 | justify-content: flex-end;
328 | }
329 | .toc ul ul,
330 | #index ul {
331 | padding-left: 1.5em;
332 | }
333 | .toc > ul > li {
334 | margin-top: .5em;
335 | }
336 | }
337 | %def>
338 |
339 | <%def name="print()" filter="minify_css">
340 | @media print {
341 | #sidebar h1 {
342 | page-break-before: always;
343 | }
344 | .source {
345 | display: none;
346 | }
347 | }
348 | @media print {
349 | * {
350 | background: transparent !important;
351 | color: #000 !important; /* Black prints faster: h5bp.com/s */
352 | box-shadow: none !important;
353 | text-shadow: none !important;
354 | }
355 |
356 | a[href]:after {
357 | content: " (" attr(href) ")";
358 | font-size: 90%;
359 | }
360 | /* Internal, documentation links, recognized by having a title,
361 | don't need the URL explicity stated. */
362 | a[href][title]:after {
363 | content: none;
364 | }
365 |
366 | abbr[title]:after {
367 | content: " (" attr(title) ")";
368 | }
369 |
370 | /*
371 | * Don't show links for images, or javascript/internal links
372 | */
373 |
374 | .ir a:after,
375 | a[href^="javascript:"]:after,
376 | a[href^="#"]:after {
377 | content: "";
378 | }
379 |
380 | pre,
381 | blockquote {
382 | border: 1px solid #999;
383 | page-break-inside: avoid;
384 | }
385 |
386 | thead {
387 | display: table-header-group; /* h5bp.com/t */
388 | }
389 |
390 | tr,
391 | img {
392 | page-break-inside: avoid;
393 | }
394 |
395 | img {
396 | max-width: 100% !important;
397 | }
398 |
399 | @page {
400 | margin: 0.5cm;
401 | }
402 |
403 | p,
404 | h2,
405 | h3 {
406 | orphans: 3;
407 | widows: 3;
408 | }
409 |
410 | h1,
411 | h2,
412 | h3,
413 | h4,
414 | h5,
415 | h6 {
416 | page-break-after: avoid;
417 | }
418 | }
419 | %def>
420 |
--------------------------------------------------------------------------------
/seedir/realdir.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Note: this module fails doctesting
4 |
5 | """
6 | This module provides code for producing folder structure strings for directories.
7 | Currently, the only tool here is `seedir()`, the primary function of the
8 | package `seedir`. This returns or prints the folder structure for a given path.
9 | The main algorithm for determining the folder structure string is within the
10 | seedir.folderstructure.FolderStructure class.
11 | """
12 |
13 | import os
14 | import pathlib
15 |
16 | from seedir.folderstructure import PathlibStructure, RealDirStructure
17 |
18 | def _parse_path(path):
19 | '''Helper function added to parse the input to `seedir.realdir.seedir()`.
20 | Detects strings (paths) or pathlib objects.'''
21 |
22 | if isinstance(path, str):
23 | path = os.path.abspath(os.path.expanduser(path))
24 | elif isinstance(path, pathlib.Path):
25 | path = path.expanduser().resolve()
26 | else:
27 | raise TypeError(f"Can only parse str or pathlib.Path, not {type(path)}.")
28 |
29 | return path
30 |
31 | def seedir(path=None, style='lines', printout=True, indent=2, uniform=None,
32 | anystart=None, anyend=None, depthlimit=None, itemlimit=None,
33 | beyond=None, first=None, sort=False, sort_reverse=False,
34 | sort_key=None, include_folders=None, exclude_folders=None,
35 | include_files=None, exclude_files=None, regex=False, mask=None,
36 | formatter=None, sticky_formatter=False,
37 | acceptable_listdir_errors=PermissionError,
38 | denied_string=' [ACCESS DENIED]', **kwargs):
39 | '''
40 |
41 | Primary function of the seedir package: generate folder trees for
42 | computer directories.
43 |
44 | ## EXAMPLES
45 |
46 | ```
47 | >>> import seedir as sd
48 |
49 | ```
50 |
51 | Make a basic tree diagram:
52 |
53 | ```
54 | >>> c = 'path/to/doc'
55 | >>> sd.seedir(c)
56 | doc/
57 | ├─_static/
58 | │ ├─embedded/
59 | │ │ ├─deep_file
60 | │ │ └─very/
61 | │ │ └─deep/
62 | │ │ └─folder/
63 | │ │ └─very_deep_file
64 | │ └─less_deep_file
65 | ├─about.rst
66 | ├─conf.py
67 | └─index.rst
68 |
69 | ```
70 |
71 | Select different styles for the tree:
72 |
73 | ```
74 | >>> sd.seedir(c, style='dash')
75 | doc/
76 | |-_static/
77 | | |-embedded/
78 | | | |-deep_file
79 | | | |-very/
80 | | | |-deep/
81 | | | |-folder/
82 | | | |-very_deep_file
83 | | |-less_deep_file
84 | |-about.rst
85 | |-conf.py
86 | |-index.rst
87 |
88 | ```
89 |
90 | Sort the folder contents, separting folders and files:
91 |
92 | ```
93 | >>> sd.seedir(c, sort=True, first='files')
94 | doc/
95 | ├─about.rst
96 | ├─conf.py
97 | ├─index.rst
98 | └─_static/
99 | ├─less_deep_file
100 | └─embedded/
101 | ├─deep_file
102 | └─very/
103 | └─deep/
104 | └─folder/
105 | └─very_deep_file
106 |
107 | ```
108 |
109 | Limit the folder depth or items included:
110 |
111 | ```
112 | >>> sd.seedir(c, depthlimit=2, itemlimit=1)
113 | doc/
114 | ├─_static/
115 | │ ├─embedded/
116 | │ └─less_deep_file
117 | └─about.rst
118 |
119 | ```
120 |
121 | Include or exclude specific items (with or without regular expressions):
122 |
123 | ```
124 | >>> sd.seedir(c, exclude_folders='_static')
125 | doc/
126 | ├─about.rst
127 | ├─conf.py
128 | └─index.rst
129 |
130 | ```
131 |
132 | Parameters
133 | ----------
134 | path : str, pathlib.Path, or None, optional
135 | System path of a directory. If None, current working directory is
136 | used. The path can be either a string path or a pathlib object.
137 | In both cases, the path is converted to an absolute path, and the
138 | tilde (~) is expanded.
139 | style : 'lines', 'dash', 'arrow', 'spaces', 'plus', or 'emoji', optional
140 | Style to use. The default is `'lines'`. A style determines the set
141 | of characters ("tokens") used to represent the base structure of
142 | the directory (e.g. which items belong to which folders, when items
143 | are the last member of a folder, etc.). The actual tokens being used
144 | by each style can be viewed with `seedir.printing.get_styleargs()`.
145 | printout : bool, optional
146 | Print the folder structure in the console. The default is `True`. When
147 | `False`, the folder diagram is returned as a string.
148 | indent : int (>= 0), optional
149 | Number of spaces separating items from their parent folder.
150 | The default is `2`.
151 | uniform : str or None, optional
152 | Characters to use for all tokens when creating the tree diagram.
153 | The default is `None`. When not `None`, the extend, space, split, and
154 | final tokens are replaced with `uniform` (the `'spaces'` style is
155 | essentially `uniform = ' '`).
156 | anystart : str or None, optional
157 | Characters to prepend before any item (i.e. folder or file). The
158 | default is `None`. Specific starts for folders and files can be
159 | specified (see `**kwargs`).
160 | anyend : str or None, optional
161 | Characters to append after any item (i.e. folder or file). The
162 | default is `None`. Specific ends for folders and files can be
163 | specified (see `**kwargs`).
164 | depthlimit : int or None, optional
165 | Limit the depth of folders to traverse. Folders at the `depthlimit` are
166 | included, but their contents are not shown (with the exception of the
167 | beyond parameter being specified). The default is `None`, which can
168 | cause exceptionally long runtimes for deep or extensive directories.
169 | itemlimit : int or None, optional
170 | Limit the number of items in a directory to show. Items beyond the
171 | `itemlimit` can be expressed using the `beyond` parameter. The files and
172 | folders left out are determined by the sorting parameters
173 | (`sort`, `sort_reverse`, `sort_key`). The default is `None`.
174 | beyond : str ('ellipsis', 'content' or a string starting with an underscore) or None, optional
175 | String to indicate directory contents beyond the `itemlimit` or the
176 | `depthlimit`. The default is `None`. Options are: `'ellipsis'` (`'...'`),
177 | `'content'` or `'contents'` (the number of files and folders beyond), or
178 | a string starting with `'_'` (everything after the leading underscore
179 | will be returned)
180 | first : 'files', 'folders', or None, optional
181 | Sort the directory so that either files or folders appear first.
182 | The default is `None`.
183 | sort : bool, optional
184 | Sort the directory. With no other specifications, the sort will be a
185 | simple alphabetical sort of the item names, but this can be altered
186 | with the `first`, `sort_reverse`, and `sort_key parameters`.
187 | The default is `False`.
188 | sort_reverse : bool, optional
189 | Reverse the sorting determined by `sort` or `sort_key`.
190 | The default is `False`.
191 | sort_key : function, optional
192 | Key to use for sorting file or folder names, akin to the `key` parameter
193 | of the builtin `sorted()` or `list.sort()`. The function should take a
194 | string as an argument. The default is `None`.
195 | include_folders, exclude_folders, include_files, exclude_files : str, list-like, or None, optional
196 | Folder / file names to include or exclude. The default is `None`. By
197 | default, these are interpreted literally. Pass `regex=True` for
198 | using regular expressions.
199 | regex : bool, optional
200 | Interpret the strings of include/exclude file/folder arguments as
201 | regular expressions. The default is `False`.
202 | mask : function, optional
203 | Function for filtering items. Absolute paths of each individual item
204 | are passed to the `mask` function. If `True` is returned, the
205 | item is kept. The default is `None`. The type of the object
206 | passed to `mask` corresponds with that passed as input:
207 | `str` or `pathlib.Path`.
208 | formatter : function, optional
209 | Function for customizing the directory printing logic and style
210 | based on specific folders & files. When passed, the formatter
211 | is called on each item in the file tree, and the current arguments
212 | are updated based what is returned.
213 |
214 | The formatter function should accept a system path as a
215 | single argument (either relative or absolute, depending on what is passed
216 | to the `path` argument), and it should return either a dictionary or None.
217 | The dictionary should have names of arguments as keys and their respective
218 | setting as values.
219 |
220 | The following options can meaningfully be toggled by passing a formatter
221 | function: `depthlimit`, `itemlimit`, `beyond`, `first`, `sort`, `sort_reverse`,
222 | `sort_key`, `include_folders`, `regex`, `mask`, as well as any seedir token
223 | keywords (`extend`, `space`, `split`, `final`, `folderstart`, `filestart`,
224 | `folderend`, `fileend`).
225 |
226 | Note that in version 0.3.0, formatter could only be used to update
227 | the style tokens. It can now be used to udpate those as well as the other
228 | arguments listed above.
229 |
230 | If None is returned by formatter, the tokens will be set by `style`.
231 |
232 | Note that items exlcuded by the inclusion/exclusion arguments (or the
233 | `mask`) *will not* be seen by formatter. Similarly, any folder tree
234 | entries created by the `beyond` argument *will not* be seen by formatter.
235 |
236 | The type of the object passed to `formatter` corresponds with that
237 | passed as input: `str` or `pathlib.Path`.
238 |
239 | sticky_formatter : bool, optional
240 | When True, updates to argumnts made by the `formatter` (see above)
241 | will be permanent. Thus, if arguments are updated when the `formatter`
242 | is called on a folder, its children will (recursively) inherit
243 | those new arguments.
244 | acceptable_listdir_errors : Exception, tuple, or None
245 |
246 | **New in v0.5.0**
247 |
248 | Set errors which, when raised when listing the contents of a folder,
249 | do not halt traversal. This parameter was added to allow
250 | folders to be skipped when a `PermissionError` is raised. For folders
251 | which raise an acceptable error, an additional string is added to their
252 | entry in the diagram (see `denied_string`).
253 |
254 | Providing one Exception causes only that type of Exception to be ignored.
255 | Multiple Exception types can be handled by passing mutple Exceptions
256 | as a tuple. Pass `None` to not allow any Exceptions (in this case,
257 | an error is raised).
258 |
259 | Exception types which are not provided will still be raised.
260 |
261 | The default is `PermissionError`, which will skip folders
262 | for which the caller does not have permissions to access.
263 |
264 | denied_string : str
265 |
266 | String tag to signify that a folder was not able to be traversed
267 | due to one of the `acceptable_listdir_errors` being raised. This
268 | is a string added after the folder name (and `folderend`) strings.
269 | The default is `" [ACCESS DENIED]"`.
270 |
271 | **kwargs : str
272 | Specific tokens to use for creating the file tree diagram. The tokens
273 | use by each builtin style can be seen with `seedir.printing.get_styleargs()`.
274 | Valid options are `extend` (characters to show the extension of a directory
275 | while its children are traversed), `space` (character to provide the
276 | correct indentation of an item when some of its parent / grandparent
277 | directories are completely traversed), `split` (characters to show a
278 | folder or file within a directory, with more items following),
279 | `final` (characters to show a folder or file within a directory,
280 | with no more items following), `folderstart` (characters to prepend
281 | before any folder), `filestart` (characters to preppend before any
282 | file), `folderend` (characters to append after any folder), and
283 | `fileend` (characters to append after any file). The following shows
284 | the default tokens for the `'lines'` style:
285 |
286 | >>> import seedir as sd
287 | >>> sd.get_styleargs('lines')
288 | {'split': '├─', 'extend': '│ ', 'space': ' ', 'final': '└─', 'folderstart': '', 'filestart': '', 'folderend': '/', 'fileend': ''}
289 |
290 | All default style tokens are 2 character strings, except for
291 | the file/folder start/end tokens. Style tokens from `**kwargs` are not
292 | affected by the indent parameter. The `uniform`, `anystart`, and
293 | `anyend` parameters can be used to affect multiple style tokens.
294 |
295 | Notes
296 | -------
297 |
298 | The parameter `slash` was deprecated in 0.5.0. Pass `folderend` as
299 | an additional keyword argument instead.
300 |
301 | Returns
302 | -------
303 | s (str) or None
304 | The tree diagram (as a string) or `None` if `prinout = True`, in which
305 | case the tree diagram is printed in the console.
306 |
307 | '''
308 |
309 | if path is None:
310 | path = os.getcwd()
311 |
312 | path = _parse_path(path)
313 |
314 | # call
315 | args = dict(style=style,
316 | printout=printout,
317 | indent=indent,
318 | uniform=uniform,
319 | anystart=anystart,
320 | anyend=anyend,
321 | depthlimit=depthlimit,
322 | itemlimit=itemlimit,
323 | beyond=beyond,
324 | first=first,
325 | sort=sort,
326 | sort_reverse=sort_reverse,
327 | sort_key=sort_key,
328 | include_folders=include_folders,
329 | exclude_folders=exclude_folders,
330 | include_files=include_files,
331 | exclude_files=exclude_files,
332 | regex=regex,
333 | mask=mask,
334 | formatter=formatter,
335 | sticky_formatter=sticky_formatter,
336 | acceptable_listdir_errors=acceptable_listdir_errors,
337 | denied_string=denied_string,
338 | **kwargs)
339 |
340 | structure = PathlibStructure() if isinstance(path, pathlib.Path) else RealDirStructure()
341 |
342 | return structure(path, **args)
343 |
--------------------------------------------------------------------------------
/docs/seedir/printing.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | seedir.printing API documentation
8 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
Module seedir.printing
24 |
25 |
26 |
General module of resources and helpers for printing and making folder trees
27 | in seedir.
28 |
29 |
30 | Expand source code
31 |
32 |
# -*- coding: utf-8 -*-
33 | """
34 | General module of resources and helpers for printing and making folder trees
35 | in seedir.
36 |
37 | """
38 |
39 | __pdoc__ = {'is_match': False,
40 | 'format_indent': False,
41 | 'words': False}
42 |
43 |
44 |
45 | import copy
46 | import os
47 | import re
48 |
49 |
50 | STYLE_DICT = {
51 | 'lines': {'split':'├─',
52 | 'extend':'│ ',
53 | 'space':' ',
54 | 'final':'└─',
55 | 'folderstart':'',
56 | 'filestart':'',
57 | 'folderend': '/',
58 | 'fileend': ''},
59 | 'dash': {'split':'|-',
60 | 'extend':'| ',
61 | 'space':' ',
62 | 'final':'|-',
63 | 'folderstart':'',
64 | 'filestart':'',
65 | 'folderend': '/',
66 | 'fileend': ''},
67 | 'spaces':{'split':' ',
68 | 'extend':' ',
69 | 'space':' ',
70 | 'final':' ',
71 | 'folderstart':'',
72 | 'filestart':'',
73 | 'folderend': '/',
74 | 'fileend': ''},
75 | 'plus': {'split':'+-',
76 | 'extend':'| ',
77 | 'space':' ',
78 | 'final':'+-',
79 | 'folderstart':'',
80 | 'filestart':'',
81 | 'folderend': '/',
82 | 'fileend': ''},
83 | 'arrow': {'split':' ',
84 | 'extend':' ',
85 | 'space':' ',
86 | 'final':' ',
87 | 'folderstart':'>',
88 | 'filestart':'>',
89 | 'folderend': '/',
90 | 'fileend': ''}
91 | }
92 | '''"Tokens" used to create folder trees in different styles'''
93 |
94 | try:
95 | import emoji
96 | STYLE_DICT["emoji"] = {
97 | 'split':'├─',
98 | 'extend':'│ ',
99 | 'space':' ',
100 | 'final':'└─',
101 | 'folderstart':emoji.emojize(':file_folder:' + ' '),
102 | 'filestart':emoji.emojize(':page_facing_up:' + ' '),
103 | 'folderend': '/',
104 | 'fileend': ''
105 | }
106 | except ImportError:
107 | pass
108 |
109 |
110 | filepath = os.path.dirname(os.path.abspath(__file__))
111 | wordpath = os.path.join(filepath, 'words.txt')
112 | with open(wordpath, 'r') as wordfile:
113 | words = [line.strip() for line in wordfile.readlines()]
114 | """List of dictionary words for seedir.fakedir.randomdir()"""
115 |
116 | # functions
117 |
118 | def is_match(pattern, string, regex=True):
119 | '''Function for matching strings using either regular expression
120 | or literal interpretation.'''
121 | if regex:
122 | return bool(re.search(pattern, string))
123 | else:
124 | return pattern == string
125 |
126 | def get_styleargs(style):
127 | '''
128 | Return the string tokens associated with different styles for printing
129 | folder trees with `seedir.realdir.seedir()`.
130 |
131 | Parameters
132 | ----------
133 | style : str
134 | Style name. Current options are `'lines'`, `'spaces'`, `'arrow'`,
135 | `'plus'`, `'dash'`, or `'emoji'`.
136 |
137 | Raises
138 | ------
139 | ValueError
140 | Style not recognized.
141 |
142 | ImportError
143 | 'emoji' style requested but emoji package not installed.
144 |
145 | Returns
146 | -------
147 | dict
148 | Dictionary of tokens for the given style.
149 |
150 | '''
151 | if style not in STYLE_DICT and style == 'emoji':
152 | error_text = 'style "emoji" requires "emoji" to be installed'
153 | error_text += ' (pip install emoji) '
154 | raise ImportError(error_text)
155 | elif style not in STYLE_DICT:
156 | error_text = 'style "{}" not recognized, must be '.format(style)
157 | error_text += 'lines, spaces, arrow, plus, dash, or emoji'
158 | raise ValueError(error_text)
159 | else:
160 | return copy.deepcopy(STYLE_DICT[style])
161 |
162 | def format_indent(style_dict, indent=2):
163 | '''
164 | Format the indent of style tokens, from seedir.STYLE_DICT or returned
165 | by seedir.get_styleargs().
166 |
167 | Note that as of v0.3.1, the dictionary is modified in place,
168 | rather than a new copy being created.
169 |
170 | Parameters
171 | ----------
172 | style_dict : dict
173 | Dictionary of style tokens.
174 | indent : int, optional
175 | Number of spaces to indent. The default is 2. With 0, all tokens
176 | become the null string. With 1, all tokens are only the first
177 | character. With 2, the style tokens are returned unedited. When >2,
178 | the final character of each token (excep the file/folder start/end tokens)
179 | are extened n - indent times, to give a string whose
180 | length is equal to indent.
181 |
182 | Returns
183 | -------
184 | output : dict
185 | New dictionary of edited tokens.
186 |
187 | '''
188 | indentable = ['split', 'extend', 'space', 'final']
189 | if indent < 0 or not isinstance(indent, int):
190 | raise ValueError('indent must be a non-negative integer')
191 | elif indent == 0:
192 | for key in indentable:
193 | style_dict[key] = ''
194 | elif indent == 1:
195 | for key in indentable:
196 | style_dict[key] = style_dict[key][0]
197 | elif indent > 2:
198 | extension = indent - 2
199 | for key in indentable:
200 | val = style_dict[key]
201 | style_dict[key] = val + val[-1] * extension
202 |
203 | return None
204 |
205 |
206 |
207 |
208 |
209 |
Global variables
210 |
211 |
var STYLE_DICT
212 |
213 |
"Tokens" used to create folder trees in different styles
214 |
215 |
216 |
217 |
218 |
Functions
219 |
220 |
221 | def get_styleargs(style)
222 |
223 |
224 |
Return the string tokens associated with different styles for printing
225 | folder trees with seedir().
226 |
Parameters
227 |
228 |
style : str
229 |
Style name.
230 | Current options are 'lines', 'spaces', 'arrow',
231 | 'plus', 'dash', or 'emoji'.
232 |
233 |
Raises
234 |
235 |
ValueError
236 |
Style not recognized.
237 |
ImportError
238 |
'emoji' style requested but emoji package not installed.
239 |
240 |
Returns
241 |
242 |
dict
243 |
Dictionary of tokens for the given style.
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
274 |
275 |
278 |
279 |
280 |
--------------------------------------------------------------------------------
/docs/templates/html.mako:
--------------------------------------------------------------------------------
1 | <%
2 | import os
3 |
4 | import pdoc
5 | from pdoc.html_helpers import extract_toc, glimpse, to_html as _to_html, format_git_link
6 |
7 |
8 | def link(dobj: pdoc.Doc, name=None):
9 | name = name or dobj.qualname + ('()' if isinstance(dobj, pdoc.Function) else '')
10 | if isinstance(dobj, pdoc.External) and not external_links:
11 | return name
12 | url = dobj.url(relative_to=module, link_prefix=link_prefix,
13 | top_ancestor=not show_inherited_members)
14 | return f'{name}'
15 |
16 |
17 | def to_html(text):
18 | return _to_html(text, docformat=docformat, module=module, link=link, latex_math=latex_math)
19 |
20 |
21 | def get_annotation(bound_method, sep=':'):
22 | annot = show_type_annotations and bound_method(link=link) or ''
23 | if annot:
24 | annot = ' ' + sep + '\N{NBSP}' + annot
25 | return annot
26 | %>
27 |
28 | <%def name="ident(name)">${name}%def>
29 |
30 | <%def name="show_source(d)">
31 | % if (show_source_code or git_link_template) and d.source and d.obj is not getattr(d.inherits, 'obj', None):
32 | <% git_link = format_git_link(git_link_template, d) %>
33 | % if show_source_code:
34 |
35 |
36 | Expand source code
37 | % if git_link:
38 | Browse git
39 | %endif
40 |
41 |