# ALS Parcial 2a 2018/19 MIT License Baltasar <jbgarcia@uvigo.es>
import json
"""
1. La clase Registro es capaz de albergar varios datos que pueden ser accedidos por nombre, por nombre construido (r#i), o por índice. Para construir un objeto, se le puede pasar o bien un diccionario, o bien una lista (en este caso, las claves serán las citadas r#i). Los únicos métodos en la clase son: __init__(), __getattr__(), __len__() (que devuelve el número de elementos), y __str__() (que devuelve el contenido del objeto en formato de diccionario, utilizando comillas dobles y un espacio tras ‘,’ y ‘:’).
r1 = Registro({"huevos": 15, "patatas": 5})
print(r1.r0, r1.get(0), r1.huevos) # 15 15 15
print(r1.r1, r1.get(1), r1.patatas) # 5 5 5
print(r1) # {“huevos”: 15, “patatas”: 5}
r2 = Registro([“a”, “b”])
print(r2.r0, r2.get(0)) # a a
print(r2.r1, r2.get(1)) # b b
print(r2) # {“r0”: “a”, “r1”: “b”}
2. Cree los métodos to_json(f) y from_json(f). El primero escribe la codificación JSON del objeto como un archivo, la segunda toma un archivo con contenido en formato JSON y crea un objeto con dicho contenido.
r2 = Registro([“a”, “b”, “c”])
with open(“datos.json”, “wt”) as f:
r2.to_json(f) # {“r0”: “a”, “r1”: “b”, “r2”: “c”}
with open(“datos.json”, “rt”) as f:
print(str(Registro.from_json(f))) # {“r0”: “a”, “r1”: “b”, “r2”: “c”}
3. Escriba la función filtra_registros(lr, f), que recibe como parámetros una lista de registros y una función que devolverá verdadero o falso según el registro que se le pase. Deben utilizarse exclusivamente lambdas, y para esta función en particular, filtrar la lista.
resultado = filtra_registros([r1, r2], lambda r: isinstance(r.r0, int))
print(resultado) # [r1]
"""
class Registro:
def __init__ ( self , datos) :
if isinstance ( datos, dict ) :
self .__dict__ = datos
elif ( isinstance ( datos, list )
or isinstance ( datos, tuple )
or isinstance ( datos, set ) ) :
for i, x in enumerate ( list ( datos) ) :
self .__dict__ [ 'r' + str ( i) ] = x
else :
self .__dict__ [ "r0" ] = datos
def __getattr__ ( self , s) :
def getPos( i) :
return self .__dict__ [ list ( self .__dict__ .keys ( ) ) [ i] ]
toret = None
if s.startswith ( 'r' ) :
try :
toret = getPos( int ( s[ 1 :] ) )
except ( KeyError , ValueError ) :
toret = None
elif s.startswith ( 'get' ) :
toret = lambda i: getPos( i)
return toret
def to_json( self , f) :
return json.dump ( self .__dict__ , f)
@ staticmethod
def from_json( f) :
toret = Registro( { } )
toret.__dict__ = json.load ( f)
return toret
def __len__ ( self ) :
return len ( self .__dict__ )
def __str__ ( self ) :
toret = "{"
separador = ""
for key in self .__dict__ .keys ( ) :
value = self .__dict__ [ key]
if isinstance ( value, str ) :
value = "\" " + value + "\" "
else :
value = str ( value)
toret += separador
toret += "\" " + key + "\" : "
toret += value
separador = ", "
return toret + '}'
filtra_registros = lambda lr, f: ( [ ] if lr == [ ]
else [ lr[ 0 ] ] + filtra_registros( lr[ 1 :] , f)
if f( lr[ 0 ] )
else filtra_registros( lr[ 1 :] , f) )
import io
import unittest
class TestRegistro( unittest .TestCase ) :
def setUp( self ) :
self .r1 = Registro( { "huevos" : 15 , "patatas" : 5 , "salchichas" : 12 } )
self .r2 = Registro( [ 1 , 2 , 3 , 4 , 5 ] )
self .r3 = Registro( 'a' )
self .todos_registros = [ self .r1 , self .r2 , self .r3 ]
self .todos_resultados = [
"{\" huevos\" :15,\" patatas\" :5,\" salchichas\" :12}" ,
"{\" r0\" :1,\" r1\" :2,\" r2\" :3,\" r3\" :4,\" r4\" :5}" ,
"{\" r0\" :\" a\" }"
]
def testRegistroPorIndiceGet( self ) :
r1 = [ 15 , 5 , 12 ]
r2 = [ 1 , 2 , 3 , 4 , 5 ]
r3 = [ 'a' ]
todos_resultados = [ r1, r2, r3]
self .assertEqual ( len ( todos_resultados) , len ( self .todos_registros ) )
for i, l in enumerate ( todos_resultados) :
r = self .todos_registros [ i]
self .assertEqual ( len ( l) , len ( r) )
for n, x in enumerate ( l) :
self .assertEqual ( x, r.get ( n) )
self .assertEqual ( x, getattr ( r, "r" + str ( n) ) )
def testRegistroStr( self ) :
self .assertEqual ( len ( self .todos_resultados ) , len ( self .todos_registros ) )
for i, resultado in enumerate ( self .todos_resultados ) :
resultado_registro = TestRegistro.prepara_resultado ( str ( self .todos_registros [ i] ) )
resultado = TestRegistro.prepara_resultado ( resultado)
self .assertEqual ( resultado, resultado_registro)
def testRegistroR1PorNombre( self ) :
self .assertEqual ( 15 , self .r1 .huevos )
self .assertEqual ( 5 , self .r1 .patatas )
self .assertEqual ( 12 , self .r1 .salchichas )
def testRegistroToJSON( self ) :
for r in self .todos_registros :
with io.StringIO ( ) as f:
r.to_json ( f)
self .assertEqual ( str ( r) , f.getvalue ( ) .strip ( ) )
def tesRegistroFromJSON( self ) :
for i, r in enumerate ( self .todos_registros ) :
json_r = TestRegistro.prepara_resultado ( str ( r) )
with io.StringIO ( self .todos_resultados [ i] ) as f:
loaded_r = Registro.from_json ( f)
resultado = TestRegistro.prepara_resultado ( str ( loaded_r) )
self .assertEqual ( resultado, json_r)
def testFiltraRegistros( self ) :
resultado = filtra_registros( self .todos_registros , lambda r: isinstance ( r.r0 , int ) )
self .assertEqual ( [ self .r1 , self .r2 ] , resultado)
@ staticmethod
def prepara_resultado( s) :
return s.strip ( ) .replace ( '\' ' , '"' ) .replace ( ' ' , "" )
if __name__ == "__main__" :
unittest .main ( )
IyBBTFMgUGFyY2lhbCAyYSAyMDE4LzE5IE1JVCBMaWNlbnNlIEJhbHRhc2FyIDxqYmdhcmNpYUB1dmlnby5lcz4KCgppbXBvcnQganNvbgoKCiIiIgogICAgMS4gTGEgY2xhc2UgUmVnaXN0cm8gZXMgY2FwYXogZGUgYWxiZXJnYXIgdmFyaW9zIGRhdG9zIHF1ZSBwdWVkZW4gc2VyIGFjY2VkaWRvcyBwb3Igbm9tYnJlLCBwb3Igbm9tYnJlIGNvbnN0cnVpZG8gKHIjaSksIG8gcG9yIMOtbmRpY2UuIFBhcmEgY29uc3RydWlyIHVuIG9iamV0bywgc2UgbGUgcHVlZGUgcGFzYXIgbyBiaWVuIHVuIGRpY2Npb25hcmlvLCBvIGJpZW4gdW5hIGxpc3RhIChlbiBlc3RlIGNhc28sIGxhcyBjbGF2ZXMgc2Vyw6FuIGxhcyBjaXRhZGFzIHIjaSkuIExvcyDDum5pY29zIG3DqXRvZG9zIGVuIGxhIGNsYXNlIHNvbjogX19pbml0X18oKSwgX19nZXRhdHRyX18oKSwgX19sZW5fXygpIChxdWUgZGV2dWVsdmUgZWwgbsO6bWVybyBkZSBlbGVtZW50b3MpLCB5IF9fc3RyX18oKSAocXVlIGRldnVlbHZlIGVsIGNvbnRlbmlkbyBkZWwgb2JqZXRvIGVuIGZvcm1hdG8gZGUgZGljY2lvbmFyaW8sIHV0aWxpemFuZG8gY29taWxsYXMgZG9ibGVzIHkgdW4gZXNwYWNpbyB0cmFzIOKAmCzigJkgeSDigJg64oCZKS4KCiAgICAJcjEgPSBSZWdpc3Rybyh7Imh1ZXZvcyI6IDE1LCAicGF0YXRhcyI6IDV9KQoJcHJpbnQocjEucjAsIHIxLmdldCgwKSwgcjEuaHVldm9zKQkJIyAxNSAxNSAxNQoJcHJpbnQocjEucjEsIHIxLmdldCgxKSwgcjEucGF0YXRhcykJCSMgIDUgIDUgIDUKCXByaW50KHIxKQkJCQkJCSMge+KAnGh1ZXZvc+KAnTogMTUsIOKAnHBhdGF0YXPigJ06IDV9CgoJcjIgPSBSZWdpc3Rybyhb4oCcYeKAnSwg4oCcYuKAnV0pCglwcmludChyMi5yMCwgcjIuZ2V0KDApKQkJCQkjIGEgYQoJcHJpbnQocjIucjEsIHIyLmdldCgxKSkJCQkJIyBiIGIKCXByaW50KHIyKQkJCQkJCSMge+KAnHIw4oCdOiDigJxh4oCdLCDigJxyMeKAnTog4oCcYuKAnX0KCgogICAgMi4gQ3JlZSBsb3MgbcOpdG9kb3MgdG9fanNvbihmKSB5IGZyb21fanNvbihmKS4gRWwgcHJpbWVybyBlc2NyaWJlIGxhIGNvZGlmaWNhY2nDs24gSlNPTiBkZWwgb2JqZXRvIGNvbW8gdW4gYXJjaGl2bywgbGEgc2VndW5kYSB0b21hIHVuIGFyY2hpdm8gY29uIGNvbnRlbmlkbyBlbiBmb3JtYXRvIEpTT04geSBjcmVhIHVuIG9iamV0byBjb24gZGljaG8gY29udGVuaWRvLgoKCXIyID0gUmVnaXN0cm8oW+KAnGHigJ0sIOKAnGLigJ0sIOKAnGPigJ1dKQoKCXdpdGggb3BlbijigJxkYXRvcy5qc29u4oCdLCDigJx3dOKAnSkgYXMgZjoKCQlyMi50b19qc29uKGYpCQkJCQkjIHvigJxyMOKAnTog4oCcYeKAnSwg4oCccjHigJ06IOKAnGLigJ0sIOKAnHIy4oCdOiDigJxj4oCdfQoKCXdpdGggb3BlbijigJxkYXRvcy5qc29u4oCdLCDigJxydOKAnSkgYXMgZjoKCQlwcmludChzdHIoUmVnaXN0cm8uZnJvbV9qc29uKGYpKSkJIyB74oCccjDigJ06IOKAnGHigJ0sIOKAnHIx4oCdOiDigJxi4oCdLCDigJxyMuKAnTog4oCcY+KAnX0KCiAgICAgICAKICAgIDMuIEVzY3JpYmEgbGEgZnVuY2nDs24gZmlsdHJhX3JlZ2lzdHJvcyhsciwgZiksIHF1ZSByZWNpYmUgY29tbyBwYXLDoW1ldHJvcyB1bmEgbGlzdGEgZGUgcmVnaXN0cm9zIHkgdW5hIGZ1bmNpw7NuIHF1ZSBkZXZvbHZlcsOhIHZlcmRhZGVybyBvIGZhbHNvIHNlZ8O6biBlbCByZWdpc3RybyBxdWUgc2UgbGUgcGFzZS4gRGViZW4gdXRpbGl6YXJzZSBleGNsdXNpdmFtZW50ZSBsYW1iZGFzLCB5IHBhcmEgZXN0YSBmdW5jacOzbiBlbiBwYXJ0aWN1bGFyLCBmaWx0cmFyIGxhIGxpc3RhLgoKCXJlc3VsdGFkbyA9IGZpbHRyYV9yZWdpc3Ryb3MoW3IxLCByMl0sIGxhbWJkYSByOiBpc2luc3RhbmNlKHIucjAsIGludCkpCglwcmludChyZXN1bHRhZG8pCQkJCQkjIFtyMV0KCiIiIgoKCmNsYXNzIFJlZ2lzdHJvOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIGRhdG9zKToKICAgICAgICBpZiBpc2luc3RhbmNlKGRhdG9zLCBkaWN0KToKICAgICAgICAgICAgc2VsZi5fX2RpY3RfXyA9IGRhdG9zCiAgICAgICAgZWxpZiAoaXNpbnN0YW5jZShkYXRvcywgbGlzdCkKICAgICAgICAgICAgb3IgaXNpbnN0YW5jZShkYXRvcywgdHVwbGUpCiAgICAgICAgICAgIG9yIGlzaW5zdGFuY2UoZGF0b3MsIHNldCkpOgogICAgICAgICAgICBmb3IgaSwgeCBpbiBlbnVtZXJhdGUobGlzdChkYXRvcykpOgogICAgICAgICAgICAgICAgc2VsZi5fX2RpY3RfX1sncicgKyBzdHIoaSldID0geAogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHNlbGYuX19kaWN0X19bInIwIl0gPSBkYXRvcwogICAgICAgICAgICAKICAgIGRlZiBfX2dldGF0dHJfXyhzZWxmLCBzKToKICAgICAgICBkZWYgZ2V0UG9zKGkpOgogICAgICAgICAgICByZXR1cm4gc2VsZi5fX2RpY3RfX1tsaXN0KHNlbGYuX19kaWN0X18ua2V5cygpKVtpXV0KICAgICAgICAKICAgICAgICB0b3JldCA9IE5vbmUKICAgICAgICAKICAgICAgICBpZiBzLnN0YXJ0c3dpdGgoJ3InKToKICAgICAgICAgICAgdHJ5OgogICAgICAgICAgICAgICAgdG9yZXQgPSBnZXRQb3MoaW50KHNbMTpdKSkKICAgICAgICAgICAgZXhjZXB0IChLZXlFcnJvciwgVmFsdWVFcnJvcik6CiAgICAgICAgICAgICAgICB0b3JldCA9IE5vbmUKICAgICAgICBlbGlmIHMuc3RhcnRzd2l0aCgnZ2V0Jyk6CiAgICAgICAgICAgIHRvcmV0ID0gbGFtYmRhIGk6IGdldFBvcyhpKQogICAgICAgICAgICAgICAgCiAgICAgICAgcmV0dXJuIHRvcmV0CiAgICAKICAgIGRlZiB0b19qc29uKHNlbGYsIGYpOgogICAgICAgIHJldHVybiBqc29uLmR1bXAoc2VsZi5fX2RpY3RfXywgZikKICAgICAgICAKICAgIEBzdGF0aWNtZXRob2QKICAgIGRlZiBmcm9tX2pzb24oZik6CiAgICAgICAgdG9yZXQgPSBSZWdpc3Rybyh7fSkKICAgICAgICB0b3JldC5fX2RpY3RfXyA9IGpzb24ubG9hZChmKQogICAgICAgIHJldHVybiB0b3JldAogICAgICAgIAogICAgZGVmIF9fbGVuX18oc2VsZik6CiAgICAgICAgcmV0dXJuIGxlbihzZWxmLl9fZGljdF9fKQogICAgICAgICAgICAKICAgIGRlZiBfX3N0cl9fKHNlbGYpOgogICAgICAgIHRvcmV0ID0gInsiCiAgICAgICAgc2VwYXJhZG9yID0gIiIKICAgICAgICBmb3Iga2V5IGluIHNlbGYuX19kaWN0X18ua2V5cygpOgogICAgICAgICAgICB2YWx1ZSA9IHNlbGYuX19kaWN0X19ba2V5XQogICAgICAgICAgICAKICAgICAgICAgICAgaWYgaXNpbnN0YW5jZSh2YWx1ZSwgc3RyKToKICAgICAgICAgICAgICAgIHZhbHVlID0gIlwiIiArIHZhbHVlICsgIlwiIgogICAgICAgICAgICBlbHNlOgogICAgICAgICAgICAgICAgdmFsdWUgPSBzdHIodmFsdWUpCiAgICAgICAgICAgIAogICAgICAgICAgICB0b3JldCArPSBzZXBhcmFkb3IKICAgICAgICAgICAgdG9yZXQgKz0gIlwiIiArIGtleSArICJcIjogIgogICAgICAgICAgICB0b3JldCArPSB2YWx1ZQogICAgICAgICAgICBzZXBhcmFkb3IgPSAiLCAiCiAgICAgICAgcmV0dXJuIHRvcmV0ICsgJ30nCgoKZmlsdHJhX3JlZ2lzdHJvcyA9IGxhbWJkYSBsciwgZjogKFtdIGlmIGxyID09IFtdCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIFtsclswXV0gKyBmaWx0cmFfcmVnaXN0cm9zKGxyWzE6XSwgZikKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIGYobHJbMF0pCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGZpbHRyYV9yZWdpc3Ryb3MobHJbMTpdLCBmKSkKCgppbXBvcnQgaW8KaW1wb3J0IHVuaXR0ZXN0CgoKY2xhc3MgVGVzdFJlZ2lzdHJvKHVuaXR0ZXN0LlRlc3RDYXNlKToKICAgIGRlZiBzZXRVcChzZWxmKToKICAgICAgICBzZWxmLnIxID0gUmVnaXN0cm8oeyJodWV2b3MiOiAxNSwgInBhdGF0YXMiOiA1LCAic2FsY2hpY2hhcyI6IDEyfSkKICAgICAgICBzZWxmLnIyID0gUmVnaXN0cm8oWzEsIDIsIDMsIDQsIDVdKQogICAgICAgIHNlbGYucjMgPSBSZWdpc3RybygnYScpCiAgICAgICAgc2VsZi50b2Rvc19yZWdpc3Ryb3MgPSBbc2VsZi5yMSwgc2VsZi5yMiwgc2VsZi5yM10KICAgICAgICBzZWxmLnRvZG9zX3Jlc3VsdGFkb3MgPSBbCiAgICAgICAgICAgICJ7XCJodWV2b3NcIjoxNSxcInBhdGF0YXNcIjo1LFwic2FsY2hpY2hhc1wiOjEyfSIsCiAgICAgICAgICAgICJ7XCJyMFwiOjEsXCJyMVwiOjIsXCJyMlwiOjMsXCJyM1wiOjQsXCJyNFwiOjV9IiwKICAgICAgICAgICAgIntcInIwXCI6XCJhXCJ9IgogICAgICAgIF0KICAgICAgICAKICAgIGRlZiB0ZXN0UmVnaXN0cm9Qb3JJbmRpY2VHZXQoc2VsZik6CiAgICAgICAgcjEgPSBbMTUsIDUsIDEyXQogICAgICAgIHIyID0gWzEsIDIsIDMsIDQsIDVdCiAgICAgICAgcjMgPSBbJ2EnXQogICAgICAgIHRvZG9zX3Jlc3VsdGFkb3MgPSBbcjEsIHIyLCByM10KICAgICAgICAKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGxlbih0b2Rvc19yZXN1bHRhZG9zKSwgbGVuKHNlbGYudG9kb3NfcmVnaXN0cm9zKSkKICAgICAgICBmb3IgaSwgbCBpbiBlbnVtZXJhdGUodG9kb3NfcmVzdWx0YWRvcyk6CiAgICAgICAgICAgIHIgPSBzZWxmLnRvZG9zX3JlZ2lzdHJvc1tpXQogICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKGxlbihsKSwgbGVuKHIpKQogICAgICAgICAgICBmb3IgbiwgeCBpbiBlbnVtZXJhdGUobCk6CiAgICAgICAgICAgICAgICBzZWxmLmFzc2VydEVxdWFsKHgsIHIuZ2V0KG4pKQogICAgICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbCh4LCBnZXRhdHRyKHIsICJyIiArIHN0cihuKSkpCiAgICAgICAgICAgICAgICAKICAgIGRlZiB0ZXN0UmVnaXN0cm9TdHIoc2VsZik6CiAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChsZW4oc2VsZi50b2Rvc19yZXN1bHRhZG9zKSwgbGVuKHNlbGYudG9kb3NfcmVnaXN0cm9zKSkKICAgICAgICBmb3IgaSwgcmVzdWx0YWRvIGluIGVudW1lcmF0ZShzZWxmLnRvZG9zX3Jlc3VsdGFkb3MpOgogICAgICAgICAgICByZXN1bHRhZG9fcmVnaXN0cm8gPSBUZXN0UmVnaXN0cm8ucHJlcGFyYV9yZXN1bHRhZG8oc3RyKHNlbGYudG9kb3NfcmVnaXN0cm9zW2ldKSkKICAgICAgICAgICAgcmVzdWx0YWRvID0gVGVzdFJlZ2lzdHJvLnByZXBhcmFfcmVzdWx0YWRvKHJlc3VsdGFkbykKICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChyZXN1bHRhZG8sIHJlc3VsdGFkb19yZWdpc3RybykKICAgICAgICAgICAgICAgICAgICAKICAgIGRlZiB0ZXN0UmVnaXN0cm9SMVBvck5vbWJyZShzZWxmKToKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDE1LCBzZWxmLnIxLmh1ZXZvcykKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDUsIHNlbGYucjEucGF0YXRhcykKICAgICAgICBzZWxmLmFzc2VydEVxdWFsKDEyLCBzZWxmLnIxLnNhbGNoaWNoYXMpCiAgICAgICAgCiAgICBkZWYgdGVzdFJlZ2lzdHJvVG9KU09OKHNlbGYpOgogICAgICAgIGZvciByIGluIHNlbGYudG9kb3NfcmVnaXN0cm9zOgogICAgICAgICAgICB3aXRoIGlvLlN0cmluZ0lPKCkgYXMgZjoKICAgICAgICAgICAgICAgIHIudG9fanNvbihmKQogICAgICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChzdHIociksIGYuZ2V0dmFsdWUoKS5zdHJpcCgpKQogICAgICAgICAgICAKICAgIGRlZiB0ZXNSZWdpc3Ryb0Zyb21KU09OKHNlbGYpOgogICAgICAgIGZvciBpLCByIGluIGVudW1lcmF0ZShzZWxmLnRvZG9zX3JlZ2lzdHJvcyk6CiAgICAgICAgICAgIGpzb25fciA9IFRlc3RSZWdpc3Ryby5wcmVwYXJhX3Jlc3VsdGFkbyhzdHIocikpCiAgICAgICAgICAgIAogICAgICAgICAgICB3aXRoIGlvLlN0cmluZ0lPKHNlbGYudG9kb3NfcmVzdWx0YWRvc1tpXSkgYXMgZjoKICAgICAgICAgICAgICAgIGxvYWRlZF9yID0gUmVnaXN0cm8uZnJvbV9qc29uKGYpCgogICAgICAgICAgICByZXN1bHRhZG8gPSBUZXN0UmVnaXN0cm8ucHJlcGFyYV9yZXN1bHRhZG8oc3RyKGxvYWRlZF9yKSkKICAgICAgICAgICAgc2VsZi5hc3NlcnRFcXVhbChyZXN1bHRhZG8sIGpzb25fcikKICAgICAgICAgICAgCiAgICBkZWYgdGVzdEZpbHRyYVJlZ2lzdHJvcyhzZWxmKToKICAgICAgICByZXN1bHRhZG8gPSBmaWx0cmFfcmVnaXN0cm9zKHNlbGYudG9kb3NfcmVnaXN0cm9zLCBsYW1iZGEgcjogaXNpbnN0YW5jZShyLnIwLCBpbnQpKQogICAgICAgIHNlbGYuYXNzZXJ0RXF1YWwoW3NlbGYucjEsIHNlbGYucjJdLCByZXN1bHRhZG8pCiAgICAgICAgCiAgICBAc3RhdGljbWV0aG9kCiAgICBkZWYgcHJlcGFyYV9yZXN1bHRhZG8ocyk6CiAgICAgICAgcmV0dXJuIHMuc3RyaXAoKS5yZXBsYWNlKCdcJycsICciJykucmVwbGFjZSgnICcsICIiKQoKCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICB1bml0dGVzdC5tYWluKCkK