import itertools
import os
import re
from typing import List
class Command:
"""Base command class which all commands inherit from.
Command class implements all common functions and utilities
between commands, like file and directories handling, and specific
commands like arbitrary, text, or picture commands inherit it.
"""
def __init__(self, args):
"""Instantiate an object with the files/directory to work on."""
self.dir_path = args.dir_path
self._extract_files(args)
self._files_paths = None
def _extract_files(self, args):
"""
Returns the files specified by the user, if any.
Throws exception if no file matches user input.
"""
self.files_list = None
if args.name is not None:
self.files_list = self._file_from_name(args.name)
elif args.names_file is not None:
self.files_list = self._names_from_file(args.names_file)
elif args.rgx is not None:
self.files_list = self._files_from_rgx(args.rgx)
elif args.rgx_file is not None:
self.files_list = self._rgx_from_file(args.rgx_file)
else:
self.files_list = self._extract_all_files()
if len(self.files_list) == 0:
raise FileNotFoundError("No files match")
def _files_from_rgx(self, rgx):
"""
Looks for files in the directory `self.dir_path` with names
matched to the provided regex and returns those files names.
"""
f = []
for (dir_path, dirnames, filenames) in os.walk(self.dir_path):
f.extend(filenames)
break
prog = re.compile(rgx)
m = []
for file_name in f:
matched = prog.match(file_name)
# matched.span() => (match start index, match end index)
# Check that the file name is matched as a whole
if matched and matched.span()[1] == len(file_name):
m.append(file_name)
return m
import collections
import os
import pytest
from fipy.parser import parser
from fipy.commands.command import Command
class TestCommand:
"""Tests for the command class."""
def _populate_tmp_dir(self, tmpdir, dirs, files):
dirs = [tmpdir.mkdir(x) for x in dirs]
files = [tmpdir.join(x).write('') for x in files]
def test_files_from_rgx_no_match(self, tmpdir):
dirs = ['abc', '1abc', 'x1.txt']
files = ['x.txt', 'x.tsf', '1abc.png']
self._populate_tmp_dir(tmpdir, dirs, files)
args = parser.parse_args(
['-p', str(tmpdir), '-r', 's[0-9]*.txt',
'any', 'rename', '-asc']
)
with pytest.raises(FileNotFoundError):
command = Command(args)
First of all, is it a good practice to set self.dir_path
and make the function use it, or pass it to the function as a parameter? (_files_from_rgx
function)
And if I want to write unit tests, should I test write a test for the function and another for the constructor, or write tests for the constructor, which implicitly will enter the function which I have done in the test above?