def iterables_funcionan_correctamente_fuera_de_un_vacio(self): # Error no detectado donde estaba principalmente enfocado en el # caso de uso -vvv ... ¡los incrementables 'normales' nunca # dejaron el estado 'esperando valor' en el analizador! así que # _subsequent_ artefacto nombres & such nunca se analizaron # correctamente, siempre se agregaron a la lista. c = Contexto("miartefacto", args=[Argumento("milista", tipo=list)]) c2 = Contexto("otroartefacto") argv = [ "miartefacto", "--milista", "val", "--milista", "val2", "otroartefacto", ] resultado = Analizador([c, c2]).analizar_args(argv) # Cuando el error está presente, el resultado solo tiene un # contexto (para 'mi artefacto') y su 'milista' consiste en # ['val', 'val2', 'otro artefacto']. (el medio '--milista' se # manejó semi-correctamente). milista = resultado[0].args.milista.valor assert milista == ["val", "val2"] contextos = len(resultado) err = "¡Obtuve {} resultados de análisis de contexto en lugar de 2!".format( contextos) assert contextos == 2, err assert resultado[1].nombre == "otroartefacto"
def analiza_lista_de_cadenas_sys_argv_style(self): "analiza la lista de cadenas sys.argv-style" # Pruebas no hinchables FTL miartefacto = Contexto(nombre="miartefacto") miartefacto.agregar_arg("arg") p = Analizador(contextos=[miartefacto]) p.analizar_args(["miartefacto", "--arg", "valor"])
def nombre_de_artefacto(self): # miartefacto --foo myotroartefacto c1 = Contexto("miartefacto", args=(Argumento("foo", opcional=True), )) c2 = Contexto("otroartefacto") p = Analizador([c1, c2]) self._prueba_para_ambiguedad("--foo otroartefacto", p)
def devuelve_solo_contextos_mencionados(self): artefacto1 = Contexto("miartefacto") artefacto2 = Contexto("otroartefacto") resultado = Analizador( (artefacto1, artefacto2)).analizar_args(["otroartefacto"]) assert len(resultado) == 1 assert resultado[0].nombre == "otroartefacto"
def siempre_incluye_contexto_inicial_si_se_le_dio_uno(self): # Incluso si no se vieron banderas nucleo/iniciales t1 = Contexto("t1") init = Contexto() resultado = Analizador((t1, ), inicial=init).analizar_args(["t1"]) assert resultado[0].nombre is None assert resultado[1].nombre == "t1"
def por_si_mismo_caso_base(self): artefacto1 = Contexto("miartefacto") init = Contexto(args=[Argumento("help", opcional=True)]) analizador = Analizador(inicial=init, contextos=[artefacto1]) resultado = analizador.analizar_args(["miartefacto", "--help"]) assert len(resultado) == 2 assert resultado[0].args.help.valor == "miartefacto" assert "help" not in resultado[1].args
def valor_que_requiere_que_banderas_cores_tambien_trabajen_correctamente( self): "banderas de núcleo que requieren-valor también funcionan correctamente" inicial = Contexto(args=[Argumento("ocultar")]) artefacto1 = Contexto("miartefacto") analizador = Analizador(inicial=inicial, contextos=[artefacto1]) resultado = analizador.analizar_args( ["miartefacto", "--ocultar", "ambos"]) assert resultado[0].args.ocultar.valor == "ambos"
def otros_tokens_luego_generan_errores_de_analisis(self): # NOTE: esto se debe a la carcasa especial donde suministramos # el nombre del artefacto como valor cuando la bandera se # llama literalmente "ayuda". artefacto1 = Contexto("miartefacto") init = Contexto(args=[Argumento("help", opcional=True)]) analizador = Analizador(inicial=init, contextos=[artefacto1]) with raises(ErrorDeAnalisis, match=r".*foobar.*"): analizador.analizar_args( ["miartefacto", "--help", "foobar"])
def banderas_core_funcionan_normalmente_cuando_no_hay_conflicto( self): # Contexto de análisis inicial con un --echo, más un artefacto sin argumentos inicial = Contexto(args=[self._echo()]) artefacto1 = Contexto("miartefacto") analizador = Analizador(inicial=inicial, contextos=[artefacto1]) # Llamar con --echo en el contexto por-artefacto, espere # que el contexto central se actualice (vs un error) resultado = analizador.analizar_args(["miartefacto", "--echo"]) assert resultado[0].args.echo.valor is True
def cuando_los_argumentos_de_conflicto_por_artefacto_ganan(self): # Contexto de análisis inicial con un --echo, más artefacto con el mismo inicial = Contexto(args=[self._echo()]) artefacto1 = Contexto("miartefacto", args=[self._echo()]) analizador = Analizador(inicial=inicial, contextos=[artefacto1]) # Llamar con --echo en el contexto por-artefacto, espere que # el contexto artefacto se actualice, y no nucleo. resultado = analizador.analizar_args(["miartefacto", "--echo"]) assert resultado[0].args.echo.valor is False assert resultado[1].args.echo.valor is True
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 es_feliz_manejando_el_mismo_artefacto_varias_veces(self): artefacto1 = Contexto("miartefacto") resultado = Analizador( (artefacto1, )).analizar_args(["miartefacto", "miartefacto"]) assert len(resultado) == 2 for x in resultado: assert x.nombre == "miartefacto"
def args_posicionales_comen_nombres_de_contexto_validos_de_otra_manera( self): miartefacto = Contexto( "miartefacto", args=[ Argumento("pos", posicional=True), Argumento("nonpos", default="default"), ], ) Contexto("lolwut") resultado = Analizador([miartefacto]).analizar_args( ["miartefacto", "lolwut"]) r = resultado[0] assert r.args["pos"].valor == "lolwut" assert r.args["nonpos"].valor == "default" assert len(resultado) == 1 # Not 2
def argumentos_miembros_de_contexto_devueltos_contienen_valores_dados( self): c = Contexto("miartefacto", args=(Argumento("booleano", tipo=bool), )) resultado = Analizador( (c, )).analizar_args(["miartefacto", "--booleano"]) assert resultado[0].args["booleano"].valor is True
def bool_core_pero_por_cadena_de_artefacto(self): # Contexto inicial de análisis con bool --ocultar, y un # artefacto con un regular (cadena) --ocultar inicial = Contexto( args=[Argumento("ocultar", tipo=bool, default=False)]) artefacto1 = Contexto("miartefacto", args=[Argumento("ocultar")]) analizador = Analizador(inicial=inicial, contextos=[artefacto1]) # Espera que, como la versión del artefacto gana, seamos # capaces de llamarlo con un valor. (Si hubiera bichos raros # en los que la bandera del núcleo informara al análisis, esto fallaría.) resultado = analizador.analizar_args( ["miartefacto", "--ocultar", "ambos"]) assert resultado[0].args.ocultar.valor is False assert resultado[1].args.ocultar.valor == "ambos"
def _analizador(self, arguments=None): if arguments is None: arguments = (Argumento(nombres=("foo", "f"), opcional=True, default="midefault"), ) self.contexto = Contexto("miartefacto", args=arguments) self.analizador = Analizador([self.contexto]) return self.analizador
def argumentos_que_toman_valores_obtienen_defaults_anulados_correctamente( self): # noqa args = (Argumento("arg", tipo=str), Argumento("arg2", tipo=int)) c = Contexto("miartefacto", args=args) argv = ["miartefacto", "--arg", "mival", "--arg2", "25"] resultado = Analizador((c, )).analizar_args(argv) assert resultado[0].args["arg"].valor == "mival" assert resultado[0].args["arg2"].valor == 25
def args_de_artefacto_funcionan_correctamente(self): artefacto1 = Contexto("miartefacto", args=(Argumento("bah"), )) resultado = Analizador((artefacto1, )).analizar_args([ "miartefacto", "--bah", "mehval1", "miartefacto", "--bah", "mehval2" ]) assert resultado[0].args.bah.valor == "mehval1" assert resultado[1].args.bah.valor == "mehval2"
def representa_valores_perdidos_de_argumentos_posicionales(self): arg1 = Argumento("arg1", posicional=True) arg2 = Argumento("arg2", posicional=False) arg3 = Argumento("arg3", posicional=True) c = Contexto(nombre="foo", args=(arg1, arg2, arg3)) assert c.faltan_argumentos_posicionales == [arg1, arg3] c.args_posicionales[0].valor = "wat" assert c.faltan_argumentos_posicionales == [arg3] c.args_posicionales[1].valor = "hrm" assert c.faltan_argumentos_posicionales == []
def argumentos_devueltos_no_dados_contienen_valores_pordefecto(self): # Es decir un Contexto con argumentos A y B, dued sin mención # de B, debería resultar en B existente en el resultado, con # None, o el argumento no existe. a = Argumento("nombre", tipo=str) b = Argumento("edad", default=7) c = Contexto("miartefacto", args=(a, b)) Analizador( (c, )).analizar_args(["miartefacto", "--nombre", "blah"]) assert c.args["edad"].valor == 7
def maneja_multiples_banderas_booleanas_por_contexto(self): c = Contexto( "miartefacto", args=(Argumento("foo", tipo=bool), Argumento("bar", tipo=bool)), ) r = Analizador([c ]).analizar_args(["miartefacto", "--foo", "--bar"]) a = r[0].args assert a.foo.valor is True assert a.bar.valor is True
def arg_posicionales_omitidos_genera_ParseError(self): try: arg = Argumento("pos", posicional=True) arg2 = Argumento("maspos", posicional=True) miartefacto = Contexto(nombre="miartefacto", args=[arg, arg2]) Analizador(contextos=[miartefacto]).analizar_args( ["miartefacto"]) except ErrorDeAnalisis as e: esperado = "'miartefacto' no recibió los argumentos posicionales requeridos: 'pos', 'maspos'" # noqa assert str(e) == esperado else: assert False, "No subió ErrorDeAnalisis!"
def clona_contexto_inicial(self): a = Argumento("foo", tipo=bool) assert a.valor is None c = Contexto(args=(a, )) p = Analizador(inicial=c) assert p.inicial is c r = p.analizar_args(["--foo"]) assert p.inicial is c c2 = r[0] assert c2 is not c a2 = c2.args["foo"] assert a2 is not a assert a.valor is None assert a2.valor is True
def clona_sin_contextos_iniciales(self): a = Argumento("foo") assert a.valor is None c = Contexto(nombre="miartefacto", args=(a, )) p = Analizador(contextos=(c, )) assert p.contextos["miartefacto"] is c r = p.analizar_args(["miartefacto", "--foo", "val"]) assert p.contextos["miartefacto"] is c c2 = r[0] assert c2 is not c a2 = c2.args["foo"] assert a2 is not a assert a.valor is None assert a2.valor == "val"
def args_posicionales_todavia_se_pueden_dar_como_banderas(self): # AKA "argumentos posicionales pueden venir en cualquier parte del contexto" pos1 = Argumento("pos1", posicional=True) pos2 = Argumento("pos2", posicional=True) nonpos = Argumento("nonpos", posicional=False, default="jeje") miartefacto = Contexto("miartefacto", args=[pos1, pos2, nonpos]) assert miartefacto.args_posicionales == [pos1, pos2] r = Analizador([miartefacto]).analizar_args([ "miartefacto", "--nonpos", "hum", "--pos2", "pos2val", "pos1val", ])[0] assert r.args["pos1"].valor == "pos1val" assert r.args["pos2"].valor == "pos2val" assert r.args["nonpos"].valor == "hum"
def setup(self): self.c = Contexto()
class agregar_arg: def setup(self): self.c = Contexto() def puede_tomar_una_instancia_de_Argumento(self): a = Argumento(nombres=("foo", )) self.c.agregar_arg(a) assert self.c.args["foo"] is a def puede_tomar_el_nombre_arg(self): self.c.agregar_arg("foo") assert "foo" in self.c.args def puede_tomar_kwargs_para_un_solo_Argumento(self): self.c.agregar_arg(nombres=("foo", "bar")) assert "foo" in self.c.args and "bar" in self.c.args def genera_ValueError_en_duplicado(self): self.c.agregar_arg(nombres=("foo", "bar")) with raises(ValueError): self.c.agregar_arg(nombre="bar") def agrega_un_nombre_similarabandera_a_las_banderas_de_puntos(self): "agrega un nombre banderalike a .banderas" self.c.agregar_arg("foo") assert "--foo" in self.c.banderas def agrega_todos_nombres_a_punto_banderas(self): "agrega todos los nombres a .banderas" self.c.agregar_arg(nombres=("foo", "bar")) assert "--foo" in self.c.banderas assert "--bar" in self.c.banderas def agrega_true_a_bools_a_banderas_inversas(self): self.c.agregar_arg(nombre="mibandera", default=True, tipo=bool) assert "--mibandera" in self.c.banderas assert "--no-mibandera" in self.c.banderas_inversas assert self.c.banderas_inversas["--no-mibandera"] == "--mibandera" def banderas_inv_trabajan_bien_con_nombres_guionbajo_en_artefactos( self): # Use un Artefacto aquí en lugar de crear un argumento en # bruto(raw), estamos probando parcialmente la transformación de # Artefacto.obtener_argumentos() 'de nombres-subrayados aquí. Sí, eso # lo convierte en una prueba de integración, pero es bueno probarlo # aquí en este nivel y no solo en cli pruebas. @artefacto def miartefacto(c, opcion_guionbajo=True): pass self.c.agregar_arg(miartefacto.obtener_argumentos()[0]) banderas = self.c.banderas_inversas["--no-opcion-guionbajo"] assert banderas == "--opcion-guionbajo" def convierte_los_nombres_de_un_solo_caracter_en_banderas_cortas(self): self.c.agregar_arg("f") assert "-f" in self.c.banderas assert "--f" not in self.c.banderas def agrega_args_posicionales_a_args_posicionales(self): self.c.agregar_arg(nombre="pos", posicional=True) assert self.c.args_posicionales[0].nombre == "pos" def args_posicionales_vacios_cuando_no_se_da_ninguno(self): assert len(self.c.args_posicionales) == 0 def args_posicionales_llenos_en_orden(self): self.c.agregar_arg(nombre="pos1", posicional=True) assert self.c.args_posicionales[0].nombre == "pos1" self.c.agregar_arg(nombre="abc", posicional=True) assert self.c.args_posicionales[1].nombre == "abc" def modificaciones_posicionales_de_los_args_afectan_la_copia_de_los_args( self): self.c.agregar_arg(nombre="hrm", posicional=True) assert self.c.args["hrm"].valor == self.c.args_posicionales[ 0].valor self.c.args_posicionales[0].valor = 17 assert self.c.args["hrm"].valor == self.c.args_posicionales[ 0].valor
def args_se_muestran_como_repr(self): cadena = str(Contexto("bar", args=[Argumento("arg1")])) assert (cadena == "<analizador/Contexto 'bar': {'arg1': <Argumento: arg1>}>" ) # noqa
def sin_args_la_salida_es_simple(self): assert str(Contexto("foo")) == "<analizador/Contexto 'foo'>"
def setup(self): self.c = Contexto(args=( Argumento("foo"), Argumento(nombres=("bar", "biz")), Argumento("baz", nombre_de_atributo="wat"), ))