11import sys
22
3- from Cython .Build import cythonize
3+ import os .path
4+ import pathlib
45
5- vi = sys .version_info
6- if vi < (3 , 8 ):
7- raise RuntimeError ('httptools require Python 3.8 or greater' )
8- else :
9- import os .path
10- import pathlib
11-
12- from setuptools import setup , Extension
13- from setuptools .command .build_ext import build_ext as build_ext
6+ from setuptools import setup , Extension
7+ from setuptools .command .build_ext import build_ext as build_ext
148
159
1610CFLAGS = ['-O2' ]
1711
1812ROOT = pathlib .Path (__file__ ).parent
1913
20- CYTHON_DEPENDENCY = 'Cython>=3.1.0'
21-
2214
2315class httptools_build_ext (build_ext ):
2416 user_options = build_ext .user_options + [
17+ ('cython-always' , None ,
18+ 'run cythonize() even if .c files are present' ),
19+ ('cython-annotate' , None ,
20+ 'Produce a colorized HTML version of the Cython source.' ),
21+ ('cython-directives=' , None ,
22+ 'Cythion compiler directives' ),
2523 ('use-system-llhttp' , None ,
2624 'Use the system provided llhttp, instead of the bundled one' ),
2725 ('use-system-http-parser' , None ,
2826 'Use the system provided http-parser, instead of the bundled one' ),
2927 ]
3028
3129 boolean_options = build_ext .boolean_options + [
30+ 'cython-always' ,
31+ 'cython-annotate' ,
3232 'use-system-llhttp' ,
3333 'use-system-http-parser' ,
3434 ]
@@ -43,6 +43,9 @@ def initialize_options(self):
4343 super ().initialize_options ()
4444 self .use_system_llhttp = False
4545 self .use_system_http_parser = False
46+ self .cython_always = False
47+ self .cython_annotate = None
48+ self .cython_directives = None
4649
4750 def finalize_options (self ):
4851 # finalize_options() may be called multiple times on the
@@ -51,6 +54,43 @@ def finalize_options(self):
5154 if getattr (self , '_initialized' , False ):
5255 return
5356
57+ need_cythonize = self .cython_always
58+ cfiles = {}
59+
60+ for extension in self .distribution .ext_modules :
61+ for i , sfile in enumerate (extension .sources ):
62+ if sfile .endswith ('.pyx' ):
63+ prefix , ext = os .path .splitext (sfile )
64+ cfile = prefix + '.c'
65+
66+ if os .path .exists (cfile ) and not self .cython_always :
67+ extension .sources [i ] = cfile
68+ else :
69+ if os .path .exists (cfile ):
70+ cfiles [cfile ] = os .path .getmtime (cfile )
71+ else :
72+ cfiles [cfile ] = 0
73+ need_cythonize = True
74+
75+ if need_cythonize :
76+ from Cython .Build import cythonize
77+
78+ directives = {}
79+ if self .cython_directives :
80+ for directive in self .cython_directives .split (',' ):
81+ k , _ , v = directive .partition ('=' )
82+ if v .lower () == 'false' :
83+ v = False
84+ if v .lower () == 'true' :
85+ v = True
86+
87+ directives [k ] = v
88+
89+ self .distribution .ext_modules [:] = cythonize (
90+ self .distribution .ext_modules ,
91+ compiler_directives = directives ,
92+ annotate = self .cython_annotate )
93+
5494 super ().finalize_options ()
5595
5696 self ._initialized = True
@@ -100,14 +140,6 @@ def build_extensions(self):
100140 'unable to read the version from httptools/_version.py' )
101141
102142
103- setup_requires = []
104-
105- if (not (ROOT / 'httptools' / 'parser' / 'parser.c' ).exists () or
106- '--cython-always' in sys .argv ):
107- # No Cython output, require Cython to build.
108- setup_requires .append (CYTHON_DEPENDENCY )
109-
110-
111143setup (
112144 version = VERSION ,
113145 platforms = ['macOS' , 'POSIX' , 'Windows' ],
@@ -116,7 +148,7 @@ def build_extensions(self):
116148 cmdclass = {
117149 'build_ext' : httptools_build_ext ,
118150 },
119- ext_modules = cythonize ( [
151+ ext_modules = [
120152 Extension (
121153 "httptools.parser.parser" ,
122154 sources = [
@@ -131,14 +163,7 @@ def build_extensions(self):
131163 ],
132164 extra_compile_args = CFLAGS ,
133165 ),
134- ]) ,
166+ ],
135167 include_package_data = True ,
136168 exclude_package_data = {"" : ["*.c" , "*.h" ]},
137- test_suite = 'tests.suite' ,
138- setup_requires = setup_requires ,
139- extras_require = {
140- 'test' : [
141- CYTHON_DEPENDENCY
142- ]
143- }
144169)
0 commit comments