#!/usr/bin/env python# -*- coding: utf-8 -*-## This file is part of the `pypath` python module## Copyright 2014-2023# EMBL, EMBL-EBI, Uniklinik RWTH Aachen, Heidelberg University## Authors: see the file `README.rst`# Contact: Dénes Türei (turei.denes@gmail.com)## Distributed under the GPLv3 License.# See accompanying file LICENSE.txt or copy at# https://www.gnu.org/licenses/gpl-3.0.html## Website: https://pypath.omnipathdb.org/#fromfuture.utilsimportiteritemsimportimportlibimportosimportitertoolsimportjsonimportpypath.share.sessionassessionimportpypath.omnipath.databases.buildasbuild_logger=session.Logger(name='db_define')_log=_logger._log_console=_logger._console
[docs]@classmethoddeffrom_json(cls,path,label=None):""" :param str path: Path to JSON file with database definition. """data=cls._parse_json(path=path,label=label)returncls(**data)
@staticmethoddef_parse_json(path,label=None):data=DatabaseDefinition._read_json(path)or{}iflabel:iflabelindata:data=data[label]data['label']=labelelse:_console('Entry `%s` not available in file `%s`.'%(label,path,))returndata@staticmethoddef_read_json(path):ifnotos.path.exists(path):_console('No such file: `%s`.'%path)else:withopen(path)asjson_file:returnjson.load(json_file)
[docs]@classmethoddeffrom_dict(cls,dct,label=None):""" :param dict dct: Dictionary containing the parameters for the database definition. """iflabel:dct['label']=labelreturncls(**dct)
[docs]classDatabaseClass(object):""" Describes a class of databases which can be filled with different data but here the module and the class implementing the database are defined. """
def__repr__(self):return('<Database class `%s`, module: `%s`, class or method: `%s`>'%(self.label,self.module,self.method.__name__ifhasattr(self.method,'__name__')elseself.method,))defget_class(self):ifcallable(self.method):returnself.methodelse:try:mod=importlib.import_module(self.module)ifhasattr(mod,self.method):returngetattr(mod,self.method)else:_console('Module `%s` has no class or method `%s`.'%(self.module,self.method,))exceptImportError:_console('Failed to import `%s`.'%self.module)@classmethoddeffrom_json(self,path,label=None):data=DatabaseDefinition._parse_json(path=path,label=label)returncls(**data)@classmethoddeffrom_dict(cls,dct,label=None):iflabel:dct['label']=labelreturncls(**dct)
def__repr__(self):return'<Database definitions: %u classes and %u definitions>'%(len(self.classes),len(self.databases),)defload(self):ifisinstance(self._classes,str):self._log('Reading database classes from `%s`'%self._classes)self._classes=DatabaseDefinition._read_json(self._classes)ifisinstance(self._databases,str):self._log('Reading database definitions from `%s`'%self._databases)self._databases=DatabaseDefinition._read_json(self._databases)self.classes=dict((label,DatabaseClass.from_dict(label=label,dct=param))forlabel,paraminiteritems(self._classes))self.databases=dict((label,DatabaseDefinition.from_dict(label=label,dct=param))forlabel,paraminiteritems(self._databases))defget_db_class(self,label):iflabelinself.classes:returnself.classes[label]else:self._log('No such database class: `%s`.'%label)defget_db_definition(self,label):iflabelnotinself.databases:self._log('Warning: no parameters for label `%s`, ''returning empty dict.'%label)returnself.databases[label]iflabelinself.databaseselse{}defget_class(self,label):dbclass=self.get_db_class(label)ifdbclass:returndbclass.get_class()
[docs]defclass_and_param(self,label):""" For a database definition label returns the class or method and its arguments which are necessary to build the database according to the definition. """db_def=self.get_db_definition(label)ifdb_def:db_class=db_def.dbclassifnotcallable(db_class):ifisinstance(db_class,dict):db_class=DatabaseClass(**db_class)elifisinstance(db_class,str):db_class=self.get_db_class(db_class)returndb_class,db_def
[docs]defbuild(self,label):""" For a database definition label returns an instance of the database: creates an instance of the class or calls the method with the arguments in the database definition. Returns the database instance. """db_class,db_def=self.class_and_param(label)ifdb_class:returnbuild.build(db_class,db_def)