utils.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. # !/usr/bin/env python3
  2. # -*- coding: UTF-8 -*-
  3. ################################################################################
  4. #
  5. # Copyright (c) 2024 Baidu.com, Inc. All Rights Reserved
  6. #
  7. ################################################################################
  8. """
  9. Author: PaddlePaddle Authors
  10. """
  11. import os
  12. import sys
  13. import json
  14. import subprocess
  15. import contextlib
  16. from parsley import makeGrammar
  17. def _check_call(*args, **kwargs):
  18. return subprocess.check_call(*args, **kwargs)
  19. def _check_output(*args, **kwargs):
  20. return subprocess.check_output(*args, **kwargs)
  21. def check_installation_using_pip(pkg):
  22. """ check_installation_using_pip """
  23. out = _check_output(['pip', 'list', '--format', 'json'])
  24. out = out.rstrip()
  25. lst = json.loads(out)
  26. return any(ele['name'] == pkg for ele in lst)
  27. def uninstall_package_using_pip(pkg):
  28. """ uninstall_package_using_pip """
  29. return _check_call([sys.executable, '-m', 'pip', 'uninstall', '-y', pkg])
  30. def install_packages_using_pip(pkgs,
  31. editable=False,
  32. req_files=None,
  33. cons_files=None,
  34. no_deps=False,
  35. pip_flags=None):
  36. """ install_packages_using_pip """
  37. args = [sys.executable, '-m', 'pip', 'install']
  38. if editable:
  39. args.append('-e')
  40. if req_files is not None:
  41. for req_file in req_files:
  42. args.append('-r')
  43. args.append(req_file)
  44. if cons_files is not None:
  45. for cons_file in cons_files:
  46. args.append('-c')
  47. args.append(cons_file)
  48. if isinstance(pkgs, str):
  49. pkgs = [pkgs]
  50. args.extend(pkgs)
  51. if pip_flags is not None:
  52. args.extend(pip_flags)
  53. return _check_call(args)
  54. def install_deps_using_pip():
  55. """ install requirements """
  56. current_file_path = os.path.dirname(os.path.abspath(__file__))
  57. deps_path = os.path.join(current_file_path, 'requirements.txt')
  58. args = [sys.executable, '-m', 'pip', 'install', '-r', deps_path]
  59. return _check_call(args)
  60. def clone_repos_using_git(url, branch=None):
  61. """ clone_repos_using_git """
  62. args = ['git', 'clone']
  63. if isinstance(url, str):
  64. url = [url]
  65. args.extend(url)
  66. if branch is not None:
  67. args.extend(['-b', branch])
  68. return _check_call(args)
  69. def update_repos_using_git():
  70. """ update_repos_using_git """
  71. args = ['git', 'pull']
  72. return _check_call(args)
  73. def remove_repos_using_rm(name):
  74. """ remove_repos_using_rm """
  75. return _check_call(['rm', '-rf', name])
  76. def build_wheel_using_pip(pkg, dst_dir='./', with_deps=False, pip_flags=None):
  77. """ build_wheel_using_pip """
  78. args = [sys.executable, '-m', 'pip', 'wheel', '--wheel-dir', dst_dir]
  79. if not with_deps:
  80. args.append('--no-deps')
  81. if pip_flags is not None:
  82. args.extend(pip_flags)
  83. args.append(pkg)
  84. return _check_call(args)
  85. @contextlib.contextmanager
  86. def mute():
  87. """ mute """
  88. with open(os.devnull, 'w') as f:
  89. with contextlib.redirect_stdout(f), contextlib.redirect_stderr(f):
  90. yield
  91. @contextlib.contextmanager
  92. def switch_working_dir(new_wd):
  93. """ switch_working_dir """
  94. cwd = os.getcwd()
  95. os.chdir(new_wd)
  96. try:
  97. yield
  98. finally:
  99. os.chdir(cwd)
  100. def _build_dep_spec_pep508_grammar():
  101. # Refer to https://peps.python.org/pep-0508/
  102. grammar = """
  103. wsp = ' ' | '\t'
  104. version_cmp = wsp* <'<=' | '<' | '!=' | '==' | '>=' | '>' | '~=' | '==='>
  105. version = wsp* <(letterOrDigit | '-' | '_' | '.' | '*' | '+' | '!')+>
  106. version_one = version_cmp:op version:v wsp* -> (op, v)
  107. version_many = version_one:v1 (wsp* ',' version_one)*:v2 -> [v1] + v2
  108. versionspec = ('(' version_many:v ')' ->v) | version_many
  109. urlspec = '@' wsp* <uri_reference>
  110. marker_op = version_cmp | (wsp* 'in') | (wsp* 'not' wsp+ 'in')
  111. python_str_c = (wsp | letter | digit | '(' | ')' | '.' | '{' | '}' |
  112. '-' | '_' | '*' | '#' | ':' | ';' | ',' | '/' | '?' |
  113. '[' | ']' | '!' | '~' | '`' | '@' | '$' | '%' | '^' |
  114. '&' | '=' | '+' | '|' | '<' | '>' )
  115. dquote = '"'
  116. squote = '\\''
  117. comment = '#' <anything*>:s end -> s
  118. python_str = (squote <(python_str_c | dquote)*>:s squote |
  119. dquote <(python_str_c | squote)*>:s dquote) -> s
  120. env_var = ('python_version' | 'python_full_version' |
  121. 'os_name' | 'sys_platform' | 'platform_release' |
  122. 'platform_system' | 'platform_version' |
  123. 'platform_machine' | 'platform_python_implementation' |
  124. 'implementation_name' | 'implementation_version' |
  125. 'extra' # ONLY when defined by a containing layer
  126. )
  127. marker_var = wsp* (env_var | python_str)
  128. marker_expr = marker_var:l marker_op:o marker_var:r -> (o, l, r)
  129. | wsp* '(' marker:m wsp* ')' -> m
  130. marker_and = marker_expr:l wsp* 'and' marker_expr:r -> ('and', l, r)
  131. | marker_expr:m -> m
  132. marker_or = marker_and:l wsp* 'or' marker_and:r -> ('or', l, r)
  133. | marker_and:m -> m
  134. marker = marker_or
  135. quoted_marker = ';' wsp* marker
  136. identifier_end = letterOrDigit | (('-' | '_' | '.' )* letterOrDigit)
  137. identifier = <letterOrDigit identifier_end* >
  138. name = identifier
  139. extras_list = identifier:i (wsp* ',' wsp* identifier)*:ids -> [i] + ids
  140. extras = '[' wsp* extras_list?:e wsp* ']' -> e
  141. name_req = (name:n wsp* extras?:e wsp* versionspec?:v wsp* quoted_marker?:m
  142. -> (n, e or [], v or [], m))
  143. url_req = (name:n wsp* extras?:e wsp* urlspec:v (wsp+ | end) quoted_marker?:m
  144. -> (n, e or [], v, m))
  145. specification = wsp* (url_req | name_req):s wsp* comment? -> s
  146. # The result is a tuple - name, list-of-extras,
  147. # list-of-version-constraints-or-a-url, marker-ast or None
  148. uri_reference = <uri | relative_ref>
  149. uri = scheme ':' hier_part ('?' query )? ('#' fragment)?
  150. hier_part = ('//' authority path_abempty) | path_absolute | path_rootless | path_empty
  151. absolute_uri = scheme ':' hier_part ('?' query )?
  152. relative_ref = relative_part ('?' query )? ('#' fragment )?
  153. relative_part = '//' authority path_abempty | path_absolute | path_noscheme | path_empty
  154. scheme = letter (letter | digit | '+' | '-' | '.')*
  155. authority = (userinfo '@' )? host (':' port )?
  156. userinfo = (unreserved | pct_encoded | sub_delims | ':')*
  157. host = ip_literal | ipv4_address | reg_name
  158. port = digit*
  159. ip_literal = '[' (ipv6_address | ipvfuture) ']'
  160. ipvfuture = 'v' hexdig+ '.' (unreserved | sub_delims | ':')+
  161. ipv6_address = (
  162. (h16 ':'){6} ls32
  163. | '::' (h16 ':'){5} ls32
  164. | (h16 )? '::' (h16 ':'){4} ls32
  165. | ((h16 ':')? h16 )? '::' (h16 ':'){3} ls32
  166. | ((h16 ':'){0,2} h16 )? '::' (h16 ':'){2} ls32
  167. | ((h16 ':'){0,3} h16 )? '::' h16 ':' ls32
  168. | ((h16 ':'){0,4} h16 )? '::' ls32
  169. | ((h16 ':'){0,5} h16 )? '::' h16
  170. | ((h16 ':'){0,6} h16 )? '::' )
  171. h16 = hexdig{1,4}
  172. ls32 = (h16 ':' h16) | ipv4_address
  173. ipv4_address = dec_octet '.' dec_octet '.' dec_octet '.' dec_octet
  174. nz = ~'0' digit
  175. dec_octet = (
  176. digit # 0-9
  177. | nz digit # 10-99
  178. | '1' digit{2} # 100-199
  179. | '2' ('0' | '1' | '2' | '3' | '4') digit # 200-249
  180. | '25' ('0' | '1' | '2' | '3' | '4' | '5') )# %250-255
  181. reg_name = (unreserved | pct_encoded | sub_delims)*
  182. path = (
  183. path_abempty # begins with '/' or is empty
  184. | path_absolute # begins with '/' but not '//'
  185. | path_noscheme # begins with a non-colon segment
  186. | path_rootless # begins with a segment
  187. | path_empty ) # zero characters
  188. path_abempty = ('/' segment)*
  189. path_absolute = '/' (segment_nz ('/' segment)* )?
  190. path_noscheme = segment_nz_nc ('/' segment)*
  191. path_rootless = segment_nz ('/' segment)*
  192. path_empty = pchar{0}
  193. segment = pchar*
  194. segment_nz = pchar+
  195. segment_nz_nc = (unreserved | pct_encoded | sub_delims | '@')+
  196. # non-zero-length segment without any colon ':'
  197. pchar = unreserved | pct_encoded | sub_delims | ':' | '@'
  198. query = (pchar | '/' | '?')*
  199. fragment = (pchar | '/' | '?')*
  200. pct_encoded = '%' hexdig
  201. unreserved = letter | digit | '-' | '.' | '_' | '~'
  202. reserved = gen_delims | sub_delims
  203. gen_delims = ':' | '/' | '?' | '#' | '(' | ')?' | '@'
  204. sub_delims = '!' | '$' | '&' | '\\'' | '(' | ')' | '*' | '+' | ',' | ';' | '='
  205. hexdig = digit | 'a' | 'A' | 'b' | 'B' | 'c' | 'C' | 'd' | 'D' | 'e' | 'E' | 'f' | 'F'
  206. """
  207. compiled = makeGrammar(grammar, {})
  208. return compiled
  209. _pep508_grammar = None
  210. def to_dep_spec_pep508(s):
  211. """ to_dep_spec_pep508 """
  212. global _pep508_grammar
  213. if _pep508_grammar is None:
  214. _pep508_grammar = _build_dep_spec_pep508_grammar()
  215. parsed = _pep508_grammar(s)
  216. return parsed.specification()
  217. def env_marker_ast2expr(marker_ast):
  218. """ env_marker_ast2expr """
  219. MARKER_VARS = (
  220. 'python_version',
  221. 'python_full_version',
  222. 'os_name',
  223. 'sys_platform',
  224. 'platform_release',
  225. 'platform_system',
  226. 'platform_version',
  227. 'platform_machine',
  228. 'platform_python_implementation',
  229. 'implementation_name',
  230. 'implementation_version',
  231. 'extra' # ONLY when defined by a containing layer
  232. )
  233. o, l, r = marker_ast
  234. if isinstance(l, tuple):
  235. l = env_marker_ast2expr(l)
  236. else:
  237. assert isinstance(l, str)
  238. if l not in MARKER_VARS:
  239. l = repr(l)
  240. if isinstance(r, tuple):
  241. r = env_marker_ast2expr(r)
  242. else:
  243. assert isinstance(r, str)
  244. if r not in MARKER_VARS:
  245. r = repr(r)
  246. return f"{l} {o} {r}"