Compare commits

61 Commits

Author SHA1 Message Date
5d4788475e bumped version 2025-10-16 20:00:53 +02:00
de6f0ac17e update README.md 2025-10-16 19:53:49 +02:00
f148beedf5 removed old version file 2025-10-16 19:52:40 +02:00
82e6856439 changed the way on how to get the version to a json file, added helper to libreftit 2025-10-16 19:51:16 +02:00
6cbb352efb added prettifyed version output 2025-10-16 18:16:15 +02:00
ecd460d3ad removed comments 2025-10-16 18:15:33 +02:00
1c47c68c11 i guess it works 2025-10-14 21:31:05 +02:00
d5dcd35696 ups, i made a version bumper 2025-10-13 23:08:34 +02:00
9e954d0790 version bump 2025-10-13 23:07:46 +02:00
171370ecac update README.md 2025-10-12 19:54:53 +02:00
fb78fe459f update README.md 2025-10-12 19:47:16 +02:00
16aba4c60f added doc strings to librefit and cleaned refit.py 2025-10-12 19:45:07 +02:00
2ad1d32fcc update README.md 2025-10-12 19:44:17 +02:00
2b324fe2ef update README.md 2025-10-05 19:58:11 +02:00
99d90d607d update README.md 2025-10-05 19:44:32 +02:00
8c81064743 added support for file extensions 2025-10-05 19:43:09 +02:00
9c39b773da added custom naming to recursion and fixed naming in filemode 2025-10-05 15:58:36 +02:00
46ea1db65d -n flag no longer required for recursive mode 2025-10-05 12:12:49 +02:00
f7ab347316 cleanup 2025-10-04 19:47:56 +02:00
2b1167b3ce cleanup 2025-10-04 19:44:41 +02:00
fe3f32c2af update README.md 2025-10-04 19:20:30 +02:00
e9b491e81d patch bump 2025-10-04 19:19:48 +02:00
e243f5f379 added linear recursion 2025-10-04 19:19:22 +02:00
c1e76b660a added recursive functions and number length function 2025-10-04 19:17:17 +02:00
1c557913f9 update README.md 2025-10-04 19:16:07 +02:00
67e68da880 added TODO 2025-10-04 12:18:00 +02:00
8df12ec6f4 fixed numbering in recursion 2025-10-04 12:16:59 +02:00
9d2d6931e3 fixed recursion 2025-10-04 09:09:02 +02:00
acd3f5fe39 added recursion, needs debugging 2025-10-03 19:13:53 +02:00
0e84c959ce update README.md 2025-10-03 19:13:20 +02:00
aa5041a46c added tests for the path function 2025-10-03 09:48:36 +02:00
fb4e8a3be6 back to an working state 2025-10-02 20:47:40 +02:00
36333b3b99 removed redundant TODO 2025-10-02 15:50:58 +02:00
91e474c3b8 added TODO comments 2025-10-02 15:46:24 +02:00
e8ef3c6e53 added TODO comments 2025-10-02 15:40:36 +02:00
f4f5f9bc6b split decider and input_validator 2025-10-02 15:12:04 +02:00
3c1d881de7 cleanup 2025-10-02 15:11:40 +02:00
b4e5694b7b update README 2025-10-02 13:41:46 +02:00
691b68cb4c modified .gitignore 2025-10-01 22:20:23 +02:00
461533b717 new decicion logic WIP 2025-10-01 16:07:08 +02:00
caff94ab41 decider WIP 2025-10-01 08:06:26 +02:00
efcec653cb refactor librefit and added docstrings 2025-09-30 20:56:27 +02:00
a0f2f83a8a refactor get_standard_name_number() and added proper docstring 2025-09-30 17:46:36 +02:00
af80345ff6 refactor get_standard_folder_name() and added proper docstring 2025-09-30 17:21:12 +02:00
f96d9b3257 test 2025-09-30 15:56:23 +02:00
b0e3594b49 added proper docstring and refactored get_standard_file_name() 2025-09-30 09:35:25 +02:00
cf828c7f97 update a Docstring to better explain the __call__ function 2025-09-30 08:05:00 +02:00
49e16a522c added comments to file creation function 2025-09-30 07:59:02 +02:00
927d5358f5 update Version 2025-09-29 22:23:19 +02:00
0bbfb9b9bf made the current directory the default input 2025-09-29 22:03:53 +02:00
a012f8f1e2 update README.md 2025-09-29 22:02:46 +02:00
394b940841 update README.md 2025-09-29 21:49:19 +02:00
b615f52313 added file creation 2025-09-29 21:38:42 +02:00
799e0239a1 update README.md 2025-09-29 21:37:50 +02:00
5270fab084 update README 2025-09-29 20:13:34 +02:00
5469a01c09 logging improvements 2025-09-29 20:11:16 +02:00
9b86007e34 trying to get the tests to run 2025-09-29 17:51:56 +02:00
40bf210067 added gewt_default_file_name() and wrote tests 2025-09-29 15:36:18 +02:00
ae19816da1 update .gitignore 2025-09-28 21:18:35 +02:00
d2041c5355 added filemode 2025-09-28 19:51:06 +02:00
c8bf85cb6a added version file 2025-09-28 18:10:05 +02:00
12 changed files with 777 additions and 95 deletions

3
.gitignore vendored
View File

@@ -1,5 +1,6 @@
release releases
version.py version.py
tester
# ---> Python # ---> Python
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files

View File

@@ -1,13 +1,25 @@
# Python Programs and Scripts Repository # Python Programs and Scripts Repository
![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54) ![Python](https://img.shields.io/badge/python-3670A0?style=for-the-badge&logo=python&logoColor=ffdd54)
Collection of my python scripts and programs. Containing tools to manipulate the behavior of the system. Collection of my python scripts and programs. Containing tools to
manipulate the behavior of the system.
## Wanna Do´s
- Program which creates an file containing a version and
- Creating a Module which loads configuration files
- GUI auto-clicker which accepts command line activation
## tempbox ## tempbox
A script which allows the user to execute commands in a temporary A script which allows the user to execute commands in a temporary
directory. directory.
### Wannado´s After execution, all contents within the folder get removed.
## refit
A file and folder manipulation tool. The aim is to unify various steps
from moving to creating and deleting directories and folder with one
tool.
- switch between temp file and temp dir

211
pyvers/src/pyvers.py Normal file
View File

@@ -0,0 +1,211 @@
import json
import os
import argparse
import sys
# ======================================================================
# Constantes
FILE_NAME = "version.json"
# ======================================================================
# ======================================================================
# Parser
parser = argparse.ArgumentParser(
prog="pyvers",
description="xD",
)
parser.add_argument(
"config",
help="The location of the config file to edit.",
type=str,
)
parser.add_argument(
"--patch",
help="Bumps the patch version by one.",
action="store_true",
)
parser.add_argument(
"--minor",
help="Bumps the minor version by one.",
action="store_true",
)
parser.add_argument(
"--major",
help="Bumps the major version by one.",
action="store_true",
)
args = parser.parse_args()
# ======================================================================
# ======================================================================
# Functions
def create_version_file(file_path) -> None:
"""Creates a version.json file with all versions set to 0 at the
input location.
Args:
file_path: (str): Path with file name.
Example:
>>>create_version_file(/path/to/file)
file:
{
"minor": 0,
"major": 0,
"patch": 0
}"""
# Defining the dictionary with the initial version numbers.
initial_version = {"minor": 0, "major": 0, "patch": 0}
# Opening/creating the file to write the dictionary as json to it.
file = open(file_path, "x")
file.write(json.dumps(initial_version, indent=4))
print("File written successfully.")
return
def load_version(input_path) -> dict[str, int]:
"""Opens the given file and returns its contents."""
# Open given path and loading the files contents into a variable
file_path = open(input_path)
prog_version = json.load(file_path)
return prog_version
def pretty_version(input_path) -> None:
"""Prints the version in a prettifyed format."""
prog_version = load_version(input_path)
pretty_version = (
f"{prog_version['major']}.{prog_version['minor']}.{prog_version['patch']}"
)
print(pretty_version)
def bump_patch(version_file) -> None:
"""Bumps the patch number of the given file by one."""
# Get the version as dictionary
version = load_version(version_file)
# Adding one to the version from the file and updating
# the dictionary
new_version = version["patch"] + 1
version.update({"patch": new_version})
# Opening the file and overwriting its contents.
with open(version_file, "w") as f:
f.write(json.dumps(version, indent=4))
def bump_minor(version_file) -> None:
"""Bumps the minor version number of the given file by one."""
# Get the version as dictionary
version = load_version(version_file)
# Adding one to the version from the file and updating
# the dictionary
new_version = version["minor"] + 1
version.update({"minor": new_version})
# Opening the file and overwriting its contents.
with open(version_file, "w") as f:
f.write(json.dumps(version, indent=4))
def bump_major(version_file) -> None:
"""Bumps the major version number of the given file by one."""
# Get the version as dictionary
version = load_version(version_file)
# Adding one to the version from the file and updating
# the dictionary
new_version = version["major"] + 1
version.update({"major": new_version})
# Opening the file and overwriting its contents.
with open(version_file, "w") as f:
f.write(json.dumps(version, indent=4))
def version_bumper(version_file, major_version, minor_version, patch) -> None:
"""Decides what version to bump, based on the users passed flags"""
if patch:
bump_patch(version_file)
if minor_version:
bump_minor(version_file)
if major_version:
bump_major(version_file)
def check_for_file(input_path: str) -> bool:
"""Checks if the file 'version.json' exists at the given path.
Args:
input_path ( str ): Path to check for the file.
Example:
>>>check_for_file(".")
'False'
>>>check_for_file("version.json")
'True'
>>>check_for_file("./version.json")
'True'
"""
if FILE_NAME in input_path:
file_path = os.path.expanduser(input_path)
if os.path.exists(file_path):
return True
else:
return False
elif os.path.exists(os.path.join(input_path, FILE_NAME)):
return True
else:
return False
def request_to_create():
"""Prompts the user if he wants to create the file and exits if the
user declines or presses any other character instead of 'y/Y'"""
PROMPT = "The file does not exist, do you want to create it? [y/n]"
PROMPT += "\n>>>"
response = input(PROMPT)
if "y" in response or "Y" in response:
file_path = os.path.join(
os.path.expanduser(args.config),
FILE_NAME,
)
create_version_file(file_path)
return
else:
parser.print_help()
sys.exit(1)
# ======================================================================
# Dispatching
if check_for_file(args.config):
file_path = os.path.join(os.path.expanduser(args.config), FILE_NAME)
if args.patch or args.minor or args.major:
version_bumper(
version_file=file_path,
major_version=args.major,
minor_version=args.minor,
patch=args.patch,
)
else:
pretty_version(file_path)
if check_for_file(args.config) is False:
request_to_create()
file_path = os.path.join(os.path.expanduser(args.config), FILE_NAME)
version_bumper(
version_file=file_path,
major_version=args.major,
minor_version=args.minor,
patch=args.patch,
)

View File

@@ -1,19 +1,46 @@
# refit # refit
`refit` is a file, directory manipulation and creation tool. `refit` is a file and directory manipulation tool. Currently it can
create a flat folder and file structure
as well as an linear directory structure.
## ToDos ## ToDos
1. folder and file creation 1. folder and file creation
1.1 simple file creation 1.1 simple file and folder creation
1.2 recursive file creation 1.2 recursive file and folder creation
1.3 file creation
2. file movement 2. file movement
2.1 apply a pattern what to move to where 2.1 file deletion
3. file removal
3.1 remove all files like '*.tar' - implement config file containing version, default names and other
configurations
- make file and directory creation start counting at 1 instead of 0
- Add security check which benchmarks the creation of folders and files
before the first execution in order to prevent either python, the file
system or the system in general to crash.
## Changelog ## Changelog
<2025-10-16> V0.3.9 - Changed how the version is read
<2025-10-05> V0.3.8 - Added file extension to file creation mode
<2025-10-05> V0.3.7 - Added custom naming for level and branch in
recursive mode
<2025-10-05> V0.3.6 - Recursive mode no longer requires the -n flag
<2025-10-04> V0.3.5 - Added a function which returns the length of a
number
<2025-10-04> V0.3.5 - Changed the recursive mode into an linear x*y
pattern
<2025-10-04> V0.3.4 - Added recursive directory creation and fixed
numbered naming
<2025-10-03> V0.3.3 - Added the beginning of recursive mode
<2025-09-30> V0.3.2 - Refactoring librefit and added proper docstrings;
begun to remove the check for the valid input and put it in the decider
<2025-09-29> V0.3.1 - Removed the requirement for an input
<2025-09-29> V0.3.0 - Added file creation in the pattern like
directories
<2025-09-29> V0.2.4 - Improved logging and log readability
<2025-09-28> V0.2.3 - Added logging for version file and --filemode
path to the decider
<2025-09-28> V0.2.0 - Added librefit for standard functions <2025-09-28> V0.2.0 - Added librefit for standard functions
<2025-09-28> V0.1.0 - Added the creation of multiple numbered directories in a given directory with the pattern default directory_n <2025-09-28> V0.1.0 - Added the creation of multiple numbered
directories in a given directory with the pattern default directory_n

10
refit/pyproject.toml Normal file
View File

@@ -0,0 +1,10 @@
[build-system]
requires = ["setuptools>=61.0.0"]
build-backend = "setuptools.build_meta"
[project]
name = "refit"
version = "0.0.1"
[tool.setuptools.packages]
find = { where = ["src"] }

0
refit/src/__init__.py Normal file
View File

View File

@@ -1,35 +1,277 @@
import os
import sys
import json
from .refit_logger import logger from .refit_logger import logger
# TODO: Make a standard function for reading config files, so it is
# reusable
def get_standard_name_number(current_number, number_str_length):
"""returns a number string filled to the length of the input number""" def get_int_length(number: int) -> int:
current_number = str(current_number) """Takes an number as its input and returns the numbers diget amount.
standard_name_number = str.zfill(current_number, number_str_length)
logger.debug(f"standard_name_number={standard_name_number}") This function takes an integer number, converts it into a string and
converts its digets. It returns the length of the number as an integer.
Args:
number (int): The number you need the length of
Examples:
>>> get_int_length(100)
'3'
>>> get_int_length(10)
'2'
>>> get_int_length(4000)
'4'
"""
number_string = str(number)
amount_didgets = len(number_string)
return amount_didgets
def get_standard_name_number(current_number: int, number_str_length: int) -> str:
"""Returns a number string filled to the length of the input number
This function returns the number in a standartized way as a string.
As input it takes the current number of the string to build and a
number which determines the length of the string.
Args:
current_number (str): The current number of the item.
number_str_length (int): The length of the string which gets returned.
Examples:
>>> get_standard_name_number(1, 2)
'01'
>>> get_standard_name_number(23, 4)
'0023'
"""
# logger.debug(
# f"FUNC: get_standard_name_number() index={current_number} string_length={number_str_length}"
# )
temp_current_number = str(current_number)
standard_name_number = str.zfill(temp_current_number, number_str_length)
# logger.debug(
# f"FUNC: get_standard_name_number() return value= '{standard_name_number}'"
# )
return standard_name_number return standard_name_number
def get_standard_folder_name(name): def get_standard_folder_name(name: str) -> str:
"""returns the default name if name=None else, it returns the first """Returnes a standard name either from a list or the default value.
given name to the argument --name as astring"""
logger.debug("get_standard_folder_name() call")
if name is None:
logger.warning("No name assigned, continue with default.")
standard_folder_name = "directory"
else:
logger.debug(f"{name}, Type: {type(name)}, Length: {len(name)}")
# Checks if multiple names are passed to the --name argument This function sanitizes the input, which gets passed as a list or None from
# if so, only the first one gets used. argparse. The function either chooses the first entry of the list, given to
if len(name) > 1: the --name argument or returns the default value 'directory'
_NAMES_WARNING = f"{len(name)} names given, only one required.\nContinuing with '{name[0]}' as name."
logger.warning(_NAMES_WARNING) Args:
print(_NAMES_WARNING) name (list[str] | None): A list of names if passed to the --name argument
standard_folder_name = name[0] or None if no name is passed.
Returns:
str: The file name. Returns 'file' as default value if name argument is 'None'
otherwise the first element of the list.
Examples:
>>> get_standard_file_name(None)
'file'
>>> get_standard_file_name(["example"])
'example'
>>> get_standard_file_name(["directory_name", "example"])
'directory_name'
"""
standard_folder_name = name[0] if name is not None else "directory"
logger.debug(f"{standard_folder_name}, Type: {type(standard_folder_name)}")
else:
standard_folder_name = name[0]
logger.debug("Continuing with expected input")
logger.debug("get_standard_folder_name() exit.")
return standard_folder_name return standard_folder_name
def get_standard_file_name(name) -> str:
"""Returnes a name either from a list or the default value.
This function sanitizes the input, which gets passed as a list or None from
argparse. The function either chooses the first entry of the list, given to
the --name argument or returns the default value 'file'
Args:
name (list[str] | None): A list of names if passed to the --name argument
or None if no name is passed.
Returns:
str: The file name. Returns 'file' as default value if name argument is 'None'
otherwise the first element of the list.
Examples:
>>> get_standard_file_name(None)
'file'
>>> get_standard_file_name(["example"])
'example'
>>> get_standard_file_name(["file_name", "example"])
'file_name'
"""
standard_file_name = name[0] if name is not None else "file"
return standard_file_name
def get_current_path(path) -> str:
"""Checks if the path argument is emty and applies the current directory as working path.
This function takes an list with strings as an input. If the input is `None` the current
directory is taken as the working directory.
If the path is passed, a check for its existence takes place.
Args:
path (str): _The current working directory._
Returns:
str: _Returns the path of the current directory after check for existence_
"""
logger.debug(f"FUNC: get_current_path() MSG: entered function with path = '{path}'")
if path is None:
# Set the current directory if none is passed with the command.
path = "."
# logger.warning(
# f"FUNC: {get_current_path.__name__}() MSG: Path now has the value: '{path}'"
# )
return path
else:
# Checks if the path, entered by the user, exists.
if os.path.exists(path) is True:
# logger.debug(
# f"FUNC: {get_current_path.__name__} MSG: Path '{path}' exists, continue...."
# )
return path
else:
ERROR_MESSAGE = (
f"FUNC: {get_current_path.__name__} MSG: '{path}' does not exist"
)
logger.warning(ERROR_MESSAGE)
print(ERROR_MESSAGE)
sys.exit(1)
def create_linear_directories(
input_path: str, target_depth: int, current_depth: int, name
):
"""Creates the linear directories for the x*y pattern
If no name is given the name of the level is defaulted to 'level'.
Otherwise it takes the second input of the --name argument. In the
end it appends the number of the folder.
Args:
input_path ( str ): _The current working directory.
target_depth ( int ): _The depth on how deepo directories are created._
current_depth ( int ): _The current depth of the folder creation._
name ( list[str] | None ): _The name of the level directories._
"""
# logger.debug(
# f"FUNC: create_linear_directories(entered) VALUES: path='{input_path}', target_depth='{target_depth}', current_depth='{current_depth}'"
# )
# TODO: Find a way on how to specify the type in the function call
# and let the if statement pass.
# Get base directory name
if name is None:
base_name = "level"
else:
base_name = name[1]
if current_depth > target_depth:
return
# Create directory name
directory_name = (
base_name
+ "_"
+ get_standard_name_number(current_depth, get_int_length(target_depth))
)
# Create the path where to create directory
path = os.path.join(input_path, directory_name)
os.mkdir(path)
# Recursive call of itself
create_linear_directories(path, target_depth, current_depth + 1, name)
def create_parallel_directories(input_path: str, target_depth: int, width: int, name):
"""Creates the branches which house the levels.
As input it takes the input_path and the width from which it creates
the branches of the structure. Afterwards it passes the target_depth
to another function to create the levels of each branch.
If 'None' is passed to the '--name' argument, the default name 'branch'
gets used as base directory name.
Args:
input_path ( str ): _The current working directory.
target_depth ( int ): _The depth on how deepo directories are created._
width ( int ): _The ammount of branches to create._
name ( list[str] | None ): _The name of the level directories._
"""
# logger.debug(
# f"FUNC: create_parallel_directories(entered) VALUES: path='{input_path}', target_depth='{target_depth}', width='{width}', name={name}"
# )
# TODO: Find a way on how to specify the type in the function call
# and let the if statement pass.
# Get base directory name
if name is None:
base_name = "branch"
else:
base_name = name[0]
for i in range(width):
# Create directory name
directory_name = (
base_name + "_" + get_standard_name_number(i, get_int_length(width))
)
# Create the path where to create directory
path = os.path.join(input_path, directory_name)
os.mkdir(path)
# Recursive call of itself
create_linear_directories(
input_path=path,
target_depth=target_depth,
current_depth=0,
name=name,
)
def get_version_from_file(input_path) -> str:
"""Returns the version of the program.
The function accepts an path to a version file as a string and it
returns it version number formatted.
Arg:
input_path (str): The absolute or relative path to the
version file.
Example:
>>>get_version_from_file("/path/to/file.json")
'0.2.1'"""
# Expands the input path
expanded_path = os.path.expanduser(input_path)
# Opening the file and reading its contents, saving as as an dict.
file_path = open(expanded_path)
prog_version = json.load(file_path)
# Formatting the output before returning the string again
pretty_version = (
f"{prog_version['major']}.{prog_version['minor']}.{prog_version['patch']}"
)
return pretty_version

View File

@@ -1,20 +1,17 @@
import os import os
from pathlib import Path
import sys
from .refit_logger import logger from .refit_logger import logger
from . import librefit from . import librefit
logger.debug("Initiated refit_create.py")
# ----------------------------------------------------------------------
class Refit_Create: class Refit_Create:
"""A class to create folders and files. """A class to create folders and files.
It first calls the decider which lets the create_input_valid() function It first calls the decider which lets the create_input_valid() function
check if the input argument exists. If create_input_valid() returns check if the input argument exists. If create_input_valid() returns
'True' it continues to execute the command as per the given arguments. 'True' it continues to execute the command as per the given arguments."""
default folder name: directory"""
def __init__(self, args): def __init__(self, args):
"""Initiating variables for creation""" """Initiating variables for creation"""
@@ -23,60 +20,149 @@ class Refit_Create:
self.name = args.name self.name = args.name
self.input = args.input self.input = args.input
self.n = args.n self.n = args.n
self.filemode = args.filemode
def create_input_valid(self): self.recursive = args.recursive
"""Checks if the input is valid and returns either True or self.e = args.e
throws an error in log and terminal."""
logger.debug("in create_input_valid()")
if self.input is None:
logger.warning(f"{self.input} cannot be None")
print("Input argument missing. Use 'refit create -h' for help")
raise ValueError("Input missing")
return True
def create_n_folders(self, n, input, name): def create_n_folders(self, n, input, name):
"""Creates an set ammount of folders. Using the default directory """Creates an set ammount of folders. Using the default directory
name if no other is provided.""" name if no other is provided."""
logger.debug("in create_n_folders()") logger.debug(f"FUNC: create_n_folders() ARGS: n={n} input={input} name={name}")
# Creating the length of the suffix number_string. # Creating the length of the suffix number_string.
length_n = len(str(n)) length_n = librefit.get_int_length(n)
# Get either the default folder name or the input name as string. # Get either the default folder name or the input name as string.
folder_name = librefit.get_standard_folder_name(name) folder_name = librefit.get_standard_folder_name(name)
logger.debug(f"Length of numbering string:{length_n}")
logger.debug(f"Folder name: {folder_name}")
while n > 0: while n > 0:
# iterating down for the files number. # iterating down for the files number.
i = str(n - 1) folder_number = n - 1
# Passing the number and the length of the string to get the string back. # Passing the number and the length of the string to get the string back.
number_string = librefit.get_standard_name_number(i, length_n) number_string = librefit.get_standard_name_number(folder_number, length_n)
# Creating path for the folder # Creating path for the folder
temp_name = f"{folder_name}_{number_string}" temp_name = f"{folder_name}_{number_string}"
logger.debug(f"temp_name= {temp_name}")
folder_creation_path = os.path.join(input, temp_name) folder_creation_path = os.path.join(input, temp_name)
logger.debug(f"Created: {folder_creation_path}")
# Creating folder and subtracting n by one for the number_string # Creating folder and subtracting n by one for the number_string
os.mkdir(folder_creation_path) os.mkdir(folder_creation_path)
n -= 1 n -= 1
def rf_create_decider(self): def create_n_files(self, n, input, name, file_extension):
"""Coordination of the 'create' sub command""" """Creates an set ammount of files, using the default file name
if none is provided."""
if self.create_input_valid():
logger.debug("valid input -> continue")
self.create_n_folders(self.n, self.input, self.name)
logger.debug( logger.debug(
"End of run---------------------------------------------------------" f"FUNC: create_n_files() MSG: Entered function VALUES: n={self.n} name={self.name} input={self.input}"
) )
# Creating the length of the suffix number_string.
length_n = librefit.get_int_length(n)
# Get the name from the input argument.
file_name = librefit.get_standard_file_name(name)
while n > 0:
# Get number of the file(s) to create
file_number = n - 1
number_string = librefit.get_standard_name_number(file_number, length_n)
# Get the name of the file, either applying default or using first list item.
if file_extension is not None:
temp_name = f"{file_name}_{number_string}.{file_extension}"
else:
temp_name = f"{file_name}_{number_string}"
file_path = Path(os.path.join(input, temp_name)) # Build file path
file_path.touch(exist_ok=True) # creating file
# Counting down n for the next ieration of the while-loop
n -= 1
def create_recursive(self, recursive, name, input):
"""Creating directories recursively"""
logger.debug(
f"FUNC: create_recursive(beginning) MSG: entered function with following arguments: recursive='{recursive}' name='{name}' input='{input}'"
)
librefit.create_parallel_directories(
input_path=input,
target_depth=recursive[0],
width=recursive[1],
name=name,
)
def input_validator(self):
"""Function, which checks if the user input is valid"""
# Check working directory
if self.input is None:
self.input = librefit.get_current_path(self.input)
logger.info(f"FUNC: input_validator(input check) VALUE: input={self.input}")
# Check for conflicting flags
if self.recursive is not None and self.filemode:
logger.error(
f"FUNC: input_validator(recursive&filemode?) VALUES: recursive='{self.recursive}', filemode={self.filemode}"
)
print("Filemode and recursive do not work together.")
sys.exit(1)
# Check if recursive input is an empty list
if self.recursive is not None:
if len(self.recursive) < 2:
logger.error(
"FUNC:input_validator(recursive) MSG: Invalid input, enter 2 numbers!"
)
sys.exit(1)
# Exit the program if the -n argument is not passed
if self.n is None and self.recursive is None:
logger.error(
f"FUNC create_dispatcher(n=None ?) MSG: the number value cannot be '{self.n}'"
)
print("Use the '-n' flag for the create command.")
sys.exit(1)
else:
return True
def create_dispatcher(self):
"""Coordination of the 'create' sub command"""
logger.debug(
f"FUNC: create_dispatcher() MSG: Entered decider function {self.args}"
)
if self.input_validator():
if self.filemode:
logger.debug(
f"FUNC: create_dispatcher(filemode) MSG: given arguments: n={self.n} input={self.input} name={self.name} file_extension={self.e}"
)
self.create_n_files(self.n, self.input, self.name, self.e)
elif self.recursive is not None:
logger.debug(
f"FUNC: create_dispatcher(recursive) MSG: given arguments: n={self.n} input={self.input} name={self.name} recursive={self.recursive}"
)
self.create_recursive(self.recursive, self.name, self.input)
elif not self.recursive and not self.filemode:
logger.debug(
f"FUNC: create_dispatcher(n_folder) MSG: given arguments: n={self.n} input={self.input} name={self.name}"
)
self.create_n_folders(self.n, self.input, self.name)
else:
logger.debug(
f"FUNC: create_dispatcher(exit no input) MSG: given arguments: n={self.n} input={self.input} name={self.name} recursive={self.recursive}"
)
print(
"Use '-n' argument to create directories.\nPlease use 'refit create -h' for help"
)
sys.exit(1)
def __call__(self): def __call__(self):
"""Gets called when the object is treated as an function""" """Gets called when the 'create' subcommand is used."""
self.rf_create_decider() self.create_dispatcher()

View File

@@ -27,6 +27,3 @@ def handle_exception(exec_type, exec_value, exec_traceback):
sys.excepthook = handle_exception sys.excepthook = handle_exception
# logger.debug(f"Log path:\t{log_dir}")
# logger.debug(f"Log file:\t{log_file}")

View File

@@ -3,22 +3,21 @@ import sys
from modules.refit_logger import logger from modules.refit_logger import logger
from modules.refit_create import Refit_Create from modules.refit_create import Refit_Create
from modules.librefit import get_version_from_file
from version import GET_VERSION_NUMBER # NOTE: The final version file needs a dedicated place to live in
# so the version number is always readable, independent from where it
current_version = GET_VERSION_NUMBER() # is executed
REFIT_VERSION = get_version_from_file("~/Documents/git/python/refit/src/version.json")
# Setting Global Variables
REFIT_VERSION = f"Refit Beta {current_version}"
# ---------------------------ARGPARSE START--------------------------- # ---------------------------ARGPARSE START---------------------------
# Main Parser # Main Parser
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
prog="Refit", prog="refit",
description="This is a file and directory manipulation tool.\ description="""This is a file and directory manipulation tool. It can create, move and delete files and directories as well as renaming them""",
it can create, move and delete files and directories as well as \
renaming them",
epilog=REFIT_VERSION, epilog=REFIT_VERSION,
formatter_class=argparse.RawDescriptionHelpFormatter,
) )
# Main Parser Arguments # Main Parser Arguments
@@ -26,19 +25,51 @@ parser = argparse.ArgumentParser(
# Create Parser # Create Parser
subparser = parser.add_subparsers( subparser = parser.add_subparsers(
title="Commands", title="Commands",
dest="create",
required=False, required=False,
) )
# Create Parser Arguments # Create Parser Arguments
create_parser = subparser.add_parser("create", help="creates a new file/folder") create_parser = subparser.add_parser(
create_parser.add_argument("-n", type=int, help="number of items") name="create",
create_parser.add_argument("-i", "--input", help="input file") description="The create sub command lets you create files, folders and directory structures.",
help="The create sub command lets you create files, folders and directory structures.",
)
create_parser.add_argument(
"-n",
metavar="COUNT",
type=int,
help="Number of items",
)
create_parser.add_argument(
"-i",
"--input",
metavar="PATH",
help="Input path. If not specified the current directory is used.",
)
create_parser.add_argument( create_parser.add_argument(
"--name", "--name",
nargs="*", nargs="*",
help="the name of the folder you want to create\n Default: directory", help="the name of the folder you want to create\n Default: directory",
) )
create_parser.add_argument(
"--filemode",
action="store_true",
help="creates files instead of directories",
)
create_parser.add_argument(
"-r",
"--recursive",
metavar="INT",
type=int,
nargs=2,
help="""Sets the recursive mode for folders to true. First argumet
is for the depth and the second for the width.""",
)
create_parser.add_argument(
"-e",
type=str,
help="File extension which gets appended to the end of the file name.",
)
create_parser.set_defaults(command_class=Refit_Create) create_parser.set_defaults(command_class=Refit_Create)
args = parser.parse_args() args = parser.parse_args()
@@ -46,13 +77,13 @@ args = parser.parse_args()
# Dispatcher # Dispatcher
# determines what code gets addressed based of the users choosen flags. # determines what code gets addressed based of the users chosen flags.
if hasattr(args, "command_class"): if hasattr(args, "command_class"):
logger.debug("In hasattr()") # logger.debug(f"In dispatcher with args: {args}")
Refit_Create = args.command_class Refit_Create = args.command_class
create_command_instance = Refit_Create(args) create_command_instance = Refit_Create(args)
create_command_instance() create_command_instance()
else: else:
parser.print_help() parser.print_help()
logger.info("No input, exiting with error:1") logger.info("No input, exiting with exit code: 1")
sys.exit(1) sys.exit(1)

5
refit/src/version.json Normal file
View File

@@ -0,0 +1,5 @@
{
"minor": 3,
"major": 0,
"patch": 9
}

60
refit/test_librefit.py Normal file
View File

@@ -0,0 +1,60 @@
from src.modules.librefit import (
get_current_path,
get_standard_folder_name,
get_standard_name_number,
get_standard_file_name,
)
def test_get_default_file_name():
"""Tests if the function returns the correct value"""
default_name = get_standard_file_name(None)
assert "file" in default_name
def test_get_default_folder_name():
"""Test if the default directory name gets returned"""
default_name = get_standard_folder_name(None)
assert "directory" in default_name
def test_get_standard_name_number():
"""Tests if the number function returns the correctly formatted string."""
name_number = get_standard_name_number(20, 3)
assert "020" in name_number
def test_get_filename():
"""Tests if a passed filename is returned properly"""
filename = get_standard_file_name(["testname"])
assert "testname" in filename
def test_get_folder_name():
"""Tests if the function returns the passed folder name correctly"""
folder_name = ["folder"]
return_folder_name = get_standard_folder_name(folder_name)
assert "folder" in return_folder_name
def test_folder_name_list():
"""The function is supposed to only return the first name of the
passed list"""
folder_names = ["folder1", "folder2", "folder3"]
return_folder_name = get_standard_folder_name(folder_names)
assert "folder1" in return_folder_name
def test_get_current_directory():
"""Tests if the directory is set to the current directory, if None
is passed with the argument"""
path = None
directory = get_current_path(path)
assert "." in directory
def test_for_existing_path():
"""Tests if the function returns the correct path."""
path = "/home/cerberus/Documents/books/"
directory = get_current_path(path)
assert "/home/cerberus/Documents/books/" in directory