saucenao.files.filter   A
last analyzed

Complexity

Total Complexity 29

Size/Duplication

Total Lines 148
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 29
eloc 73
dl 0
loc 148
ccs 68
cts 68
cp 1
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A Filter.file_system_objects() 0 12 3
A Filter.apply_modified_date() 0 12 2
F Filter.apply() 0 50 17
A Filter.__init__() 0 19 1
A Filter._get_timestamp_from_datestring() 0 15 4
A Filter.apply_creation_date() 0 12 2
1
#!/usr/bin/python
2
# -*- coding: utf-8 -*-
3 1
import datetime
4 1
import os
5 1
import re
6 1
from pathlib import Path
7 1
from stat import ST_CTIME, ST_MTIME, ST_SIZE
8 1
from typing import Generator
9
10 1
from saucenao.files.constraint import Constraint
11
12
13 1
class Filter:
14
    """
15
    Filter to apply constraints for multiple metadata entries of the files.
16
    Obviously the files have to exist or they'll automatically get removed.
17
    Returns a generator object
18
    """
19
20 1
    _directory = None
21 1
    _file_system_objects = None
22
23 1
    def __init__(self, assert_is_folder=False, assert_is_file=False, creation_date=None, modified_date=None, name=None,
24
                 file_type=None, size=None):
25
        """Initializing function
26
27
        :type assert_is_folder: bool
28
        :type assert_is_file: bool
29
        :type creation_date: Constraint
30
        :type modified_date: Constraint
31
        :type name: Constraint
32
        :type file_type: Constraint
33
        :type size: Constraint
34
        """
35 1
        self._filter_assert_is_folder = assert_is_folder
36 1
        self._filter_assert_is_file = assert_is_file
37 1
        self._filter_creation_date = creation_date
38 1
        self._filter_modified_date = modified_date
39 1
        self._filter_name = name
40 1
        self._filter_file_type = file_type
41 1
        self._filter_file_size = size
42
43 1
    @property
44
    def file_system_objects(self):
45
        """Property for file system objects
46
47
        :return:
48
        """
49 1
        if self._file_system_objects is None:
50 1
            if self._directory:
51 1
                return os.listdir(self._directory)
52
            else:
53 1
                return []
54 1
        return self._file_system_objects
55
56 1
    @staticmethod
57 1
    def _get_timestamp_from_datestring(date_string) -> float:
58
        """Convert the given date string to timestamp
59
60
        :param date_string:
61
        :return:
62
        """
63 1
        if re.match(r'\d+.\d+.\d+ \d+:\d+:\d+', date_string):
64 1
            return datetime.datetime.strptime(date_string, "%d.%m.%Y %H:%M:%S").timestamp()
65 1
        elif re.match(r'\d+.\d+.\d+ \d+:\d+', date_string):
66 1
            return datetime.datetime.strptime(date_string, "%d.%m.%Y %H:%M").timestamp()
67 1
        elif re.match(r'\d+.\d+.\d+', date_string):
68 1
            return datetime.datetime.strptime(date_string, "%d.%m.%Y").timestamp()
69
        else:
70 1
            raise AttributeError("The date doesn't fit the format: d.m.Y[ H:M[:S]]")
71
72 1
    def apply(self, directory='', file_system_objects=None) -> Generator[str, None, None]:
73
        """Apply the filter values to the given FSOs(File System Objects)
74
75
        :type directory: str
76
        :type file_system_objects: list|tuple|Generator
77
        :return:
78
        """
79 1
        self._directory = directory
80 1
        self._file_system_objects = file_system_objects
81
82 1
        for file_system_object in self.file_system_objects:
83 1
            abs_path = os.path.join(directory, file_system_object)
84
85
            # check if the FSO exists, else we can't access the metadata
86 1
            if not os.path.exists(abs_path):
87 1
                continue
88
89
            # check if the FSO is a file
90 1
            if self._filter_assert_is_file and not os.path.isfile(abs_path):
91 1
                continue
92
93
            # check if the FSO is a folder
94 1
            if self._filter_assert_is_folder and not os.path.isdir(abs_path):
95 1
                continue
96
97 1
            file_stats = os.stat(abs_path)
98
99
            # check if the FSO creation date matches the constraint
100 1
            if self._filter_creation_date and not self.apply_creation_date(file_stats):
101 1
                continue
102
103
            # check if the FSO modification date matches the constraint
104 1
            if self._filter_modified_date and not self.apply_modified_date(file_stats):
105 1
                continue
106
107
            # check if the FSO name matches the constraint
108 1
            if self._filter_name and not self._filter_name.cmp_func(file_system_object, self._filter_name.value):
109 1
                continue
110
111
            # check if the FSO suffix matches the constraint
112 1
            if self._filter_file_type and not self._filter_file_type.cmp_func(Path(abs_path).suffix,
113
                                                                              self._filter_file_type.value):
114 1
                continue
115
116
            # check if the FSO size matches the constraint
117 1
            if self._filter_file_size and not self._filter_file_size.cmp_func(file_stats[ST_SIZE],
118
                                                                              self._filter_file_size.value):
119 1
                continue
120
121 1
            yield file_system_object
122
123 1
    def apply_creation_date(self, file_stats: os.stat_result) -> bool:
124
        """Apply creation date option
125
126
        :param file_stats:
127
        :return:
128
        """
129 1
        creation_time = file_stats[ST_CTIME]
130 1
        expected_creation_time = self._get_timestamp_from_datestring(self._filter_creation_date.value)
131 1
        if self._filter_creation_date.cmp_func(creation_time, expected_creation_time):
132 1
            return True
133
        else:
134 1
            return False
135
136 1
    def apply_modified_date(self, file_stats: os.stat_result) -> bool:
137
        """Apply modified date option
138
139
        :param file_stats:
140
        :return:
141
        """
142 1
        modified_time = file_stats[ST_MTIME]
143 1
        expected_modified_time = self._get_timestamp_from_datestring(self._filter_modified_date.value)
144 1
        if self._filter_modified_date.cmp_func(modified_time, expected_modified_time):
145 1
            return True
146
        else:
147
            return False
148