Skip to content

Commit

Permalink
[FEATURE] Use enum output_file_open_mode to handle overwriting perm…
Browse files Browse the repository at this point in the history
…ission

Signed-off-by: Lydia Buntrock <[email protected]>
  • Loading branch information
Irallia committed Aug 26, 2020
1 parent 51e2bca commit 21fa77e
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 99 deletions.
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_indexer_step1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"fa","fasta"}});
parser.add_option(args.index_path, 'o', "output", "The output index file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"index"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"index"}});
}

//![main]
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_indexer_step2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"fa","fasta"}});
parser.add_option(args.index_path, 'o', "output", "The output index file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"index"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"index"}});
}

int main(int argc, char const ** argv)
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_indexer_step3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"fa","fasta"}});
parser.add_option(args.index_path, 'o', "output", "The output index file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"index"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"index"}});
}

int main(int argc, char const ** argv)
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"index"}});
parser.add_option(args.sam_path, 'o', "output", "The output SAM file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"sam"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"sam"}});
parser.add_option(args.errors, 'e', "error", "Maximum allowed errors.",
seqan3::option_spec::DEFAULT,
seqan3::arithmetic_range_validator{0, 4});
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"index"}});
parser.add_option(args.sam_path, 'o', "output", "The output SAM file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"sam"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"sam"}});
parser.add_option(args.errors, 'e', "error", "Maximum allowed errors.",
seqan3::option_spec::DEFAULT,
seqan3::arithmetic_range_validator{0, 4});
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"index"}});
parser.add_option(args.sam_path, 'o', "output", "The output SAM file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"sam"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"sam"}});
parser.add_option(args.errors, 'e', "error", "Maximum allowed errors.",
seqan3::option_spec::DEFAULT,
seqan3::arithmetic_range_validator{0, 4});
Expand Down
2 changes: 1 addition & 1 deletion doc/tutorial/read_mapper/read_mapper_step4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ void initialise_argument_parser(seqan3::argument_parser & parser, cmd_arguments
seqan3::input_file_validator{{"index"}});
parser.add_option(args.sam_path, 'o', "output", "The output SAM file path.",
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{{"sam"}});
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"sam"}});
parser.add_option(args.errors, 'e', "error", "Maximum allowed errors.",
seqan3::option_spec::DEFAULT,
seqan3::arithmetic_range_validator{0, 4});
Expand Down
77 changes: 35 additions & 42 deletions include/seqan3/argument_parser/validators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,15 @@ class input_file_validator : public file_validator_base
}
};

//!\brief Stores, if it is valid to overwrite the output file.
enum output_file_open_mode
{
//!\brief Allow to overwrite the output file
overwritable,
//!\brief Forbid overwriting the output file
exclusive
};

/*!\brief A validator that checks if a given path is a valid output file.
* \ingroup argument_parser
* \implements seqan3::validator
Expand All @@ -600,76 +609,60 @@ class input_file_validator : public file_validator_base
template <typename file_t = void>
class output_file_validator : public file_validator_base
{
public:
//!\brief Stores, if it is valid to overwrite the output file.
bool allow_overwrite = false; // ToDo: bool oder enum? Für jedes File einzeln entscheiden, also zum Pfad dazugeben? Oder als Vektor angeben?
private:
//!\brief Stores the current mode, if it is valid to overwrite the output file.
output_file_open_mode mode;

public:
static_assert(std::same_as<file_t, void> || detail::has_type_valid_formats<file_t>,
"Expected either a template type with a static member called valid_formats (a file type) or void.");

// Wenn enum, dann: ?
// static_assert(std::same_as<allow_overwrite, void> || detail::has_type_valid_formats<file_t>,
// "Wenn gesetzt, prüfe ob file existiert.");

// Import from base class.
using typename file_validator_base::option_value_type;

/*!\name Constructors, destructor and assignment
* \{
*/

//!\copydoc seqan3::input_file_validator::input_file_validator()
output_file_validator()
output_file_validator() = delete; //!< Deleted.
output_file_validator(output_file_validator const &) = default; //!< Defaulted.
output_file_validator(output_file_validator &&) = default; //!< Defaulted.
output_file_validator & operator=(output_file_validator const &) = default; //!< Defaulted.
output_file_validator & operator=(output_file_validator &&) = default; //!< Defaulted.
virtual ~output_file_validator() = default; //!< Virtual Destructor.

/*!\brief Constructs from a given collection of valid extensions.
* \param[in] mode Sets a flag, if it is valid to overwrite the output file.
*
* \details
*
* This constructor is only available if `file_t` does not name a valid seqan3 file type that contains a
* static member `valid_formats`.
*/
explicit output_file_validator(output_file_open_mode const mode) : file_validator_base{}, mode{mode}
{
if constexpr (!std::same_as<file_t, void>)
file_validator_base::extensions = detail::valid_file_extensions<typename file_t::valid_formats>();
}

output_file_validator(output_file_validator const &) = default; //!< Defaulted.
output_file_validator(output_file_validator &&) = default; //!< Defaulted.
output_file_validator & operator=(output_file_validator const &) = default; //!< Defaulted.
output_file_validator & operator=(output_file_validator &&) = default; //!< Defaulted.
virtual ~output_file_validator() = default; //!< Virtual Destructor.

//!\copydoc seqan3::input_file_validator::input_file_validator(std::vector<std::string>)
explicit output_file_validator(std::vector<std::string> extensions)
//!\cond
requires std::same_as<file_t, void>
//!\endcond
: file_validator_base{}
{
file_validator_base::extensions = std::move(extensions);
}

/*!\brief Constructs from a given collection of valid extensions.
* \param[in] extensions The valid extensions to validate for.
* \param[in] allow_overwrite Sets a flag, if it is valid to overwrite the output file.
* \param[in] mode Sets a flag, if it is valid to overwrite the output file.
*
* \details
*
* This constructor is only available if `file_t` does not name a valid seqan3 file type that contains a
* static member `valid_formats`.
*/
explicit output_file_validator(std::vector<std::string> extensions, bool allow_overwrite)
explicit output_file_validator(output_file_open_mode const mode, std::vector<std::string> extensions)
//!\cond
requires std::same_as<file_t, void>
//!\endcond
: file_validator_base{}, allow_overwrite{allow_overwrite}
: file_validator_base{}, mode{mode}
{
file_validator_base::extensions = std::move(extensions);
}

/*!\brief Constructs from a given collection of valid extensions.
* \param[in] allow_overwrite Sets a flag, if it is valid to overwrite the output file.
*
* \details
*
* This constructor is only available if `file_t` does not name a valid seqan3 file type that contains a
* static member `valid_formats`.
*/ explicit output_file_validator(bool allow_overwrite) : file_validator_base{}, allow_overwrite{allow_overwrite}
{}


// Import base constructor.
using file_validator_base::file_validator_base;
//!\}
Expand All @@ -686,7 +679,7 @@ class output_file_validator : public file_validator_base
{
try
{
if (!allow_overwrite && std::filesystem::exists(file))
if ((mode == exclusive) && std::filesystem::exists(file))
throw validation_error{detail::to_string("The file ", file, " already exists!")};

// Check if file has any write permissions.
Expand All @@ -707,9 +700,9 @@ class output_file_validator : public file_validator_base
//!\brief Returns a message that can be appended to the (positional) options help page info.
std::string get_help_page_message() const
{
if (allow_overwrite)
if (mode == overwritable)
return "Write permissions must be granted." + valid_extensions_help_page_message();
else
else // mode == exclusive
return "The output file must not exist already and write permissions must be granted." +
valid_extensions_help_page_message();
}
Expand Down
3 changes: 2 additions & 1 deletion test/snippet/argument_parser/validators_output_directory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ int main(int argc, const char ** argv)
std::filesystem::path mydir{};

myparser.add_option(mydir, 'd', "dir", "The output directory for storing the files.",
seqan3::option_spec::DEFAULT, seqan3::output_directory_validator{});
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive});
//! [validator_call]

// an exception will be thrown if the user specifies a directory that cannot be created by the filesystem either
Expand Down
8 changes: 5 additions & 3 deletions test/snippet/argument_parser/validators_output_file.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ int main(int argc, const char ** argv)
//! [validator_call]
std::filesystem::path myfile{};

// Add the output_file_open_mode, to allow overwriting existing files, or to avoid this.
myparser.add_option(myfile,'f',"file","Output file containing the processed sequences.",
seqan3::option_spec::DEFAULT, seqan3::output_file_validator{{"fa","fasta"}});
// Add an additional `true`, to allow overwriting existing files.
// seqan3::option_spec::DEFAULT, seqan3::output_file_validator{{"fa","fasta"}, true});
seqan3::option_spec::DEFAULT,
seqan3::output_file_validator{seqan3::output_file_open_mode::overwritable, {"fa","fasta"}});
// or
// seqan3::output_file_validator{seqan3::output_file_open_mode::exclusive, {"fa","fasta"}});
//! [validator_call]

// an exception will be thrown if the user specifies a filename
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,16 @@
int main(int argc, const char ** argv)
{
// Default constructed validator has an empty extension list.
seqan3::output_file_validator validator1{};
seqan3::output_file_validator validator1{seqan3::output_file_open_mode::exclusive};
seqan3::debug_stream << validator1.get_help_page_message() << "\n";

// Specify your own extensions for the output file.
seqan3::output_file_validator validator2{std::vector{std::string{"exe"}, std::string{"fasta"}}};
seqan3::output_file_validator validator2{seqan3::output_file_open_mode::exclusive,
std::vector{std::string{"exe"}, std::string{"fasta"}}};
seqan3::debug_stream << validator2.get_help_page_message() << "\n";

// Give the seqan3 file type as a template argument to get all valid extensions for this file.
seqan3::output_file_validator<seqan3::sequence_file_output<>> validator3{};
seqan3::output_file_validator<seqan3::sequence_file_output<>> validator3{seqan3::output_file_open_mode::exclusive};
seqan3::debug_stream << validator3.get_help_page_message() << "\n";

return 0;
Expand Down
Loading

0 comments on commit 21fa77e

Please sign in to comment.