Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UGENE-5291 WD can't work with files with ; in name #1588

Open
wants to merge 21 commits into
base: master
Choose a base branch
from

Conversation

rasputinkirill
Copy link
Member

@rasputinkirill rasputinkirill commented Mar 19, 2024

Устроит такое решение?
Если да дополню тестом и трансляциями.

@rasputinkirill rasputinkirill requested a review from a team as a code owner March 19, 2024 00:13
@yalgaer
Copy link
Collaborator

yalgaer commented Mar 19, 2024

Я бы попробовала корректно поддержать файлы с допустимыми символами.
У нас есть код, который объединяет списки имен файлов используя ';' и после восстанавливает оригинальные имена из списков (WorkflowUtils::unpackListOfDatasets).

Нужно сделать 2 модификации в этих методах: энкодить и декодить "плохие" имена файлов по примеру того как это делается в веб: https://doc.qt.io/qt-6/qurl.html#toEncoded.

Можно выбрать любой свой вид энкодинга (энкодить только ';' ), так чтобы при этом максимально сохранялось визуальное представление файла в закодированном виде.

@rasputinkirill
Copy link
Member Author

Решение с энкодингом не универсально.
Дело в том, что URLLineEdit и в кастомные поля воркеров пользователь может ввести данные руками, и мы не сможем определить где пользователь имел ввиду точку с запятой в имени файла, а где как разделитель файлов.
Поэтому остается абсолютно такая же ситуация как в текущем решении, тут мы можем гарантированно определить когда пользователь подразумевает несколько файлов, а когда имя с точкой с запятой только в случае с диалогами. А в случае ручного ввода мы не сможем определить и корректно заэнкодить.
Так что все же предлагаем оставить мое решение:

  • проверять корректность имен файлов в случае ввода через диалог и информировать пользователя
  • проверять на на этапе валидации схемы входные url (сюда попадут все которые были введены вручную)

@yalgaer
Copy link
Collaborator

yalgaer commented Mar 19, 2024

Если такой файл может быть в файловой системе, то UGENE должен уметь его открывать. Давай решать задачу в этом контексте.

@rasputinkirill
Copy link
Member Author

Если такой файл может быть в файловой системе, то UGENE должен уметь его открывать. Давай решать задачу в этом контексте.

У меня есть только такой вариант решения:
В WorkflowUtils::validateInputFiles когда полученый на вход список url засплитили в список, валидатор в цикле начинает проверять их наличие на файловой системе. Если файла нету - он пытается конструирует url из текущего элемента, точки с запятой и следующего элемента списка, и снова проверяет наличие файла на файловой системе и так пока не найдет файл или не закончится список.
Если список закончился, а файл не обнаружен пишет ошибку "Не могу найти один из файлов из этого списка: " и выводит список с того элемента на котором застрял.

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

Ну или предложи свое решение.

@yalgaer
Copy link
Collaborator

yalgaer commented Mar 20, 2024

Решение простое: изучить и выбрать какой вид encoding в данном случае будет наиболее приемлем.

Кодирование/декодирование URL- это именно то что используют как командные шелы в операционных системах, так и строки с параметрами в интернет.

Примеры:

  1. Имя файла может содержать пробел, но в командной строке это разделитель параметров. Как-то это проблема решается как на Windows так и на Linux
  2. Значение параметра в URL может содержать знак =. Но знак = это разделитель ключ/значение для параметров. И тут проблема решена.

Так же и в UGENE это проблема может быть решена во всех местах где мы сериализируем/парсим список имен файлов.

К самой файловой системе при этом обращаться не нужно - список имен файлов должен однозначно кодироваться и декодироваться без внешнего контекста.

Проанализируй и выбери наиболее приемлемый нам вариант решения. Например:

  1. Эскейпить ';' если это часть имени файла
  2. Заключать имя файла в кавычки если в нем есть "плохие" символы и эскейпить кавычки.
  3. Энкодить плохие символы как URL параметры в интернет.
  4. Что-то еще более крутое и интересное.

@rasputinkirill
Copy link
Member Author

Попробовал поэкспериментировать с экранированием кавычками, но столкнулся с проблемой.
QFileInfo и QFile в принципе не работают нормально с путями в которых есть ";" и путь юникс-стайл.
Вызовы функций вернут false

    QFileInfo ffff("C:/ugene_issue_files/5291/A;nnota;tio;ns.txt");
    ffff.exists();
    QFile::exists("C:/ugene_issue_files/5291/A;nnota;tio;ns.txt");    

На линуксе сам юджин (не WD) даже не открывает файлы по таким путям.
image

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 1, 2024

Попробовал поэкспериментировать с экранированием кавычками, но столкнулся с проблемой. QFileInfo и QFile в принципе не работают нормально с путями в которых есть ";" и путь юникс-стайл. Вызовы функций вернут false

    QFileInfo ffff("C:/ugene_issue_files/5291/A;nnota;tio;ns.txt");
    ffff.exists();
    QFile::exists("C:/ugene_issue_files/5291/A;nnota;tio;ns.txt");    

На линуксе сам юджин (не WD) даже не открывает файлы по таким путям. image

Попробуй заескейпить плохие символы. Что если у QT спросить список файлов в каталоге среди которых будет "плохие"?
Мне кажется не может такого быть чтобы на Linux были файлы которые QT вообще не может открыть.

@rasputinkirill
Copy link
Member Author

QFileInfo ffff("C:/ugene_issue_files/5291/A\;nnota\;tio\;ns.txt");
ffff.exists();
QFile::exists("C:/ugene_issue_files/5291/A\;nnota\;tio\;ns.txt");

Заэскейпленые не воспринимает.

QDir dir("C:/ugene_issue_files/5291/");
QStringList entries = dir.entryList();

Тут в списке все файлы присутствуют.
На линуксе так же. Причем при сборке ворнинги на \; Unknown escape sequence.

Если что то, скриншот выше это месседж бокса с ошибкой - это я просто через File->Open попробовал открыть файл с проблемным именем. Это я к тому что если делать поддержку точки с запятой в путях, то это надо будет по всему приложению в итоге делать, а не только в дизайнере.

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 2, 2024

Qt нормально работает с файлами у которых в имени есть точка с запятой:
image
image

В рамках этого бага достаточно исправить описанную проблему - не нужно переделывать весь UGENE. На остальные места можно завести другие баги.

@rasputinkirill
Copy link
Member Author

Попробовал сделать с экранированием всей строки заключением в двойные кавычки.
Но столкнулся с проблемой, что в самом формате uwl файла который создается и потом запускается присутствуют кавычки, а если при сериализации файла он встречает двойные кавычки то меняет их на одинарные.
Экранировать пути в одинарными кавычками тоже не выйдет - так как это допустимый в путях файлов.
Так же а принципе при любом типе экранирования, хоть символа, хоть всей строки в кодле придется обрабатывать все места где мы этот файл пытаемся открыть.
А еще тут не видно сразу масштаба необходимых работ, исправляешь одну проблему - появляяются еще места где это не работает.

Пока я все это пытался делать обнаружил что датасеты должны нормально работать с путями с ";" так как там файлы всегда передаются для обработки по одному и неопределенности не возникает.
Поэтому предлагаю такие исправления:

  • проверить что датасеты корректно обрабатывют проблемные пути и убрать проверку для них
  • в URLLineEdit при вводе проблемного пути выдавать пользователю предупреждение

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 10, 2024

А что именно будет в предупреждении?
Если мы скажем что в результате будет неопределенное поведение - то это нехорошо.

Можно ли при сохранении в UWL экранировать и переводы строк и кавычки по примеру URL encoding?
Это может быть расширением возможностей формата UWL: например так:

files: urls("url1", "url2"...) где url в кавычках уже безопасный (encoded)
?

@rasputinkirill
Copy link
Member Author

А что именно будет в предупреждении? Если мы скажем что в результате будет неопределенное поведение - то это нехорошо.

В предупреждении будет написано "путь до файла ';', такие пути не поддерживаются этим элементом, переименуйте и/или положите файл в другую папку.".

Можно ли при сохранении в UWL экранировать и переводы строк и кавычки по примеру URL encoding? Это может быть расширением возможностей формата UWL: например так:

files: urls("url1", "url2"...) где url в кавычках уже безопасный (encoded) ?

Думаю, если делать "по-красоте" то для данных из URLLineEdit обертку как для dataset и показывать пользователю в воркере пути как он их ввел - с ";" в путях, а внутри юджина гонять эти данные в заэнкоженном виде. Так же и в схему писать в заэнкоженном виде, а при загрузке и показе схемы пользователю приводить к "человеческому" виду.

Я бы ограничился с вариантом с проверкой работоспособности датасетов и предупреждением в URLLineEdit. Мне кажется поддержка такого вида имен файлов не стоит уже потраченного времени на эту задачу.

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 12, 2024

В качестве временного/быстрого решения можно сделать так, чтобы UGENE вообще не давал записывать/запускать то, в результате чего он не уверен.

Можно ли вместо "предупреждения" сделать блокировку на запуск?

@rasputinkirill
Copy link
Member Author

rasputinkirill commented Apr 12, 2024

Не совсем понял что имеешь в виду, ведь сейчас так и есть. Пытаемся запустить схему - валидатор говорит что в схеме ошибки тоько они выглядят коряво из-за попытки распаристь путь по кускам разделенными ";", например для пути "c:\ugene_issue_files\5291\A;;nnota;;tio;n_names.txt" будет так:
image

Схема запущена не будет.

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 14, 2024

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

Если мы не можем различить - не нужно ни warning, ни ошибки - мы должны работать с ; как с разделителем.

Если же мы знаем, что ; каким-то образом пришел в элемент как символ в имени файла - тут мы должны отказать в исполнении/записи этого имени, так как при чтении мы будем трактовать его как разделитель. Правильно?

@rasputinkirill
Copy link
Member Author

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

Если мы не можем различить - не нужно ни warning, ни ошибки - мы должны работать с ; как с разделителем.

Сейчас работает так - во время валидации когда проверяется что все входные пути существуют ; интерпретируется как разделитель. Появляются ошибки валидации и все прерывается, предлагаешь убрать эту проверку в валидаторе схемы?

Если же мы знаем, что ; каким-то образом пришел в элемент как символ в имени файла - тут мы должны отказать в исполнении/записи этого имени, так как при чтении мы будем трактовать его как разделитель. Правильно?

Ну не совсем, я предлагал что если пользователь ввел в URLLineEdit путь с ; то не принимать его ввод и выдавать MessageBox с просьбой переименовать/поменять путь.
При этом так же проверить и отредактировать проверку для путей пришедших из датасетов так как пути из них обрабатываются по одной штуке и ; в них никогда не бывает разделителем.

Так же мне тут еще идея пришла, сделать класс URLLineEdit для мест где ожидается ввод одного пути и для мест где вводится список. Тогда, если из URLLineEdit в котором ожидается ввод одного пути пришел url то не пытаться парсить его как список файлов и тогда будет однозначность насчет данных пришедших из него. А проверку и предупреждение делать только в тех где список вводим.
У меня если честно ощущение, что у нас даже нет (или их буквально единицы) воркеров где мы ожидаем ввод списка файлов.
Тогда получится что в датасетах проблемные пути допустимы, в большей части воркеров допустимы и только в некоторых будет предупреждение при вводе.

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 15, 2024

Мне было бы интересно сделать поддержку multiple URLS в UWL таким образом, что не возникает неопределенности.
Но если это перебор - давай сделаем минимум твоим способом. Напиши как тот простой и лучший с твоей точки зрения способ готов для review

@rasputinkirill
Copy link
Member Author

Поменял проверку путей для датасетов, так как там всегда единственный url приходит для проверки.
Директории тоже всегда по одной проверяются, поэтому переименовал и поменял метод.
В URLLineEdit добавил отображение предупреждения

src/corelibs/U2Designer/src/WorkflowGUIUtils.h Outdated Show resolved Hide resolved
src/corelibs/U2Designer/src/support/URLLineEdit.cpp Outdated Show resolved Hide resolved
const QStringList urlsList = urls.split(';');
for (const QString& url : qAsConst(urlsList)) {
CHECK_EXT_CONTINUE(validateInputFile(url, notificationList));
res = false;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Есть ли смысл тут продолжать проверять файлы после первой ошибки? Ошибок может быть тысячи?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тоже думал так сделать, но оставил старое поведение.
Если пользователь получит ошибку на пачку файлов он их пачкой и исправит, а не по одной будет. Можно ввести лимит на количество ошибок, например. IDE так же делают. Что думаешь?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Нужно выдавать только одну ошибку. Если хочешь можешь в ее текст включить первые N файлов

@rasputinkirill
Copy link
Member Author

Исправление устраивает, пишу тесты?

@yalgaer
Copy link
Collaborator

yalgaer commented Apr 19, 2024

Исправление устраивает, пишу тесты?

Да

Copy link
Collaborator

@yalgaer yalgaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Меняю статус requested review -> request changes. Причина: часть комментариев не исправлена

Copy link
Collaborator

@yalgaer yalgaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ну нужно говорить в сообщении об ошибке о символе ;

Вероятность имено этой исчезающе мала по сравнению с обычной: файл не найден по каким-то другим причинам. В этом случае мы только запутаем пользователя своей рекомендацией. Можешь добавить это в доку если хочешь и сослаться из ошибки на доку.

Достаточно показать пользователю имя файла как мы его понимаем - дальше он поймет сам что не так

@rasputinkirill
Copy link
Member Author

Хорошо, поменял в случае ручного ввода. Если пользователь выбирал через гуи оставил текущее сообщение - тут вполне однозначно что выбран файл с плохим путем\именем.

Copy link
Collaborator

@yalgaer yalgaer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Тест должен быть без workarounds и извинений: если иначе не работает, надо исправлять или просто писать тест иначе (так как текущие проблемы в тесте не относятся к тестируемуму исправлению)

Если мы оставили 2 варианта поведения: c и без ручнного ввода: можно ли протестировать оба варианта?

@rasputinkirill
Copy link
Member Author

rasputinkirill commented May 21, 2024

Не понял что не так с тестом, мы тут тестируем и ручной ввод, и ввод через gui и то что в датасетах можно любой путь задать.
То что перекликиваем элемент я написал, проблема возникает из-за потери фокуса после появления месседж бокса.

@yalgaer
Copy link
Collaborator

yalgaer commented May 22, 2024

То что перекликиваем элемент я написал, проблема возникает из-за потери фокуса после появления месседж бокса.

Перекликивание говорит о баге в WD - либо элемент в фокусе и на него не нужно кликать чтобы увидеть его детали, либо не в фокусе - тогда достаточно кликнуть только на него.

Кликать на другой элемент и потом возвращаться к текущему - это workaround для бага.

Не понял что не так с тестом, мы тут тестируем и ручной ввод, и ввод через gui и то что в датасетах можно любой путь задать.

Не вижу где тестируется текст нового сообщения об ошибке

@rasputinkirill
Copy link
Member Author

Так устроит?

@yalgaer
Copy link
Collaborator

yalgaer commented May 23, 2024

Замечаний нет, жду зеленые тесты

@rasputinkirill
Copy link
Member Author

На маке несвязанный тест упал, считаем что успех?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants