2010-10-28 10 views
5

¿Cómo puedo automatizar una prueba para exigir que un cuerpo de código Python 2.x no contenga instancias de cadenas (solo instancias Unicode)?Python 2.x: cómo automatizar la aplicación de Unicode en lugar de cadena?

Por ejemplo.

¿Puedo hacerlo desde dentro del código?

¿Hay alguna herramienta de análisis estático que tenga esta característica?

Editar:

quería esto para una aplicación en Python 2.5, pero resulta que esto no es realmente posible porque:

  1. 2,5 no es compatible con unicode_literals diccionario
  2. kwargs las claves no pueden ser objetos unicode, solo cadenas

Así que estoy aceptando la respuesta que dice que no es posible, aunque sea por diferentes razones :)

+2

'desde __future__ import unicode_literals' –

+0

@Ignacio, suena prometedor! Pero, ¿se opondrá si el código también importa módulos de terceros que no lo conocen? –

+0

No, las directivas de compilación a través de '__future__' solo afectan el módulo actual. –

Respuesta

1

Usted no puede imponer que todos cadenas son Unicode; incluso con from __future__ import unicode_literals en un módulo, cadenas de bytes se pueden escribir como b'...', ya que pueden en Python 3.

Hay era una opción que podría ser utilizado para obtener el mismo efecto que unicode_literals a nivel mundial: la opción de línea de comandos -U. Sin embargo, fue abandonado temprano en el 2.x serie porque básicamente rompió todos los guiones.

¿Cuál es su propósito para esto? No es deseable abolir cadenas de bytes. No son "malos" y las cadenas Unicode no son universalmente "mejores"; son dos animales separados y los necesitarás a los dos. Sin duda, se necesitarán cadenas de bytes para hablar con archivos binarios y servicios de red.

Si desea estar preparado para la transición a Python 3, la mejor solución es escribir b'...' para todas las cadenas que realmente quiere decir que son bytes, y u'...' para las cadenas que son inherentemente Unicode. El formato de cadena predeterminado '...' se puede usar para todo lo demás, lugares donde no le importe y/o si Python 3 cambia el tipo de cadena predeterminado.

+1

El propósito es que estoy escribiendo una aplicación multilingüe que tiene que estar en 2.5, y me olvido de escribir el 'u' en las cadenas que no necesitan unicode, pero pueden hacerlo si se editan. Entiendo que las cadenas regulares están bien en muchos casos, pero en este caso necesito algo que me ayude a ser consistente y expresar claramente mi intención. –

1

Me parece que realmente necesitas analizar el código con un analizador de Python honesto a bueno. A continuación, deberá explorar el AST que su analizador produce para ver si contiene algún literal de cadena.

Parece que Python viene con un analizador sintáctico fuera de la caja. A partir de este documentation Tengo este ejemplo de código de trabajo:

import parser 
from token import tok_name 

def checkForNonUnicode(codeString): 
    return checkForNonUnicodeHelper(parser.suite(codeString).tolist()) 

def checkForNonUnicodeHelper(lst): 
    returnValue = True 
    nodeType = lst[0] 
    if nodeType in tok_name and tok_name[nodeType] == 'STRING': 
     stringValue = lst[1] 
     if stringValue[0] != "u": # Kind of hacky. Does this always work? 
      print "%s is not unicode!" % stringValue 
      returnValue = False 

    else: 
     for subNode in [lst[n] for n in range(1, len(lst))]: 
      if isinstance(subNode, list): 
       returnValue = returnValue and checkForNonUnicodeHelper(subNode) 

    return returnValue 

print checkForNonUnicode(""" 
def foo(): 
    a = 'This should blow up!' 
""") 
print checkForNonUnicode(""" 
def bar(): 
    b = u'although this is ok.' 
""") 

que imprime

'This should blow up!' is not unicode! 
False 
True 

Ahora cadenas de documentación no son Unicode, pero se debe permitir, por lo que podría tener que hacer algo más complicado como from symbol import sym_name donde puede buscar qué tipos de nodos son para definiciones de clases y funciones. Entonces, el primer subnodo que es simplemente una cadena, es decir, que no forma parte de una tarea o lo que sea, se debe permitir que no sea unicode.

¡Buena pregunta!

Editar

Sólo un comentario seguimiento. Convenientemente para sus propósitos, parser.suite en realidad no evalúa su código python. Esto significa que puede ejecutar este analizador sobre sus archivos de Python sin preocuparse por nombrar o importar errores. Por ejemplo, digamos que usted tiene myObscureUtilityFile.py que contiene

from ..obscure.relative.path import whatever 

Puede

checkForNonUnicode(open('/whoah/softlink/myObscureUtilityFile.py').read()) 
+0

No es necesario analizar el código. Solo producir los lexemas debería ser suficiente; si algún lexema no es Unicode, su archivo no pasó la prueba. Si su archivo contiene "referencias externas" (por ejemplo, from_future), entonces no puede saber sin analizar * todos * los archivos involucrados, pero sospecho que esto no forma parte de la definición de su problema. –

0

Nuestro SD Source Code Search Engine (SCSE) puede proporcionar este resultado directamente.

El SCSE proporciona una forma de buscar muy rápidamente en grandes conjuntos de archivos utilizando parte de la estructura del lenguaje para permitir consultas precisas y minimizar los falsos positivos. Maneja una amplia variedad de idiomas , incluso al mismo tiempo, incluyendo Python. Una GUI muestra resultados de búsqueda y una página de texto real del archivo que contiene un hit seleccionado.

Utiliza información léxica de los lenguajes de origen como base para las consultas, compuesta por varias palabras clave de idioma y tokens de patrones que coinciden con elementos de lenguaje de contenido variable. SCSE conoce los tipos de lexemas disponibles en el idioma. Uno puede buscar un identificador genérico (utilizando el token de consulta I) o un identificador que coincida con alguna expresión regulatr. Similarmente, on puede buscar una cadena genérica (utilizando el token de consulta "S" para "cualquier tipo de literal de cadena") o para un tipo específico de cadena (para Python incluyendo "UnicodeStrings", cadenas no unicode, etc., que colectivamente componen el conjunto de cosas de Python que comprende "S").

Así que una búsqueda:

'for' ... I=ij* 

encuentra la palabra clave 'para' cerca ("...") un identificador cuyo prefijo es 'ij' y te muestra todos los éxitos. (Espacio en blanco específico del lenguaje, incluyendo los saltos de línea y los comentarios son ignorados

Una búsqueda trivial:

S 

encuentra todos los literales de cadena Esto es a menudo una muy gran conjunto: -..}

Una búsqueda

UnicodeStrings 

encuentra todos los literales de cadena que se definen como Unicode léxico Cuerdas (u "...")

Lo que quiere son todas las cadenas que no sean UnicodeStrings. El SCSE proporciona un operador "restar" que resta hits de un tipo que se superponen hits de otro. Entonces, la pregunta, "¿qué cadenas no son Unicode" se expresa concisamente como:

S-UnicodeStrings 

Todos los impactos se muestra será la cadenas que no son cadenas Unicode, su pregunta precisa.

El SCSE proporciona servicios de registro para que pueda registrar visitas. Puede ejecutar SCSE desde una línea de comando, habilitando una consulta con guiones para su respuesta. Poner esto en un script de comando proporcionaría una herramienta que da su respuesta directamente.

Cuestiones relacionadas