/src/thirdparty/staticfiles/utils.py

https://github.com/zodiak/django_ondev · Python · 165 lines · 128 code · 12 blank · 25 comment · 13 complexity · fa973f6ed774f13caa2ba5e0781e204b MD5 · raw file

  1. import os
  2. import fnmatch
  3. import warnings
  4. from inspect import getmembers
  5. from django.conf import settings
  6. def get_files_for_app(app, ignore_patterns=[]):
  7. """
  8. Return a list containing the relative source paths for all files that
  9. should be copied for an app.
  10. """
  11. from staticfiles.storage import AppStaticStorage
  12. warnings.warn(
  13. "The staticfiles.utils.get_files_for_app utility function is "
  14. "deprecated. Use staticfiles.storage.AppStaticStorage.get_files "
  15. "instead.", PendingDeprecationWarning)
  16. return AppStaticStorage(app).get_files(ignore_patterns)
  17. def get_app_prefix(app):
  18. """
  19. Return the path name that should be prepended to files for this app.
  20. """
  21. from staticfiles.storage import AppStaticStorage
  22. warnings.warn(
  23. "The staticfiles.utils.get_app_prefix utility function is "
  24. "deprecated. Use staticfiles.storage.AppStaticStorage.get_prefix "
  25. "instead.", PendingDeprecationWarning)
  26. return AppStaticStorage(app).get_prefix()
  27. def is_ignored(path, ignore_patterns=[]):
  28. """
  29. Return True or False depending on whether the ``path`` should be
  30. ignored (if it matches any pattern in ``ignore_patterns``).
  31. """
  32. for pattern in ignore_patterns:
  33. if fnmatch.fnmatchcase(path, pattern):
  34. return True
  35. return False
  36. def get_files(storage, ignore_patterns=[], location=''):
  37. """
  38. Recursively walk the storage directories yielding the paths
  39. of all files that should be copied.
  40. """
  41. directories, files = storage.listdir(location)
  42. for fn in files:
  43. if is_ignored(fn, ignore_patterns):
  44. continue
  45. if location:
  46. fn = os.path.join(location, fn)
  47. yield fn
  48. for dir in directories:
  49. if is_ignored(dir, ignore_patterns):
  50. continue
  51. if location:
  52. dir = os.path.join(location, dir)
  53. for fn in get_files(storage, ignore_patterns, dir):
  54. yield fn
  55. class AppSettings(object):
  56. """
  57. An app setting object to be used for handling app setting defaults
  58. gracefully and providing a nice API for them. Say you have an app
  59. called ``myapp`` and want to define a few defaults, and refer to the
  60. defaults easily in the apps code. Add a ``settings.py`` to your app::
  61. from path.to.utils import AppSettings
  62. class MyAppSettings(AppSettings):
  63. SETTING_1 = "one"
  64. SETTING_2 = (
  65. "two",
  66. )
  67. Then initialize the setting with the correct prefix in the location of
  68. of your choice, e.g. ``conf.py`` of the app module::
  69. settings = MyAppSettings(prefix="MYAPP")
  70. The ``MyAppSettings`` instance will automatically look at Django's
  71. global setting to determine each of the settings and respect the
  72. provided ``prefix``. E.g. adding this to your site's ``settings.py``
  73. will set the ``SETTING_1`` setting accordingly::
  74. MYAPP_SETTING_1 = "uno"
  75. Usage
  76. -----
  77. Instead of using ``from django.conf import settings`` as you would
  78. usually do, you can switch to using your apps own settings module
  79. to access the app settings::
  80. from myapp.conf import settings
  81. print myapp_settings.MYAPP_SETTING_1
  82. ``AppSettings`` instances also work as pass-throughs for other
  83. global settings that aren't related to the app. For example the
  84. following code is perfectly valid::
  85. from myapp.conf import settings
  86. if "myapp" in settings.INSTALLED_APPS:
  87. print "yay, myapp is installed!"
  88. Custom handling
  89. ---------------
  90. Each of the settings can be individually configured with callbacks.
  91. For example, in case a value of a setting depends on other settings
  92. or other dependencies. The following example sets one setting to a
  93. different value depending on a global setting::
  94. from django.conf import settings
  95. class MyCustomAppSettings(AppSettings):
  96. ENABLED = True
  97. def configure_enabled(self, value):
  98. return value and not self.DEBUG
  99. custom_settings = MyCustomAppSettings("MYAPP")
  100. The value of ``custom_settings.MYAPP_ENABLED`` will vary depending on the
  101. value of the global ``DEBUG`` setting.
  102. Each of the app settings can be customized by providing
  103. a method ``configure_<lower_setting_name>`` that takes the default
  104. value as defined in the class attributes as the only parameter.
  105. The method needs to return the value to be use for the setting in
  106. question.
  107. """
  108. def __dir__(self):
  109. return sorted(list(set(self.__dict__.keys() + dir(settings))))
  110. __members__ = lambda self: self.__dir__()
  111. def __getattr__(self, name):
  112. if name.startswith(self._prefix):
  113. raise AttributeError("%r object has no attribute %r" %
  114. (self.__class__.__name__, name))
  115. return getattr(settings, name)
  116. def __setattr__(self, name, value):
  117. super(AppSettings, self).__setattr__(name, value)
  118. if name in dir(settings):
  119. setattr(settings, name, value)
  120. def __init__(self, prefix):
  121. super(AppSettings, self).__setattr__('_prefix', prefix)
  122. for name, value in filter(self.issetting, getmembers(self.__class__)):
  123. prefixed_name = "%s_%s" % (prefix.upper(), name.upper())
  124. value = getattr(settings, prefixed_name, value)
  125. callback = getattr(self, "configure_%s" % name.lower(), None)
  126. if callable(callback):
  127. value = callback(value)
  128. delattr(self.__class__, name)
  129. setattr(self, prefixed_name, value)
  130. def issetting(self, (name, value)):
  131. return name == name.upper()