Completed
Push — 0.5.3 ( f700f6...c9a091 )
by Felipe A.
01:03
created

ArgParse._plugin()   A

Complexity

Conditions 2

Size

Total Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
#!/usr/bin/env python
2
# -*- coding: utf-8 -*-
3
4
import sys
5
import os
6
import os.path
7
import argparse
8
import fnmatch
9
import re
10
import flask
11
import warnings
12
import collections
13
14
from . import app, compat
15
from .compat import PY_LEGACY
16
17
18
class ArgParse(argparse.ArgumentParser):
19
    default_directory = os.path.abspath(compat.getcwd())
20
    default_host = os.getenv('BROWSEPY_HOST', '127.0.0.1')
21
    default_port = os.getenv('BROWSEPY_PORT', '8080')
22
    pattern_class = collections.namedtuple(
23
        'Pattern', ('original', 'regex', 'deep', 'rooted')
24
        )
25
26
    description = 'extendable web file browser'
27
28
    def __init__(self):
29
        super(ArgParse, self).__init__(description=self.description)
30
31
        self.add_argument(
32
            'host', nargs='?',
33
            default=self.default_host,
34
            help='address to listen (default: %(default)s)')
35
        self.add_argument(
36
            'port', nargs='?', type=int,
37
            default=self.default_port,
38
            help='port to listen (default: %(default)s)')
39
        self.add_argument(
40
            '--directory', metavar='PATH', type=self._directory,
41
            default=self.default_directory,
42
            help='base serving directory (default: current path)')
43
        self.add_argument(
44
            '--initial', metavar='PATH', type=self._directory,
45
            help='initial directory (default: same as --directory)')
46
        self.add_argument(
47
            '--removable', metavar='PATH', type=self._directory,
48
            default=None,
49
            help='base directory for remove (default: none)')
50
        self.add_argument(
51
            '--upload', metavar='PATH', type=self._directory,
52
            default=None,
53
            help='base directory for upload (default: none)')
54
        self.add_argument(
55
            '--exclude', metavar='PATTERN', type=self._pattern,
56
            action='append',
57
            default=[],
58
            help='exclude paths by pattern (multiple allowed)')
59
        self.add_argument(
60
            '--plugin', metavar='MODULE',
61
            action='append',
62
            default=[],
63
            help='load plugin module (multiple allowed)')
64
        self.add_argument('--debug', action='store_true', help='debug mode')
65
66
    def _pattern(self, arg):
67
        deep = '**' in arg
68
        rooted = arg.startswith('/')
69
        return self.pattern_class(arg, fnmatch.translate(arg), deep, rooted)
70
71
    def _directory(self, arg):
72
        if not arg:
73
            return None
74
        if PY_LEGACY and hasattr(sys.stdin, 'encoding'):
75
            encoding = sys.stdin.encoding or sys.getdefaultencoding()
76
            arg = arg.decode(encoding)
77
        if os.path.isdir(arg):
78
            return os.path.abspath(arg)
79
        self.error('%s is not a valid directory' % arg)
80
81
82
def main(argv=sys.argv[1:], app=app, parser=ArgParse, run_fnc=flask.Flask.run):
83
    plugin_manager = app.extensions['plugin_manager']
84
    args = plugin_manager.load_arguments(argv, parser())
85
    plugins = args.plugin[:]
86
    if args.plugin and any(',' in plugin for plugin in args.plugin):
87
        warnings.warn(
88
            'Comma-separated --plugin value is deprecated, '
89
            'use multiple --plugin instead.'
90
            )
91
        added = 0
92
        for n, plugin in enumerate(plugins[:]):
93
            if ',' in plugin:
94
                multi = plugin.split(',')
95
                plugins[n + added:n + added + 1] = multi
96
                added += len(multi) - 1
97
    os.environ['DEBUG'] = 'true' if args.debug else ''
98
    app.config.update(
99
        directory_base=args.directory,
100
        directory_start=args.initial or args.directory,
101
        directory_remove=args.removable,
102
        directory_upload=args.upload,
103
        plugin_modules=plugins
104
        )
105
    if args.exclude:
106
        redeep = re.compile(
107
            '|'.join(i.regex for i in args.exclude if i.deep)
108
            ).match
109
        reflat = re.compile(
110
            '{sep}({pattern})'.format(
111
                sep=re.escape(os.sep),
112
                pattern='|'.join(i.regex for i in args.exclude if not i.deep)
113
                )
114
            ).search
115
        app.config['exclude_fnc'] = lambda path: redeep(path) or reflat(path)
116
    plugin_manager.reload()
117
    run_fnc(
118
        app,
119
        host=args.host,
120
        port=args.port,
121
        debug=args.debug,
122
        use_reloader=False,
123
        threaded=True
124
        )
125
126
127
if __name__ == '__main__':
128
    main()
129