/telemetry/config_parser.py

https://github.com/svpcom/wifibroadcast
Python | 116 lines | 68 code | 29 blank | 19 comment | 18 complexity | fbe1fccebe15569c1f892f8ec8bc4e0c MD5 | raw file
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. # Copyright (C) 2018, 2019 Vasily Evseenko <svpcom@p2ptech.org>
  4. #
  5. # This program is free software; you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation; version 3.
  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 General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License along
  15. # with this program; if not, write to the Free Software Foundation, Inc.,
  16. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  17. #
  18. from __future__ import unicode_literals
  19. from __future__ import print_function
  20. from __future__ import division
  21. from __future__ import absolute_import
  22. from future import standard_library
  23. standard_library.install_aliases()
  24. from builtins import *
  25. import configparser
  26. import ast
  27. import copy
  28. import glob
  29. import os
  30. from twisted.python import log
  31. class ConfigError(Exception):
  32. pass
  33. class Settings(object):
  34. # Used for interpolation of string values
  35. def __getitem__(self, attr):
  36. try:
  37. section, attr = attr.split('.')
  38. except ValueError:
  39. raise KeyError(attr)
  40. return getattr(getattr(self, section), attr)
  41. def __repr__(self):
  42. return repr(self.__dict__)
  43. def __deepcopy__(self, memo):
  44. return copy.deepcopy(self.__dict__, memo)
  45. class Section(object):
  46. def __repr__(self):
  47. return repr(self.__dict__)
  48. def __deepcopy__(self, memo):
  49. return copy.deepcopy(self.__dict__, memo)
  50. def parse_config(basedir, cfg_patterns, interpolate=True):
  51. settings = Settings()
  52. settings.path = Section()
  53. settings.path.cfg_root = basedir
  54. settings.common = Section()
  55. used_files = []
  56. for g in cfg_patterns:
  57. for f in (glob.glob(os.path.join(basedir, g)) if isinstance(g, str) else [g]):
  58. fd = open(f) if isinstance(f, str) else f
  59. filename = getattr(fd, 'filename', str(fd))
  60. try:
  61. fd.seek(0) # handle case when source config is fd
  62. config = configparser.RawConfigParser()
  63. try:
  64. config.readfp(fd, filename=filename)
  65. except Exception as v:
  66. raise ConfigError(v)
  67. used_files.append(filename)
  68. fd.seek(0)
  69. for section in config.sections():
  70. _s = getattr(settings, section, Section())
  71. for item, value in config.items(section):
  72. try:
  73. value = ast.literal_eval(value)
  74. if interpolate and isinstance(value, str):
  75. # Interpolate string using current settings
  76. value = value % settings
  77. except:
  78. err = '[%s] %s = %s' % (section, item, value)
  79. log.msg('Config parse error: %s' % (err,), isError=1)
  80. raise ConfigError('Parse error: %s' % (err,))
  81. setattr(_s, item, value)
  82. s_name=str(section)
  83. setattr(settings, s_name, _s)
  84. finally:
  85. if isinstance(f, str):
  86. fd.close()
  87. return settings, used_files