1212
1313
1414class Downloader (object ):
15+ """Class that downloads a dxFeed C API bundle and places the necessary include or lib files"""
16+
1517 def __init__ (self , version : str , path_to_extract : Path ,
1618 path_to_copy_includes : Path , path_to_copy_libs : Path ):
19+ """
20+ Parameters
21+ ----------
22+ version : str
23+ The dxFeed C API version
24+ path_to_extract : Path
25+ The temporary directory where the bundle should be unpacked
26+ path_to_copy_includes : Path
27+ The directory where the include files should be placed
28+ path_to_copy_libs
29+ The directory where the library files should be placed
30+ """
31+
1732 self .__version = version
1833 self .__path_to_extract = path_to_extract
1934 self .__path_to_copy_includes = path_to_copy_includes
2035 self .__path_to_copy_libs = path_to_copy_libs
2136
22- def download (self ) -> str :
23- __c_api_extracted_root_dir = self . __path_to_extract / f'dxfeed-c-api- { self . __version } -no-tls'
24- is_x64 = 8 * struct . calcsize ( "P" ) == 64
37+ def download (self , dxfeed_c_api_bundle_url_template : str ) -> str :
38+ """
39+ The method that does the bulk of the work of downloading and placement files.
2540
26- if platform .system () == 'Windows' :
27- current_os = 'windows'
28- elif platform .system () == 'Darwin' :
29- current_os = 'macosx'
30- else :
31- current_os = 'centos' # Since centos uses an earlier version of libc
3241
33- if (not os .path .exists (self .__path_to_extract )) or (not os .path .exists (__c_api_extracted_root_dir )):
34- url = f'https://github.com/dxFeed/dxfeed-c-api/releases/download/{ self .__version } /dxfeed-c-api-' \
35- f'{ self .__version } -{ current_os } -no-tls.zip '
42+ Parameters
43+ ----------
44+ dxfeed_c_api_bundle_url_template: str
45+ The URL template for zipped dxFeed C API bundle. Parameters used:
46+ {version} - The C API version
47+ {os} - The target OS
48+
49+ Returns
50+ -------
51+ : str
52+ The resulting name of the library, which is required to build an extension
53+
54+ """
55+ c_api_extracted_root_path = self .__path_to_extract / f'dxfeed-c-api-{ self .__version } -no-tls'
56+ is_x64 = 8 * struct .calcsize ('P' ) == 64
57+
58+ url_template_os = 'centos' # Since centos uses an earlier version of libc
59+
60+ if platform .system () == 'Darwin' :
61+ url_template_os = 'macosx'
62+ elif platform .system () == 'Windows' :
63+ url_template_os = 'windows'
64+
65+ if (not os .path .exists (self .__path_to_extract )) or (not os .path .exists (c_api_extracted_root_path )):
66+ url = dxfeed_c_api_bundle_url_template .format (version = self .__version , os = url_template_os )
3667 print (f'Downloading the "{ url } "' )
3768 resp = urlopen (url )
3869 zipfile = ZipFile (BytesIO (resp .read ()))
3970 print (f'Extracting to "{ self .__path_to_extract } "' )
4071 zipfile .extractall (self .__path_to_extract )
4172
42- if is_x64 :
43- c_api_x64_suffix = '_64'
44- else :
45- c_api_x64_suffix = ''
73+ c_api_x64_suffix = '_64' if is_x64 else ''
74+ resulting_c_api_library_name = f'DXFeed{ c_api_x64_suffix } '
4675
47- __c_api_library_name = f'DXFeed{ c_api_x64_suffix } '
76+ # Determine and fixing paths for unpacked artifacts.
77+ # The workaround is related to the packaging feature on POSIX systems in the dxFeed API' CI\CD.
78+ if is_x64 :
79+ if platform .system () != 'Windows' :
80+ c_api_extracted_root_path = c_api_extracted_root_path / f'DXFeedAll-{ self .__version } -x64-no-tls'
4881
49- if platform .system () == 'Windows' :
50- if is_x64 :
51- c_api_extracted_library_dir = __c_api_extracted_root_dir / 'bin' / 'x64'
52- c_api_library_file_name = f'{ __c_api_library_name } .dll'
53- c_api_library_file_name2 = f'{ __c_api_library_name } .lib'
54- else :
55- c_api_extracted_library_dir = __c_api_extracted_root_dir / 'bin' / 'x86'
56- c_api_library_file_name = f'{ __c_api_library_name } .dll'
57- c_api_library_file_name2 = f'{ __c_api_library_name } .lib'
58- elif platform .system () == 'Darwin' :
59- if is_x64 :
60- __c_api_extracted_root_dir = __c_api_extracted_root_dir / f'DXFeedAll-{ self .__version } -x64-no-tls'
61- c_api_extracted_library_dir = __c_api_extracted_root_dir / 'bin' / 'x64'
62- c_api_library_file_name = f'lib{ __c_api_library_name } .dylib'
63- else :
64- raise Exception ('Unsupported platform' )
82+ c_api_extracted_library_path = c_api_extracted_root_path / 'bin' / 'x64'
6583 else :
66- if is_x64 :
67- __c_api_extracted_root_dir = __c_api_extracted_root_dir / f'DXFeedAll-{ self .__version } -x64-no-tls'
68- c_api_extracted_library_dir = __c_api_extracted_root_dir / 'bin' / 'x64'
69- c_api_library_file_name = f'lib{ __c_api_library_name } .so'
84+ if platform .system () == 'Windows' :
85+ c_api_extracted_library_path = c_api_extracted_root_path / 'bin' / 'x86'
7086 else :
71- raise Exception ('Unsupported platform' )
87+ raise RuntimeError ('Unsupported platform' )
88+
89+ # Determine possible prefixes and extensions for library files
90+ lib_file_name_prefixes = ['' ] * 2
91+ lib_file_name_extensions = ['dll' , 'lib' ]
92+
93+ if platform .system () != 'Windows' :
94+ lib_file_name_prefixes = ['lib' ]
95+ lib_file_name_extensions = ['dylib' ] if platform .system () == 'Darwin' else ['so' ]
96+
97+ # Create paths for libraries to be copied
98+ c_api_library_file_source_paths = []
99+ c_api_library_file_dest_paths = []
100+
101+ for idx , prefix in enumerate (lib_file_name_prefixes ):
102+ file_name = f'{ prefix } { resulting_c_api_library_name } .{ lib_file_name_extensions [idx ]} '
103+ c_api_library_file_source_paths .append (c_api_extracted_library_path / file_name )
104+ c_api_library_file_dest_paths .append (self .__path_to_copy_libs / file_name )
105+
106+ print ('Copying all headers' )
107+ # Copying all headers
108+ if not Path (self .__path_to_copy_includes ).exists ():
109+ shutil .copytree (c_api_extracted_root_path / 'include' , self .__path_to_copy_includes )
110+
111+ # Create a directory where we will copy libraries, if necessary
112+ if not Path (self .__path_to_copy_libs ).exists ():
113+ print (f'Creating the { self .__path_to_copy_libs } path' )
114+ os .makedirs (self .__path_to_copy_libs )
72115
73- if not os .path .exists (self .__path_to_copy_includes ):
74- shutil .copytree (__c_api_extracted_root_dir / 'include' , self .__path_to_copy_includes )
75- if not os .path .exists (self .__path_to_copy_libs / c_api_library_file_name ):
76- if not os .path .exists (self .__path_to_copy_libs ):
77- os .makedirs (self .__path_to_copy_libs )
78- shutil .copyfile (c_api_extracted_library_dir / c_api_library_file_name ,
79- self .__path_to_copy_libs / c_api_library_file_name )
80- if platform .system () == 'Windows' :
81- # noinspection PyUnboundLocalVariable
82- if not os .path .exists (self .__path_to_copy_libs / c_api_library_file_name2 ):
83- shutil .copyfile (c_api_extracted_library_dir / c_api_library_file_name2 ,
84- self .__path_to_copy_libs / c_api_library_file_name2 )
116+ print ('Copying the required libraries' )
117+ # Copying the required libraries
118+ for idx , path in enumerate (c_api_library_file_source_paths ):
119+ print (f' { path } -> { c_api_library_file_dest_paths [idx ]} ' )
120+ shutil .copyfile (path , c_api_library_file_dest_paths [idx ])
85121
86- return __c_api_library_name
122+ return resulting_c_api_library_name
87123
88124
89125try :
@@ -108,7 +144,7 @@ def download(self) -> str:
108144c_api_bin_dir = root_path / 'dxfeed' / 'core'
109145
110146downloader = Downloader (c_api_version , path_to_extract , c_api_include_dir , c_api_bin_dir )
111- c_api_library_name = downloader .download ()
147+ c_api_library_name = downloader .download (pyproject [ 'build' ][ 'native-dependencies' ][ 'dxfeed_c_api_bundle_url_template' ] )
112148
113149if platform .system () == 'Windows' :
114150 runtime_library_dirs = None
0 commit comments