# -*- coding: utf-8 -*-# vim: tabstop=4 shiftwidth=4 softtabstop=4# Copyright (C) 2015-2025 GEM Foundation# OpenQuake is free software: you can redistribute it and/or modify it# under the terms of the GNU Affero General Public License as published# by the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.# OpenQuake is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU General Public License for more details.# You should have received a copy of the GNU Affero General Public License# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>."""Compatibility layer for Python 2 and 3. Mostly copied from six and future,but reduced to the subset of utilities needed by GEM. This is done toavoid an external dependency."""importmathimportbuiltinsimportnumpy
[docs]defencode(val):""" Encode a string assuming the encoding is UTF-8. :param: a unicode or bytes object :returns: bytes """ifisinstance(val,(list,tuple,numpy.ndarray)):# encode a sequence of stringsreturn[encode(v)forvinval]elifisinstance(val,str):returnval.encode('utf-8')else:# assume it was an already encoded objectreturnval
[docs]defdecode(val):""" Decode an object assuming the encoding is UTF-8. :param: a unicode or bytes object :returns: a unicode object """ifisinstance(val,(list,tuple,numpy.ndarray)):return[decode(v)forvinval]elifhasattr(val,'decode'):# assume it is an encoded bytes objectreturnval.decode('utf-8')else:returnstr(val)
# NB: using numpy.round would be advisable, but it would break# plenty of tests, including the AELO tests, so it is a no go
[docs]defround(x,d=0):""" Python2-compatible round function """p=10**dreturnfloat(math.floor((x*p)+math.copysign(0.5,x)))/p
[docs]defraise_(tp,value=None,tb=None):""" A function that matches the Python 2.x ``raise`` statement. This allows re-raising exceptions with the cls value and traceback on Python 2 and 3. """ifvalueisnotNoneandisinstance(tp,Exception):raiseTypeError("instance exception may not have a separate value")ifvalueisnotNone:exc=tp(value)else:exc=tpifexc.__traceback__isnottb:raiseexc.with_traceback(tb)raiseexc
# the following is used in the SMTK# copied from http://lucumr.pocoo.org/2013/5/21/porting-to-python-3-redux/
[docs]defwith_metaclass(meta,*bases):""" Returns an instance of meta inheriting from the given bases. To be used to replace the __metaclass__ syntax. """classmetaclass(meta):__call__=type.__call____init__=type.__init__def__new__(mcl,name,this_bases,d):ifthis_basesisNone:returntype.__new__(mcl,name,(),d)returnmeta(name,bases,d)returnmetaclass('temporary_class',None,{})