def subcolecciones_sin_nombre(self): subcolecc = Coleccion() subcol_nombre = Coleccion("hola") # Estamos vinculando al nombre 'subcolecc', pero subcolecc en sí # no tiene atributo/valor .nombre, que es lo que se está probando. # Cuando hay un error, ese hecho hará que serializado() muera en # sorted() al compararlo con subcol_nombre (que tiene un nombre de # cadena). raiz = Coleccion(subcol_nombre, subcolecc=subcolecc) esperado = dict( nombre=None, default=None, help=None, artefactos=[], colecciones=[ # Espere anónimo primero ya que los ordenamos como si su # nombre fuera la cadena vacía. dict( artefactos=[], colecciones=[], nombre=None, default=None, help=None, ), dict( artefactos=[], colecciones=[], nombre="hola", default=None, help=None, ), ], ) assert esperado == raiz.serializado()
def genera_ValueError_si_coleccion_sin_nombre(self): # Las colecciones no-root deben tener un nombre explícito dado a # través de kwarg, tener un atributo de nombre establecido o ser # un módulo con __name__ definido. raiz = Coleccion() sub = Coleccion() with raises(ValueError): raiz.ad_coleccion(sub)
def se_filtra_a_los_nombres_de_las_subcolecciones(self): @artefacto def mi_artefacto(c): pass colecc = Coleccion(interior_colecc=Coleccion(mi_artefacto)) contextos = colecc.a_contextos() assert contextos[0].nombre == "interior-colecc.mi-artefacto"
def Lrutas_de_subcoleccion_no_válidas_resultan_en_KeyError(self): # Directamente no válido with raises(KeyError): Coleccion("bah").configuracion("nop.artefacto") # Existe pero el nivel es incorrecto (debería ser # 'root.artefacto', no solo 'artefacto') interior = Coleccion("interior", self.artefacto) with raises(KeyError): Coleccion("raiz", interior).configuracion("artefacto")
def kwargs_actuan_como_args_de_nombre_para_objetos_dados(self): sub = Coleccion() @artefacto def artefacto1(c): pass hng = Coleccion(loltask=artefacto1, notsub=sub) assert hng["loltask"] == artefacto1 assert hng.colecciones["notsub"] == sub
def arglista_posicional_preserva_el_orden_dado(self): @artefacto(posicional=("segundo", "primero")) def miartefacto(c, primero, segundo, third): pass colecc = Coleccion() colecc.ad_artefacto(miartefacto) c = colecc.a_contextos()[0] esperado = [c.args["segundo"], c.args["primero"]] assert c.args_posicionales == esperado
def acceso_fusiona_desde_subcolecciones(self): interior = Coleccion("interior", self.artefacto) interior.configurar({"foo": "bar"}) self.raiz.configurar({"biz": "baz"}) # With no interior coleccion assert set(self.raiz.configuracion().keys()) == {"biz"} # With interior coleccion self.raiz.ad_coleccion(interior) claves = set(self.raiz.configuracion("interior.artefacto").keys()) assert claves == {"foo", "biz"}
def padres_sobrescriben_a_hijos_en_el_camino(self): interior = Coleccion("interior", self.artefacto) interior.configurar({"foo": "interior"}) self.raiz.ad_coleccion(interior) # Antes de actualizar la configuración coleccion raiz, refleja el int assert self.raiz.configuracion( "interior.artefacto")["foo"] == "interior" self.raiz.configurar({"foo": "exterior"}) # Después, refleja el exterior (ya que ahora anulaciones) assert self.raiz.configuracion( "interior.artefacto")["foo"] == "exterior"
def coleccion_vacía_con_nombre_docstringed(self): esperado = dict( nombre="foo", help="Hola doc", artefactos=[], default=None, colecciones=[], ) colecc = Coleccion("foo") colecc.__doc__ = "Hola doc" assert esperado == colecc.serializado()
def devuelve_lista_de_tuplas_de_ayuda(self): # TODO: considere rehacer ayuda_para para ser más flexible en la # entrada --arg value o bandera; o incluso objetos Argumento. ? # @artefacto (ayuda = {"otroarg": "otra ayuda"}) @artefacto(help={"otroarg": "otra ayuda"}) def miartefacto(c, miarg, otroarg): pass c = Coleccion(miartefacto).a_contextos()[0] esperado = [c.ayuda_para("--miarg"), c.ayuda_para("--otroarg")] assert c.help_tuplas() == esperado
def setup(self): # Contexto normal, no relacionado con artefacto/colección self.ordinario = Contexto( args=(Argumento("foo"), Argumento("bar", help="bar el baz"))) # Artefacto/Colección Contexto generado # (expondrá banderas n tales) @artefacto(help={"otroarg": "otra ayuda"}, opcional=["valopc"]) def miartefacto(c, miarg, otroarg, valopc, intval=5): pass col = Coleccion(miartefacto) self.tasked = col.a_contextos()[0]
def devuelve_objs_Coleccion_unicos_para_el_mismo_modulo_de_entrada( self): # Ignorando self.c por ahora, en caso de que cambie más tarde. # Primero, un módulo sin raíz Hangar mod = load("integracion") c1 = Coleccion.del_modulo(mod) c2 = Coleccion.del_modulo(mod) assert c1 is not c2 # Ahora uno *con* una raíz Hangar (que anteriormente tenía errores) mod2 = load("raiz_explicita") c3 = Coleccion.del_modulo(mod2) c4 = Coleccion.del_modulo(mod2) assert c3 is not c4
class ad_coleccion: def setup(self): self.c = Coleccion() def agrega_coleccion_como_subcoleccion_de_self(self): c2 = Coleccion("foo") self.c.ad_coleccion(c2) assert "foo" in self.c.colecciones def puede_tomar_objetos_modulo(self): self.c.ad_coleccion(load("integracion")) assert "integracion" in self.c.colecciones def genera_ValueError_si_coleccion_sin_nombre(self): # Las colecciones no-root deben tener un nombre explícito dado a # través de kwarg, tener un atributo de nombre establecido o ser # un módulo con __name__ definido. raiz = Coleccion() sub = Coleccion() with raises(ValueError): raiz.ad_coleccion(sub) def genera_ValueError_si_la_coleccion_tiene_el_mismo_nombre_que_el_artefacto( self): self.c.ad_artefacto(_miartefacto, "sub") with raises(ValueError): self.c.ad_coleccion(Coleccion("sub"))
def rutas_de_subcolecciones_pueden_tener_puntos(self): hoja = Coleccion("hoja", self.artefacto) hoja.configurar({"clave": "hoja-valor"}) medio = Coleccion("medio", hoja) raiz = Coleccion("raiz", medio) config = raiz.configuracion("medio.hoja.artefacto") assert config == {"clave": "hoja-valor"}
def _meh(self): @artefacto def artefacto1(c): pass @artefacto def artefacto2(c): pass @artefacto def artefacto3(c): pass submeh = Coleccion("submeh", artefacto3) return Coleccion("bah", artefacto1, artefacto2, submeh)
def los_alias_tambien_estan_discontinuos(self): @artefacto(alias=["hola_estoy_subguionado"]) def cualquier(c): pass contextos = Coleccion(cualquier).a_contextos() assert "hola-estoy-subguionado" in contextos[0].alias
def _guiones_bajos_anidados(self, nombre_auto_guion=None): @artefacto(alias=["otro_nombre"]) def mi_artefacto(c): pass @artefacto(alias=["otro_interior"]) def artefacto_interno(c): pass # NOTE: explícitamente no dar kwarg a la subcolección; esto # prueba que el espacio de nombres de nivel superior realiza # la transformación inversa cuando es necesario. sub = Coleccion("interior_colecc", artefacto_interno) return Coleccion(mi_artefacto, sub, nombre_auto_guion=nombre_auto_guion)
def se_filtra_a_artefactos_de_subcoleccion(self): @artefacto def artefacto_externo(c): pass @artefacto def artefacto_interno(c): pass colecc = Coleccion(artefacto_externo, interior=Coleccion(artefacto_interno)) contextos = colecc.a_contextos() esperado = { "artefacto-exterior", "interior.interior-artefacto" } assert {x.nombre for x in contextos} == esperado
def los_guiones_bajos_iniciales_y_finales_no_se_ven_afectados( self): @artefacto def _lo_que_siempre_(c): pass @artefacto def _enfriador_interior_(c): pass interior = Coleccion("interior", _enfriador_interior_) contextos = Coleccion(_lo_que_siempre_, interior).a_contextos() esperado = { "_lo_que-siempre_", "interior._enfriador-interior_" } assert {x.nombre for x in contextos} == esperado
def nombre_docstring_default_y_artefactos(self): esperado = dict( nombre="desplegar", help="Cómo desplegar código y configs.", artefactos=[ dict( nombre="db", help="Implementar en nuestros DB servers.", alias=["db-servers"], ), dict( nombre="omnipresente", help="Implementar en todos los objetivos.", alias=[], ), dict( nombre="web", help="Actualiza y rebota los servidores web.", alias=[], ), ], default="omnipresente", colecciones=[], ) with ruta_de_soporte(): from arbol import desplegar colecc = Coleccion.del_modulo(desplegar) assert esperado == colecc.serializado()
def los_nombres_de_los_submodulos_eliminan_al_ultimo_fragmento(self): with ruta_de_soporte(): from paquete import modulo c = Coleccion.del_modulo(modulo) assert modulo.__name__ == "paquete.modulo" assert c.nombre == "modulo" assert "miartefacto" in c # Sanity
def colección_vacia(self): esperado = dict(nombre=None, help=None, artefactos=[], default=None, colecciones=[]) assert esperado == Coleccion().serializado()
def coleccion_con_nombre_vacia(self): esperado = dict(nombre="foo", help=None, artefactos=[], default=None, colecciones=[]) assert esperado == Coleccion("foo").serializado()
def respeta_los_artefactos_pordefecto_de_la_subcoleccion_en_el_nombre_de_la_subcoleccion( self): sub = Coleccion.del_modulo(load("decoradores")) self.c.ad_coleccion(sub) # Sanity assert self.c["decoradores.biz"] is sub["biz"] # Real prueba assert self.c["decoradores"] is self.c["decoradores.biz"]
def nombres_de_contexto_se_vuelven_discontinuos_automaticamente( self): @artefacto def mi_artefacto(c): pass contextos = Coleccion(mi_artefacto).a_contextos() assert contextos[0].nombre == "mi-artefacto"
def arg_cadena_inicial_engrana_con_varargs_y_kwargs(self): @artefacto def artefacto1(c): pass @artefacto def artefacto2(c): pass sub = Coleccion("sub") hng = Coleccion("raiz", artefacto1, sub, sometask=artefacto2) for x, y in ( (hng.nombre, "raiz"), (hng["artefacto1"], artefacto1), (hng.colecciones["sub"], sub), (hng["algunartefacto"], artefacto2), ): assert x == y
def Ruta_no_valida(self): # Esto realmente es solo probar el comportamiento de Lexicon/dict, # pero bueno, bueno ser explícito, especialmente si alguna vez # queremos que esto se convierta en Salida u otra excepción # personalizada. (Por ahora, la mayoría / todas las personas que # llaman capturan manualmente KeyError y generan Salida solo para # mantener la mayoría del uso de Salida en lo alto del stack ...) with raises(KeyError): coleccion = Coleccion.del_modulo(load("arbol")) coleccion.subcoleccion_desde_ruta("jeje.cualquier.pieza")
def setup(self): mod = load("raiz_explicita") mod.hng.configurar({ "clave": "incorporado", "otraclave": "yup", "subconfig": { "miclave": "mivalor" }, }) mod.hng.nombre = "builtin_name" self.nocambiado = Coleccion.del_modulo(mod) self.cambiado = Coleccion.del_modulo( mod, nombre="anular_nombre", config={ "clave": "anular", "subconfig": { "miotraclave": "miotrovalor" }, }, )
def setup(self): @artefacto(posicional=[], iterable=["mi_lista"], incremento=["verbose"]) def mi_artefacto( c, micadena, s, booleano=False, b=False, v=False, nombre_largo=False, bool_true=True, _guionbajo_principal=False, guionbajo_posterior=False, mi_lista=None, verbose=0, ): pass @artefacto(alias=["mi_artefacto27"]) def mi_artefacto2(c): pass @artefacto(default=True) def mi_artefacto3(c, micadena): pass @artefacto def mi_artefacto4(c, limpiar=False, browse=False): pass @artefacto(alias=["otro"], default=True) def sub_artefacto(c): pass sub_colecc = Coleccion("sub_colecc", sub_artefacto) self.c = Coleccion(mi_artefacto, mi_artefacto2, mi_artefacto3, mi_artefacto4, sub_colecc)
def setup(self): @artefacto def miartefacto(c, texto, booleano=False, number=5): print(texto) @artefacto(alias=["miartefacto27"]) def miartefacto2(c): pass @artefacto(alias=["otroartefacto"], default=True) def subartefacto(c): pass sub = Coleccion("sub", subartefacto) self.c = Coleccion(miartefacto, miartefacto2, sub) self.contextos = self.c.a_contextos() alias_tups = [list(x.alias) for x in self.contextos] self.alias = reduce(operator.add, alias_tups, []) # Focus on 'miartefacto' as it has the more interesting sig self.contexto = [ x for x in self.contextos if x.nombre == "miartefacto" ][0]