I am making a CLI tool using python and click. I have a command called ext
that has two options --type
and --path
and then another command ext
. The function organizes the files in the specified path based on the extension specified in the given type. This is the command and the error I get:
Categorize ext --type image --path C:\Users\ACERq\Pictures\Screenshots ext
join() argument must be str, bytes, or os.PathLike object, not 'NoneType'
I have another similar command which takes just one path option, that function works properly with the same path
import click
from src.services.ext_functions import *
class Context:
def __init__(self, type, path):
self.type = type
self.path = path
@click.group()
@click.option("-t", "--type", type=str, help = "Type of extension", required=False, default="media")
@click.option("-p", "--path", type=str, help = "Path to organize", required=False, default=os.getcwd())
@click.pass_context
def main(ctx, type, path):
"""Organize files based on extension"""
ctx.obj = Context(type, path)
pass
@main.command()
@click.pass_context
def ext(ctx):
"""Organize files based on specified extension types"""
extension = ctx.obj.type
folder_to_track = ctx.obj.path
click.echo(extension_category(extension, folder_to_track))
@main.command()
@click.pass_context
def all(ctx):
"""Organize all files based on extension types"""
folder_to_track = ctx.obj.path
click.echo(all_extensions_category(folder_to_track))
Full traceback
Traceback (most recent call last):
File "D:\Python-projects\Categorize-CLI\.venv\Scripts\Categorize-script.py", line 33, in <module>
sys.exit(load_entry_point('Categorize-CLI', 'console_scripts', 'Categorize')())
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1130, in __call__
return self.main(*args, **kwargs)
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1055, in main
rv = self.invoke(ctx)
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1657, in invoke
return _process_result(sub_ctx.command.invoke(sub_ctx))
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 1404, in invoke
return ctx.invoke(self.callback, **ctx.params)
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\core.py", line 760, in invoke
return __callback(*args, **kwargs)
File "D:\Python-projects\Categorize-CLI\.venv\lib\site-packages\click\decorators.py", line 26, in new_func
return f(get_current_context(), *args, **kwargs)
File "d:\python-projects\categorize-cli\src\commands\ext.py", line 23, in ext
click.echo(extension_category(extension, folder_to_track))
File "d:\python-projects\categorize-cli\src\services\ext_functions.py", line 82, in extension_category
folder_path = os.path.join(folder_to_track, folder_name)
File "C:\Users\ACERq\AppData\Local\Programs\Python\Python310\lib\ntpath.py", line 117, in join
genericpath._check_arg_types('join', path, *paths)
File "C:\Users\ACERq\AppData\Local\Programs\Python\Python310\lib\genericpath.py", line 152, in _check_arg_types
raise TypeError(f'{funcname}() argument must be str, bytes, or '
TypeError: join() argument must be str, bytes, or os.PathLike object, not 'NoneType'
extension_category()
def extension_category(extension, folder_to_track):
start_time = time.monotonic()
movedFiles = False
count = 0
if check_files(folder_to_track):
for file in os.listdir(folder_to_track):
if not os.path.isdir(os.path.join(folder_to_track, file)):
try:
file_mappings = collections.defaultdict()
for filename in os.listdir(folder_to_track):
for value in extension:
if not os.path.isdir(os.path.join(folder_to_track, filename)) and any(
filename.endswith(value) for filename in os.listdir(folder_to_track)) == True:
file_mappings.setdefault(get_key(extension), []).append(filename)
for folder_name, folder_items in file_mappings.items():
folder_path = os.path.join(folder_to_track, folder_name)
folder_exists = os.path.exists(folder_path)
if not folder_exists:
os.mkdir(folder_path)
for filename in os.listdir(folder_to_track):
for value in extension:
if not os.path.isdir(os.path.join(folder_to_track, filename)) and filename.endswith(
value):
count = count + 1
source = os.path.join(folder_to_track, filename)
destination = os.path.join(folder_path, filename)
moveIncrementing(source,destination) # move all files containing sub_file_name in their filenames
movedFiles = True
if folder_exists:
for filename in os.listdir(folder_to_track):
for value in extension:
if not os.path.isdir(os.path.join(folder_to_track, filename)) and filename.endswith(
value):
count = count + 1
source = os.path.join(folder_to_track, filename)
destination = os.path.join(folder_path, filename)
moveIncrementing(source,
destination) # move all files containing sub_file_name in their filenames
movedFiles = True
end_time = time.monotonic()
displayProgressbar(count)
if movedFiles:
if count == 1:
return f"Successfully moved {count} file{os.linesep}Time taken: {timedelta(seconds=end_time - start_time)}"
else:
return f"Successfully moved {count} files{os.linesep}Time taken: {timedelta(seconds=end_time - start_time)}"
else:
return "Files with that extension do not exist in {}".format(folder_to_track)
except Exception as e:
print(e)
return f'{folder_to_track}: is either empty or not organizable'
else:
return f'{folder_to_track}: is either empty or not organizable'
If I call the function like this: extension_category(image, r"C:\Users\ACERq\Pictures\Screenshots")
it works
Update I managed to make it work but then I encountered a new problem
When I just check if the inputted value is equal to the extension then it works but when I add some more modifications it doesn't work
I finally fixed the problem, I thought the problem was due to the parameter
folder_to_track
but it was actually the second parameterextension
that was causing the issue. The function took the parameter as the value of the extensions-dict and not the key. So instead ofimage
as the extension, it should be[".png", ".jpg"]
etc