# thule [t-OOL-ee]
A dumb, yet useful, file walker.
![Cat](./thule.png?raw=true "thule")
## Usage
1. Import `from thule import Actions, Walker`
2. Subclass Actions for your use case (e.g. `class JSONtoYAML(Actions):`)
3. Define in your class any or all of the following:
- one or more functions suffixed with `_directory`, will run on any directory (or subdirectory) under the path passed to the walker's accept method
- one or more functions suffixed with `_file`, will run on every file contained in any directory (or any subdirectory) under the path passed to the walker's accept method
- one or more functions suffixed with `_final`, will run after all directories, subdirectories, and files have been visited under the path passed to the walker's accept method
4. Instantiate the subclassed Actions (e.g. `converter = JSONtoYAML()`)
5. Instantiate a Walker (e.g. `walker = Walker()`)
6. Call accept on the walker (e.g. `walker.accept(<path>, converter)`)
## Example
### JSON to YAML Converter
Starting data
```shell
├── dir1
│ ├── file2.json
│ ├── sub1
│ │ ├── file3.json
│ │ └── file4.json
│ └── sub2
│ └── file5.json
├── dir2
│ └── sub3
│ └── file6.json
├── dir3
│ ├── sub4
│ │ └── file7.json
│ └── sub5
│ ├── file8.json
│ └── file9.json
└── file1.json
```
Thule Script to convert JSON to YAML
```python
"""
json_to_yaml.py
converts all json files
in nested directories to yaml files
removes old json files
"""
import os
import sys
import json
import yaml
from thule import Actions, Walker
class JSONtoYAML(Actions):
def __init__(self):
self.num_processed = 0
def print_directory(self, dir_path):
print(f"processing files in {dir_path}")
def convert_file(self, dir_path, file_name):
if file_name.endswith(".json"):
try:
print(f" converting {file_name}....", end="", flush=True)
file_path = os.path.join(dir_path, file_name)
with open(file_path, 'r') as jf:
data = json.load(jf)
with open(file_path.replace(".json", ".yaml"), 'w') as yf:
yaml.dump(data, yf)
os.remove(file_path)
self.num_processed += 1
except Exception:
print("[failed]")
else:
print("[done]")
def total_converted_final(self):
print(f"{self.num_processed} files in total were converted from JSON to YAML")
if __name__ == "__main__":
cwd = os.getcwd()
if len(sys.argv) > 2:
print("usage: python example.py <relative path to root dir>")
exit(1)
rel_path = sys.argv[1]
abs_path = os.path.join(cwd, rel_path)
converter = JSONtoYAML()
walker = Walker()
walker.accept(abs_path, converter)
```
Run the script as follows: `python json_to_yaml.py relative/path/test_json`
Script Output
```
processing files in cwd/relative/path/test_json
converting file1.json....[done]
processing files in cwd/relative/path/test_json/dir2
processing files in cwd/relative/path/test_json/dir2/sub3
converting file6.json....[done]
processing files in cwd/relative/path/test_json/dir3
processing files in cwd/relative/path/test_json/dir3/sub5
converting file9.json....[done]
converting file8.json....[done]
processing files in cwd/relative/path/test_json/dir3/sub4
converting file7.json....[done]
processing files in cwd/relative/path/test_json/dir1
converting file2.json....[done]
processing files in cwd/relative/path/test_json/dir1/sub1
converting file4.json....[done]
converting file3.json....[done]
processing files in cwd/relative/path/test_json/dir1/sub2
converting file5.json....[done]
9 files in total were converted from JSON to YAML
```
Resulting Data
```shell
├── dir1
│ ├── file2.yaml
│ ├── sub1
│ │ ├── file3.yaml
│ │ └── file4.yaml
│ └── sub2
│ └── file5.yaml
├── dir2
│ └── sub3
│ └── file6.yaml
├── dir3
│ ├── sub4
│ │ └── file7.yaml
│ └── sub5
│ ├── file8.yaml
│ └── file9.yaml
└── file1.yaml
```
Raw data
{
"_id": null,
"home_page": "https://github.com/cjengdahl/thule",
"name": "thule",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "file walker",
"author": "Cory Engdahl",
"author_email": "cjengdahl@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/de/c8/11e3d7b1125789cb6e9b66509f4deacde4ef54852375d59e255dabef822c/thule-1.0.tar.gz",
"platform": null,
"description": "# thule [t-OOL-ee]\n\nA dumb, yet useful, file walker.\n\n\n![Cat](./thule.png?raw=true \"thule\")\n\n## Usage\n\n1. Import `from thule import Actions, Walker`\n2. Subclass Actions for your use case (e.g. `class JSONtoYAML(Actions):`)\n3. Define in your class any or all of the following:\n - one or more functions suffixed with `_directory`, will run on any directory (or subdirectory) under the path passed to the walker's accept method\n - one or more functions suffixed with `_file`, will run on every file contained in any directory (or any subdirectory) under the path passed to the walker's accept method\n - one or more functions suffixed with `_final`, will run after all directories, subdirectories, and files have been visited under the path passed to the walker's accept method\n4. Instantiate the subclassed Actions (e.g. `converter = JSONtoYAML()`)\n5. Instantiate a Walker (e.g. `walker = Walker()`)\n6. Call accept on the walker (e.g. `walker.accept(<path>, converter)`)\n\n## Example\n### JSON to YAML Converter\n\nStarting data\n\n```shell\n\u251c\u2500\u2500 dir1\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 file2.json\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 sub1\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 file3.json\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 file4.json\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub2\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file5.json\n\u251c\u2500\u2500 dir2\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub3\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file6.json\n\u251c\u2500\u2500 dir3\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 sub4\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 file7.json\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub5\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 file8.json\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file9.json\n\u2514\u2500\u2500 file1.json\n```\n\nThule Script to convert JSON to YAML\n\n```python\n\"\"\"\njson_to_yaml.py\nconverts all json files\nin nested directories to yaml files\nremoves old json files\n\"\"\"\nimport os\nimport sys\nimport json\nimport yaml\nfrom thule import Actions, Walker\n\nclass JSONtoYAML(Actions):\n\n def __init__(self):\n self.num_processed = 0\n\n def print_directory(self, dir_path):\n print(f\"processing files in {dir_path}\")\n\n def convert_file(self, dir_path, file_name):\n if file_name.endswith(\".json\"):\n try:\n print(f\" converting {file_name}....\", end=\"\", flush=True)\n file_path = os.path.join(dir_path, file_name)\n with open(file_path, 'r') as jf:\n data = json.load(jf)\n with open(file_path.replace(\".json\", \".yaml\"), 'w') as yf:\n yaml.dump(data, yf)\n os.remove(file_path)\n self.num_processed += 1\n except Exception:\n print(\"[failed]\")\n else:\n print(\"[done]\")\n\n def total_converted_final(self):\n print(f\"{self.num_processed} files in total were converted from JSON to YAML\")\n\n\nif __name__ == \"__main__\":\n\n cwd = os.getcwd()\n if len(sys.argv) > 2:\n print(\"usage: python example.py <relative path to root dir>\")\n exit(1)\n\n rel_path = sys.argv[1]\n abs_path = os.path.join(cwd, rel_path)\n\n converter = JSONtoYAML()\n walker = Walker()\n walker.accept(abs_path, converter)\n```\n\nRun the script as follows: `python json_to_yaml.py relative/path/test_json`\n\nScript Output\n\n```\nprocessing files in cwd/relative/path/test_json\n converting file1.json....[done]\nprocessing files in cwd/relative/path/test_json/dir2\nprocessing files in cwd/relative/path/test_json/dir2/sub3\n converting file6.json....[done]\nprocessing files in cwd/relative/path/test_json/dir3\nprocessing files in cwd/relative/path/test_json/dir3/sub5\n converting file9.json....[done]\n converting file8.json....[done]\nprocessing files in cwd/relative/path/test_json/dir3/sub4\n converting file7.json....[done]\nprocessing files in cwd/relative/path/test_json/dir1\n converting file2.json....[done]\nprocessing files in cwd/relative/path/test_json/dir1/sub1\n converting file4.json....[done]\n converting file3.json....[done]\nprocessing files in cwd/relative/path/test_json/dir1/sub2\n converting file5.json....[done]\n9 files in total were converted from JSON to YAML\n```\n\nResulting Data\n\n```shell\n\u251c\u2500\u2500 dir1\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 file2.yaml\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 sub1\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u251c\u2500\u2500 file3.yaml\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 file4.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub2\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file5.yaml\n\u251c\u2500\u2500 dir2\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub3\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file6.yaml\n\u251c\u2500\u2500 dir3\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 sub4\n\u2502\u00a0\u00a0 \u2502\u00a0\u00a0 \u2514\u2500\u2500 file7.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 sub5\n\u2502\u00a0\u00a0 \u251c\u2500\u2500 file8.yaml\n\u2502\u00a0\u00a0 \u2514\u2500\u2500 file9.yaml\n\u2514\u2500\u2500 file1.yaml\n```\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Module to facilitate actions on a file tree.",
"version": "1.0",
"split_keywords": [
"file",
"walker"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "96116aa9a6adb3ccaf0182b97e0d66db5ffa3bcdf16acb7b3d044a6b7f1b1d18",
"md5": "ef3a4e37820bef204b843eb79c654dfd",
"sha256": "413f4f2c8d74c4b07c1199fdf721498e835001904a7e6a0a97285bca0839e342"
},
"downloads": -1,
"filename": "thule-1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "ef3a4e37820bef204b843eb79c654dfd",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 3644,
"upload_time": "2023-04-17T02:45:40",
"upload_time_iso_8601": "2023-04-17T02:45:40.528663Z",
"url": "https://files.pythonhosted.org/packages/96/11/6aa9a6adb3ccaf0182b97e0d66db5ffa3bcdf16acb7b3d044a6b7f1b1d18/thule-1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "dec811e3d7b1125789cb6e9b66509f4deacde4ef54852375d59e255dabef822c",
"md5": "4e5af417ccd423c9b14a59554c85e20a",
"sha256": "9779748a9129b9cb51b3bc81b709d6d71fb5815ac98be79d1584dc1c328ee39f"
},
"downloads": -1,
"filename": "thule-1.0.tar.gz",
"has_sig": false,
"md5_digest": "4e5af417ccd423c9b14a59554c85e20a",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 3447,
"upload_time": "2023-04-17T02:45:43",
"upload_time_iso_8601": "2023-04-17T02:45:43.676141Z",
"url": "https://files.pythonhosted.org/packages/de/c8/11e3d7b1125789cb6e9b66509f4deacde4ef54852375d59e255dabef822c/thule-1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-04-17 02:45:43",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "cjengdahl",
"github_project": "thule",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "thule"
}