# Path: netjsonconfig/utils.py
# def sorted_dict(dict_):
#     return OrderedDict(sorted(dict_.items()))
# 
# Path: netjsonconfig/backends/base/parser.py
# class BaseParser(object):
#     """
#     Base Parser class
#     Parsers are used to parse a string or tar.gz
#     which represents the router configuration
#     """
# 
#     def __init__(self, config):
#         if isinstance(config, str):
#             data = self.parse_text(config)
#         # presence of read() method
#         # indicates a file-like object
#         elif hasattr(config, 'read'):
#             data = self.parse_tar(config)
#         else:
#             raise ParseError('Unrecognized format')
#         self.intermediate_data = data
# 
#     def parse_text(self, config):
#         raise NotImplementedError()
# 
#     def parse_tar(self, config):
#         raise NotImplementedError()


import re
import tarfile
from ...utils import sorted_dict
from ..base.parser import BaseParser
                    'contents': tar.extractfile(member).read().decode(),
                }
            )
        return self.parse_text(text)

    def _get_vpns(self, text):
        results = re.split(vpn_pattern, text)
        vpns = []
        for result in results:
            result = result.strip()
            if not result:
                continue
            vpns.append(self._get_config(result))
        return {'openvpn': vpns}

    def _get_config(self, contents):
        lines = contents.split('\n')
        name = lines[0]
        config = {'name': name}
        for line in lines[1:]:
            line = line.strip()
            if not line:
                continue
            match = re.search(config_pattern, line)
            parts = match.groups()
            key = parts[0].replace('-', '_')
            value = parts[1]
            if not value:
                value = True
            config[key] = value

# Path: netjsonconfig/utils.py
# def sorted_dict(dict_):
#     return OrderedDict(sorted(dict_.items()))
# 
# Path: netjsonconfig/backends/base/parser.py
# class BaseParser(object):
#     """
#     Base Parser class
#     Parsers are used to parse a string or tar.gz
#     which represents the router configuration
#     """
# 
#     def __init__(self, config):
#         if isinstance(config, str):
#             data = self.parse_text(config)
#         # presence of read() method
#         # indicates a file-like object
#         elif hasattr(config, 'read'):
#             data = self.parse_tar(config)
#         else:
#             raise ParseError('Unrecognized format')
#         self.intermediate_data = data
# 
#     def parse_text(self, config):
#         raise NotImplementedError()
# 
#     def parse_tar(self, config):
#         raise NotImplementedError()


# Path: netjsonconfig/backends/openvpn/parser.py
import re
import tarfile
from ...utils import sorted_dict
from ..base.parser import BaseParser

                    'contents': tar.extractfile(member).read().decode(),
                }
            )
        return self.parse_text(text)

    def _get_vpns(self, text):
        results = re.split(vpn_pattern, text)
        vpns = []
        for result in results:
            result = result.strip()
            if not result:
                continue
            vpns.append(self._get_config(result))
        return {'openvpn': vpns}

    def _get_config(self, contents):
        lines = contents.split('\n')
        name = lines[0]
        config = {'name': name}
        for line in lines[1:]:
            line = line.strip()
            if not line:
                continue
            match = re.search(config_pattern, line)
            parts = match.groups()
            key = parts[0].replace('-', '_')
            value = parts[1]
            if not value:
                value = True
            config[key] = value

        return sorted_dict(config)