staticdirect.py 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. # GNU MediaGoblin -- federated, autonomous media hosting
  2. # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
  3. #
  4. # This program is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU Affero General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This program is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU Affero General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU Affero General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. ####################################
  17. # Staticdirect infrastructure.
  18. # Borrowed largely from cc.engine
  19. # by Chris Webber & Creative Commons
  20. #
  21. # This needs documentation!
  22. ####################################
  23. import logging
  24. import six
  25. _log = logging.getLogger(__name__)
  26. class StaticDirect(object):
  27. """
  28. Direct to a static resource.
  29. This StaticDirect class can take a series of "domains" to
  30. staticdirect to. In general, you should supply a None domain, as
  31. that's the "default" domain.
  32. Things work like this::
  33. >>> staticdirect = StaticDirect(
  34. ... {None: "/static/",
  35. ... "theme": "http://example.org/themestatic/"})
  36. >>> staticdirect("css/monkeys.css")
  37. "/static/css/monkeys.css"
  38. >>> staticdirect("images/lollerskate.png", "theme")
  39. "http://example.org/themestatic/images/lollerskate.png"
  40. """
  41. def __init__(self, domains):
  42. self.domains = dict(
  43. [(key, value.rstrip('/'))
  44. for key, value in six.iteritems(domains)])
  45. self.cache = {}
  46. def __call__(self, filepath, domain=None):
  47. if domain in self.cache and filepath in self.cache[domain]:
  48. return self.cache[domain][filepath]
  49. static_direction = self.cache.setdefault(
  50. domain, {})[filepath] = self.get(filepath, domain)
  51. return static_direction
  52. def get(self, filepath, domain=None):
  53. return '%s/%s' % (
  54. self.domains[domain], filepath.lstrip('/'))
  55. class PluginStatic(object):
  56. """Pass this into the ``'static_setup'`` hook to register your
  57. plugin's static directory.
  58. This has two mandatory attributes that you must pass in on class
  59. init:
  60. - *name:* this name will be both used for lookup in "urlgen" for
  61. your plugin's static resources and for the subdirectory that
  62. it'll be "mounted" to for serving via your web browser. It
  63. *MUST* be unique. If writing a plugin bundled with MediaGoblin
  64. please use the pattern 'coreplugin__foo' where 'foo' is your
  65. plugin name. All external plugins should use their modulename,
  66. so if your plugin is 'mg_bettertags' you should also call this
  67. name 'mg_bettertags'.
  68. - *file_path:* the directory your plugin's static resources are
  69. located in. It's recommended that you use
  70. pkg_resources.resource_filename() for this.
  71. An example of using this::
  72. from pkg_resources import resource_filename
  73. from mediagoblin.tools.staticdirect import PluginStatic
  74. hooks = {
  75. 'static_setup': lambda: PluginStatic(
  76. 'mg_bettertags',
  77. resource_filename('mg_bettertags', 'static'))
  78. }
  79. """
  80. def __init__(self, name, file_path):
  81. self.name = name
  82. self.file_path = file_path
  83. def __call__(self):
  84. return self