planet.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. #!/usr/bin/env python
  2. """The Planet aggregator.
  3. A flexible and easy-to-use aggregator for generating websites.
  4. Visit http://www.planetplanet.org/ for more information and to download
  5. the latest version.
  6. Requires Python 2.1, recommends 2.3.
  7. """
  8. __authors__ = [ "Scott James Remnant <scott@netsplit.com>",
  9. "Jeff Waugh <jdub@perkypants.org>" ]
  10. __license__ = "Python"
  11. import os
  12. import sys
  13. import time
  14. import locale
  15. import urlparse
  16. import planet
  17. from ConfigParser import ConfigParser
  18. # Default configuration file path
  19. CONFIG_FILE = "config.ini"
  20. # Defaults for the [Planet] config section
  21. PLANET_NAME = "Unconfigured Planet"
  22. PLANET_LINK = "Unconfigured Planet"
  23. PLANET_FEED = None
  24. OWNER_NAME = "Anonymous Coward"
  25. OWNER_EMAIL = ""
  26. LOG_LEVEL = "WARNING"
  27. FEED_TIMEOUT = 20 # seconds
  28. # Default template file list
  29. TEMPLATE_FILES = "examples/basic/planet.html.tmpl"
  30. def config_get(config, section, option, default=None, raw=0, vars=None):
  31. """Get a value from the configuration, with a default."""
  32. if config.has_option(section, option):
  33. return config.get(section, option, raw=raw, vars=None)
  34. else:
  35. return default
  36. def main():
  37. config_file = CONFIG_FILE
  38. offline = 0
  39. verbose = 0
  40. for arg in sys.argv[1:]:
  41. if arg == "-h" or arg == "--help":
  42. print "Usage: planet [options] [CONFIGFILE]"
  43. print
  44. print "Options:"
  45. print " -v, --verbose DEBUG level logging during update"
  46. print " -o, --offline Update the Planet from the cache only"
  47. print " -h, --help Display this help message and exit"
  48. print
  49. sys.exit(0)
  50. elif arg == "-v" or arg == "--verbose":
  51. verbose = 1
  52. elif arg == "-o" or arg == "--offline":
  53. offline = 1
  54. elif arg.startswith("-"):
  55. print >>sys.stderr, "Unknown option:", arg
  56. sys.exit(1)
  57. else:
  58. config_file = arg
  59. # Read the configuration file
  60. config = ConfigParser()
  61. config.read(config_file)
  62. if not config.has_section("Planet"):
  63. print >>sys.stderr, "Configuration missing [Planet] section."
  64. sys.exit(1)
  65. # Read the [Planet] config section
  66. planet_name = config_get(config, "Planet", "name", PLANET_NAME)
  67. planet_link = config_get(config, "Planet", "link", PLANET_LINK)
  68. planet_feed = config_get(config, "Planet", "feed", PLANET_FEED)
  69. owner_name = config_get(config, "Planet", "owner_name", OWNER_NAME)
  70. owner_email = config_get(config, "Planet", "owner_email", OWNER_EMAIL)
  71. if verbose:
  72. log_level = "DEBUG"
  73. else:
  74. log_level = config_get(config, "Planet", "log_level", LOG_LEVEL)
  75. feed_timeout = config_get(config, "Planet", "feed_timeout", FEED_TIMEOUT)
  76. template_files = config_get(config, "Planet", "template_files",
  77. TEMPLATE_FILES).split(" ")
  78. # Default feed to the first feed for which there is a template
  79. if not planet_feed:
  80. for template_file in template_files:
  81. name = os.path.splitext(os.path.basename(template_file))[0]
  82. if name.find('atom')>=0 or name.find('rss')>=0:
  83. planet_feed = urlparse.urljoin(planet_link, name)
  84. break
  85. # Define locale
  86. if config.has_option("Planet", "locale"):
  87. # The user can specify more than one locale (separated by ":") as
  88. # fallbacks.
  89. locale_ok = False
  90. for user_locale in config.get("Planet", "locale").split(':'):
  91. user_locale = user_locale.strip()
  92. try:
  93. locale.setlocale(locale.LC_ALL, user_locale)
  94. except locale.Error:
  95. pass
  96. else:
  97. locale_ok = True
  98. break
  99. if not locale_ok:
  100. print >>sys.stderr, "Unsupported locale setting."
  101. sys.exit(1)
  102. # Activate logging
  103. planet.logging.basicConfig()
  104. planet.logging.getLogger().setLevel(planet.logging.getLevelName(log_level))
  105. log = planet.logging.getLogger("planet.runner")
  106. try:
  107. log.warning
  108. except:
  109. log.warning = log.warn
  110. # timeoutsocket allows feedparser to time out rather than hang forever on
  111. # ultra-slow servers. Python 2.3 now has this functionality available in
  112. # the standard socket library, so under 2.3 you don't need to install
  113. # anything. But you probably should anyway, because the socket module is
  114. # buggy and timeoutsocket is better.
  115. if feed_timeout:
  116. try:
  117. feed_timeout = float(feed_timeout)
  118. except:
  119. log.warning("Feed timeout set to invalid value '%s', skipping", feed_timeout)
  120. feed_timeout = None
  121. if feed_timeout and not offline:
  122. try:
  123. from planet import timeoutsocket
  124. timeoutsocket.setDefaultSocketTimeout(feed_timeout)
  125. log.debug("Socket timeout set to %d seconds", feed_timeout)
  126. except ImportError:
  127. import socket
  128. if hasattr(socket, 'setdefaulttimeout'):
  129. log.debug("timeoutsocket not found, using python function")
  130. socket.setdefaulttimeout(feed_timeout)
  131. log.debug("Socket timeout set to %d seconds", feed_timeout)
  132. else:
  133. log.error("Unable to set timeout to %d seconds", feed_timeout)
  134. # run the planet
  135. my_planet = planet.Planet(config)
  136. my_planet.run(planet_name, planet_link, template_files, offline)
  137. my_planet.generate_all_files(template_files, planet_name,
  138. planet_link, planet_feed, owner_name, owner_email)
  139. if __name__ == "__main__":
  140. main()