Python 2.x: как автоматизировать принудительное использование юникода вместо строки? - PullRequest
5 голосов
/ 29 октября 2010

Как я могу автоматизировать тест для обеспечения того, чтобы тело кода Python 2.x не содержало строковых экземпляров (только экземпляры Юникода)?

Например.

Можно ли сделать это изнутрикод?

Есть ли инструмент статического анализа, который имеет эту функцию?

Редактировать:

Я хотел это для приложения в Python 2.5,но оказывается, что это на самом деле невозможно, потому что:

  1. 2.5 не поддерживает unicode_literals
  2. ключи словаря kwargs не могут быть объектами Unicode, только строки

Итак, я принимаю ответ, в котором говорится, что это невозможно, хотя по разным причинам:)

Ответы [ 3 ]

1 голос
/ 29 октября 2010

Вы не можете принудительно установить, что все строки имеют Unicode; даже если в модуле from __future__ import unicode_literals, строки байтов можно записать как b'...', как в Python 3.

Там был параметр, который можно использовать для получения того же эффекта, что и unicode_literals в глобальном масштабе: параметр командной строки -U. Однако он был заброшен в начале серии 2.x, потому что он в основном сломал каждый сценарий.

Какова ваша цель для этого? Не желательно отменять строки байтов. Они не «плохие», а строки Unicode не всегда «лучше»; это два разных животных, и вам понадобятся оба. Байтные строки, безусловно, понадобятся для общения с двоичными файлами и сетевыми службами.

Если вы хотите быть готовым к переходу на Python 3, лучше всего написать b'...' для всех строк, которые вы действительно подразумеваете в байтах, и u'...' для строк, которые по своей природе являются Unicode. Формат строки '...' по умолчанию можно использовать для всего остального, где вас не волнует и / или изменяет ли Python 3 тип строки по умолчанию.

1 голос
/ 29 октября 2010

Мне кажется, что вам действительно нужно проанализировать код с честным паролем python-парсера. Затем вам нужно будет покопаться в AST, который создает ваш парсер, чтобы увидеть, содержит ли он строковые литералы.

Похоже, Python поставляется с парсером из коробки. Из этой документации я получил работающий пример кода:

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.'
""")

который печатает

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

Теперь строки документа не являются юникодом, но должны быть разрешены, поэтому вам, возможно, придется сделать что-то более сложное, например from symbol import sym_name, где вы можете посмотреть, какие типы узлов предназначены для определения классов и функций. Тогда первый подузел, который является просто строкой, то есть не частью присваивания или чего-либо еще, должен быть разрешен не быть юникодом.

Хороший вопрос!

Редактировать

Просто дополнительный комментарий. Удобно для ваших целей, parser.suite на самом деле не оценивает ваш код Python. Это означает, что вы можете запускать этот анализатор над своими файлами Python, не беспокоясь об именах или ошибках импорта. Например, предположим, у вас есть myObscureUtilityFile.py, который содержит

from ..obscure.relative.path import whatever

Вы можете

checkForNonUnicode(open('/whoah/softlink/myObscureUtilityFile.py').read())
0 голосов
/ 01 ноября 2010

Наша Система поиска исходного кода SD (SCSE) может предоставить этот результат напрямую.

SCSE предоставляет возможность чрезвычайно быстрого поиска в больших наборах файлов с использованием некоторой языковой структуры для обеспечения точных запросов и минимизации ложных срабатываний. Он обрабатывает широкий спектр языков, даже в то же время, в том числе Python. Графический интерфейс пользователя отображает результаты поиска и страницу с текущим текстом из файла, содержащего выбранный результат.

Он использует лексическую информацию из исходных языков в качестве основы для запросов, состоящих из различных ключевых слов языка и токенов шаблонов, которые соответствуют различным элементам языка содержимого. SCSE знает типы лексем, доступных в языке. Можно искать общий идентификатор (используя токен запроса I) или идентификатор, соответствующий какому-либо выражению regulatr. Аналогично, on может искать общую строку (используя токен запроса «S» для «любого вида строкового литерала») или для конкретного тип строки (для Python, включая «UnicodeStrings», не-Unicode-строки и т. д., которые в совокупности составляют набор элементов Python, содержащих «S»).

Итак, поиск:

 'for' ... I=ij*

находит ключевое слово 'for' возле ("...") идентификатора, префикс которого равен "ij", и показывает все попадания. (Пробелы, зависящие от языка, включая разрывы строк и комментарии, игнорируются.

Тривиальный поиск:

  S

находит все строковые литералы. Это часто довольно большой набор: -}

Поиск

 UnicodeStrings

находит все строковые литералы, которые лексически определены как строки Unicode (u "...")

Все, что вы хотите, это строки, которые не являются UnicodeStrings. SCSE предоставляет оператор вычитания, который вычитает попадания одного вида, которые перекрывают попадания другого. Итак, ваш вопрос, «какие строки не являются юникодом», выражается кратко:

  S-UnicodeStrings

Все показанные хиты будут строками, которые не являются строками Unicode, ваш точный вопрос.

SCSE предоставляет средства ведения журналов, чтобы вы могли записывать попадания. Вы можете запустить SCSE из командной строки, включив запрос на ответ по сценарию. Если поместить это в командный скрипт, инструмент даст ваш ответ напрямую.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...