Source code for gavo.base.common

"""
Common code for DaCHS's base package.
"""

#c Copyright 2008-2023, the GAVO project <gavo@ari.uni-heidelberg.de>
#c
#c This program is free software, covered by the GNU GPL.  See the
#c COPYING file in the source distribution.


import warnings

from gavo.utils.excs import (  #noflake: exceptions are historically in base	
	Error,
	BadCode, DataError, EmptyData, ExecutiveAction, LiteralParseError,
	MultiplicityError, NotFoundError, ParseException, RDNotFound,
	ReportableError, RestrictedElement, SkipThis, StructureError,
	SourceParseError, ValidationError)
	

[docs]class NotGivenType(type): def __str__(self): raise StructureError( "%s cannot be stringified"%self.__class__.__name__) def __repr__(self): return "<Not given/empty>" def __bool__(self): return False
[docs]class NotGiven(object, metaclass=NotGivenType): """A sentinel class for defaultless values that can remain undefined. """
[docs]class Ignore(ExecutiveAction): """An executive action causing an element to be not adopted by its parent. Raise this in -- typically -- onElementComplete if the element just built goes somewhere else but into its parent structure (or is somehow benignly unusable). Classic use case: Active Tags. """
[docs]class Replace(ExecutiveAction): """An executive action replacing the current child with the Exception's argument. Use this sparingly. I'd like to get rid of it. """ def __init__(self, newOb, newName=None): self.newOb, self.newName = newOb, newName
[docs]class Parser(object): """is an object that routes events. It is constructed with up to three functions for handling start, value, and end events; these would override methods ``start_``, ``end_``, or ``value_``. Thus, you can simply implement when inheriting from Parser. In that case, no call the the constructor is necessary (i.e., Parser works as a mixin as well). """ def __init__(self, start=None, value=None, end=None): self.start, self.value, self.end = start, value, end
[docs] def feedEvent(self, ctx, type, name, value): if type=="start": return self.start_(ctx, name, value) elif type=="value": return self.value_(ctx, name, value) elif type=="end": return self.end_(ctx, name, value) else: raise StructureError( "Illegal event type while building: '%s'"%type)
[docs]class StructParseDebugMixin(object): """put this before Parser in the parent class list of a struct, and you'll see the events coming in to your parser. """
[docs] def feedEvent(self, ctx, type, name, value): print(type, name, value, self) return Parser.feedEvent(self, ctx, type, name, value)
[docs]class StructCallbacks: """A class terminating super() calls for the structure callbacks. Structs, when finished, call completeElement(ctx), validate(), and onElementComplete() in sequence. All these need to up-call. This mixin provides non-upcalling implementations of these methods, and it needs to be present in mixins for structure. This will only work properly if self actually is a struct, as we rely on the presence of name_ attributes in case of prematurely terminated method resolution. """ def __warnTermination(self, methname): if hasattr(super(), methname): args = (self.name_, " ".join(c.__name__ for c in self.__class__.__mro__)) warnings.warn("Discarding validate method while calling up" " from {}, mro {} ".format(*args))
[docs] def validate(self): self.__warnTermination("validate")
[docs] def completeElement(self, ctx): self.__warnTermination("completeElement")
[docs] def onElementComplete(self): self.__warnTermination("onElementComplete")
[docs] def setParent(self, parent): self.__warnTermination("setParent")