We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Handle multiple files
Would be nice to run batch analyses

```bash
$ slither contracts/*.sol
usage: slither.py contract.sol [flag]
slither: error: unrecognized arguments: contracts/B.sol contracts/C.sol ...
```

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `slither/__main__.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 import argparse
4 import glob
5 import json
6 import logging
7 import os
8 import sys
9 import traceback
10 
11 from pkg_resources import iter_entry_points
12 
13 from slither.detectors.abstract_detector import (AbstractDetector,
14                                                  DetectorClassification,
15                                                  classification_txt)
16 from slither.printers.abstract_printer import AbstractPrinter
17 from slither.slither import Slither
18 
19 logging.basicConfig()
20 logger = logging.getLogger("Slither")
21 
22 def output_to_markdown(detector_classes):
23     """
24         Pretty print of the detectors to README.md
25     """
26     detectors_list = []
27     for detector in detector_classes:
28         argument = detector.ARGUMENT
29         # dont show the backdoor example
30         if argument == 'backdoor':
31             continue
32         help_info = detector.HELP
33         impact = detector.IMPACT
34         confidence = classification_txt[detector.CONFIDENCE]
35         detectors_list.append((argument, help_info, impact, confidence))
36 
37     # Sort by impact, confidence, and name
38     detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[3], element[0]))
39     idx = 1
40     for (argument, help_info, impact, confidence) in detectors_list:
41         print('{} | `{}` | {} | {} | {}'.format(idx,
42                                                 argument,
43                                                 help_info,
44                                                 classification_txt[impact],
45                                                 confidence))
46         idx = idx +1
47 
48 def process(filename, args, detector_classes, printer_classes):
49     """
50     The core high-level code for running Slither static analysis.
51 
52     Returns:
53         list(result), int: Result list and number of contracts analyzed
54     """
55     slither = Slither(filename, args.solc, args.disable_solc_warnings, args.solc_args)
56 
57     for detector_cls in detector_classes:
58         slither.register_detector(detector_cls)
59 
60     for printer_cls in printer_classes:
61         slither.register_printer(printer_cls)
62 
63     analyzed_contracts_count = len(slither.contracts)
64 
65     results = []
66 
67     if printer_classes:
68         slither.run_printers()  # Currently printers does not return results
69 
70     elif detector_classes:
71         detector_results = slither.run_detectors()
72         detector_results = [x for x in detector_results if x]  # remove empty results
73         detector_results = [item for sublist in detector_results for item in sublist]  # flatten
74 
75         results.extend(detector_results)
76 
77     return results, analyzed_contracts_count
78 
79 
80 def output_json(results, filename):
81     with open(filename, 'w') as f:
82         json.dump(results, f)
83 
84 
85 def exit(results):
86     if not results:
87         sys.exit(0)
88     sys.exit(len(results))
89 
90 
91 def main():
92     """
93     NOTE: This contains just a few detectors and printers that we made public.
94     """
95     from slither.detectors.examples.backdoor import Backdoor
96     from slither.detectors.variables.uninitialized_state_variables import UninitializedStateVarsDetection
97     from slither.detectors.attributes.constant_pragma import ConstantPragma
98     from slither.detectors.attributes.old_solc import OldSolc
99     from slither.detectors.attributes.locked_ether import LockedEther
100     from slither.detectors.functions.arbitrary_send import ArbitrarySend
101     from slither.detectors.functions.suicidal import Suicidal
102     from slither.detectors.reentrancy.reentrancy import Reentrancy
103     from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars
104     from slither.detectors.variables.unused_state_variables import UnusedStateVars
105     from slither.detectors.variables.possible_const_state_variables import ConstCandidateStateVars
106     from slither.detectors.statements.tx_origin import TxOrigin
107     from slither.detectors.statements.assembly import Assembly
108     from slither.detectors.operations.low_level_calls import LowLevelCalls
109     from slither.detectors.naming_convention.naming_convention import NamingConvention
110 
111     detectors = [Backdoor,
112                  UninitializedStateVarsDetection,
113                  ConstantPragma,
114                  OldSolc,
115                  Reentrancy,
116                  UninitializedStorageVars,
117                  LockedEther,
118                  ArbitrarySend,
119                  Suicidal,
120                  UnusedStateVars,
121                  TxOrigin,
122                  Assembly,
123                  LowLevelCalls,
124                  NamingConvention,
125                  ConstCandidateStateVars]
126 
127     from slither.printers.summary.function import FunctionSummary
128     from slither.printers.summary.contract import ContractSummary
129     from slither.printers.inheritance.inheritance import PrinterInheritance
130     from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph
131     from slither.printers.functions.authorization import PrinterWrittenVariablesAndAuthorization
132     from slither.printers.summary.slithir import PrinterSlithIR
133 
134     printers = [FunctionSummary,
135                 ContractSummary,
136                 PrinterInheritance,
137                 PrinterInheritanceGraph,
138                 PrinterWrittenVariablesAndAuthorization,
139                 PrinterSlithIR]
140 
141     # Handle plugins!
142     for entry_point in iter_entry_points(group='slither_analyzer.plugin', name=None):
143         make_plugin = entry_point.load()
144 
145         plugin_detectors, plugin_printers = make_plugin()
146 
147         if not all(issubclass(d, AbstractDetector) for d in plugin_detectors):
148             raise Exception('Error when loading plugin %s, %r is not a detector' % (entry_point, d))
149 
150         if not all(issubclass(p, AbstractPrinter) for p in plugin_printers):
151             raise Exception('Error when loading plugin %s, %r is not a printer' % (entry_point, p))
152 
153         # We convert those to lists in case someone returns a tuple
154         detectors += list(plugin_detectors)
155         printers += list(plugin_printers)
156 
157     main_impl(all_detector_classes=detectors, all_printer_classes=printers)
158 
159 
160 def main_impl(all_detector_classes, all_printer_classes):
161     """
162     :param all_detector_classes: A list of all detectors that can be included/excluded.
163     :param all_printer_classes: A list of all printers that can be included.
164     """
165     args = parse_args(all_detector_classes, all_printer_classes)
166 
167     if args.markdown:
168         output_to_markdown(all_detector_classes)
169         return
170 
171     detector_classes = choose_detectors(args, all_detector_classes)
172     printer_classes = choose_printers(args, all_printer_classes)
173 
174     default_log = logging.INFO if not args.debug else logging.DEBUG
175 
176     for (l_name, l_level) in [('Slither', default_log),
177                               ('Contract', default_log),
178                               ('Function', default_log),
179                               ('Node', default_log),
180                               ('Parsing', default_log),
181                               ('Detectors', default_log),
182                               ('FunctionSolc', default_log),
183                               ('ExpressionParsing', default_log),
184                               ('TypeParsing', default_log),
185                               ('Printers', default_log)]:
186         l = logging.getLogger(l_name)
187         l.setLevel(l_level)
188 
189     try:
190         filename = args.filename
191 
192         if os.path.isfile(filename):
193             (results, number_contracts) = process(filename, args, detector_classes, printer_classes)
194 
195         elif os.path.isdir(filename):
196             extension = "*.sol" if not args.solc_ast else "*.json"
197             filenames = glob.glob(os.path.join(filename, extension))
198             number_contracts = 0
199             results = []
200             for filename in filenames:
201                 (results_tmp, number_contracts_tmp) = process(filename, args, detector_classes, printer_classes)
202                 number_contracts += number_contracts_tmp
203                 results += results_tmp
204             # if args.json:
205             #    output_json(results, args.json)
206             # exit(results)
207 
208         else:
209             raise Exception("Unrecognised file/dir path: '#{filename}'".format(filename=filename))
210 
211         if args.json:
212             output_json(results, args.json)
213         # Dont print the number of result for printers
214         if printer_classes:
215             logger.info('%s analyzed (%d contracts)', filename, number_contracts)
216         else:
217             logger.info('%s analyzed (%d contracts), %d result(s) found', filename, number_contracts, len(results))
218         exit(results)
219 
220     except Exception:
221         logging.error('Error in %s' % args.filename)
222         logging.error(traceback.format_exc())
223         sys.exit(-1)
224 
225 
226 def parse_args(detector_classes, printer_classes):
227     parser = argparse.ArgumentParser(description='Slither',
228                                      usage="slither.py contract.sol [flag]",
229                                      formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=35))
230 
231     parser.add_argument('filename',
232                         help='contract.sol file')
233 
234     parser.add_argument('--solc',
235                         help='solc path',
236                         action='store',
237                         default='solc')
238 
239     parser.add_argument('--solc-args',
240                         help='Add custom solc arguments. Example: --solc-args "--allow-path /tmp --evm-version byzantium".',
241                         action='store',
242                         default=None)
243 
244     parser.add_argument('--disable-solc-warnings',
245                         help='Disable solc warnings',
246                         action='store_true',
247                         default=False)
248 
249     parser.add_argument('--solc-ast',
250                         help='Provide the ast solc file',
251                         action='store_true',
252                         default=False)
253 
254     parser.add_argument('--json',
255                         help='Export results as JSON',
256                         action='store',
257                         default=None)
258 
259     parser.add_argument('--exclude-informational',
260                         help='Exclude informational impact analyses',
261                         action='store_true',
262                         default=False)
263 
264     parser.add_argument('--exclude-low',
265                         help='Exclude low impact analyses',
266                         action='store_true',
267                         default=False)
268 
269     parser.add_argument('--exclude-medium',
270                         help='Exclude medium impact analyses',
271                         action='store_true',
272                         default=False)
273 
274     parser.add_argument('--exclude-high',
275                         help='Exclude high impact analyses',
276                         action='store_true',
277                         default=False)
278 
279     for detector_cls in detector_classes:
280         detector_arg = '--detect-{}'.format(detector_cls.ARGUMENT)
281         detector_help = '{}'.format(detector_cls.HELP)
282         parser.add_argument(detector_arg,
283                             help=detector_help,
284                             action="append_const",
285                             dest="detectors_to_run",
286                             const=detector_cls.ARGUMENT)
287 
288     # Second loop so that the --exclude are shown after all the detectors
289     for detector_cls in detector_classes:
290         exclude_detector_arg = '--exclude-{}'.format(detector_cls.ARGUMENT)
291         exclude_detector_help = 'Exclude {} detector'.format(detector_cls.ARGUMENT)
292         parser.add_argument(exclude_detector_arg,
293                             help=exclude_detector_help,
294                             action="append_const",
295                             dest="detectors_to_exclude",
296                             const=detector_cls.ARGUMENT)
297 
298     for printer_cls in printer_classes:
299         printer_arg = '--printer-{}'.format(printer_cls.ARGUMENT)
300         printer_help = 'Print {}'.format(printer_cls.HELP)
301         parser.add_argument(printer_arg,
302                             help=printer_help,
303                             action="append_const",
304                             dest="printers_to_run",
305                             const=printer_cls.ARGUMENT)
306 
307     # debugger command
308     parser.add_argument('--debug',
309                         help=argparse.SUPPRESS,
310                         action="store_true",
311                         default=False)
312 
313     parser.add_argument('--markdown',
314                         help=argparse.SUPPRESS,
315                         action="store_true",
316                         default=False)
317 
318     return parser.parse_args()
319 
320 
321 def choose_detectors(args, all_detector_classes):
322     # If detectors are specified, run only these ones
323     if args.detectors_to_run:
324         return [d for d in all_detector_classes if d.ARGUMENT in args.detectors_to_run]
325 
326     detectors_to_run = all_detector_classes
327 
328     if args.exclude_informational:
329         detectors_to_run = [d for d in detectors_to_run if
330                             d.IMPACT != DetectorClassification.INFORMATIONAL]
331     if args.exclude_low:
332         detectors_to_run = [d for d in detectors_to_run if
333                             d.IMPACT != DetectorClassification.LOW]
334     if args.exclude_medium:
335         detectors_to_run = [d for d in detectors_to_run if
336                             d.IMPACT != DetectorClassification.MEDIUM]
337     if args.exclude_high:
338         detectors_to_run = [d for d in detectors_to_run if
339                             d.IMPACT != DetectorClassification.HIGH]
340     if args.detectors_to_exclude:
341         detectors_to_run = [d for d in detectors_to_run if
342                             d.ARGUMENT not in args.detectors_to_exclude]
343     return detectors_to_run
344 
345 
346 def choose_printers(args, all_printer_classes):
347     # by default, dont run any printer
348     printers_to_run = []
349     if args.printers_to_run:
350         printers_to_run = [p for p in all_printer_classes if
351                            p.ARGUMENT in args.printers_to_run]
352     return printers_to_run
353 
354 
355 if __name__ == '__main__':
356     main()
357
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/slither/__main__.py b/slither/__main__.py
--- a/slither/__main__.py
+++ b/slither/__main__.py
@@ -184,12 +184,16 @@
     try:
         filename = args.filename
 
+        globbed_filenames = glob.glob(filename, recursive=True)
+
         if os.path.isfile(filename):
             (results, number_contracts) = process(filename, args, detector_classes, printer_classes)
 
-        elif os.path.isdir(filename):
+        elif os.path.isdir(filename) or len(globbed_filenames) > 0:
             extension = "*.sol" if not args.solc_ast else "*.json"
             filenames = glob.glob(os.path.join(filename, extension))
+            if len(filenames) == 0:
+                filenames = globbed_filenames
             number_contracts = 0
             results = []
             for filename in filenames:

{"golden_diff": "diff --git a/slither/__main__.py b/slither/__main__.py\n--- a/slither/__main__.py\n+++ b/slither/__main__.py\n@@ -184,12 +184,16 @@\n     try:\n         filename = args.filename\n \n+        globbed_filenames = glob.glob(filename, recursive=True)\n+\n         if os.path.isfile(filename):\n             (results, number_contracts) = process(filename, args, detector_classes, printer_classes)\n \n-        elif os.path.isdir(filename):\n+        elif os.path.isdir(filename) or len(globbed_filenames) > 0:\n             extension = \"*.sol\" if not args.solc_ast else \"*.json\"\n             filenames = glob.glob(os.path.join(filename, extension))\n+            if len(filenames) == 0:\n+                filenames = globbed_filenames\n             number_contracts = 0\n             results = []\n             for filename in filenames:\n", "issue": "Handle multiple files\nWould be nice to run batch analyses\r\n\r\n```bash\r\n$ slither contracts/*.sol\r\nusage: slither.py contract.sol [flag]\r\nslither: error: unrecognized arguments: contracts/B.sol contracts/C.sol ...\r\n```\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nimport argparse\nimport glob\nimport json\nimport logging\nimport os\nimport sys\nimport traceback\n\nfrom pkg_resources import iter_entry_points\n\nfrom slither.detectors.abstract_detector import (AbstractDetector,\n                                                 DetectorClassification,\n                                                 classification_txt)\nfrom slither.printers.abstract_printer import AbstractPrinter\nfrom slither.slither import Slither\n\nlogging.basicConfig()\nlogger = logging.getLogger(\"Slither\")\n\ndef output_to_markdown(detector_classes):\n    \"\"\"\n        Pretty print of the detectors to README.md\n    \"\"\"\n    detectors_list = []\n    for detector in detector_classes:\n        argument = detector.ARGUMENT\n        # dont show the backdoor example\n        if argument == 'backdoor':\n            continue\n        help_info = detector.HELP\n        impact = detector.IMPACT\n        confidence = classification_txt[detector.CONFIDENCE]\n        detectors_list.append((argument, help_info, impact, confidence))\n\n    # Sort by impact, confidence, and name\n    detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[3], element[0]))\n    idx = 1\n    for (argument, help_info, impact, confidence) in detectors_list:\n        print('{} | `{}` | {} | {} | {}'.format(idx,\n                                                argument,\n                                                help_info,\n                                                classification_txt[impact],\n                                                confidence))\n        idx = idx +1\n\ndef process(filename, args, detector_classes, printer_classes):\n    \"\"\"\n    The core high-level code for running Slither static analysis.\n\n    Returns:\n        list(result), int: Result list and number of contracts analyzed\n    \"\"\"\n    slither = Slither(filename, args.solc, args.disable_solc_warnings, args.solc_args)\n\n    for detector_cls in detector_classes:\n        slither.register_detector(detector_cls)\n\n    for printer_cls in printer_classes:\n        slither.register_printer(printer_cls)\n\n    analyzed_contracts_count = len(slither.contracts)\n\n    results = []\n\n    if printer_classes:\n        slither.run_printers()  # Currently printers does not return results\n\n    elif detector_classes:\n        detector_results = slither.run_detectors()\n        detector_results = [x for x in detector_results if x]  # remove empty results\n        detector_results = [item for sublist in detector_results for item in sublist]  # flatten\n\n        results.extend(detector_results)\n\n    return results, analyzed_contracts_count\n\n\ndef output_json(results, filename):\n    with open(filename, 'w') as f:\n        json.dump(results, f)\n\n\ndef exit(results):\n    if not results:\n        sys.exit(0)\n    sys.exit(len(results))\n\n\ndef main():\n    \"\"\"\n    NOTE: This contains just a few detectors and printers that we made public.\n    \"\"\"\n    from slither.detectors.examples.backdoor import Backdoor\n    from slither.detectors.variables.uninitialized_state_variables import UninitializedStateVarsDetection\n    from slither.detectors.attributes.constant_pragma import ConstantPragma\n    from slither.detectors.attributes.old_solc import OldSolc\n    from slither.detectors.attributes.locked_ether import LockedEther\n    from slither.detectors.functions.arbitrary_send import ArbitrarySend\n    from slither.detectors.functions.suicidal import Suicidal\n    from slither.detectors.reentrancy.reentrancy import Reentrancy\n    from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars\n    from slither.detectors.variables.unused_state_variables import UnusedStateVars\n    from slither.detectors.variables.possible_const_state_variables import ConstCandidateStateVars\n    from slither.detectors.statements.tx_origin import TxOrigin\n    from slither.detectors.statements.assembly import Assembly\n    from slither.detectors.operations.low_level_calls import LowLevelCalls\n    from slither.detectors.naming_convention.naming_convention import NamingConvention\n\n    detectors = [Backdoor,\n                 UninitializedStateVarsDetection,\n                 ConstantPragma,\n                 OldSolc,\n                 Reentrancy,\n                 UninitializedStorageVars,\n                 LockedEther,\n                 ArbitrarySend,\n                 Suicidal,\n                 UnusedStateVars,\n                 TxOrigin,\n                 Assembly,\n                 LowLevelCalls,\n                 NamingConvention,\n                 ConstCandidateStateVars]\n\n    from slither.printers.summary.function import FunctionSummary\n    from slither.printers.summary.contract import ContractSummary\n    from slither.printers.inheritance.inheritance import PrinterInheritance\n    from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph\n    from slither.printers.functions.authorization import PrinterWrittenVariablesAndAuthorization\n    from slither.printers.summary.slithir import PrinterSlithIR\n\n    printers = [FunctionSummary,\n                ContractSummary,\n                PrinterInheritance,\n                PrinterInheritanceGraph,\n                PrinterWrittenVariablesAndAuthorization,\n                PrinterSlithIR]\n\n    # Handle plugins!\n    for entry_point in iter_entry_points(group='slither_analyzer.plugin', name=None):\n        make_plugin = entry_point.load()\n\n        plugin_detectors, plugin_printers = make_plugin()\n\n        if not all(issubclass(d, AbstractDetector) for d in plugin_detectors):\n            raise Exception('Error when loading plugin %s, %r is not a detector' % (entry_point, d))\n\n        if not all(issubclass(p, AbstractPrinter) for p in plugin_printers):\n            raise Exception('Error when loading plugin %s, %r is not a printer' % (entry_point, p))\n\n        # We convert those to lists in case someone returns a tuple\n        detectors += list(plugin_detectors)\n        printers += list(plugin_printers)\n\n    main_impl(all_detector_classes=detectors, all_printer_classes=printers)\n\n\ndef main_impl(all_detector_classes, all_printer_classes):\n    \"\"\"\n    :param all_detector_classes: A list of all detectors that can be included/excluded.\n    :param all_printer_classes: A list of all printers that can be included.\n    \"\"\"\n    args = parse_args(all_detector_classes, all_printer_classes)\n\n    if args.markdown:\n        output_to_markdown(all_detector_classes)\n        return\n\n    detector_classes = choose_detectors(args, all_detector_classes)\n    printer_classes = choose_printers(args, all_printer_classes)\n\n    default_log = logging.INFO if not args.debug else logging.DEBUG\n\n    for (l_name, l_level) in [('Slither', default_log),\n                              ('Contract', default_log),\n                              ('Function', default_log),\n                              ('Node', default_log),\n                              ('Parsing', default_log),\n                              ('Detectors', default_log),\n                              ('FunctionSolc', default_log),\n                              ('ExpressionParsing', default_log),\n                              ('TypeParsing', default_log),\n                              ('Printers', default_log)]:\n        l = logging.getLogger(l_name)\n        l.setLevel(l_level)\n\n    try:\n        filename = args.filename\n\n        if os.path.isfile(filename):\n            (results, number_contracts) = process(filename, args, detector_classes, printer_classes)\n\n        elif os.path.isdir(filename):\n            extension = \"*.sol\" if not args.solc_ast else \"*.json\"\n            filenames = glob.glob(os.path.join(filename, extension))\n            number_contracts = 0\n            results = []\n            for filename in filenames:\n                (results_tmp, number_contracts_tmp) = process(filename, args, detector_classes, printer_classes)\n                number_contracts += number_contracts_tmp\n                results += results_tmp\n            # if args.json:\n            #    output_json(results, args.json)\n            # exit(results)\n\n        else:\n            raise Exception(\"Unrecognised file/dir path: '#{filename}'\".format(filename=filename))\n\n        if args.json:\n            output_json(results, args.json)\n        # Dont print the number of result for printers\n        if printer_classes:\n            logger.info('%s analyzed (%d contracts)', filename, number_contracts)\n        else:\n            logger.info('%s analyzed (%d contracts), %d result(s) found', filename, number_contracts, len(results))\n        exit(results)\n\n    except Exception:\n        logging.error('Error in %s' % args.filename)\n        logging.error(traceback.format_exc())\n        sys.exit(-1)\n\n\ndef parse_args(detector_classes, printer_classes):\n    parser = argparse.ArgumentParser(description='Slither',\n                                     usage=\"slither.py contract.sol [flag]\",\n                                     formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=35))\n\n    parser.add_argument('filename',\n                        help='contract.sol file')\n\n    parser.add_argument('--solc',\n                        help='solc path',\n                        action='store',\n                        default='solc')\n\n    parser.add_argument('--solc-args',\n                        help='Add custom solc arguments. Example: --solc-args \"--allow-path /tmp --evm-version byzantium\".',\n                        action='store',\n                        default=None)\n\n    parser.add_argument('--disable-solc-warnings',\n                        help='Disable solc warnings',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--solc-ast',\n                        help='Provide the ast solc file',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--json',\n                        help='Export results as JSON',\n                        action='store',\n                        default=None)\n\n    parser.add_argument('--exclude-informational',\n                        help='Exclude informational impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-low',\n                        help='Exclude low impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-medium',\n                        help='Exclude medium impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-high',\n                        help='Exclude high impact analyses',\n                        action='store_true',\n                        default=False)\n\n    for detector_cls in detector_classes:\n        detector_arg = '--detect-{}'.format(detector_cls.ARGUMENT)\n        detector_help = '{}'.format(detector_cls.HELP)\n        parser.add_argument(detector_arg,\n                            help=detector_help,\n                            action=\"append_const\",\n                            dest=\"detectors_to_run\",\n                            const=detector_cls.ARGUMENT)\n\n    # Second loop so that the --exclude are shown after all the detectors\n    for detector_cls in detector_classes:\n        exclude_detector_arg = '--exclude-{}'.format(detector_cls.ARGUMENT)\n        exclude_detector_help = 'Exclude {} detector'.format(detector_cls.ARGUMENT)\n        parser.add_argument(exclude_detector_arg,\n                            help=exclude_detector_help,\n                            action=\"append_const\",\n                            dest=\"detectors_to_exclude\",\n                            const=detector_cls.ARGUMENT)\n\n    for printer_cls in printer_classes:\n        printer_arg = '--printer-{}'.format(printer_cls.ARGUMENT)\n        printer_help = 'Print {}'.format(printer_cls.HELP)\n        parser.add_argument(printer_arg,\n                            help=printer_help,\n                            action=\"append_const\",\n                            dest=\"printers_to_run\",\n                            const=printer_cls.ARGUMENT)\n\n    # debugger command\n    parser.add_argument('--debug',\n                        help=argparse.SUPPRESS,\n                        action=\"store_true\",\n                        default=False)\n\n    parser.add_argument('--markdown',\n                        help=argparse.SUPPRESS,\n                        action=\"store_true\",\n                        default=False)\n\n    return parser.parse_args()\n\n\ndef choose_detectors(args, all_detector_classes):\n    # If detectors are specified, run only these ones\n    if args.detectors_to_run:\n        return [d for d in all_detector_classes if d.ARGUMENT in args.detectors_to_run]\n\n    detectors_to_run = all_detector_classes\n\n    if args.exclude_informational:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.INFORMATIONAL]\n    if args.exclude_low:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.LOW]\n    if args.exclude_medium:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.MEDIUM]\n    if args.exclude_high:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.HIGH]\n    if args.detectors_to_exclude:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.ARGUMENT not in args.detectors_to_exclude]\n    return detectors_to_run\n\n\ndef choose_printers(args, all_printer_classes):\n    # by default, dont run any printer\n    printers_to_run = []\n    if args.printers_to_run:\n        printers_to_run = [p for p in all_printer_classes if\n                           p.ARGUMENT in args.printers_to_run]\n    return printers_to_run\n\n\nif __name__ == '__main__':\n    main()\n", "path": "slither/__main__.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nimport argparse\nimport glob\nimport json\nimport logging\nimport os\nimport sys\nimport traceback\n\nfrom pkg_resources import iter_entry_points\n\nfrom slither.detectors.abstract_detector import (AbstractDetector,\n                                                 DetectorClassification,\n                                                 classification_txt)\nfrom slither.printers.abstract_printer import AbstractPrinter\nfrom slither.slither import Slither\n\nlogging.basicConfig()\nlogger = logging.getLogger(\"Slither\")\n\ndef output_to_markdown(detector_classes):\n    \"\"\"\n        Pretty print of the detectors to README.md\n    \"\"\"\n    detectors_list = []\n    for detector in detector_classes:\n        argument = detector.ARGUMENT\n        # dont show the backdoor example\n        if argument == 'backdoor':\n            continue\n        help_info = detector.HELP\n        impact = detector.IMPACT\n        confidence = classification_txt[detector.CONFIDENCE]\n        detectors_list.append((argument, help_info, impact, confidence))\n\n    # Sort by impact and name\n    detectors_list = sorted(detectors_list, key=lambda element: (element[2], element[0]))\n    for (argument, help_info, impact, confidence) in detectors_list:\n        print('`--detect-{}`| Detect {} | {} | {}'.format(argument,\n                                                          help_info,\n                                                          classification_txt[impact],\n                                                          confidence))\n\ndef process(filename, args, detector_classes, printer_classes):\n    \"\"\"\n    The core high-level code for running Slither static analysis.\n\n    Returns:\n        list(result), int: Result list and number of contracts analyzed\n    \"\"\"\n    slither = Slither(filename, args.solc, args.disable_solc_warnings, args.solc_args)\n\n    for detector_cls in detector_classes:\n        slither.register_detector(detector_cls)\n\n    for printer_cls in printer_classes:\n        slither.register_printer(printer_cls)\n\n    analyzed_contracts_count = len(slither.contracts)\n\n    results = []\n\n    if printer_classes:\n        slither.run_printers()  # Currently printers does not return results\n\n    elif detector_classes:\n        detector_results = slither.run_detectors()\n        detector_results = [x for x in detector_results if x]  # remove empty results\n        detector_results = [item for sublist in detector_results for item in sublist]  # flatten\n\n        results.extend(detector_results)\n\n    return results, analyzed_contracts_count\n\n\ndef output_json(results, filename):\n    with open(filename, 'w') as f:\n        json.dump(results, f)\n\n\ndef exit(results):\n    if not results:\n        sys.exit(0)\n    sys.exit(len(results))\n\n\ndef main():\n    \"\"\"\n    NOTE: This contains just a few detectors and printers that we made public.\n    \"\"\"\n    from slither.detectors.examples.backdoor import Backdoor\n    from slither.detectors.variables.uninitialized_state_variables import UninitializedStateVarsDetection\n    from slither.detectors.attributes.constant_pragma import ConstantPragma\n    from slither.detectors.attributes.old_solc import OldSolc\n    from slither.detectors.attributes.locked_ether import LockedEther\n    from slither.detectors.functions.arbitrary_send import ArbitrarySend\n    from slither.detectors.functions.suicidal import Suicidal\n    from slither.detectors.reentrancy.reentrancy import Reentrancy\n    from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars\n    from slither.detectors.variables.unused_state_variables import UnusedStateVars\n    from slither.detectors.statements.tx_origin import TxOrigin\n    from slither.detectors.statements.assembly import Assembly\n    from slither.detectors.operations.low_level_calls import LowLevelCalls\n    from slither.detectors.naming_convention.naming_convention import NamingConvention\n\n    detectors = [Backdoor,\n                 UninitializedStateVarsDetection,\n                 ConstantPragma,\n                 OldSolc,\n                 Reentrancy,\n                 UninitializedStorageVars,\n                 LockedEther,\n                 ArbitrarySend,\n                 Suicidal,\n                 UnusedStateVars,\n                 TxOrigin,\n                 Assembly,\n                 LowLevelCalls,\n                 NamingConvention]\n\n    from slither.printers.summary.function import FunctionSummary\n    from slither.printers.summary.contract import ContractSummary\n    from slither.printers.inheritance.inheritance import PrinterInheritance\n    from slither.printers.inheritance.inheritance_graph import PrinterInheritanceGraph\n    from slither.printers.functions.authorization import PrinterWrittenVariablesAndAuthorization\n    from slither.printers.summary.slithir import PrinterSlithIR\n\n    printers = [FunctionSummary,\n                ContractSummary,\n                PrinterInheritance,\n                PrinterInheritanceGraph,\n                PrinterWrittenVariablesAndAuthorization,\n                PrinterSlithIR]\n\n    # Handle plugins!\n    for entry_point in iter_entry_points(group='slither_analyzer.plugin', name=None):\n        make_plugin = entry_point.load()\n\n        plugin_detectors, plugin_printers = make_plugin()\n\n        if not all(issubclass(d, AbstractDetector) for d in plugin_detectors):\n            raise Exception('Error when loading plugin %s, %r is not a detector' % (entry_point, d))\n\n        if not all(issubclass(p, AbstractPrinter) for p in plugin_printers):\n            raise Exception('Error when loading plugin %s, %r is not a printer' % (entry_point, p))\n\n        # We convert those to lists in case someone returns a tuple\n        detectors += list(plugin_detectors)\n        printers += list(plugin_printers)\n\n    main_impl(all_detector_classes=detectors, all_printer_classes=printers)\n\n\ndef main_impl(all_detector_classes, all_printer_classes):\n    \"\"\"\n    :param all_detector_classes: A list of all detectors that can be included/excluded.\n    :param all_printer_classes: A list of all printers that can be included.\n    \"\"\"\n    args = parse_args(all_detector_classes, all_printer_classes)\n\n    if args.markdown:\n        output_to_markdown(all_detector_classes)\n        return\n\n    detector_classes = choose_detectors(args, all_detector_classes)\n    printer_classes = choose_printers(args, all_printer_classes)\n\n    default_log = logging.INFO if not args.debug else logging.DEBUG\n\n    for (l_name, l_level) in [('Slither', default_log),\n                              ('Contract', default_log),\n                              ('Function', default_log),\n                              ('Node', default_log),\n                              ('Parsing', default_log),\n                              ('Detectors', default_log),\n                              ('FunctionSolc', default_log),\n                              ('ExpressionParsing', default_log),\n                              ('TypeParsing', default_log),\n                              ('Printers', default_log)]:\n        l = logging.getLogger(l_name)\n        l.setLevel(l_level)\n\n    try:\n        filename = args.filename\n\n        globbed_filenames = glob.glob(filename, recursive=True)\n\n        if os.path.isfile(filename):\n            (results, number_contracts) = process(filename, args, detector_classes, printer_classes)\n\n        elif os.path.isdir(filename) or len(globbed_filenames) > 0:\n            extension = \"*.sol\" if not args.solc_ast else \"*.json\"\n            filenames = glob.glob(os.path.join(filename, extension))\n            if len(filenames) == 0:\n                filenames = globbed_filenames\n            number_contracts = 0\n            results = []\n            for filename in filenames:\n                (results_tmp, number_contracts_tmp) = process(filename, args, detector_classes, printer_classes)\n                number_contracts += number_contracts_tmp\n                results += results_tmp\n            # if args.json:\n            #    output_json(results, args.json)\n            # exit(results)\n\n        else:\n            raise Exception(\"Unrecognised file/dir path: '#{filename}'\".format(filename=filename))\n\n        if args.json:\n            output_json(results, args.json)\n        # Dont print the number of result for printers\n        if printer_classes:\n            logger.info('%s analyzed (%d contracts)', filename, number_contracts)\n        else:\n            logger.info('%s analyzed (%d contracts), %d result(s) found', filename, number_contracts, len(results))\n        exit(results)\n\n    except Exception:\n        logging.error('Error in %s' % args.filename)\n        logging.error(traceback.format_exc())\n        sys.exit(-1)\n\n\ndef parse_args(detector_classes, printer_classes):\n    parser = argparse.ArgumentParser(description='Slither',\n                                     usage=\"slither.py contract.sol [flag]\",\n                                     formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=35))\n\n    parser.add_argument('filename',\n                        help='contract.sol file')\n\n    parser.add_argument('--solc',\n                        help='solc path',\n                        action='store',\n                        default='solc')\n\n    parser.add_argument('--solc-args',\n                        help='Add custom solc arguments. Example: --solc-args \"--allow-path /tmp --evm-version byzantium\".',\n                        action='store',\n                        default=None)\n\n    parser.add_argument('--disable-solc-warnings',\n                        help='Disable solc warnings',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--solc-ast',\n                        help='Provide the ast solc file',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--json',\n                        help='Export results as JSON',\n                        action='store',\n                        default=None)\n\n    parser.add_argument('--exclude-informational',\n                        help='Exclude informational impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-low',\n                        help='Exclude low impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-medium',\n                        help='Exclude medium impact analyses',\n                        action='store_true',\n                        default=False)\n\n    parser.add_argument('--exclude-high',\n                        help='Exclude high impact analyses',\n                        action='store_true',\n                        default=False)\n\n    for detector_cls in detector_classes:\n        detector_arg = '--detect-{}'.format(detector_cls.ARGUMENT)\n        detector_help = 'Detection of {}'.format(detector_cls.HELP)\n        parser.add_argument(detector_arg,\n                            help=detector_help,\n                            action=\"append_const\",\n                            dest=\"detectors_to_run\",\n                            const=detector_cls.ARGUMENT)\n\n    # Second loop so that the --exclude are shown after all the detectors\n    for detector_cls in detector_classes:\n        exclude_detector_arg = '--exclude-{}'.format(detector_cls.ARGUMENT)\n        exclude_detector_help = 'Exclude {} detector'.format(detector_cls.ARGUMENT)\n        parser.add_argument(exclude_detector_arg,\n                            help=exclude_detector_help,\n                            action=\"append_const\",\n                            dest=\"detectors_to_exclude\",\n                            const=detector_cls.ARGUMENT)\n\n    for printer_cls in printer_classes:\n        printer_arg = '--printer-{}'.format(printer_cls.ARGUMENT)\n        printer_help = 'Print {}'.format(printer_cls.HELP)\n        parser.add_argument(printer_arg,\n                            help=printer_help,\n                            action=\"append_const\",\n                            dest=\"printers_to_run\",\n                            const=printer_cls.ARGUMENT)\n\n    # debugger command\n    parser.add_argument('--debug',\n                        help=argparse.SUPPRESS,\n                        action=\"store_true\",\n                        default=False)\n\n    parser.add_argument('--markdown',\n                        help=argparse.SUPPRESS,\n                        action=\"store_true\",\n                        default=False)\n\n    return parser.parse_args()\n\n\ndef choose_detectors(args, all_detector_classes):\n    # If detectors are specified, run only these ones\n    if args.detectors_to_run:\n        return [d for d in all_detector_classes if d.ARGUMENT in args.detectors_to_run]\n\n    detectors_to_run = all_detector_classes\n\n    if args.exclude_informational:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.INFORMATIONAL]\n    if args.exclude_low:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.LOW]\n    if args.exclude_medium:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.MEDIUM]\n    if args.exclude_high:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.IMPACT != DetectorClassification.HIGH]\n    if args.detectors_to_exclude:\n        detectors_to_run = [d for d in detectors_to_run if\n                            d.ARGUMENT not in args.detectors_to_exclude]\n    return detectors_to_run\n\n\ndef choose_printers(args, all_printer_classes):\n    # by default, dont run any printer\n    printers_to_run = []\n    if args.printers_to_run:\n        printers_to_run = [p for p in all_printer_classes if\n                           p.ARGUMENT in args.printers_to_run]\n    return printers_to_run\n\n\nif __name__ == '__main__':\n    main()\n", "path": "slither/__main__.py"}]}