cython

Форк
0
/
CmdLine.py 
243 строки · 12.0 Кб
1
#
2
#   Cython - Command Line Parsing
3
#
4

5

6
import os
7
from argparse import ArgumentParser, Action, SUPPRESS
8
from . import Options
9

10

11
class ParseDirectivesAction(Action):
12
    def __call__(self, parser, namespace, values, option_string=None):
13
        old_directives = dict(getattr(namespace, self.dest,
14
                                      Options.get_directive_defaults()))
15
        directives = Options.parse_directive_list(
16
            values, relaxed_bool=True, current_settings=old_directives)
17
        setattr(namespace, self.dest, directives)
18

19

20
class ParseOptionsAction(Action):
21
    def __call__(self, parser, namespace, values, option_string=None):
22
        options = dict(getattr(namespace, self.dest, {}))
23
        for opt in values.split(','):
24
            if '=' in opt:
25
                n, v = opt.split('=', 1)
26
                v = v.lower() not in ('false', 'f', '0', 'no')
27
            else:
28
                n, v = opt, True
29
            options[n] = v
30
        setattr(namespace, self.dest, options)
31

32

33
class ParseCompileTimeEnvAction(Action):
34
    def __call__(self, parser, namespace, values, option_string=None):
35
        old_env = dict(getattr(namespace, self.dest, {}))
36
        new_env = Options.parse_compile_time_env(values, current_settings=old_env)
37
        setattr(namespace, self.dest, new_env)
38

39

40
class ActivateAllWarningsAction(Action):
41
    def __call__(self, parser, namespace, values, option_string=None):
42
        directives = getattr(namespace, 'compiler_directives', {})
43
        directives.update(Options.extra_warnings)
44
        namespace.compiler_directives = directives
45

46

47
class SetLenientAction(Action):
48
    def __call__(self, parser, namespace, values, option_string=None):
49
        namespace.error_on_unknown_names = False
50
        namespace.error_on_uninitialized = False
51

52

53
class SetGDBDebugAction(Action):
54
    def __call__(self, parser, namespace, values, option_string=None):
55
        namespace.gdb_debug = True
56
        namespace.output_dir = os.curdir
57

58

59
class SetGDBDebugOutputAction(Action):
60
    def __call__(self, parser, namespace, values, option_string=None):
61
        namespace.gdb_debug = True
62
        namespace.output_dir = values
63

64

65
class SetAnnotateCoverageAction(Action):
66
    def __call__(self, parser, namespace, values, option_string=None):
67
        namespace.annotate = True
68
        namespace.annotate_coverage_xml = values
69

70

71
def create_cython_argparser():
72
    description = "Cython (https://cython.org/) is a compiler for code written in the "\
73
                  "Cython language.  Cython is based on Pyrex by Greg Ewing."
74

75
    parser = ArgumentParser(description=description, argument_default=SUPPRESS)
76

77
    parser.add_argument("-V", "--version", dest='show_version', action='store_const', const=1,
78
                      help='Display version number of cython compiler')
79
    parser.add_argument("-l", "--create-listing", dest='use_listing_file', action='store_const', const=1,
80
                      help='Write error messages to a listing file')
81
    parser.add_argument("-I", "--include-dir", dest='include_path', action='append',
82
                      help='Search for include files in named directory '
83
                           '(multiple include directories are allowed).')
84
    parser.add_argument("-o", "--output-file", dest='output_file', action='store', type=str,
85
                      help='Specify name of generated C file')
86
    parser.add_argument("-t", "--timestamps", dest='timestamps', action='store_const', const=1,
87
                      help='Only compile newer source files')
88
    parser.add_argument("-f", "--force", dest='timestamps', action='store_const', const=0,
89
                      help='Compile all source files (overrides implied -t)')
90
    parser.add_argument("-v", "--verbose", dest='verbose', action='count',
91
                      help='Be verbose, print file names on multiple compilation')
92
    parser.add_argument("-p", "--embed-positions", dest='embed_pos_in_docstring', action='store_const', const=1,
93
                      help='If specified, the positions in Cython files of each '
94
                           'function definition is embedded in its docstring.')
95
    parser.add_argument("--cleanup", dest='generate_cleanup_code', action='store', type=int,
96
                      help='Release interned objects on python exit, for memory debugging. '
97
                           'Level indicates aggressiveness, default 0 releases nothing.')
98
    parser.add_argument("-w", "--working", dest='working_path', action='store', type=str,
99
                      help='Sets the working directory for Cython (the directory modules are searched from)')
100
    parser.add_argument("--gdb", action=SetGDBDebugAction, nargs=0,
101
                      help='Output debug information for cygdb')
102
    parser.add_argument("--gdb-outdir", action=SetGDBDebugOutputAction, type=str,
103
                      help='Specify gdb debug information output directory. Implies --gdb.')
104
    parser.add_argument("-D", "--no-docstrings", dest='docstrings', action='store_false',
105
                      help='Strip docstrings from the compiled module.')
106
    parser.add_argument('-a', '--annotate', action='store_const', const='default', dest='annotate',
107
                      help='Produce a colorized HTML version of the source.')
108
    parser.add_argument('--annotate-fullc', action='store_const', const='fullc', dest='annotate',
109
                      help='Produce a colorized HTML version of the source '
110
                           'which includes entire generated C/C++-code.')
111
    parser.add_argument("--annotate-coverage", dest='annotate_coverage_xml', action=SetAnnotateCoverageAction, type=str,
112
                      help='Annotate and include coverage information from cov.xml.')
113
    parser.add_argument("--line-directives", dest='emit_linenums', action='store_true',
114
                      help='Produce #line directives pointing to the .pyx source')
115
    parser.add_argument("-+", "--cplus", dest='cplus', action='store_const', const=1,
116
                      help='Output a C++ rather than C file.')
117
    parser.add_argument('--embed', action='store_const', const='main',
118
                      help='Generate a main() function that embeds the Python interpreter. '
119
                           'Pass --embed=<method_name> for a name other than main().')
120
    parser.add_argument('-2', dest='language_level', action='store_const', const=2,
121
                      help='Compile based on Python-2 syntax and code semantics.')
122
    parser.add_argument('-3', dest='language_level', action='store_const', const=3,
123
                      help='Compile based on Python-3 syntax and code semantics.')
124
    parser.add_argument('--3str', dest='language_level', action='store_const', const='3',
125
                      help='Compile based on Python-3 syntax and code semantics (same as -3 since Cython 3.1).')
126
    parser.add_argument("--lenient", action=SetLenientAction, nargs=0,
127
                      help='Change some compile time errors to runtime errors to '
128
                           'improve Python compatibility')
129
    parser.add_argument("--capi-reexport-cincludes", dest='capi_reexport_cincludes', action='store_true',
130
                      help='Add cincluded headers to any auto-generated header files.')
131
    parser.add_argument("--fast-fail", dest='fast_fail', action='store_true',
132
                      help='Abort the compilation on the first error')
133
    parser.add_argument("-Werror", "--warning-errors", dest='warning_errors', action='store_true',
134
                      help='Make all warnings into errors')
135
    parser.add_argument("-Wextra", "--warning-extra", action=ActivateAllWarningsAction, nargs=0,
136
                      help='Enable extra warnings')
137

138
    parser.add_argument('-X', '--directive', metavar='NAME=VALUE,...',
139
                      dest='compiler_directives', type=str,
140
                      action=ParseDirectivesAction,
141
                      help='Overrides a compiler directive')
142
    parser.add_argument('-E', '--compile-time-env', metavar='NAME=VALUE,...',
143
                      dest='compile_time_env', type=str,
144
                      action=ParseCompileTimeEnvAction,
145
                      help='Provides compile time env like DEF would do.')
146
    parser.add_argument("--module-name",
147
                      dest='module_name', type=str, action='store',
148
                      help='Fully qualified module name. If not given, is '
149
                           'deduced from the import path if source file is in '
150
                           'a package, or equals the filename otherwise.')
151
    parser.add_argument('-M', '--depfile', action='store_true', help='produce depfiles for the sources')
152
    parser.add_argument('sources', nargs='*', default=[])
153

154
    # TODO: add help
155
    parser.add_argument("-z", "--pre-import", dest='pre_import', action='store', type=str, help=SUPPRESS)
156
    parser.add_argument("--convert-range", dest='convert_range', action='store_true', help=SUPPRESS)
157
    parser.add_argument("--no-c-in-traceback", dest='c_line_in_traceback', action='store_false', help=SUPPRESS)
158
    parser.add_argument("--cimport-from-pyx", dest='cimport_from_pyx', action='store_true', help=SUPPRESS)
159
    parser.add_argument("--old-style-globals", dest='old_style_globals', action='store_true', help=SUPPRESS)
160

161
    # debug stuff:
162
    from . import DebugFlags
163
    for name in vars(DebugFlags):
164
        if name.startswith("debug"):
165
            option_name = name.replace('_', '-')
166
            parser.add_argument("--" + option_name, action='store_true', help=SUPPRESS)
167

168
    return parser
169

170

171
def parse_command_line_raw(parser, args):
172
    # special handling for --embed and --embed=xxxx as they aren't correctly parsed
173
    def filter_out_embed_options(args):
174
        with_embed, without_embed = [], []
175
        for x in args:
176
            if x == '--embed' or x.startswith('--embed='):
177
                with_embed.append(x)
178
            else:
179
                without_embed.append(x)
180
        return with_embed, without_embed
181

182
    with_embed, args_without_embed = filter_out_embed_options(args)
183

184
    arguments, unknown = parser.parse_known_args(args_without_embed)
185

186
    sources = arguments.sources
187
    del arguments.sources
188

189
    # unknown can be either debug, embed or input files or really unknown
190
    for option in unknown:
191
        if option.startswith('-'):
192
            parser.error("unknown option " + option)
193
        else:
194
            sources.append(option)
195

196
    # embed-stuff must be handled extra:
197
    for x in with_embed:
198
        if x == '--embed':
199
            name = 'main'  # default value
200
        else:
201
            name = x[len('--embed='):]
202
        setattr(arguments, 'embed', name)
203

204
    return arguments, sources
205

206

207
def parse_command_line(args):
208
    parser = create_cython_argparser()
209
    arguments, sources = parse_command_line_raw(parser, args)
210

211
    work_dir = getattr(arguments, 'working_path', '')
212
    for source in sources:
213
        if work_dir and not os.path.isabs(source):
214
            source = os.path.join(work_dir, source)
215
        if not os.path.exists(source):
216
            import errno
217
            raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), source)
218

219
    options = Options.CompilationOptions(Options.default_options)
220
    for name, value in vars(arguments).items():
221
        if name.startswith('debug'):
222
            from . import DebugFlags
223
            if name in dir(DebugFlags):
224
                setattr(DebugFlags, name, value)
225
            else:
226
                parser.error("Unknown debug flag: %s\n" % name)
227
        elif hasattr(Options, name):
228
            setattr(Options, name, value)
229
        else:
230
            setattr(options, name, value)
231

232
    if options.use_listing_file and len(sources) > 1:
233
        parser.error("cython: Only one source file allowed when using -o\n")
234
    if len(sources) == 0 and not options.show_version:
235
        parser.error("cython: Need at least one source file\n")
236
    if Options.embed and len(sources) > 1:
237
        parser.error("cython: Only one source file allowed when using --embed\n")
238
    if options.module_name:
239
        if options.timestamps:
240
            parser.error("cython: Cannot use --module-name with --timestamps\n")
241
        if len(sources) > 1:
242
            parser.error("cython: Only one source file allowed when using --module-name\n")
243
    return options, sources
244

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.