Test Failed
Push — master ( eb8f9d...e6cb19 )
by Cyb3r
04:31 queued 10s
created

MetaStalk.main.MetaStalk.exif_check()   A

Complexity

Conditions 3

Size

Total Lines 24
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 3

Importance

Changes 0
Metric Value
cc 3
eloc 10
nop 2
dl 0
loc 24
ccs 11
cts 11
cp 1
crap 3
rs 9.9
c 0
b 0
f 0
1
# -*- coding: utf-8 -*-
2 1
"""Main function of MetaStalk.
3
Run get any metadata from photos
4
and creates graphs from the metadata using MetaStalk.Modules"""
5 1
import argparse
6 1
from collections import OrderedDict
7 1
import os
8 1
import logging
9 1
import timeit
10 1
import exifreader
11 1
from MetaStalk import __version__
12 1
import MetaStalk.utils as utils
13
import MetaStalk.modules as modules
14
15 1
16
class MetaStalk:
17
    """MetaStalk
18
    ---
19
20
    Main Class for all MetaStalk work
21 1
    """
22 1
23 1
    def __init__(self):
24 1
        self.log = logging.getLogger("MetaStalk")
25 1
        self.t_start = timeit.default_timer()
26
        self.valid, self.invalid = [], []
27 1
        self.plots = {}
28
29
    def run(self, args: argparse.Namespace) -> None:
30
        """ run function
31
32
        Process files and passes the information on utils.graph to generates graphs.
33
        Will also pass plots to utils.export if the flag is set.
34
35
        Parameters
36 1
        ----------
37
        args : argparse.Namespace
38 1
            The arguments that were passed from command line
39
        """
40
        self.parse_files(args.files)
41
42
        self.plots = {
43
            "Stats": modules.stats(self.valid, self.invalid),
44
            "GPS": modules.gps_check(self.valid),
45
            "Timestamp": modules.date_time(self.valid),
46
            "Model": modules.pie_chart(self.valid, "Image Model"),
47 1
            "Manufacturer": modules.pie_chart(self.valid, "Image Make"),
48 1
            "Focal": modules.pie_chart(self.valid, "EXIF FocalLength"),
49 1
            "Producer": modules.pie_chart(self.valid, "Image Software"),
50 1
        }
51
        if args.alphabetic:
52 1
            self.plots = OrderedDict(sorted(self.plots.items()))
53
        if args.export:
54 1
            utils.export(args.export, args.output, self.plots)
55
        if not args.export_only:
56
            utils.graph(self.plots, self.t_start, args.test, args.no_open)
57
58
    def parse_files(self, path_list: list) -> None:
59
        """
60
         Use to complete the directory parsing and file adding. Does not return anything
61
         but adds the files to to either the invalid or valid list.
62
63 1
        Parameters
64 1
        ----------
65 1
        path_list : list
66 1
            The list of paths to search for files
67 1
        """
68 1
        for path in path_list:
69 1
            if os.path.isdir(path):
70
                self.log.debug("Detected path as a directory")
71 1
                for root, _, files in os.walk(path):
72
                    for item in files:
73 1
                        item_path = os.path.join(root, item)
74
                        self.exif_check(item_path)
75
            else:
76
                self.exif_check(path)
77
78
    def exif_check(self, file_path: str) -> None:
79
        """exif_check
80
81 1
        Used to append files if the path is not a directory.
82 1
83 1
        Parameters
84 1
        ----------
85 1
        file_path : str
86 1
            The path of the file to check to see if it has exif metadata
87 1
88
        Returns
89 1
        -------
90 1
91
        """
92
        with open(file_path, "rb") as f:
93 1
            tags = exifreader.process_file(f)
94
            f.close()
95
        if tags:
96
            tags["item"] = file_path
97
            self.valid.append(tags)
98
            self.log.debug("%s has metadata", file_path)
99 1
        else:
100
            self.invalid.append(file_path)
101
            self.log.debug("%s has no metadata data", file_path)
102 1
103
104 1
def start():
105
    """ start
106 1
    ---
107
108
    Function needed to start MetaStalk. Does all the argument parsing.
109 1
    """
110
    parser = argparse.ArgumentParser(
111
        prog="MetaStalk", description="Tool to graph " "image metadata."
112 1
    )
113
    parser.add_argument(
114 1
        "files", nargs="*", default=None, help="Path of photos to check."
115
    )
116
    parser.add_argument(
117
        "-a",
118 1
        "--alphabetic",
119
        help="Sorts charts in alphabetical order rather than" " the default order",
120 1
        default=False,
121
        action="store_true",
122
    )
123 1
    parser.add_argument(
124 1
        "-d",
125 1
        "--debug",
126 1
        help="Sets logging level to DEBUG.",
127 1
        action="store_const",
128 1
        dest="loglevel",
129
        const=logging.DEBUG,
130
        default=logging.WARNING,
131
    )
132
    parser.add_argument(
133
        "-e",
134
        "--export",
135
        choices=["pdf", "svg", "webp", "jpeg", "png", "html", "html_offline"],
136
        help="Exports the graphs rather than all on one web page",
137
    )
138
    parser.add_argument(
139
        "--export-only",
140
        help="Makes it so that MetaStalk only export",
141
        default=False,
142
        action="store_true",
143
    )
144
    parser.add_argument(
145
        "--no-open",
146
        help="Will only start the server and not open the browser" " to view it",
147
        default=False,
148
        action="store_true",
149
    )
150
    parser.add_argument(
151
        "-o",
152
        "--output",
153
        default="metastalk_exports",
154
        help="The name of the directory to output exports to. "
155
        "Will be created if it does not exist. "
156
        "Defaults to metastalk_exports.",
157
    )
158
    parser.add_argument(
159
        "-t",
160
        "--test",
161
        default=False,
162
        action="store_true",
163
        help="Does not show the graphs at the end.",
164
    )
165
    parser.add_argument(
166
        "-v",
167
        "--verbose",
168
        help="Sets logging level to INFO",
169
        action="store_const",
170
        dest="loglevel",
171
        const=logging.INFO,
172
    )
173
    args = parser.parse_args()
174
    log = utils.make_logger("MetaStalk", args.loglevel)
175
    log.info("MetaStalk starting")
176
    if utils.check_update(__version__):
177
        log.warning(
178
            "There is a newer version of MetaStalk available.\n"
179
            "Run pip3 install -U metastalk"
180
        )
181
    if not args.files:
182
        log.error("ERROR: No path was inputted.")
183
        raise FileNotFoundError("No path was inputted.")
184
    metastalk = MetaStalk()  # pragma: no cover
185
    metastalk.run(args)  # pragma: no cover
186