Passed
Push — master ( 13be50...a4d20f )
by Cyb3r
01:55
created

MetaStalk.main.MetaStalk.__init__()   A

Complexity

Conditions 1

Size

Total Lines 5
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 5
nop 1
dl 0
loc 5
ccs 5
cts 5
cp 1
crap 1
rs 10
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 1
import MetaStalk.modules as modules
14
15
16 1
class MetaStalk:
17
    """MetaStalk
18
    ---
19
20
    Main Class for all MetaStalk work
21
    """
22
23 1
    def __init__(self):
24 1
        self.log = logging.getLogger("MetaStalk")
25 1
        self.t_start = timeit.default_timer()
26 1
        self.valid, self.invalid = [], []
27 1
        self.plots = {}
28
29 1
    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
        ----------
37
        args : argparse.Namespace
38
            The arguments that were passed from command line
39
        """
40 1
        self.parse_files(args.files)
41
42 1
        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
            "Manufacturer": modules.pie_chart(self.valid, "Image Make"),
48
            "Focal": modules.pie_chart(self.valid, "EXIF FocalLength"),
49
            "Producer": modules.pie_chart(self.valid, "Image Software"),
50
        }
51 1
        if args.alphabetic:
52 1
            self.plots = OrderedDict(sorted(self.plots.items()))
53 1
        if args.export:
54 1
            utils.export(args.export, args.output, self.plots)
55 1
        if not args.export_only:
56 1
            utils.graph(self.plots, self.t_start, args.test, args.no_open)
57
58 1
    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
        Parameters
64
        ----------
65
        path_list : list
66
            The list of paths to search for files
67
        """
68 1
        for path in path_list:
69 1
            if os.path.isdir(path):
70 1
                self.log.debug("Detected path as a directory")
71 1
                for root, _, files in os.walk(path):
72 1
                    for item in files:
73 1
                        item_path = os.path.join(root, item)
74 1
                        self.exif_check(item_path)
75
            else:
76 1
                self.exif_check(path)
77
78 1
    def exif_check(self, file_path: str) -> None:
79
        """exif_check
80
81
        Used to append files if the path is not a directory.
82
83
        Parameters
84
        ----------
85
        file_path : str
86
            The path of the file to check to see if it has exif metadata
87
88
        Returns
89
        -------
90
91
        """
92 1
        with open(file_path, "rb") as f:
93 1
            tags = exifreader.process_file(f)
94 1
            f.close()
95 1
        if tags:
96 1
            tags["item"] = file_path
97 1
            self.valid.append(tags)
98 1
            self.log.debug("%s has metadata", file_path)
99
        else:
100 1
            self.invalid.append(file_path)
101 1
            self.log.debug("%s has no metadata data", file_path)
102
103
104 1
def start():
105
    """ start
106
    ---
107
108
    Function needed to start MetaStalk. Does all the argument parsing.
109
    """
110 1
    parser = argparse.ArgumentParser(
111
        prog="MetaStalk", description="Tool to graph " "image metadata."
112
    )
113 1
    parser.add_argument(
114
        "files", nargs="*", default=None, help="Path of photos to check."
115
    )
116 1
    parser.add_argument(
117
        "-a",
118
        "--alphabetic",
119
        help="Sorts charts in alphabetical order rather than" " the default order",
120
        default=False,
121
        action="store_true",
122
    )
123 1
    parser.add_argument(
124
        "-d",
125
        "--debug",
126
        help="Sets logging level to DEBUG.",
127
        action="store_const",
128
        dest="loglevel",
129
        const=logging.DEBUG,
130
        default=logging.WARNING,
131
    )
132 1
    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 1
    parser.add_argument(
139
        "--export-only",
140
        help="Makes it so that MetaStalk only export",
141
        default=False,
142
        action="store_true",
143
    )
144 1
    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 1
    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 1
    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 1
    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 1
    args = parser.parse_args()
174 1
    log = utils.make_logger("MetaStalk", args.loglevel)
175 1
    log.info("MetaStalk starting")
176 1
    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 1
    if not args.files:
182 1
        log.error("ERROR: No path was inputted.")
183 1
        raise FileNotFoundError("No path was inputted.")
184
    metastalk = MetaStalk()  # pragma: no cover
185
    metastalk.run(args)  # pragma: no cover
186