Рабочий процесс для поддержки разных версий кодовой базы для разных версий Python

Я разрабатываю приложение с открытым исходным кодом под названием GarlicSim.

До сих пор я разрабатывал его только для Python 2.6. Кажется, он не работает ни с одной другой версией.

Я решил, что важно создавать его версии, которые будут поддерживать другие версии Python. Думаю сделать версию для 2.5, 3.1 и может быть 2.4.

Итак, у меня есть несколько вопросов:

  1. Что было бы хорошим способом организовать структуру папок моего репо, чтобы включить эти разные версии?
  2. Что было бы хорошим способом «объединить» изменения, которые я делаю в одной версии кода, с другими версиями? Я знаю, как делать слияния в моем SCM (то есть git), но это папки, которые находятся в одном репо, и я хочу сделать слияние между ними. Конечно, есть возможность иметь репо для каждой версии, но я думаю, что это не очень хорошая идея.

У кого-нибудь есть предложения?


person Community    schedule 10.10.2009    source источник


Ответы (4)


Отдельные ветки для отдельных версий нужны только в самых редких случаях. Вы упомянули менеджеров контекста, и они великолепны, и было бы хреново их не использовать, и вы правы. Но для Python 2.4 вам не придется их использовать. Так что будет хреново. Поэтому, если вы хотите поддерживать Python 2.4, вам придется написать версию без менеджеров контекста. Но этот будет работать и под Python 2.6, поэтому нет смысла иметь там отдельные версии.

Что касается Python 3, имея отдельную ветку есть решение, но в целом не самое лучшее. Для поддержки Python 3 есть что-то под названием 2to3, которое преобразует ваш код Python 2 в код Python 3. Он не идеален, поэтому довольно часто вам придется модифицировать код Python 2, чтобы сгенерировать хороший код Python 3, но код Python 2 в любом случае имеет тенденцию становиться лучше в результате.

С помощью Distribute (поддерживаемого форка setuptools) вы можете вести этот разговор автоматически во время установки. Таким образом, вам не нужно иметь отдельную ветку даже для Python 3. См. http://bitbucket.org/tarek/distribute/src/tip/docs/python3.txt для документации по этому вопросу.

Как пишет Пол Макгуайр, можно даже поддерживать Python 3 и Python 2 с одним и тем же кодом без использования 2to3, но я бы не рекомендовал это, если вы хотите поддерживать что-то еще, кроме 2.6 и 3.x. Вы получаете слишком много этих уродливых специальных хаков. Версия 2.6 обеспечивает достаточную прямую совместимость с Python 3, чтобы можно было писать прилично выглядящий код и поддерживать как Python 2.6, так и 3.x, но не Python 2.5 и 3.x.

person Lennart Regebro    schedule 10.10.2009

Я бы попытался сохранить одну ветку, чтобы охватить все python 2.4-2.6.

Различия не так уж и велики, ведь если вам придется написать кучу лишнего кода для 2.4, чтобы сделать что-то, что легко делается в 2.6, то в долгосрочной перспективе у вас будет меньше работы, чтобы использовать версию 2.4 для 2.5 и 2.6. .

Python 3 должен иметь другую ветку, вы все равно должны стараться сохранить как можно больше общего кода.

person John La Rooy    schedule 10.10.2009
comment
Это означало бы, что я не смогу использовать идиомы из Python 2.6, что было бы отстойно. Например, я люблю использовать контекстные менеджеры. - person Ram Rachum; 10.10.2009
comment
моя точка зрения заключалась в том, что вы пишете версию с менеджером контекста. потом переписываешь на 2.4. версия 2.4 по-прежнему будет работать в версии 2.6, так что вы продублировали некоторые усилия. Ничто не мешает вам поддерживать 4 ветки, но вам предстоит много слияний. Возможно, у вас есть общий каталог для кода, который одинаков для всех. Я не думаю, что есть какие-то волшебные пикси, которые сделают все слияние за вас. - person John La Rooy; 10.10.2009
comment
Я согласен выполнять все слияния, пока я могу работать с контекстным менеджером на своей копии 2.6. - person Ram Rachum; 10.10.2009
comment
from __future__ import with_statement работает для 2.5, поэтому, возможно, откажитесь от поддержки 2.4, если вы используете менеджеры контекста - person John La Rooy; 10.10.2009

Если ваш код не слишком зависит от производительности во время выполнения в обработчиках исключений, вы можете даже обойтись без отдельной ветки для Py3. Мне удалось сохранить одну версию pyparsing для всех моих версий Py2.x, хотя мне пришлось придерживаться подхода «наименьшего общего знаменателя», что означает, что я должен отказаться от использования некоторых конструкций, таких как выражения генератора, и ваша точка зрения, менеджеры контекста. Я использую dicts вместо наборов, и все мои генераторные выражения обёрнуты как списки, так что они всё ещё будут работать, начиная с Python 2.3. У меня есть блок в верхней части моего кода, который решает ряд проблем 2 на 3 (внесенный пользователем pyparsing Робертом Кларком):

_PY3K = sys.version_info[0] > 2
if _PY3K:
    _MAX_INT = sys.maxsize
    basestring = str
    unichr = chr
    unicode = str
    _str2dict = set
    alphas = string.ascii_lowercase + string.ascii_uppercase
else:
    _MAX_INT = sys.maxint
    range = xrange
    def _str2dict(strg):
        return dict( [(c,0) for c in strg] )
    alphas = string.lowercase + string.uppercase

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

except exceptiontype,varname:

to

except exceptionType as varname:

Конечно, если вам действительно не нужна переменная исключения, вы можете просто написать:

except exceptionType:

и это будет работать на Py2 или Py3. Но если вам нужно получить доступ к исключению, вы все равно можете придумать синтаксис, совместимый с кросс-версиями, например:

except exceptionType:
    exceptionvar = sys.exc_info()[1]

Это имеет незначительный штраф во время выполнения, что делает его непригодным для использования в некоторых местах при pyparsing, поэтому мне все еще приходится поддерживать отдельные версии Py2 и Py3. Для слияния исходного кода я использую утилиту WinMerge, которая, по моему мнению, очень удобна для синхронизации каталогов исходного кода.

Так что, хотя я храню две версии своего кода, некоторые из этих методов унификации помогают мне свести различия к абсолютному минимуму несовместимости.

person PaulMcG    schedule 10.10.2009
comment
Полезная информация, Павел. Я думаю, что я буду придерживаться отдельной ветки для v3, хотя я бы не хотел, чтобы этот мусор был в моем коде. - person Ram Rachum; 10.10.2009
comment
Возможно, можно сгенерировать код 3, используя 2to3, или, например, в случае исключений, вы можете просто использовать замену регулярного выражения для построения дерева 3 из дерева 2. - person John La Rooy; 10.10.2009
comment
@gnibbler: использовать 2to3 проще, чем регулярное выражение. У 2to3 уже есть код для преобразования, не нужно изобретать велосипед. - person Lennart Regebro; 10.10.2009
comment
Другими словами, для повторного использования кода вы должны придерживаться этого ответа. Для производительности вы бы сделали раздельный код на две ветки. - person Diones; 10.10.2009
comment
@Diones: различия в производительности здесь незначительны, и их можно полностью игнорировать. - person Lennart Regebro; 10.10.2009
comment
@Lennart: К сожалению, pyparsing использует стек для проверки путей в грамматике синтаксического анализатора, с исключениями, действующими для раскручивания стека, когда путь грамматики не совпадает. Я преобразовал обработку исключений в некритичных для производительности областях pyparsing, но есть 1 или 2 места, где я должен оставить его в формате, кроме ParseException,pe: — я измерил производительность штраф за переход на использование sys.exc_info() составляет около 10%, что я не хочу навязывать пользователям Py2 только для совместимости с Py3. Это основная причина, по которой я держу 2 кодовые базы. - person PaulMcG; 10.10.2009
comment
@Paul: Почему бы тебе не использовать 2to3? - person Lennart Regebro; 10.10.2009
comment
@Lennart: я начал работать над этим преобразованием до того, как был написан 2to3. На самом деле у меня был единственный исходный код, совместимый как с Py2, так и с ранними альфа-версиями Py3, пока в более поздней версии Py3 не была добавлена ​​несовместимая форма оператора exclude. Таким образом, к тому времени, когда 2to3 был доступен, моя версия, преобразованная в py3, уже была закончена. Но вы делаете хорошее замечание, и для меня было бы лучше запустить 2to3 для создания pyparsing_py3.py, а не вручную синхронизировать их. Какая версия Python требуется для 2to3? Я все еще на 2.5.2 для моей основной среды разработки. - person PaulMcG; 10.10.2009

В конце концов я решил иметь 4 разных форка для своего проекта: 2.4, 2.5, 2.6 и 3.1. Мой главный приоритет — 2.6, и я не хочу жертвовать элегантностью этого кода ради 2.4. Таким образом, уродливые хаки совместимости будут на более низких версиях, а не на более высоких версиях.

person Ram Rachum    schedule 10.10.2009