# -*- coding: ascii -*-u"""========================== Schema config management==========================Schema config management.:Copyright: Copyright 2010 - 2025 Andr\xe9 Malo or his licensors, as applicable:License: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License."""__author__=u"Andr\xe9 Malo"importerrnoas_errnotry:importConfigParseras_config_parserexceptImportError:importconfigparseras_config_parsertry:fromcStringIOimportStringIOas_TextIOexceptImportError:fromioimportStringIOas_TextIOfrom.import_template
[docs]classConfig(object):""" Schema config container Attributes: tables (list): Table list schemas (dict): Alien schema mapping _lines (list): Original config lines (or ``None``) """#: Template for empty config file#:#: :Type: `Template`_CONFIG_TPL=_template.Template(""" # This is a comment. I love comments. # # This files contains table names, one per line # Comments and empty lines are ignored # # If the table name contains a dot, the first part is treated as # schema name. # # If the table variable should be treated differently, use: # # name = table # # The basename of this file (modulo .schema extension) is used as # basename for the python file. """)
[docs]def__init__(self,tables,schemas,lines=None):""" Initialization Parameters: tables (list): Table list schemas (dict): (Alien) Schema mapping lines (iterable): Original config lines. If omitted or ``None``, the config lines are not available. """self.tables=tablesself.schemas=schemasself._lines=NoneiflinesisNoneelselist(lines)
[docs]@classmethoddeffrom_file(cls,name_or_file):""" Construct from config file Parameters: name_or_file (str or file): Config filename or file pointer Returns: Config: New Config instance Raises: IOError: Error reading the file (except for ENOENT, which treats the file as empty) """ifname_or_fileisNone:lines=[]else:read=getattr(name_or_file,"read",None)ifreadisNone:kwargs={}ifstrisbyteselse{"encoding":"utf-8"}try:# pylint: disable = bad-option-value, unspecified-encoding# pylint: disable = bad-option-value, consider-using-withfp=open(name_or_file,**kwargs)exceptIOErrorase:ife.errno!=_errno.ENOENT:raiselines=[]else:try:lines=fp.read().splitlines(True)finally:fp.close()else:lines=name_or_file.read().splitlines(True)returncls.from_lines(lines)
[docs]@classmethoddeffrom_lines(cls,lines):""" Create from config lines Parameters: lines (iterable) List of config lines Returns: Config: New Config instance """conf_lines=["[schemas]","[tables]"]forlineinlines:line=line.rstrip()ifnotlineorline.lstrip().startswith("#"):continueif"="inlineor("["inlineand"]"inline):conf_lines.append(line)else:name=lineif"."inname:name=name.rsplit(".",1)[1]conf_lines.append("%s = %s"%(name,line))ifbytesisstr:parser=_config_parser.RawConfigParser()parser.optionxform=lambdax:x# pylint: disable = deprecated-methodparser.readfp(_TextIO("\n".join(conf_lines)))else:parser=_config_parser.RawConfigParser(strict=False)parser.optionxform=lambdax:xparser.read_file(_TextIO("\n".join(conf_lines)))returncls.from_parser(parser,lines=lines)
[docs]@classmethoddeffrom_parser(cls,parser,lines=None):""" Construct from config parser Parameters: parser (ConfigParser.RawConfigParser): Configparser instance lines (iterable): Original config lines Returns: Config: New Config instance """# pylint: disable = unnecessary-comprehensiontables=[(name,val)forname,valinparser.items("tables")]schemas=dict((name,val)forname,valinparser.items("schemas"))returncls(tables,schemas,lines=lines)
[docs]defdump(self,fp):""" Dump config to a file Parameters: fp (file): Stream to dump to """lines=self._linesifnotlines:result=self._CONFIG_TPL.expand().splitlines(False)iflinesisNone:tables=["%s = %s"%tablefortableinself.tables]iftables:result.append("")result.extend(tables)schemas=["%s = %s"%(key,value)forkey,valueinself.schemas.items()]ifschemas:result.append("")result.append("[schemas]")result.extend(schemas)else:result=linescontent="\n".join([line.rstrip()forlineinresult])+"\n"try:fp.write("")exceptTypeError:content=content.encode("utf-8")fp.write(content)