conf.py 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. import os
  2. import sys
  3. import numbers
  4. from operator import itemgetter
  5. import six
  6. if six.PY2:
  7. from ConfigParser import SafeConfigParser as ConfigParser
  8. else:
  9. from configparser import ConfigParser
  10. from scrapy.settings import BaseSettings
  11. from scrapy.utils.deprecate import update_classpath
  12. from scrapy.utils.python import without_none_values
  13. def build_component_list(compdict, custom=None, convert=update_classpath):
  14. """Compose a component list from a { class: order } dictionary."""
  15. def _check_components(complist):
  16. if len({convert(c) for c in complist}) != len(complist):
  17. raise ValueError('Some paths in {!r} convert to the same object, '
  18. 'please update your settings'.format(complist))
  19. def _map_keys(compdict):
  20. if isinstance(compdict, BaseSettings):
  21. compbs = BaseSettings()
  22. for k, v in six.iteritems(compdict):
  23. prio = compdict.getpriority(k)
  24. if compbs.getpriority(convert(k)) == prio:
  25. raise ValueError('Some paths in {!r} convert to the same '
  26. 'object, please update your settings'
  27. ''.format(list(compdict.keys())))
  28. else:
  29. compbs.set(convert(k), v, priority=prio)
  30. return compbs
  31. else:
  32. _check_components(compdict)
  33. return {convert(k): v for k, v in six.iteritems(compdict)}
  34. def _validate_values(compdict):
  35. """Fail if a value in the components dict is not a real number or None."""
  36. for name, value in six.iteritems(compdict):
  37. if value is not None and not isinstance(value, numbers.Real):
  38. raise ValueError('Invalid value {} for component {}, please provide ' \
  39. 'a real number or None instead'.format(value, name))
  40. # BEGIN Backward compatibility for old (base, custom) call signature
  41. if isinstance(custom, (list, tuple)):
  42. _check_components(custom)
  43. return type(custom)(convert(c) for c in custom)
  44. if custom is not None:
  45. compdict.update(custom)
  46. # END Backward compatibility
  47. _validate_values(compdict)
  48. compdict = without_none_values(_map_keys(compdict))
  49. return [k for k, v in sorted(six.iteritems(compdict), key=itemgetter(1))]
  50. def arglist_to_dict(arglist):
  51. """Convert a list of arguments like ['arg1=val1', 'arg2=val2', ...] to a
  52. dict
  53. """
  54. return dict(x.split('=', 1) for x in arglist)
  55. def closest_scrapy_cfg(path='.', prevpath=None):
  56. """Return the path to the closest scrapy.cfg file by traversing the current
  57. directory and its parents
  58. """
  59. if path == prevpath:
  60. return ''
  61. path = os.path.abspath(path)
  62. cfgfile = os.path.join(path, 'scrapy.cfg')
  63. if os.path.exists(cfgfile):
  64. return cfgfile
  65. return closest_scrapy_cfg(os.path.dirname(path), path)
  66. def init_env(project='default', set_syspath=True):
  67. """Initialize environment to use command-line tool from inside a project
  68. dir. This sets the Scrapy settings module and modifies the Python path to
  69. be able to locate the project module.
  70. """
  71. cfg = get_config()
  72. if cfg.has_option('settings', project):
  73. os.environ['SCRAPY_SETTINGS_MODULE'] = cfg.get('settings', project)
  74. closest = closest_scrapy_cfg()
  75. if closest:
  76. projdir = os.path.dirname(closest)
  77. if set_syspath and projdir not in sys.path:
  78. sys.path.append(projdir)
  79. def get_config(use_closest=True):
  80. """Get Scrapy config file as a ConfigParser"""
  81. sources = get_sources(use_closest)
  82. cfg = ConfigParser()
  83. cfg.read(sources)
  84. return cfg
  85. def get_sources(use_closest=True):
  86. xdg_config_home = os.environ.get('XDG_CONFIG_HOME') or \
  87. os.path.expanduser('~/.config')
  88. sources = ['/etc/scrapy.cfg', r'c:\scrapy\scrapy.cfg',
  89. xdg_config_home + '/scrapy.cfg',
  90. os.path.expanduser('~/.scrapy.cfg')]
  91. if use_closest:
  92. sources.append(closest_scrapy_cfg())
  93. return sources