test_pkg_resources.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import sys
  2. import tempfile
  3. import os
  4. import zipfile
  5. import datetime
  6. import time
  7. import subprocess
  8. import pkg_resources
  9. try:
  10. unicode
  11. except NameError:
  12. unicode = str
  13. def timestamp(dt):
  14. """
  15. Return a timestamp for a local, naive datetime instance.
  16. """
  17. try:
  18. return dt.timestamp()
  19. except AttributeError:
  20. # Python 3.2 and earlier
  21. return time.mktime(dt.timetuple())
  22. class EggRemover(unicode):
  23. def __call__(self):
  24. if self in sys.path:
  25. sys.path.remove(self)
  26. if os.path.exists(self):
  27. os.remove(self)
  28. class TestZipProvider(object):
  29. finalizers = []
  30. ref_time = datetime.datetime(2013, 5, 12, 13, 25, 0)
  31. "A reference time for a file modification"
  32. @classmethod
  33. def setup_class(cls):
  34. "create a zip egg and add it to sys.path"
  35. egg = tempfile.NamedTemporaryFile(suffix='.egg', delete=False)
  36. zip_egg = zipfile.ZipFile(egg, 'w')
  37. zip_info = zipfile.ZipInfo()
  38. zip_info.filename = 'mod.py'
  39. zip_info.date_time = cls.ref_time.timetuple()
  40. zip_egg.writestr(zip_info, 'x = 3\n')
  41. zip_info = zipfile.ZipInfo()
  42. zip_info.filename = 'data.dat'
  43. zip_info.date_time = cls.ref_time.timetuple()
  44. zip_egg.writestr(zip_info, 'hello, world!')
  45. zip_egg.close()
  46. egg.close()
  47. sys.path.append(egg.name)
  48. cls.finalizers.append(EggRemover(egg.name))
  49. @classmethod
  50. def teardown_class(cls):
  51. for finalizer in cls.finalizers:
  52. finalizer()
  53. def test_resource_filename_rewrites_on_change(self):
  54. """
  55. If a previous call to get_resource_filename has saved the file, but
  56. the file has been subsequently mutated with different file of the
  57. same size and modification time, it should not be overwritten on a
  58. subsequent call to get_resource_filename.
  59. """
  60. import mod
  61. manager = pkg_resources.ResourceManager()
  62. zp = pkg_resources.ZipProvider(mod)
  63. filename = zp.get_resource_filename(manager, 'data.dat')
  64. actual = datetime.datetime.fromtimestamp(os.stat(filename).st_mtime)
  65. assert actual == self.ref_time
  66. f = open(filename, 'w')
  67. f.write('hello, world?')
  68. f.close()
  69. ts = timestamp(self.ref_time)
  70. os.utime(filename, (ts, ts))
  71. filename = zp.get_resource_filename(manager, 'data.dat')
  72. f = open(filename)
  73. assert f.read() == 'hello, world!'
  74. manager.cleanup_resources()
  75. class TestResourceManager(object):
  76. def test_get_cache_path(self):
  77. mgr = pkg_resources.ResourceManager()
  78. path = mgr.get_cache_path('foo')
  79. type_ = str(type(path))
  80. message = "Unexpected type from get_cache_path: " + type_
  81. assert isinstance(path, (unicode, str)), message
  82. class TestIndependence:
  83. """
  84. Tests to ensure that pkg_resources runs independently from setuptools.
  85. """
  86. def test_setuptools_not_imported(self):
  87. """
  88. In a separate Python environment, import pkg_resources and assert
  89. that action doesn't cause setuptools to be imported.
  90. """
  91. lines = (
  92. 'import pkg_resources',
  93. 'import sys',
  94. 'assert "setuptools" not in sys.modules, '
  95. '"setuptools was imported"',
  96. )
  97. cmd = [sys.executable, '-c', '; '.join(lines)]
  98. subprocess.check_call(cmd)