Skip to content

Commit

Permalink
played around
Browse files Browse the repository at this point in the history
  • Loading branch information
Daniel-Kudies committed Oct 29, 2024
1 parent df3b56e commit c82e63d
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 32 deletions.
16 changes: 14 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

```plaintext
FileOrganizer/
├── .github
│ ├── configs
│ │ └── .pylintrc # Contains the settings for the linting
│ ├── workflows
│ │ └── pylint.yml # Contains the workflow logic for the linting
├── config
│ ├── config.json # Main configuration file
│ └── file_extensions.json # Defines extensions for different file types
Expand All @@ -23,6 +28,7 @@ FileOrganizer/
│ ├── json_loader.py # Loads configurations from JSON files
│ └── main.py # Entry point to run the file organizer
├──tests
│ └── test_json_loader.py # Tests for the json_loader.py
├── requirements.txt
```

Expand All @@ -41,8 +47,14 @@ In config/config.json, specify the directories and sorting options:
In config/file_extensions.json, define file types and extensions:
```json
{
"Images": [".jpg", ".png", ".gif", ".bmp"],
"Text": [".txt", ".doc", ".pdf", ".rtf"]
"Audio": [
".aif",
".cda"
],
"Text": [
".txt",
".doc"
]
}
```

Expand Down
13 changes: 10 additions & 3 deletions config/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,17 @@
"by_extension": true
}
},
"documents": {
"path": "~/Documents",
"images": {
"path": "~/OneDrive/Bilder",
"sorting": {
"by_date": false,
"by_date": true,
"by_extension": true
}
},
"videos": {
"path": "~/Videos",
"sorting": {
"by_date": true,
"by_extension": true
}
}
Expand Down
70 changes: 59 additions & 11 deletions config/file_extensions.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,61 @@
{
"Audio": [".aif", ".cda", ".mid", ".mp3", ".ogg", ".wav", ".wma"],
"Text": [".txt", ".doc", ".pdf", ".rtf"],
"Video": [".mp4", ".avi", ".mkv", ".mov"],
"Images": [".jpg", ".png", ".gif", ".bmp"],
"Compressed": [".zip", ".rar", ".tar.gz"],
"Disc": [".iso", ".dmg"],
"Data": [".csv", ".xml", ".json"],
"Executables": [".exe", ".bat", ".jar"],
"Fonts": [".ttf", ".otf"],
"Presentations": [".ppt", ".pptx"],
"Other": [".bak", ".tmp", ".cfg"]
"Audio": [
".aif",
".cda",
".mid",
".mp3",
".ogg",
".wav",
".wma"
],
"Text": [
".txt",
".doc",
".pdf",
".rtf"
],
"Video": [
".mp4",
".avi",
".mkv",
".mov"
],
"Images": [
".jpg",
".png",
".gif",
".bmp"
],
"Compressed": [
".zip",
".rar",
".tar.gz"
],
"Disc": [
".iso",
".dmg"
],
"Data": [
".csv",
".xml",
".json"
],
"Executables": [
".exe",
".bat",
".jar"
],
"Fonts": [
".ttf",
".otf"
],
"Presentations": [
".ppt",
".pptx"
],
"Other": [
".bak",
".tmp",
".cfg"
]
}
21 changes: 12 additions & 9 deletions file_organizer/file_sorter.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ class FileSorter:
configuration. It utilizes a JsonLoader instance to load necessary
configuration and file extension mappings.
"""
def __init__ (self):
json_loader = JsonLoader()
def __init__ (self, config, extensions):
json_loader = JsonLoader(config_file=config, extensions_file_config=extensions)
json_loader.load_config()
json_loader.load_file_extensions()
self.config = json_loader.get_config()
Expand All @@ -40,15 +40,18 @@ def sort_files(self):
"""
try:
for directory, details in self.config.get("directories", {}).items():
logging.info("Processing directory: %s", {directory})
logging.info("Processing directory: %s", directory)

path = os.path.expanduser(details.get("path", ""))
logging.info("Path %s", path)
sortingoptions = details.get("sorting", {})
bydate = sortingoptions.get("by_date")
byextensions = sortingoptions.get("by_extension")

if sortingoptions.get("by_date"):
if bydate:
self.sort_file_date(path)
if sortingoptions.get("by_extension"):
self.sort_file_extensions(path, sortingoptions.get("by_date"))
if byextensions:
self.sort_file_extensions(path, bydate)

except FileNotFoundError as e:
logging.error("File sorting error: %s", e)
Expand All @@ -74,11 +77,11 @@ def sort_file_extensions(self, path, bydate):
Exception: For any other unexpected errors.
"""
try:
logging.debug("Sorting by File Extensions in Directory: %s", path)
logging.info("Sorting by File Extensions in Directory: %s", path)

self.create_extensions_folders(path)
if bydate:
logging.info("Sorting by extensions within date folders.")
logging.debug("Sorting by extensions within date folders.")

for year_folder in os.scandir(path):
if year_folder.is_dir():
Expand Down Expand Up @@ -127,7 +130,7 @@ def sort_file_date(self, path):
Exception: For any other unexpected errors.
"""
try:
logging.debug("Sorting by File Date in Directory: %s", path)
logging.info("Sorting by File Date in Directory: %s", path)

self.create_date_folder(path)

Expand Down
10 changes: 5 additions & 5 deletions file_organizer/json_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ class JsonLoader:
to read and parse the JSON data, handling errors related to
file access and JSON decoding.
"""
def __init__(self, config_file="config/config.json", file_extensions_config="config/file_extensions.json"):
def __init__(self, config_file, extensions_file_config):
self.config_file = config_file
self.file_extensions_config = file_extensions_config
self.extensions_file_config = extensions_file_config
self.config = {}
self.file_extensions = {}

Expand Down Expand Up @@ -47,10 +47,10 @@ def load_json(self, file_path):

except FileNotFoundError:
logging.error("Configuration file %s not found.", file_path)
raise
except json.JSONDecodeError:
logging.error("Error decoding JSON from %s.", file_path)
except Exception as e:
logging.error("An unexpected error occurred: %s", e)
raise
return None

def load_config(self):
Expand All @@ -68,7 +68,7 @@ def load_file_extensions(self):
extensions configuration file and store the data in the
file_extensions attribute.
"""
self.file_extensions = self.load_json(self.file_extensions_config)
self.file_extensions = self.load_json(self.extensions_file_config)

def get_config(self):
"""Retrieves the loaded configuration data.
Expand Down
11 changes: 9 additions & 2 deletions file_organizer/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
This module serves as the entry point for the FileOrganizer application.
It initializes the necessary components and triggers the file sorting process.
"""
import logging
import json
import logging
from file_sorter import FileSorter

def config_logging():
Expand All @@ -24,8 +24,15 @@ def main():
"""
try:
config_logging()

logging.info("Setting the file path to the jsons")
config_file_path = "config/config.json"
extensions_file_config_path = 'config/file_extensions.json'
logging.info("Directorys: %s", config_file_path)
logging.info("Extensions: %s", extensions_file_config_path)

logging.info("Start the FileOrganizer...")
FileSorter().sort_files()
FileSorter(config_file_path, extensions_file_config_path).sort_files()
logging.info("Completed the file sorting.")

except FileNotFoundError as e:
Expand Down
35 changes: 35 additions & 0 deletions tests/test_json_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""
Test Class for JsonLoader module for loading config.json and file_extension.json files.
This module contains the tests for the JsonLoader class, which provides methods to
load json files in specified locations.
"""
import json
import logging
import unittest
from unittest.mock import patch, mock_open
from file_organizer.json_loader import JsonLoader

class TestJsonLoader(unittest.TestCase):

def setUp(self):
self.loader = JsonLoader(config_file="", extensions_file_config="")

@patch("builtins.open", new_callable=mock_open, read_data='{"name": "vera"}')
def test_load_json_success(self, mock_file):
data = self.loader.load_json("valid_config.json")
self.assertIsNotNone(data)
self.assertEqual(data["name"], "vera")
mock_file.assert_called_once_with("valid_config.json", "r", encoding="utf-8")

def test_load_json_file_not_found(self):
with self.assertRaises(FileNotFoundError):
self.loader.load_json("not_found.json")

@patch("builtins.open", new_callable=mock_open, read_data='{"invalid":}')
def test_load_json_invalid(self, mock_open):
with self.assertRaises(json.JSONDecodeError):
self.loader.load_json("invalid.json")

if __name__ == '__main__':
unittest.main()

0 comments on commit c82e63d

Please sign in to comment.