pth.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. #!/usr/bin/env python
  2. # Licensed to Cloudera, Inc. under one
  3. # or more contributor license agreements. See the NOTICE file
  4. # distributed with this work for additional information
  5. # regarding copyright ownership. Cloudera, Inc. licenses this file
  6. # to you under the Apache License, Version 2.0 (the
  7. # "License"); you may not use this file except in compliance
  8. # with the License. You may obtain a copy of the License at
  9. #
  10. # http://www.apache.org/licenses/LICENSE-2.0
  11. #
  12. # Unless required by applicable law or agreed to in writing, software
  13. # distributed under the License is distributed on an "AS IS" BASIS,
  14. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. # See the License for the specific language governing permissions and
  16. # limitations under the License.
  17. """
  18. Tools to manipulate the .pth file in the virtualenv.
  19. """
  20. import glob
  21. import logging
  22. import os
  23. import common
  24. LOG = logging.getLogger(__name__)
  25. PTH_FILE = 'hue.pth'
  26. def _get_pth_filename():
  27. """
  28. _get_pth_filename -> Path to the .pth file.
  29. May raise SystemError if the virtual env is absent.
  30. """
  31. glob_path = os.path.join(common.VIRTUAL_ENV, 'lib', 'python*', 'site-packages')
  32. res = glob.glob(glob_path)
  33. if len(res) == 0:
  34. raise SystemError("Cannot find a Python installation in %s. "
  35. "Did you do `make hue'?" % (glob_path,))
  36. elif len(res) > 1:
  37. raise SystemError("Found multiple Python installations in %s. "
  38. "Please `make clean' first." % (glob_path,))
  39. return os.path.join(res[0], PTH_FILE)
  40. class PthFile(object):
  41. def __init__(self):
  42. """May raise SystemError if the virtual env is absent"""
  43. self._path = _get_pth_filename()
  44. self._entries = [ ]
  45. self._read()
  46. def _read(self):
  47. if os.path.exists(self._path):
  48. self._entries = set(file(self._path).read().split('\n'))
  49. def add(self, app):
  50. """
  51. Add the app and its ext eggs into the pth file
  52. """
  53. module_path = os.path.join(app.path, 'src')
  54. LOG.debug('Add to %s: %s' % (self._path, module_path))
  55. self._entries.add(module_path)
  56. # Eggs could be in ext-py/<pkg>/dist/*.egg
  57. ext_pys = app.find_ext_pys()
  58. for py in ext_pys:
  59. ext_egg = glob.glob(os.path.join(py, 'dist', '*.egg'))
  60. LOG.debug('Add to %s: %s' % (self._path, ext_egg))
  61. self._entries.update(ext_egg)
  62. # And eggs could also be in ext-eggs/*.egg
  63. for egg_file in glob.glob(os.path.join(app.path, 'ext-eggs', '*.egg')):
  64. LOG.debug('Add to %s: %s' % (self._path, egg_file))
  65. self._entries.add(egg_file)
  66. def remove(self, app):
  67. """
  68. Remove the app and its ext eggs from the pth file
  69. """
  70. for path in self._entries.copy():
  71. if path.startswith(app.path):
  72. self._entries.remove(path)
  73. def save(self):
  74. """Save the pth file"""
  75. tmp_path = self._path + '.new'
  76. file(tmp_path, 'w').write('\n'.join(sorted(self._entries)))
  77. os.rename(tmp_path, self._path)
  78. LOG.info('=== Saved %s' % (self._path,))
  79. def sync(self, apps):
  80. """Sync the .pth file with the installed apps"""
  81. self._entries = set()
  82. for app in apps:
  83. self.add(app)