Документация Engee

ArgTools

Обработка аргументов

ArgRead = Union{AbstractString, AbstractCmd, IO}

Типы ArgRead — это объединение типов, которые функция arg_read может преобразовать в читаемые дескрипторы ввода-вывода. Дополнительные сведения см. в описании arg_read.

ArgWrite = Union{AbstractString, AbstractCmd, IO}

Типы ArgWrite — это объединение типов, которые функция arg_write может преобразовать в читаемые дескрипторы ввода-вывода, кроме типа Nothing, для которого arg_write создает временный файл. Дополнительные сведения см. в описании arg_write.

arg_read(f::Function, arg::ArgRead) -> f(arg_io)

Функция arg_read принимает аргумент arg, который может иметь следующие значения:

  • AbstractString: путь к файлу, который необходимо открыть для чтения;

  • AbstractCmd: команда, которую следует выполнить для считывания ее стандартного выходного потока;

  • IO: открытый дескриптор ввода-вывода для считывания.

Независимо от того, возвращается ли управление нормально или выдается ошибка, открытый путь будет закрыт перед возвратом из arg_read, а дескриптор IO будет сброшен, но не закрыт перед возвратом из arg_read.

Обратите внимание: при открытии файла ArgTools передает lock = false в вызов open(...) для файла. Поэтому объект, возвращаемый этой функцией, не следует использовать из нескольких потоков. Данное ограничение может быть ослаблено в будущем, но на работу существующего кода это не повлияет.

arg_write(f::Function, arg::ArgWrite) -> arg
arg_write(f::Function, arg::Nothing) -> tempname()

Функция arg_read принимает аргумент arg, который может иметь следующие значения:

  • AbstractString: путь к файлу, который необходимо открыть для записи;

  • AbstractCmd: команда, которую следует выполнить для записи в ее стандартный выходной поток;

  • IO: открытый дескриптор ввода-вывода для записи;

  • Nothing: временный путь для записи.

Если управление возвращается нормально, открытый путь будет закрыт по завершении; аргумент дескриптора ввода-вывода остается открытым, но сбрасывается перед возвратом управления. Если аргумент имеет значение nothing, для записи открывается временный путь, который закрывается по завершении и возвращается функцией arg_write. Во всех остальных случаях возвращается сам аргумент arg. Это полезный шаблон, позволяющий всегда возвращать записанные данные независимо от того, был ли передан аргумент.

Если во время вычисления тела происходит ошибка, путь, открытый функцией arg_write для записи, удаляется независимо от того, был ли он передан в виде строки или в виде временного пути, сгенерированного при передаче nothing в arg.

Обратите внимание: при открытии файла ArgTools передает lock = false в вызов open(...) для файла. Поэтому объект, возвращаемый этой функцией, не следует использовать из нескольких потоков. Данное ограничение может быть ослаблено в будущем, но на работу существующего кода это не повлияет.

arg_isdir(f::Function, arg::AbstractString) -> f(arg)

Функция arg_isdir принимает аргумент arg, который должен содержать путь к существующему каталогу (в противном случае происходит ошибка), и передает этот путь в функцию f, возвращая в итоге результат вызова f(arg). Это, безусловно, наименее полезный инструмент из предлагаемых модулем ArgTools, который существует в первую очередь для согласованности с arg_mkdir и вывода соответствующих сообщений об ошибках.

arg_mkdir(f::Function, arg::AbstractString) -> arg
arg_mkdir(f::Function, arg::Nothing) -> mktempdir()

Функция arg_mkdir принимает аргумент arg, который должен содержать одно из следующих значений:

  • путь к уже существующему пустому каталогу;

  • несуществующий путь, по которому можно создать каталог;

  • nothing в этом случае создается временный каталог.

Во всех случаях возвращается путь к каталогу. Если во время вызова f(arg) происходит ошибка, каталог возвращается в исходное состояние: если он уже существовал, но был пуст, то он очищается, а если не существовал — удаляется.

Тестирование функций

arg_readers(arg :: AbstractString, [ type = ArgRead ]) do arg::Function
    ## настройка перед тестированием ##
    @arg_test arg begin
        arg :: ArgRead
        ## тестирование с использованием `arg` ##
    end
    ## очистка после тестирования ##
end

Функция arg_readers принимает путь для считывания и блок do с одним аргументом, который вызывается один раз для каждого типа тестового считывателя, поддерживаемого arg_read. Если предоставлен необязательный аргумент type, блок do вызывается только для считывателей, создающих аргументы данного типа.

В блок do передается не само значение аргумента arg, так как тестовые аргументы некоторых типов должны инициализироваться и ликвидироваться для каждого тестового случая. Рассмотрим аргумент, содержащий дескриптор открытого файла: после его использования для одного теста использовать его повторно нельзя; для следующего теста его необходимо закрыть и открыть файл снова. Аргумент arg этой функции можно преобразовать в экземпляр ArgRead с помощью @arg_test arg begin ... end.

arg_writers([ type = ArgWrite ]) do path::String, arg::Function
    ## настройка перед тестированием ##
    @arg_test arg begin
        arg :: ArgWrite
        ## тестирование с использованием `arg` ##
    end
    ## очистка после тестирования ##
end

Функция arg_writers принимает блок do, который вызывается один раз для каждого типа тестового средства записи, поддерживаемого arg_write, с временным (несуществующим) путем path и аргументом arg, который можно преобразовать в различные типы аргументов с возможностью записи в path. Если предоставлен необязательный аргумент type, блок do вызывается только для средств записи, создающих аргументы данного типа.

В блок do передается не само значение аргумента arg, так как тестовые аргументы некоторых типов должны инициализироваться и ликвидироваться для каждого тестового случая. Рассмотрим аргумент, содержащий дескриптор открытого файла: после его использования для одного теста использовать его повторно нельзя; для следующего теста его необходимо закрыть и открыть файл снова. Аргумент arg этой функции можно преобразовать в экземпляр ArgWrite с помощью @arg_test arg begin ... end.

Существует также метод arg_writers, который принимает имя пути в виде arg_readers:

arg_writers(path::AbstractString, [ type = ArgWrite ]) do arg::Function
    ## настройка перед тестированием ##
    @arg_test arg begin
        # здесь выполняется тест `arg :: ArgWrite`
        ## тестирование с использованием `arg` ##
    end
    ## очистка после тестирования ##
end

Данный метод полезен, если необходимо указать path вместо использования имени пути, сгенерированного tempname(). Так как path передается извне arg_writers, в такой форме путь не является аргументом блока do.

@arg_test arg1 arg2 ... body

Макрос @arg_test служит для преобразования функций arg, предоставленных arg_readers и arg_writers, в фактические значения аргументов. Запись @arg_test arg body эквивалентна arg(arg -> body).