03.14 Git и оформление патчей в виде файлов

  1. Как передавать изменения, если доступна только голубиная почта?
    • пересылать можно только файлы
    • git push/pull недоступны
  2. <!> Задача_1: сформируйте патчсет и наложите его на другую ветку.

    • Создание истории изменений:
      • Ниже приведен стишок из 20 строк. Считаем, что они пронумерованы с 1 по 20 (номера строк в стишок не входят).
      • Создайте в репозитории ветку "master_20220314" и работайте на ней.
      • Создайте и закоммитьте текстовый файл "opilki.txt" с нижеприведённым стишком.
      • Выберите три разных номера строк по следующей схеме: рассчитайте сумму MD5 от ваших фамилии, имени, отчества (по отдельности), от каждого полученного числа возьмите остаток от деления на 20 и добавьте 1. Если два числа совпали, увеличьте (или уменьшите) одно из них на 5 (или на 7).
        • python3 -c 'import hashlib; print(hashlib.md5("Фамилия".encode()).digest()[0]%20+1)'

      • Для каждой из трёх строк с полученными номерами:
        • Измените эту строку, но так, чтобы текст оставался рифмованным (если нет склонности к стихосложению, просто перепишите строку заглавными буквами).
        • Сделайте отдельный коммит с изменением в этой строке, назовите его "Правка строки <номер_строки>".

    • Проверка: к этому моменту на ветке "master_20220314" должна быть история из четырёх коммитов: первоначальное занесение файла и три коммита с однострочными правками.
    • Создание патчсета:
      • Создайте подкаталог "patchdir".
      • При помощи команды git format-patch с ключом --output-directory создайте в подкаталоге "patchdir" патчсет из трёх последних коммитов (т.е. не включая первоначальное занесение файла).

      • ПОКАЖИТЕ ПАТЧСЕТ ВЕДУЩИМ ПРАКТИКУМА
    • Применение патчсета:
      • Создайте ветку "check_20220314" от коммита с первоначальным занесением файла "opilki.txt" и работайте на этой ветке.
      • При помощи команды git am patchdir примените патчсет.

    • Проверка: на ветке "check_20220314" должна возникнуть история из трёх однострочных изменений.
    • push нужно сделать для обеих созданных веток; patchdir коммитить не надо

    • Стишок из 20 строк:

   1 Опять ничего не могу я понять.
   2 Опилки мои – в беспорядке.
   3 Везде и повсюду, опять и опять
   4 Меня окружают загадки.
   5 Возьмём это самое слово "опять".
   6 Зачем мы его произносим,
   7 Когда мы свободно могли бы сказать
   8 "Ошесть", и "осемь", и "овосемь"?
   9 Молчит этажерка, молчит и тахта –
  10 У них не добьёшься ответа,
  11 Зачем это хта – обязательно та,
  12 А жерка, как правило, эта!
  13 "Собака кусается"... Что ж, не беда.
  14 Загадочно то, что собака,
  15 Хотя и кусается, но никогда
  16 Себя не кусает, однако...
  17 О, если бы мог я всё это понять.
  18 Опилки пришли бы в порядок!
  19 А то мне – загадочно! – хочется спать
  20 От всех этих Трудных Загадок!
  1. Работа с исходным текстом. ast (На лекциях были inspect и dis, но на всё времени не хватит.).

    • Что и зачем нужен
    • ast.parse(), ast.dump() и ast.unparse()

    • {i} написать простейшую утилиту purify.py программа.py, которая удаляет комментарии и переформатирует программу.py, выводя результат на экран

      • К. О. спешит на помощь: unparse(parse())

    • Представление (примитивное) о структуре AST. walk()

  2. Работа с исходным текстом. difflib

    • виды diff
    • Использование Tools/scripts/diff.py

    • {i} переназвать предыдущую программу в diffpure.py и модифицировать так, чтобы выводилcя unified_diff() исходного файла и его и «purify-фированного» варианта

  3. <!> Задача_2. Антиплагиат. Написать программу antip.py файл_1.py файл_2.py, которая получает на вход два (сравнительно небольших) файла на python, и делает с ними следующее.

    1. Получает для исходного текста в каждом файле «унифицированное представление» с помощью ast.unpasre(ast.parse())

    2. Преобразует AST-дерево разбора каждого файла в т. н. «препарат» с целью минимизировать его представление (с потерей восстановимости)
      • Вариант решения: взять ast.dump(текст, annotate_fields=False) и крепко пожевать его regexp-ами или просто replace()-ами

      • Вариант решения: посмотреть, как ast.dump() обходит дерево и енаписать свой примитивный обходчик, который оставляет только нужную информацию

      • Вариант решения «по-врослому»: воспользоваться ast.NodeVisitor

      • Я воспользовался вариантом 1:
        • Выдрал из ast.dump() только идентификаторы, начинающиеся с большой буквы, после которых стоит открывающая скобка (это лексические конструкции, см грамматику в начале документации по ast), запятые (это количество элементов в конструкции) и закрывающие скобки (они указывают контекст).

        • В полученных препаратах заменил каждый «Идентификатор(» уникальным одним символом.

    3. Вычисляет нормализованное расстояние Дамерау-Левенштейна между двумя препаратами (textdistance.damerau_levenshtein.normalized_distance)

    4. Если это расстояние не превышает 0.1, сообщает о возможном плагиате, в доказательство чего выводит difflib.HtmlDiff() между унифицированными представлениями программ (в них одинаковое форматирование и опущены комментарии).

Два файла в примере из Д/З по лекциям должны распознаваться как 100% совпадающий.

TODO пример не 100% совпадения

LecturesCMC/PythonDevelopment2022/Prac/05_GitPatch (последним исправлял пользователь hbd 2022-03-14 13:31:21)