system.pyx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554
  1. #!/usr/bin/env python
  2. # encoding: utf-8
  3. # cython: profile=False
  4. import sys
  5. import os
  6. from Naked.settings import debug as DEBUG_FLAG
  7. #------------------------------------------------------------------------------
  8. #
  9. # FILE & DIRECTORY PATHS
  10. #
  11. #------------------------------------------------------------------------------
  12. #------------------------------------------------------------------------------
  13. # [ filename function ] (string)
  14. # returns file name from a file path (including the file extension)
  15. # Tests: test_SYSTEM.py :: test_sys_filename
  16. #------------------------------------------------------------------------------
  17. def filename(filepath):
  18. try:
  19. return os.path.basename(filepath)
  20. except Exception as e:
  21. if DEBUG_FLAG:
  22. sys.stderr.write("Naked Framework Error: unable to return base filename from filename() function (Naked.toolshed.system).")
  23. raise e
  24. #------------------------------------------------------------------------------
  25. # [ file_extension function ] (string)
  26. # returns file extension from a filepath
  27. # Tests: test_SYSTEM.py :: test_sys_file_extension
  28. #------------------------------------------------------------------------------
  29. def file_extension(filepath):
  30. try:
  31. return os.path.splitext(filepath)[1]
  32. except Exception as e:
  33. if DEBUG_FLAG:
  34. sys.stderr.write("Naked Framework Error: unable to return file extension with file_extension() function (Naked.toolshed.system).")
  35. raise e
  36. #------------------------------------------------------------------------------
  37. # [ directory function ] (string)
  38. # returns directory path to the filepath
  39. # Tests: test_SYSTEM.py :: test_sys_dir_path
  40. #------------------------------------------------------------------------------
  41. def directory(filepath):
  42. try:
  43. return os.path.dirname(filepath)
  44. except Exception as e:
  45. if DEBUG_FLAG:
  46. sys.stderr.write("Naked Framework Error: unable to return directory path to file with directory() function (Naked.toolshed.system).")
  47. raise e
  48. #------------------------------------------------------------------------------
  49. # [ make_path function ] (string)
  50. # returns OS independent file path from tuple of path components
  51. # Tests: test_SYSTEM.py :: test_sys_make_filepath
  52. #------------------------------------------------------------------------------
  53. def make_path(*path_list):
  54. try:
  55. return os.path.join(*path_list)
  56. except Exception as e:
  57. if DEBUG_FLAG:
  58. sys.stderr.write("Naked Framework Error: unable to make OS independent path with the make_path() function (Naked.toolshed.system).")
  59. raise e
  60. #------------------------------------------------------------------------------
  61. # [ currentdir_to_basefile decorator function ] (returns decorated original function)
  62. # concatenates the absolute working directory path to the basename of file in the first parameter of the undecorated function
  63. # Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_to_basefile
  64. #------------------------------------------------------------------------------
  65. def currentdir_to_basefile(func):
  66. try:
  67. from functools import wraps
  68. @wraps(func)
  69. def wrapper(file_name, *args, **kwargs):
  70. current_directory = os.getcwd() #get current working directory path
  71. full_path = os.path.join(current_directory, file_name) # join cwd path to the filename for full path
  72. return func(full_path, *args, **kwargs) #return the original function with the full path to file as first argument
  73. return wrapper
  74. except Exception as e:
  75. if DEBUG_FLAG:
  76. sys.stderr.write("Naked Framework Error: error with the currentdir_to_basefile() decorator function (Naked.toolshed.system).")
  77. raise e
  78. #------------------------------------------------------------------------------
  79. # [ currentdir_firstparam decorator function ] (returns decorated original function)
  80. # adds the current working directory as the first function parameter of the decorated function
  81. # Tests: test_SYSTEM.py :: test_sys_add_currentdir_path_first_arg
  82. #------------------------------------------------------------------------------
  83. def currentdir_firstparam(func):
  84. try:
  85. from functools import wraps
  86. @wraps(func)
  87. def wrapper(dir="", *args, **kwargs):
  88. current_directory = os.getcwd()
  89. return func(current_directory, *args, **kwargs)
  90. return wrapper
  91. except Exception as e:
  92. if DEBUG_FLAG:
  93. sys.stderr.write("Naked Framework Error: error with the currentdir_firstargument() decorator function (Naked.toolshed.system).")
  94. raise e
  95. #------------------------------------------------------------------------------
  96. # [ currentdir_lastargument decorator function ] (returns decorated original function)
  97. # adds the current working directory as the last function parameter of the decorated function
  98. # Note: you cannot use other named arguments in the original function with this decorator
  99. # Note: the current directory argument in the last position must be named current_dir
  100. # Tests: test_SYSTEM.py :: test_sys_add_currentdir_last_arg
  101. #------------------------------------------------------------------------------
  102. def currentdir_lastparam(func):
  103. try:
  104. from functools import wraps
  105. @wraps(func)
  106. def wrapper(*args, **kwargs):
  107. the_cwd = os.getcwd()
  108. return func(*args, current_dir=the_cwd)
  109. return wrapper
  110. except Exception as e:
  111. if DEBUG_FLAG:
  112. sys.stderr.write("Naked Framework Error: error with the currentdir_lastargument() decorator function (Naked.toolshed.system).")
  113. raise e
  114. #------------------------------------------------------------------------------
  115. # [ fullpath function ] (string)
  116. # returns the absolute path to a file that is in the current working directory
  117. # file_name = the basename of the file in the current working directory
  118. # Example usage where test.txt is in working directory:
  119. # filepath = fullpath("test.txt")
  120. # Tests: test_SYSTEM.py :: test_sys_full_path_to_file
  121. #------------------------------------------------------------------------------
  122. @currentdir_to_basefile # current directory decorator - adds the directory path up to the filename to the basefile name argument to original function
  123. def fullpath(file_name):
  124. try:
  125. return file_name
  126. except Exception as e:
  127. if DEBUG_FLAG:
  128. sys.stderr.write("Naked Framework Error: unable to return absolute path to the file with the fullpath() function (Naked.toolshed.system).")
  129. raise e
  130. #------------------------------------------------------------------------------
  131. # [ cwd function ] (string)
  132. # returns the current working directory path
  133. # does not need to be called with an argument, the decorator assigns it
  134. # Example usage:
  135. # current_dir = cwd()
  136. # Tests: test_SYSTEM.py :: test_sys_cwd_path
  137. #------------------------------------------------------------------------------
  138. @currentdir_firstparam
  139. def cwd(dir=""):
  140. try:
  141. return dir
  142. except Exception as e:
  143. if DEBUG_FLAG:
  144. sys.stderr.write("Naked Framework Error: unable to return the current working directory with the cwd() function (Naked.toolshed.system).")
  145. raise e
  146. #------------------------------------------------------------------------------
  147. #
  148. # DIRECTORY WRITES
  149. #
  150. #------------------------------------------------------------------------------
  151. ## TODO: add tests
  152. #------------------------------------------------------------------------------
  153. # [ make_dirs function ] (--none--)
  154. # make a new directory path (recursive if multiple levels of depth) if it
  155. # DOES NOT already exist
  156. #------------------------------------------------------------------------------
  157. def make_dirs(dirpath):
  158. try:
  159. import os
  160. import errno
  161. os.makedirs(dirpath)
  162. return True
  163. except OSError as ose:
  164. if ose.errno != errno.EEXIST: # directory already exists
  165. if DEBUG_FLAG:
  166. sys.stderr.write("Naked Framework Error: Could not write the directory path passed as an argument to the make_dirs() function (Naked.toolshed.system).")
  167. raise ose
  168. else:
  169. return False
  170. except Exception as e:
  171. raise e
  172. #------------------------------------------------------------------------------
  173. #
  174. # FILE & DIRECTORY TESTING
  175. #
  176. #------------------------------------------------------------------------------
  177. #------------------------------------------------------------------------------
  178. # [ file_exists function ] (boolean)
  179. # return boolean for existence of file in specified path
  180. # Tests: test_SYSTEM.py :: test_file_exists
  181. #------------------------------------------------------------------------------
  182. def file_exists(filepath):
  183. try:
  184. if os.path.exists(filepath) and os.path.isfile(filepath): # test that exists and is a file
  185. return True
  186. else:
  187. return False
  188. except Exception as e:
  189. if DEBUG_FLAG:
  190. sys.stderr.write("Naked Framework Error: error with test for the presence of the file with the file_exists() method (Naked.toolshed.system).")
  191. raise e
  192. #------------------------------------------------------------------------------
  193. # [ is_file function ] (boolean)
  194. # returns boolean for determination of whether filepath is a file
  195. # Tests: test_SYSTEM.py :: test_sys_is_file, test_sys_is_file_missing_file,
  196. # test_sys_is_file_when_dir
  197. #------------------------------------------------------------------------------
  198. def is_file(filepath):
  199. try:
  200. return os.path.isfile(filepath)
  201. except Exception as e:
  202. if DEBUG_FLAG:
  203. sys.stderr.write("Naked Framework Error: error with test for file with the is_file() function (Naked.toolshed.system).")
  204. raise e
  205. #------------------------------------------------------------------------------
  206. # [ dir_exists function ] (boolean)
  207. # return boolean for existence of directory in specified path
  208. # Tests: test_SYSTEM.py :: test_dir_exists, test_dir_exists_missing_dir
  209. #------------------------------------------------------------------------------
  210. def dir_exists(dirpath):
  211. try:
  212. if os.path.exists(dirpath) and os.path.isdir(dirpath): # test that exists and is a directory
  213. return True
  214. else:
  215. return False
  216. except Exception as e:
  217. if DEBUG_FLAG:
  218. sys.stderr.write("Naked Framework Error: error with test for directory with the dir_exists() function (Naked.toolshed.system).")
  219. raise e
  220. #------------------------------------------------------------------------------
  221. # [ is_dir function ] (boolean)
  222. # returns boolean for determination of whether dirpath is a directory
  223. # Tests: test_SYSTEM.py :: test_sys_dir_is_dir, test_sys_dir_is_dir_when_file,
  224. # test_sys_dir_is_dir_when_missing
  225. #------------------------------------------------------------------------------
  226. def is_dir(dirpath):
  227. try:
  228. return os.path.isdir(dirpath)
  229. except Exception as e:
  230. if DEBUG_FLAG:
  231. sys.stderr.write("Naked Framework Error: error with test for directory with the is_dir() function (Naked.toolshed.system).")
  232. raise e
  233. #------------------------------------------------------------------------------
  234. #
  235. # FILE METADATA
  236. #
  237. #------------------------------------------------------------------------------
  238. #------------------------------------------------------------------------------
  239. # [ filesize function ] (int)
  240. # return file size in bytes
  241. # Tests: test_SYSTEM.py :: test_sys_meta_file_size
  242. #------------------------------------------------------------------------------
  243. def file_size(filepath):
  244. try:
  245. return os.path.getsize(filepath)
  246. except Exception as e:
  247. if DEBUG_FLAG:
  248. sys.stderr.write("Naked Framework Error: unable to return file size with the file_size() function (Naked.toolshed.system).")
  249. raise e
  250. #------------------------------------------------------------------------------
  251. # [ file_mod_time function ] (string)
  252. # return the last file modification date/time
  253. # Tests: test_SYSTEM.py :: test_sys_meta_file_mod
  254. #------------------------------------------------------------------------------
  255. def file_mod_time(filepath):
  256. try:
  257. import time
  258. return time.ctime(os.path.getmtime(filepath))
  259. except Exception as e:
  260. if DEBUG_FLAG:
  261. sys.stderr.write("Naked Framework Error: unable to return file modification data with the file_mod_time() function (Naked.toolshed.system).")
  262. raise e
  263. #------------------------------------------------------------------------------
  264. #
  265. # FILE LISTINGS
  266. #
  267. #------------------------------------------------------------------------------
  268. #------------------------------------------------------------------------------
  269. # [ list_all_files function ] (list)
  270. # returns a list of all files in developer specified directory
  271. # Tests: test_SYSTEM.py :: test_sys_list_all_files, test_sys_list_all_files_emptydir
  272. #------------------------------------------------------------------------------
  273. def list_all_files(dir):
  274. try:
  275. filenames = [name for name in os.listdir(dir) if os.path.isfile(os.path.join(dir, name))]
  276. return filenames
  277. except Exception as e:
  278. if DEBUG_FLAG:
  279. sys.stderr.write("Naked Framework Error: unable to generate directory file list with the list_all_files() function (Naked.toolshed.system).")
  280. raise e
  281. #------------------------------------------------------------------------------
  282. # [ list_filter_files function ] (list)
  283. # returns a list of files filtered by developer defined file extension in developer defined directory
  284. # Usage example:
  285. # filenames = list_filter_files("py", "tests")
  286. # Tests: test_SYSTEM.py :: test_sys_list_filter_files, test_sys_list_filter_files_nomatch
  287. #------------------------------------------------------------------------------
  288. def list_filter_files(extension_filter, dir):
  289. try:
  290. if not extension_filter.startswith("."):
  291. extension_filter = "." + extension_filter
  292. filenames = [name for name in os.listdir(dir) if name.endswith(extension_filter)]
  293. return filenames
  294. except Exception as e:
  295. if DEBUG_FLAG:
  296. sys.stderr.write("Naked Framework Error: unable to return list of filtered files with the list_filter_files() function (Naked.toolshed.system).")
  297. raise e
  298. #------------------------------------------------------------------------------
  299. # [ list_all_files_cwd function ] (list)
  300. # returns a list of all files in the current working directory
  301. # Note: does not require argument, the decorator assigns the cwd
  302. # Usage example:
  303. # file_list = list_all_files_cwd()
  304. # Tests: test_SYSTEM.py :: test_sys_list_all_files_cwd
  305. #------------------------------------------------------------------------------
  306. @currentdir_firstparam
  307. def list_all_files_cwd(dir=""):
  308. try:
  309. return list_all_files(dir)
  310. except Exception as e:
  311. if DEBUG_FLAG:
  312. sys.stderr.write("Naked Framework Error: unable to return list of all files in current working directory with the list_all_files_cwd() function (Naked.toolshed.system).")
  313. raise e
  314. #------------------------------------------------------------------------------
  315. # [ list_filter_files_cwd function ] (list)
  316. # returns a list of all files in the current working directory filtered by developer specified file extension
  317. # Note: do not specify the second argument, decorator assigns it
  318. # Usage example:
  319. # file_list = list_filter_files_cwd(".py")
  320. # Tests: test_SYSTEM.py :: test_sys_filter_files_cwd, test_sys_filter_files_cwd_nomatch
  321. #------------------------------------------------------------------------------
  322. @currentdir_lastparam
  323. def list_filter_files_cwd(extension_filter, current_dir=""):
  324. try:
  325. return list_filter_files(extension_filter, current_dir)
  326. except Exception as e:
  327. if DEBUG_FLAG:
  328. sys.stderr.write("Naked Framework Error: unable to return list of filtered files in current working directory with the list_filter_files_cwd() function (Naked.toolshed.system).")
  329. raise e
  330. #------------------------------------------------------------------------------
  331. # [ list_match_files function ] (list)
  332. # returns a list of all files that match the developer specified wildcard match pattern
  333. # can optionally specify return of full path to the files (rather than relative path from cwd) by setting full_path to True
  334. # Usage examples:
  335. # file_list = list_match_files("*.py")
  336. # file_list_fullpath = list_match_files("*.py", True)
  337. # Tests: test_SYSTEM.py :: test_sys_match_files, test_sys_match_files_fullpath
  338. #------------------------------------------------------------------------------
  339. def list_match_files(match_pattern, full_path = False):
  340. try:
  341. from glob import glob
  342. filenames = glob(match_pattern)
  343. if full_path:
  344. filenames_fullpath = []
  345. cwd = os.getcwd()
  346. for name in filenames:
  347. name = os.path.join(cwd, name) #make the full path to the file
  348. filenames_fullpath.append(name) #add to the new list
  349. return filenames_fullpath #then return that list
  350. else:
  351. return filenames
  352. except Exception as e:
  353. if DEBUG_FLAG:
  354. sys.stderr.write("Naked Framework Error: unable to return list of matched files with the list_match_files() function (Naked.toolshed.system).")
  355. raise e
  356. #------------------------------------------------------------------------------
  357. #
  358. # SYMBOLIC LINK TESTING
  359. #
  360. #------------------------------------------------------------------------------
  361. #------------------------------------------------------------------------------
  362. # [ is_link function ] (boolean)
  363. # return boolean indicating whether the path is a symbolic link
  364. #------------------------------------------------------------------------------
  365. def is_link(filepath):
  366. try:
  367. return os.path.islink(filepath)
  368. except Exception as e:
  369. if DEBUG_FLAG:
  370. sys.stderr.write("Naked Framework Error: unable to determine whether path is a symbolic link with the is_link() function (Naked.toolshed.system).")
  371. raise e
  372. #------------------------------------------------------------------------------
  373. # [ real_path function ] (string)
  374. # return the real file path pointed to by a symbolic link
  375. #------------------------------------------------------------------------------
  376. def real_path(filepath):
  377. try:
  378. return os.path.realpath(filepath)
  379. except Exception as e:
  380. if DEBUG_FLAG:
  381. sys.stderr.write("Naked Framework Error: unable to return real path for symbolic link with the real_path() function (Naked.toolshed.system).")
  382. raise e
  383. #------------------------------------------------------------------------------
  384. #
  385. # DATA STREAMS
  386. #
  387. #------------------------------------------------------------------------------
  388. #------------------------------------------------------------------------------
  389. # [ stdout function ]
  390. # print to std output stream
  391. #------------------------------------------------------------------------------
  392. def stdout(text):
  393. try:
  394. print(text)
  395. except Exception as e:
  396. if DEBUG_FLAG:
  397. sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout() function (Naked.toolshed.system).")
  398. raise e
  399. #------------------------------------------------------------------------------
  400. # [ stdout_xnl function ]
  401. # print to std output stream without a newline
  402. #------------------------------------------------------------------------------
  403. def stdout_xnl(text):
  404. try:
  405. sys.stdout.write(text)
  406. except Exception as e:
  407. if DEBUG_FLAG:
  408. sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_xnl() function (Naked.toolshed.system).")
  409. raise e
  410. #------------------------------------------------------------------------------
  411. # [ stdout_iter function ]
  412. # print items in an iterable to the standard output stream with newlines after each string
  413. #------------------------------------------------------------------------------
  414. def stdout_iter(iter):
  415. try:
  416. for x in iter:
  417. stdout(x)
  418. except Exception as e:
  419. if DEBUG_FLAG:
  420. sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
  421. raise e
  422. #------------------------------------------------------------------------------
  423. # [ stdout_iter_xnl function ]
  424. # print items in an iterable to the standard output stream without newlines after each string
  425. #------------------------------------------------------------------------------
  426. def stdout_iter_xnl(iter):
  427. try:
  428. for x in iter:
  429. stdout_xnl(x)
  430. except Exception as e:
  431. if DEBUG_FLAG:
  432. sys.stderr.write("Naked Framework Error: unable to print to the standard output stream with the stdout_iter() function (Naked.toolshed.system).")
  433. raise e
  434. #------------------------------------------------------------------------------
  435. # [ stderr function ]
  436. # print to std error stream
  437. # optionally (i.e. if exit = nonzero integer) permits exit from application with developer defined exit code
  438. #------------------------------------------------------------------------------
  439. def stderr(text, exit=0):
  440. try:
  441. sys.stderr.write(text + "\n")
  442. if exit:
  443. raise SystemExit(exit)
  444. except Exception as e:
  445. if DEBUG_FLAG:
  446. sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
  447. raise e
  448. #------------------------------------------------------------------------------
  449. # [ stderr_xnl function ]
  450. # print to the standard error stream without a newline character after the `text` string
  451. #------------------------------------------------------------------------------
  452. def stderr_xnl(text, exit=0):
  453. try:
  454. sys.stderr.write(text)
  455. if exit:
  456. raise SystemExit(exit)
  457. except Exception as e:
  458. if DEBUG_FLAG:
  459. sys.stderr.write("Naked Framework Error: unable to print to the standard error stream with the stderr() function (Naked.toolshed.system).")
  460. raise e
  461. #------------------------------------------------------------------------------
  462. #
  463. # APPLICATION CONTROL
  464. #
  465. #------------------------------------------------------------------------------
  466. #------------------------------------------------------------------------------
  467. # [ exit_with_status function ]
  468. # application exit with developer specified exit status code (default = 0)
  469. # use an exit status integer argument
  470. # Tests: test_SYSTEM.py :: test_sys_exit_with_code
  471. #------------------------------------------------------------------------------
  472. def exit_with_status(exit=0):
  473. raise SystemExit(exit)
  474. #------------------------------------------------------------------------------
  475. # [ exit_fail function ]
  476. # application exit with status code 1
  477. # Tests: test_SYSTEM.py :: test_sys_exit_failure
  478. #------------------------------------------------------------------------------
  479. def exit_fail():
  480. raise SystemExit(1)
  481. #------------------------------------------------------------------------------
  482. # [ exit_success function]
  483. # application exit with status code 0
  484. # Tests: test_SYSTEM.py :: test_sys_exit_success
  485. #------------------------------------------------------------------------------
  486. def exit_success():
  487. raise SystemExit(0)
  488. if __name__ == '__main__':
  489. pass
  490. # #------------------------------------------------------------------------------
  491. # # Standard Output Tests
  492. # #------------------------------------------------------------------------------
  493. # stdout("This is a test")
  494. # for x in range(10):
  495. # stdout_xnl(str(x) + " ")
  496. # list_ten = ['10% ', '20% ', '30% ', '40% ', '50% ', '60% ', '70% ', '80% ', '90% ', '100%']
  497. # stdout_iter(list_ten)
  498. # #------------------------------------------------------------------------------
  499. # # Standard Error Tests
  500. # #------------------------------------------------------------------------------
  501. # stderr("This is a test")
  502. # stderr("This is a test", 1) #exit with status code 1