class_docstr: Parse HOCON files: https://github.com/typesafehub/config/blob/master/HOCON.md
class_docstr_tok: ["Parse","HOCON","files",":","https",":","\/\/github.com\/typesafehub\/config\/blob\/master\/HOCON.md"]
docstr: parse a HOCON content
  
  :param content: HOCON content to parse
  :type content: basestring
  :param resolve: if true, resolve substitutions
  :type resolve: boolean
  :param unresolved_value: assigned value value to unresolved substitution.
      If overriden with a default value, it will replace all unresolved value to the default value.
      If it is set to to pyhocon.STR_SUBSTITUTION then it will replace the value by
      its substitution expression (e.g., ${x})
  :type unresolved_value: boolean
  :return: a ConfigTree or a list
docstr_tok: ["parse","a","HOCON","content",":","param","content",":","HOCON","content","to","parse",":","type","content",":","basestring",":","param","resolve",":","if","true",",","resolve","substitutions",":","type","resolve",":","boolean",":","param","unresolved_value",":","assigned","value","value","to","unresolved","substitution",".","If","overriden","with","a","default","value",",","it","will","replace","all","unresolved","value","to","the","default","value",".","If","it","is","set","to","to","pyhocon.STR_SUBSTITUTION","then","it","will","replace","the","value","by","its","substitution","expression","(","e.g.",",","$","{","x","}",")",":","type","unresolved_value",":","boolean",":","return",":","a","ConfigTree","or","a","list"]
code: def parse(
      cls,
      content,
      basedir=None,
      resolve=True,
      unresolved_value=DEFAULT_SUBSTITUTION,
  ):
      """parse a HOCON content
  
      :param content: HOCON content to parse
      :type content: basestring
      :param resolve: if true, resolve substitutions
      :type resolve: boolean
      :param unresolved_value: assigned value value to unresolved substitution.
          If overriden with a default value, it will replace all unresolved value to the default value.
          If it is set to to pyhocon.STR_SUBSTITUTION then it will replace the value by
          its substitution expression (e.g., ${x})
      :type unresolved_value: boolean
      :return: a ConfigTree or a list
      """
  
      unescape_pattern = re.compile(r"\\.")
  
      def replace_escape_sequence(match):
          value = match.group(0)
          return cls.REPLACEMENTS.get(value, value)
  
      def norm_string(value):
          return unescape_pattern.sub(replace_escape_sequence, value)
  
      def unescape_string(tokens):
          return ConfigUnquotedString(norm_string(tokens[0]))
  
      def parse_multi_string(tokens):
          # remove the first and last 3 "
          return tokens[0][3:-3]
  
      def convert_number(tokens):
          n = tokens[0]
          try:
              return int(n, 10)
          except ValueError:
              return float(n)
  
      def safe_convert_number(tokens):
          n = tokens[0]
          try:
              return int(n, 10)
          except ValueError:
              try:
                  return float(n)
              except ValueError:
                  return n
  
      def convert_period(tokens):
          period_value = int(tokens.value)
          period_identifier = tokens.unit
  
          period_unit = next(
              (
                  single_unit
                  for single_unit, values in cls.get_supported_period_type_map().items()
                  if period_identifier in values
              )
          )
  
          return period(period_value, period_unit)
  
      # ${path} or ${?path} for optional substitution
      SUBSTITUTION_PATTERN = (
          r"\$\{(?P<optional>\?)?(?P<variable>[^}]+)\}(?P<ws>[ \t]*)"
      )
  
      def create_substitution(instring, loc, token):
          # remove the ${ and }
          match = re.match(SUBSTITUTION_PATTERN, token[0])
          variable = match.group("variable")
          ws = match.group("ws")
          optional = match.group("optional") == "?"
          substitution = ConfigSubstitution(
              variable, optional, ws, instring, loc
          )
          return substitution
  
      # ${path} or ${?path} for optional substitution
      STRING_PATTERN = '"(?P<value>(?:[^"\\\\]|\\\\.)*)"(?P<ws>[ \t]*)'
  
      def create_quoted_string(instring, loc, token):
          # remove the ${ and }
          match = re.match(STRING_PATTERN, token[0])
          value = norm_string(match.group("value"))
          ws = match.group("ws")
          return ConfigQuotedString(value, ws, instring, loc)
  
      def include_config(instring, loc, token):
          url = None
          file = None
          required = False
  
          if token[0] == "required":
              required = True
              final_tokens = token[1:]
          else:
              final_tokens = token
  
          if len(final_tokens) == 1:  # include "test"
              value = (
                  final_tokens[0].value
                  if isinstance(final_tokens[0], ConfigQuotedString)
                  else final_tokens[0]
              )
              if (
                  value.startswith("http://")
                  or value.startswith("https://")
                  or value.startswith("file://")
              ):
                  url = value
              else:
                  file = value
          elif (
              len(final_tokens) == 2
          ):  # include url("test") or file("test")
              value = (
                  final_tokens[1].value
                  if isinstance(token[1], ConfigQuotedString)
                  else final_tokens[1]
              )
              if final_tokens[0] == "url":
                  url = value
              else:
                  file = value
  
          if url is not None:
              logger.debug("Loading config from url %s", url)
              obj = ConfigFactory.parse_URL(
                  url,
                  resolve=False,
                  required=required,
                  unresolved_value=NO_SUBSTITUTION,
              )
          elif file is not None:
              path = (
                  file
                  if basedir is None
                  else os.path.join(basedir, file)
              )
              logger.debug("Loading config from file %s", path)
              obj = ConfigFactory.parse_file(
                  path,
                  resolve=False,
                  required=required,
                  unresolved_value=NO_SUBSTITUTION,
              )
          else:
              raise ConfigException(
                  "No file or URL specified at: {loc}: {instring}",
                  loc=loc,
                  instring=instring,
              )
  
          return ConfigInclude(
              obj if isinstance(obj, list) else obj.items()
          )
  
      @contextlib.contextmanager
      def set_default_white_spaces():
          default = ParserElement.DEFAULT_WHITE_CHARS
          ParserElement.setDefaultWhitespaceChars(" \t")
          yield
          ParserElement.setDefaultWhitespaceChars(default)
  
      with set_default_white_spaces():
          assign_expr = Forward()
          true_expr = Keyword("true", caseless=True).setParseAction(
              replaceWith(True)
          )
          false_expr = Keyword("false", caseless=True).setParseAction(
              replaceWith(False)
          )
          null_expr = Keyword("null", caseless=True).setParseAction(
              replaceWith(NoneValue())
          )
          # key = QuotedString('"', escChar='\\', unquoteResults=False) | Word(alphanums + alphas8bit + '._- /')
          regexp_numbers = r"[+-]?(\d*\.\d+|\d+(\.\d+)?)([eE][+\-]?\d+)?(?=$|[ \t]*([\$\}\],#\n\r]|//))"
          key = (
              QuotedString('"', escChar="\\", unquoteResults=False)
              | Regex(regexp_numbers, re.DOTALL).setParseAction(
                  safe_convert_number
              )
              | Word(alphanums + alphas8bit + "._- /")
          )
  
          eol = Word("\n\r").suppress()
          eol_comma = Word("\n\r,").suppress()
          comment = (Literal("#") | Literal("//")) - SkipTo(
              eol | StringEnd()
          )
          comment_eol = Suppress(Optional(eol_comma) + comment)
          comment_no_comma_eol = (comment | eol).suppress()
          number_expr = Regex(regexp_numbers, re.DOTALL).setParseAction(
              convert_number
          )
  
          period_types = itertools.chain.from_iterable(
              cls.get_supported_period_type_map().values()
          )
          period_expr = Regex(
              r"(?P<value>\d+)\s*(?P<unit>"
              + "|".join(period_types)
              + ")$"
          ).setParseAction(convert_period)
  
          # multi line string using """
          # Using fix described in http://pyparsing.wikispaces.com/share/view/3778969
          multiline_string = Regex(
              '""".*?"*"""', re.DOTALL | re.UNICODE
          ).setParseAction(parse_multi_string)
          # single quoted line string
          quoted_string = Regex(
              r'"(?:[^"\\\n]|\\.)*"[ \t]*', re.UNICODE
          ).setParseAction(create_quoted_string)
          # unquoted string that takes the rest of the line until an optional comment
          # we support .properties multiline support which is like this:
          # line1  \
          # line2 \
          # so a backslash precedes the \n
          unquoted_string = Regex(
              r'(?:[^^`+?!@*&"\[\{\s\]\}#,=\$\\]|\\.)+[ \t]*',
              re.UNICODE,
          ).setParseAction(unescape_string)
          substitution_expr = Regex(
              r"[ \t]*\$\{[^\}]+\}[ \t]*"
          ).setParseAction(create_substitution)
          string_expr = (
              multiline_string | quoted_string | unquoted_string
          )
  
          value_expr = (
              period_expr
              | number_expr
              | true_expr
              | false_expr
              | null_expr
              | string_expr
          )
  
          include_content = quoted_string | (
              (Keyword("url") | Keyword("file"))
              - Literal("(").suppress()
              - quoted_string
              - Literal(")").suppress()
          )
          include_expr = (
              Keyword("include", caseless=True).suppress()
              + (
                  include_content
                  | (
                      Keyword("required")
                      - Literal("(").suppress()
                      - include_content
                      - Literal(")").suppress()
                  )
              )
          ).setParseAction(include_config)
  
          root_dict_expr = Forward()
          dict_expr = Forward()
          list_expr = Forward()
          multi_value_expr = ZeroOrMore(
              comment_eol
              | include_expr
              | substitution_expr
              | dict_expr
              | list_expr
              | value_expr
              | (Literal("\\") - eol).suppress()
          )
          # for a dictionary : or = is optional
          # last zeroOrMore is because we can have t = {a:4} {b: 6} {c: 7} which is dictionary concatenation
          inside_dict_expr = ConfigTreeParser(
              ZeroOrMore(
                  comment_eol | include_expr | assign_expr | eol_comma
              )
          )
          inside_root_dict_expr = ConfigTreeParser(
              ZeroOrMore(
                  comment_eol | include_expr | assign_expr | eol_comma
              ),
              root=True,
          )
          dict_expr << Suppress("{") - inside_dict_expr - Suppress("}")
          root_dict_expr << Suppress(
              "{"
          ) - inside_root_dict_expr - Suppress("}")
          list_entry = ConcatenatedValueParser(multi_value_expr)
          list_expr << Suppress("[") - ListParser(
              list_entry - ZeroOrMore(eol_comma - list_entry)
          ) - Suppress("]")
  
          # special case when we have a value assignment where the string can potentially be the remainder of the line
          assign_expr << Group(
              key
              - ZeroOrMore(comment_no_comma_eol)
              - (
                  dict_expr
                  | (Literal("=") | Literal(":") | Literal("+="))
                  - ZeroOrMore(comment_no_comma_eol)
                  - ConcatenatedValueParser(multi_value_expr)
              )
          )
  
          # the file can be { ... } where {} can be omitted or []
          config_expr = (
              ZeroOrMore(comment_eol | eol)
              + (list_expr | root_dict_expr | inside_root_dict_expr)
              + ZeroOrMore(comment_eol | eol_comma)
          )
          config = config_expr.parseString(content, parseAll=True)[0]
  
          if resolve:
              allow_unresolved = (
                  resolve
                  and unresolved_value is not DEFAULT_SUBSTITUTION
                  and unresolved_value is not MANDATORY_SUBSTITUTION
              )
              has_unresolved = cls.resolve_substitutions(
                  config, allow_unresolved
              )
              if (
                  has_unresolved
                  and unresolved_value is MANDATORY_SUBSTITUTION
              ):
                  raise ConfigSubstitutionException(
                      "resolve cannot be set to True and unresolved_value to MANDATORY_SUBSTITUTION"
                  )
  
          if (
              unresolved_value is not NO_SUBSTITUTION
              and unresolved_value is not DEFAULT_SUBSTITUTION
          ):
              cls.unresolve_substitutions_to_value(
                  config, unresolved_value
              )
      return config
  
imports: import itertools
  import re
  import os
  import socket
  import contextlib
  import codecs
  from datetime import timedelta
  from pyparsing import Forward, Keyword, QuotedString, Word, Literal, Suppress, Regex, Optional, SkipTo, ZeroOrMore, Group, lineno, col, TokenConverter, replaceWith, alphanums, alphas8bit, ParseSyntaxException, StringEnd
  from pyparsing import ParserElement
  from .config_tree import ConfigTree, ConfigSubstitution, ConfigList, ConfigValues, ConfigUnquotedString, ConfigInclude, NoneValue, ConfigQuotedString
  from .exceptions import ConfigSubstitutionException, ConfigMissingException, ConfigException
  import logging
  import copy
label_desc: Use image node_id 2 for calling the ConfigParser obj's underlying member method code with example usage: obj.parse(cls, content, basedir, resolve, unresolved_value) and returns: config, cls, unescape_pattern, ConfigUnquotedString, tokens, period, substitution, ConfigQuotedString, ConfigInclude, int, int, float, float, n