PageRenderTime 50ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/oct2py/_utils.py

https://bitbucket.org/jenshnielsen/oct2py
Python | 208 lines | 150 code | 10 blank | 48 comment | 6 complexity | 70646995b4d753ce12abcd80622ce8b9 MD5 | raw file
  1. """
  2. .. module:: _utils
  3. :synopsis: Miscellaneous helper constructs
  4. .. moduleauthor:: Steven Silvester <steven.silvester@ieee.org>
  5. """
  6. import os
  7. import time
  8. import subprocess
  9. import random
  10. import atexit
  11. import inspect
  12. import dis
  13. import re
  14. import sys
  15. from glob import glob
  16. sys.path.append('..')
  17. def _open():
  18. """
  19. Start an octave session in a subprocess.
  20. Returns
  21. =======
  22. out : fid
  23. File descriptor for the Octave subprocess
  24. Raises
  25. ======
  26. Oct2PyError
  27. If the session is not opened sucessfully.
  28. Notes
  29. =====
  30. Options sent to Octave: -q is quiet startup, --braindead is
  31. Matlab compatibilty mode.
  32. On Windows, it attempts to find octave in c:\Octave if it is not
  33. on the path.
  34. """
  35. session = None
  36. if 'linux' in sys.platform:
  37. session = subprocess.Popen('octave -q --braindead',
  38. shell=True,
  39. stderr=subprocess.STDOUT,
  40. stdin=subprocess.PIPE,
  41. stdout=subprocess.PIPE,
  42. preexec_fn=os.setsid)
  43. else:
  44. try:
  45. session = subprocess.Popen('octave -q --braindead',
  46. stderr=subprocess.STDOUT,
  47. stdin=subprocess.PIPE,
  48. stdout=subprocess.PIPE)
  49. except OSError:
  50. msg = ('\n\nPlease install octave and put it in your path:\n'
  51. 'setx PATH "%PATH%;<path-to-octave-bin-dir>"\n\n')
  52. raise Oct2PyError(msg)
  53. return session
  54. def _register_del(fname):
  55. """
  56. Register a MAT file for deletion at program exit.
  57. Parameters
  58. ==========
  59. fname : str
  60. Name of file to register.
  61. """
  62. atexit.register(lambda filename=fname: _remove_files(filename))
  63. def _remove_files(filename=''):
  64. """
  65. Remove the desired file and any old MAT files.
  66. All MAT files in the current working directory over a minute old are
  67. deleted.
  68. This helps clean up orphaned HDF files in case the previous session did
  69. not close properly.
  70. Parameters
  71. ==========
  72. filename : str, optional
  73. Specific file to delete.
  74. """
  75. try:
  76. os.remove(filename)
  77. except OSError:
  78. pass
  79. files = os.listdir(os.getcwd())
  80. for fname in files:
  81. if re.match(r'(load|save)_.{10}\.(mat|hdf)', fname):
  82. try:
  83. atime = os.path.getatime(fname)
  84. except OSError:
  85. continue
  86. if (time.time() - atime > 60):
  87. try:
  88. os.remove(fname)
  89. except OSError:
  90. pass
  91. def _get_nout():
  92. """
  93. Return the number of return values the caller is expecting.
  94. Adapted from the ompc project.
  95. Returns
  96. =======
  97. out : int
  98. Number of arguments expected by caller, default is 1.
  99. """
  100. frame = inspect.currentframe()
  101. # step into the function that called us
  102. # nout is two frames back
  103. frame = frame.f_back.f_back
  104. bytecode = frame.f_code.co_code
  105. try:
  106. instruction = ord(bytecode[frame.f_lasti + 3])
  107. except TypeError:
  108. instruction = ord(chr(bytecode[frame.f_lasti + 3]))
  109. if instruction == dis.opmap['UNPACK_SEQUENCE']:
  110. try:
  111. howmany = ord(bytecode[frame.f_lasti + 4])
  112. except TypeError:
  113. howmany = ord(chr(bytecode[frame.f_lasti + 4]))
  114. return howmany
  115. elif instruction == dis.opmap['POP_TOP']:
  116. # OCTAVE always assumes at least 1 value
  117. return 1
  118. return 1
  119. def _create_file(type_, ext):
  120. """
  121. Create a file of the given type and extension with a random name.
  122. Parameters
  123. ==========
  124. type_ : str {'load', 'save'}
  125. Type of file to create (used for Octave 'save' or 'load' commands).
  126. ext : str {'mat', 'hdf'}
  127. File extension.
  128. Returns
  129. =======
  130. out : str
  131. Random MAT file name e.g. 'load_4932048302.mat'.
  132. """
  133. name = [type_, '_']
  134. name.extend([str(random.choice(range(10))) for x in range(10)])
  135. name.append('.{0}'.format(ext))
  136. return ''.join(name)
  137. class Oct2PyError(Exception):
  138. """ Called when we can't open Octave or Octave throws an error
  139. """
  140. pass
  141. class Struct(dict):
  142. """
  143. Octave style struct, enhanced.
  144. Supports dictionary and attribute style access.
  145. Examples
  146. ========
  147. >>> from oct2py import Struct
  148. >>> a = Struct()
  149. >>> a.b = 'spam' # a["b"] == 'spam'
  150. >>> a.c["d"] = 'eggs' # a.c.d == 'eggs'
  151. >>> print(a)
  152. {'c': {'d': 'eggs'}, 'b': 'spam'}
  153. """
  154. def __getattr__(self, attr):
  155. try:
  156. return self[attr]
  157. except KeyError:
  158. if not attr.startswith('_'):
  159. self[attr] = Struct()
  160. return self[attr]
  161. __setattr__ = dict.__setitem__
  162. __delattr__ = dict.__delitem__
  163. def _test():
  164. """Run the doctests for this module
  165. """
  166. doctest.testmod()
  167. if __name__ == "__main__":
  168. import doctest
  169. _test()