Switch code_templates to string.Template
Python's standard `string.Template` is significantly more performant
than the custom `code_template` formatter. At the cost of removing
custom formatting support (unused) and changing our format string to
`${foo}` instead of `$_foo_$` we can achieve an 11% speedup in the back
end code generation for C++.
diff --git a/compiler/back_end/cpp/generated_code_templates b/compiler/back_end/cpp/generated_code_templates
index 4554b39..2854233 100644
--- a/compiler/back_end/cpp/generated_code_templates
+++ b/compiler/back_end/cpp/generated_code_templates
@@ -21,10 +21,12 @@
// prefixed with `emboss_reserved_local_` to avoid conflicting with struct field
// names.
+// clang-format off
+
// ** outline ** ///////////////////////////////////////////////////////////////
// Generated by the Emboss compiler. DO NOT EDIT!
-#ifndef $_header_guard_$
-#define $_header_guard_$
+#ifndef ${header_guard}
+#define ${header_guard}
#include <stdint.h>
#include <string.h>
@@ -35,117 +37,117 @@
#include "runtime/cpp/emboss_cpp_util.h"
-$_includes_$
+${includes}
// NOLINTBEGIN
-$_body_$
+${body}
// NOLINTEND
-#endif // $_header_guard_$
+#endif // ${header_guard}
// ** include ** ///////////////////////////////////////////////////////////////
-#include "$_file_name_$"
+#include "${file_name}"
// ** body ** //////////////////////////////////////////////////////////////////
-$_type_declarations_$
-$_type_definitions_$
-$_method_definitions_$
+${type_declarations}
+${type_definitions}
+${method_definitions}
// ** namespace_wrap ** ////////////////////////////////////////////////////////
-namespace $_component_$ {
-$_body_$
-} // namespace $_component_$
+namespace ${component} {
+${body}
+} // namespace ${component}
// ** structure_view_declaration ** ////////////////////////////////////////////
template <class Storage>
-class Generic$_name_$View;
+class Generic${name}View;
// ** structure_view_class ** //////////////////////////////////////////////////
template <class View>
-struct EmbossReservedInternalIsGeneric$_name_$View;
+struct EmbossReservedInternalIsGeneric${name}View;
template <class Storage>
-class Generic$_name_$View final {
+class Generic${name}View final {
public:
- Generic$_name_$View() : backing_() {}
- explicit Generic$_name_$View(
- $_constructor_parameters_$ Storage emboss_reserved_local_bytes)
- : backing_(emboss_reserved_local_bytes) $_parameter_initializers_$
- $_initialize_parameters_initialized_true_$ {}
+ Generic${name}View() : backing_() {}
+ explicit Generic${name}View(
+ ${constructor_parameters} Storage emboss_reserved_local_bytes)
+ : backing_(emboss_reserved_local_bytes) ${parameter_initializers}
+ ${initialize_parameters_initialized_true} {}
// Views over compatible backing storage should be freely assignable.
template <typename OtherStorage>
- Generic$_name_$View(
- const Generic$_name_$View<OtherStorage> &emboss_reserved_local_other)
+ Generic${name}View(
+ const Generic${name}View<OtherStorage> &emboss_reserved_local_other)
: backing_{emboss_reserved_local_other.BackingStorage()}
- $_parameter_copy_initializers_$ {}
+ ${parameter_copy_initializers} {}
// Allow pass-through construction of backing_, but only if there is at least
// one argument, and, if exactly one argument, that argument is not a
- // (possibly c/v/ref-qualified) Generic$_name_$View.
+ // (possibly c/v/ref-qualified) Generic${name}View.
//
// Explicitly ruling out overloads that might match the copy or move
// constructor is necessary in order for the copy and move constructors to be
// reliably found during overload resolution.
template <typename Arg,
typename = typename ::std::enable_if<
- !EmbossReservedInternalIsGeneric$_name_$View<
+ !EmbossReservedInternalIsGeneric${name}View<
typename ::std::remove_cv<typename ::std::remove_reference<
Arg>::type>::type>::value>::type>
- explicit Generic$_name_$View(
- $_constructor_parameters_$ Arg &&emboss_reserved_local_arg)
+ explicit Generic${name}View(
+ ${constructor_parameters} Arg &&emboss_reserved_local_arg)
: backing_(::std::forward<Arg>(
- emboss_reserved_local_arg)) $_parameter_initializers_$
- $_initialize_parameters_initialized_true_$ {}
+ emboss_reserved_local_arg)) ${parameter_initializers}
+ ${initialize_parameters_initialized_true} {}
template <typename Arg0, typename Arg1, typename... Args>
- explicit Generic$_name_$View(
- $_constructor_parameters_$ Arg0 &&emboss_reserved_local_arg0,
+ explicit Generic${name}View(
+ ${constructor_parameters} Arg0 &&emboss_reserved_local_arg0,
Arg1 &&emboss_reserved_local_arg1, Args &&... emboss_reserved_local_args)
: backing_(::std::forward<Arg0>(emboss_reserved_local_arg0),
::std::forward<Arg1>(emboss_reserved_local_arg1),
::std::forward<Args>(
- emboss_reserved_local_args)...) $_parameter_initializers_$
- $_initialize_parameters_initialized_true_$ {}
+ emboss_reserved_local_args)...) ${parameter_initializers}
+ ${initialize_parameters_initialized_true} {}
template <typename OtherStorage>
- Generic$_name_$View<Storage> &operator=(
- const Generic$_name_$View<OtherStorage> &emboss_reserved_local_other) {
+ Generic${name}View<Storage> &operator=(
+ const Generic${name}View<OtherStorage> &emboss_reserved_local_other) {
backing_ = emboss_reserved_local_other.BackingStorage();
return *this;
}
- $_enum_usings_$
+ ${enum_usings}
bool Ok() const {
if (!IsComplete()) return false;
-$_parameter_ok_checks_$
-$_field_ok_checks_$
-$_requires_check_$
+${parameter_ok_checks}
+${field_ok_checks}
+${requires_check}
return true;
}
Storage BackingStorage() const { return backing_; }
bool IsComplete() const {
- return backing_.Ok() && IntrinsicSizeIn$_units_$().Ok() &&
- backing_.SizeIn$_units_$() >=
+ return backing_.Ok() && IntrinsicSizeIn${units}().Ok() &&
+ backing_.SizeIn${units}() >=
static_cast</**/ ::std::size_t>(
- IntrinsicSizeIn$_units_$().UncheckedRead());
+ IntrinsicSizeIn${units}().UncheckedRead());
}
-$_size_method_$
+${size_method}
template <typename OtherStorage>
bool Equals(
- Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
- $_equals_method_body_$ return true;
+ Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
+ ${equals_method_body} return true;
}
template <typename OtherStorage>
bool UncheckedEquals(
- Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
- $_unchecked_equals_method_body_$ return true;
+ Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
+ ${unchecked_equals_method_body} return true;
}
// (Unchecked)CopyFrom copies the number of bytes included in the other view,
// and ignores the size of the current view. Even if they differ before
@@ -154,25 +156,25 @@
// destination view's size should be updated by the copy.
template <typename OtherStorage>
void UncheckedCopyFrom(
- Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+ Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
backing_.UncheckedCopyFrom(
emboss_reserved_local_other.BackingStorage(),
- emboss_reserved_local_other.IntrinsicSizeIn$_units_$().UncheckedRead());
+ emboss_reserved_local_other.IntrinsicSizeIn${units}().UncheckedRead());
}
template <typename OtherStorage>
void CopyFrom(
- Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+ Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
backing_.CopyFrom(
emboss_reserved_local_other.BackingStorage(),
- emboss_reserved_local_other.IntrinsicSizeIn$_units_$().Read());
+ emboss_reserved_local_other.IntrinsicSizeIn${units}().Read());
}
template <typename OtherStorage>
bool TryToCopyFrom(
- Generic$_name_$View<OtherStorage> emboss_reserved_local_other) const {
+ Generic${name}View<OtherStorage> emboss_reserved_local_other) const {
return emboss_reserved_local_other.Ok() && backing_.TryToCopyFrom(
emboss_reserved_local_other.BackingStorage(),
- emboss_reserved_local_other.IntrinsicSizeIn$_units_$().Read());
+ emboss_reserved_local_other.IntrinsicSizeIn${units}().Read());
}
template <class Stream>
@@ -197,7 +199,7 @@
&emboss_reserved_local_colon))
return false;
if (emboss_reserved_local_colon != ":") return false;
-$_decode_fields_$
+${decode_fields}
// decode_fields will `continue` if it successfully finds a field.
return false;
}
@@ -215,7 +217,7 @@
emboss_reserved_local_stream->Write("{");
}
bool emboss_reserved_local_wrote_field = false;
-$_write_fields_$
+${write_fields}
// Avoid unused variable warnings for empty structures:
(void)emboss_reserved_local_wrote_field;
if (emboss_reserved_local_options.multiline()) {
@@ -229,12 +231,12 @@
static constexpr bool IsAggregate() { return true; }
-$_field_method_declarations_$
+${field_method_declarations}
private:
Storage backing_;
- $_parameter_fields_$
- $_parameters_initialized_flag_$
+ ${parameter_fields}
+ ${parameters_initialized_flag}
// This is a bit of a hack to handle Equals() and UncheckedEquals() between
// views with different underlying storage -- otherwise, structs with
@@ -243,66 +245,66 @@
// TODO(bolms): Revisit this once the special-case code for anonymous members
// is replaced by explicit read/write virtual fields in the IR.
template <class OtherStorage>
- friend class Generic$_name_$View;
+ friend class Generic${name}View;
};
-using $_name_$View =
- Generic$_name_$View</**/ ::emboss::support::ReadOnlyContiguousBuffer>;
-using $_name_$Writer =
- Generic$_name_$View</**/ ::emboss::support::ReadWriteContiguousBuffer>;
+using ${name}View =
+ Generic${name}View</**/ ::emboss::support::ReadOnlyContiguousBuffer>;
+using ${name}Writer =
+ Generic${name}View</**/ ::emboss::support::ReadWriteContiguousBuffer>;
template <class View>
-struct EmbossReservedInternalIsGeneric$_name_$View {
+struct EmbossReservedInternalIsGeneric${name}View {
static constexpr const bool value = false;
};
template <class Storage>
-struct EmbossReservedInternalIsGeneric$_name_$View<
- Generic$_name_$View<Storage>> {
+struct EmbossReservedInternalIsGeneric${name}View<
+ Generic${name}View<Storage>> {
static constexpr const bool value = true;
};
template <typename T>
-inline Generic$_name_$View<
+inline Generic${name}View<
/**/ ::emboss::support::ContiguousBuffer<
typename ::std::remove_reference<
decltype(*::std::declval<T>()->data())>::type,
1, 0>>
-Make$_name_$View($_constructor_parameters_$ T &&emboss_reserved_local_arg) {
- return Generic$_name_$View<
+Make${name}View(${constructor_parameters} T &&emboss_reserved_local_arg) {
+ return Generic${name}View<
/**/ ::emboss::support::ContiguousBuffer<
typename ::std::remove_reference<decltype(
*::std::declval<T>()->data())>::type,
1, 0>>(
- $_forwarded_parameters_$ ::std::forward<T>(emboss_reserved_local_arg));
+ ${forwarded_parameters} ::std::forward<T>(emboss_reserved_local_arg));
}
template <typename T>
-inline Generic$_name_$View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>
-Make$_name_$View($_constructor_parameters_$ T *emboss_reserved_local_data,
+inline Generic${name}View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>
+Make${name}View(${constructor_parameters} T *emboss_reserved_local_data,
::std::size_t emboss_reserved_local_size) {
- return Generic$_name_$View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>(
- $_forwarded_parameters_$ emboss_reserved_local_data,
+ return Generic${name}View</**/ ::emboss::support::ContiguousBuffer<T, 1, 0>>(
+ ${forwarded_parameters} emboss_reserved_local_data,
emboss_reserved_local_size);
}
template <typename T, ::std::size_t kAlignment>
-inline Generic$_name_$View<
+inline Generic${name}View<
/**/ ::emboss::support::ContiguousBuffer<T, kAlignment, 0>>
-MakeAligned$_name_$View(
- $_constructor_parameters_$ T *emboss_reserved_local_data,
+MakeAligned${name}View(
+ ${constructor_parameters} T *emboss_reserved_local_data,
::std::size_t emboss_reserved_local_size) {
- return Generic$_name_$View<
+ return Generic${name}View<
/**/ ::emboss::support::ContiguousBuffer<T, kAlignment, 0>>(
- $_forwarded_parameters_$ emboss_reserved_local_data,
+ ${forwarded_parameters} emboss_reserved_local_data,
emboss_reserved_local_size);
}
// ** decode_field ** //////////////////////////////////////////////////////////
- // If the field name matches $_field_name_$, handle it, otherwise fall
+ // If the field name matches ${field_name}, handle it, otherwise fall
// through to the next field.
- if (emboss_reserved_local_name == "$_field_name_$") {
+ if (emboss_reserved_local_name == "${field_name}") {
// TODO(bolms): How should missing optional fields be handled?
- if (!$_field_name_$().UpdateFromTextStream(
+ if (!${field_name}().UpdateFromTextStream(
emboss_reserved_local_stream)) {
return false;
}
@@ -310,12 +312,12 @@
}
// ** write_field_to_text_stream ** ////////////////////////////////////////////
- if (has_$_field_name_$().ValueOr(false)) {
+ if (has_${field_name}().ValueOr(false)) {
// Don't try to read the field if `allow_partial_output` is set and the
// field can't be `Read()`. Aggregates should still be visited, even if
// they are not `Ok()` overall, since submembers may still be `Ok()`.
if (!emboss_reserved_local_field_options.allow_partial_output() ||
- $_field_name_$().IsAggregate() || $_field_name_$().Ok()) {
+ ${field_name}().IsAggregate() || ${field_name}().Ok()) {
if (emboss_reserved_local_field_options.multiline()) {
emboss_reserved_local_stream->Write(
emboss_reserved_local_field_options.current_indent());
@@ -325,8 +327,8 @@
}
emboss_reserved_local_stream->Write(" ");
}
- emboss_reserved_local_stream->Write("$_field_name_$: ");
- $_field_name_$().WriteToTextStream(emboss_reserved_local_stream,
+ emboss_reserved_local_stream->Write("${field_name}: ");
+ ${field_name}().WriteToTextStream(emboss_reserved_local_stream,
emboss_reserved_local_field_options);
emboss_reserved_local_wrote_field = true;
if (emboss_reserved_local_field_options.multiline()) {
@@ -334,27 +336,27 @@
}
} else if (emboss_reserved_local_field_options.allow_partial_output() &&
emboss_reserved_local_field_options.comments() &&
- !$_field_name_$().IsAggregate() && !$_field_name_$().Ok()) {
+ !${field_name}().IsAggregate() && !${field_name}().Ok()) {
if (emboss_reserved_local_field_options.multiline()) {
emboss_reserved_local_stream->Write(
emboss_reserved_local_field_options.current_indent());
}
- emboss_reserved_local_stream->Write("# $_field_name_$: UNREADABLE\n");
+ emboss_reserved_local_stream->Write("# ${field_name}: UNREADABLE\n");
}
}
// ** write_read_only_field_to_text_stream ** //////////////////////////////////
- if (has_$_field_name_$().ValueOr(false) &&
+ if (has_${field_name}().ValueOr(false) &&
emboss_reserved_local_field_options.comments()) {
if (!emboss_reserved_local_field_options.allow_partial_output() ||
- $_field_name_$().IsAggregate() || $_field_name_$().Ok()) {
+ ${field_name}().IsAggregate() || ${field_name}().Ok()) {
emboss_reserved_local_stream->Write(
emboss_reserved_local_field_options.current_indent());
// TODO(bolms): When there are multiline read-only fields, add an option
// to TextOutputOptions to add `# ` to the current indent and use it
// here, so that subsequent lines are also commented out.
- emboss_reserved_local_stream->Write("# $_field_name_$: ");
- $_field_name_$().WriteToTextStream(emboss_reserved_local_stream,
+ emboss_reserved_local_stream->Write("# ${field_name}: ");
+ ${field_name}().WriteToTextStream(emboss_reserved_local_stream,
emboss_reserved_local_field_options);
emboss_reserved_local_stream->Write("\n");
} else {
@@ -362,131 +364,131 @@
emboss_reserved_local_stream->Write(
emboss_reserved_local_field_options.current_indent());
}
- emboss_reserved_local_stream->Write("# $_field_name_$: UNREADABLE\n");
+ emboss_reserved_local_stream->Write("# ${field_name}: UNREADABLE\n");
}
}
// ** constant_structure_size_method ** ////////////////////////////////////////
- static constexpr ::std::size_t SizeIn$_units_$() {
- return static_cast</**/ ::std::size_t>(IntrinsicSizeIn$_units_$().Read());
+ static constexpr ::std::size_t SizeIn${units}() {
+ return static_cast</**/ ::std::size_t>(IntrinsicSizeIn${units}().Read());
}
static constexpr bool SizeIsKnown() {
- return IntrinsicSizeIn$_units_$().Ok();
+ return IntrinsicSizeIn${units}().Ok();
}
// ** runtime_structure_size_method ** /////////////////////////////////////////
- ::std::size_t SizeIn$_units_$() const {
- return static_cast</**/ ::std::size_t>(IntrinsicSizeIn$_units_$().Read());
+ ::std::size_t SizeIn${units}() const {
+ return static_cast</**/ ::std::size_t>(IntrinsicSizeIn${units}().Read());
}
- bool SizeIsKnown() const { return IntrinsicSizeIn$_units_$().Ok(); }
+ bool SizeIsKnown() const { return IntrinsicSizeIn${units}().Ok(); }
// ** ok_method_test ** ////////////////////////////////////////////////////////
- // If we don't have enough information to determine whether $_field_$ is
+ // If we don't have enough information to determine whether ${field} is
// present in the structure, then structure.Ok() should be false.
- if (!has_$_field_$.Known()) return false;
- // If $_field_$ is present, but not Ok(), then structure.Ok() should be
- // false. If $_field_$ is not present, it does not matter whether it is
+ if (!has_${field}.Known()) return false;
+ // If ${field} is present, but not Ok(), then structure.Ok() should be
+ // false. If ${field} is not present, it does not matter whether it is
// Ok().
- if (has_$_field_$.ValueOrDefault() && !$_field_$.Ok()) return false;
+ if (has_${field}.ValueOrDefault() && !${field}.Ok()) return false;
// ** equals_method_test ** ////////////////////////////////////////////////////
- // If this->$_field_$ is not equal to emboss_reserved_local_other.$_field_$,
+ // If this->${field} is not equal to emboss_reserved_local_other.${field},
// then the structures are not equal.
- // If either structure's has_$_field_$ is unknown, then default to not
+ // If either structure's has_${field} is unknown, then default to not
// Equals().
//
// TODO(bolms): Should Equals() return Maybe<bool> and/or return true for
// non-Ok()-but-equivalent structures?
- if (!has_$_field_$.Known()) return false;
- if (!emboss_reserved_local_other.has_$_field_$.Known()) return false;
+ if (!has_${field}.Known()) return false;
+ if (!emboss_reserved_local_other.has_${field}.Known()) return false;
- // If one side has $_field_$ but the other side does not, then the fields
+ // If one side has ${field} but the other side does not, then the fields
// are not equal. We use ValueOrDefault() instead of Value() since Value()
// is more complex and non-constexpr, and we already know that
- // has_$_field_$.Known() is true for both structures.
- if (emboss_reserved_local_other.has_$_field_$.ValueOrDefault() &&
- !has_$_field_$.ValueOrDefault())
+ // has_${field}.Known() is true for both structures.
+ if (emboss_reserved_local_other.has_${field}.ValueOrDefault() &&
+ !has_${field}.ValueOrDefault())
return false;
- if (has_$_field_$.ValueOrDefault() &&
- !emboss_reserved_local_other.has_$_field_$.ValueOrDefault())
+ if (has_${field}.ValueOrDefault() &&
+ !emboss_reserved_local_other.has_${field}.ValueOrDefault())
return false;
- // If both sides have $_field_$, then check that their Equals() returns
+ // If both sides have ${field}, then check that their Equals() returns
// true.
- if (emboss_reserved_local_other.has_$_field_$.ValueOrDefault() &&
- has_$_field_$.ValueOrDefault() &&
- !$_field_$.Equals(emboss_reserved_local_other.$_field_$))
+ if (emboss_reserved_local_other.has_${field}.ValueOrDefault() &&
+ has_${field}.ValueOrDefault() &&
+ !${field}.Equals(emboss_reserved_local_other.${field}))
return false;
// ** unchecked_equals_method_test ** //////////////////////////////////////////
// The contract for UncheckedEquals() is that the caller must assure that
- // both views are Ok() (which implies that has_$_field_$.Known() is true),
+ // both views are Ok() (which implies that has_${field}.Known() is true),
// and UncheckedEquals() will never perform any assertion checks (which
- // implies that UncheckedEquals() cannot call has_$_field_$.Value()).
+ // implies that UncheckedEquals() cannot call has_${field}.Value()).
- // If this->has_$_field_$ but !emboss_reserved_local_other.has_$_field_$, or
+ // If this->has_${field} but !emboss_reserved_local_other.has_${field}, or
// vice versa, then the structures are not equal. If neither structure
- // has_$_field_$, then $_field_$ is considered equal.
- if (emboss_reserved_local_other.has_$_field_$.ValueOr(false) &&
- !has_$_field_$.ValueOr(false))
+ // has_${field}, then ${field} is considered equal.
+ if (emboss_reserved_local_other.has_${field}.ValueOr(false) &&
+ !has_${field}.ValueOr(false))
return false;
- if (has_$_field_$.ValueOr(false) &&
- !emboss_reserved_local_other.has_$_field_$.ValueOr(false))
+ if (has_${field}.ValueOr(false) &&
+ !emboss_reserved_local_other.has_${field}.ValueOr(false))
return false;
- // If $_field_$ is present in both structures, then check its equality.
- if (emboss_reserved_local_other.has_$_field_$.ValueOr(false) &&
- has_$_field_$.ValueOr(false) &&
- !$_field_$.UncheckedEquals(emboss_reserved_local_other.$_field_$))
+ // If ${field} is present in both structures, then check its equality.
+ if (emboss_reserved_local_other.has_${field}.ValueOr(false) &&
+ has_${field}.ValueOr(false) &&
+ !${field}.UncheckedEquals(emboss_reserved_local_other.${field}))
return false;
// ** structure_view_type ** ///////////////////////////////////////////////////
-$_namespace_$::Generic$_name_$View<typename $_buffer_type_$>
+${namespace}::Generic${name}View<typename ${buffer_type}>
// ** external_view_type ** ////////////////////////////////////////////////////
-$_namespace_$::$_name_$View<
- /**/ ::emboss::support::FixedSizeViewParameters<$_bits_$, $_validator_$>,
- typename $_buffer_type_$>
+${namespace}::${name}View<
+ /**/ ::emboss::support::FixedSizeViewParameters<${bits}, ${validator}>,
+ typename ${buffer_type}>
// ** enum_view_type ** ////////////////////////////////////////////////////////
-$_support_namespace_$::EnumView<
- /**/ $_enum_type_$,
- ::emboss::support::FixedSizeViewParameters<$_bits_$, $_validator_$>,
- typename $_buffer_type_$>
+${support_namespace}::EnumView<
+ /**/ ${enum_type},
+ ::emboss::support::FixedSizeViewParameters<${bits}, ${validator}>,
+ typename ${buffer_type}>
// ** array_view_adapter ** ////////////////////////////////////////////////////
-$_support_namespace_$::GenericArrayView<
- typename $_element_view_type_$, typename $_buffer_type_$, $_element_size_$,
- $_addressable_unit_size_$ $_element_view_parameter_types_$>
+${support_namespace}::GenericArrayView<
+ typename ${element_view_type}, typename ${buffer_type}, ${element_size},
+ ${addressable_unit_size} ${element_view_parameter_types}>
// ** structure_field_validator ** /////////////////////////////////////////////
-struct $_name_$ {
+struct ${name} {
template <typename ValueType>
static constexpr bool ValueIsOk(ValueType emboss_reserved_local_value) {
(void)emboss_reserved_local_value; // Silence -Wunused-parameter
- return ($_expression_$).ValueOrDefault();
+ return (${expression}).ValueOrDefault();
}
};
// ** structure_single_field_method_declarations ** ////////////////////////////
- $_visibility_$:
- typename $_type_reader_$ $_name_$() const;
- ::emboss::support::Maybe<bool> has_$_name_$() const;
+ ${visibility}:
+ typename ${type_reader} ${name}() const;
+ ::emboss::support::Maybe<bool> has_${name}() const;
// ** structure_single_field_method_definitions ** /////////////////////////////
template <class Storage>
-inline typename $_type_reader_$ Generic$_parent_type_$View<Storage>::$_name_$()
+inline typename ${type_reader} Generic${parent_type}View<Storage>::${name}()
const {
// If it's not possible to read the location of this field, provide a view
// into a null storage -- the only safe methods to call on it will be Ok() and
@@ -494,116 +496,116 @@
// call those methods at all. Similarly, if the end of the field would come
// before the start, we provide a null storage, though arguably we should
// not.
-$_parameter_subexpressions_$
- if ($_parameters_known_$ has_$_name_$().ValueOr(false)) {
-$_size_and_offset_subexpressions_$
- auto emboss_reserved_local_size = $_size_$;
- auto emboss_reserved_local_offset = $_offset_$;
+${parameter_subexpressions}
+ if (${parameters_known} has_${name}().ValueOr(false)) {
+${size_and_offset_subexpressions}
+ auto emboss_reserved_local_size = ${size};
+ auto emboss_reserved_local_offset = ${offset};
if (emboss_reserved_local_size.Known() &&
emboss_reserved_local_size.ValueOr(0) >= 0 &&
emboss_reserved_local_offset.Known() &&
emboss_reserved_local_offset.ValueOr(0) >= 0) {
- return $_type_reader_$(
- $_parameter_values_$ backing_
- .template GetOffsetStorage<$_alignment_$,
- $_static_offset_$>(
+ return ${type_reader}(
+ ${parameter_values} backing_
+ .template GetOffsetStorage<${alignment},
+ ${static_offset}>(
emboss_reserved_local_offset.ValueOrDefault(),
emboss_reserved_local_size.ValueOrDefault()));
}
}
- return $_type_reader_$();
+ return ${type_reader}();
}
template <class Storage>
inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
- return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+ return ${field_exists};
}
// ** structure_single_const_virtual_field_method_declarations ** //////////////
- $_visibility_$:
- class $_virtual_view_type_name_$ final {
+ ${visibility}:
+ class ${virtual_view_type_name} final {
public:
- using ValueType = $_logical_type_$;
+ using ValueType = ${logical_type};
- constexpr $_virtual_view_type_name_$() {}
- $_virtual_view_type_name_$(const $_virtual_view_type_name_$ &) = default;
- $_virtual_view_type_name_$($_virtual_view_type_name_$ &&) = default;
- $_virtual_view_type_name_$ &operator=(const $_virtual_view_type_name_$ &) =
+ constexpr ${virtual_view_type_name}() {}
+ ${virtual_view_type_name}(const ${virtual_view_type_name} &) = default;
+ ${virtual_view_type_name}(${virtual_view_type_name} &&) = default;
+ ${virtual_view_type_name} &operator=(const ${virtual_view_type_name} &) =
default;
- $_virtual_view_type_name_$ &operator=($_virtual_view_type_name_$ &&) =
+ ${virtual_view_type_name} &operator=(${virtual_view_type_name} &&) =
default;
- ~$_virtual_view_type_name_$() = default;
+ ~${virtual_view_type_name}() = default;
- static constexpr $_logical_type_$ Read();
- static constexpr $_logical_type_$ UncheckedRead();
+ static constexpr ${logical_type} Read();
+ static constexpr ${logical_type} UncheckedRead();
static constexpr bool Ok() { return true; }
template <class Stream>
void WriteToTextStream(Stream *emboss_reserved_local_stream,
const ::emboss::TextOutputOptions
&emboss_reserved_local_options) const {
- ::emboss::support::$_write_to_text_stream_function_$(
+ ::emboss::support::${write_to_text_stream_function}(
this, emboss_reserved_local_stream, emboss_reserved_local_options);
}
static constexpr bool IsAggregate() { return false; }
};
- static constexpr $_virtual_view_type_name_$ $_name_$() {
- return $_virtual_view_type_name_$();
+ static constexpr ${virtual_view_type_name} ${name}() {
+ return ${virtual_view_type_name}();
}
- static constexpr ::emboss::support::Maybe<bool> has_$_name_$() {
+ static constexpr ::emboss::support::Maybe<bool> has_${name}() {
return ::emboss::support::Maybe<bool>(true);
}
// ** structure_single_const_virtual_field_method_definitions ** ///////////////
-namespace $_parent_type_$ {
-inline constexpr $_logical_type_$ $_name_$() {
- return $_read_value_$.ValueOrDefault();
+namespace ${parent_type} {
+inline constexpr ${logical_type} ${name}() {
+ return ${read_value}.ValueOrDefault();
}
-} // namespace $_parent_type_$
+} // namespace ${parent_type}
template <class Storage>
-inline constexpr $_logical_type_$
-Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$::Read() {
- return $_parent_type_$::$_name_$();
+inline constexpr ${logical_type}
+Generic${parent_type}View<Storage>::${virtual_view_type_name}::Read() {
+ return ${parent_type}::${name}();
}
template <class Storage>
-inline constexpr $_logical_type_$
-Generic$_parent_type_$View<
- Storage>::$_virtual_view_type_name_$::UncheckedRead() {
- return $_parent_type_$::$_name_$();
+inline constexpr ${logical_type}
+Generic${parent_type}View<
+ Storage>::${virtual_view_type_name}::UncheckedRead() {
+ return ${parent_type}::${name}();
}
// ** structure_single_virtual_field_method_declarations ** ////////////////////
- $_visibility_$:
- class $_virtual_view_type_name_$ final {
+ ${visibility}:
+ class ${virtual_view_type_name} final {
public:
- using ValueType = $_logical_type_$;
+ using ValueType = ${logical_type};
- explicit $_virtual_view_type_name_$(
- const Generic$_parent_type_$View &emboss_reserved_local_view)
+ explicit ${virtual_view_type_name}(
+ const Generic${parent_type}View &emboss_reserved_local_view)
: view_(emboss_reserved_local_view) {}
- $_virtual_view_type_name_$() = delete;
- $_virtual_view_type_name_$(const $_virtual_view_type_name_$ &) = default;
- $_virtual_view_type_name_$($_virtual_view_type_name_$ &&) = default;
- $_virtual_view_type_name_$ &operator=(const $_virtual_view_type_name_$ &) =
+ ${virtual_view_type_name}() = delete;
+ ${virtual_view_type_name}(const ${virtual_view_type_name} &) = default;
+ ${virtual_view_type_name}(${virtual_view_type_name} &&) = default;
+ ${virtual_view_type_name} &operator=(const ${virtual_view_type_name} &) =
default;
- $_virtual_view_type_name_$ &operator=($_virtual_view_type_name_$ &&) =
+ ${virtual_view_type_name} &operator=(${virtual_view_type_name} &&) =
default;
- ~$_virtual_view_type_name_$() = default;
+ ~${virtual_view_type_name}() = default;
- $_logical_type_$ Read() const {
- EMBOSS_CHECK(view_.has_$_name_$().ValueOr(false));
+ ${logical_type} Read() const {
+ EMBOSS_CHECK(view_.has_${name}().ValueOr(false));
auto emboss_reserved_local_value = MaybeRead();
EMBOSS_CHECK(emboss_reserved_local_value.Known());
EMBOSS_CHECK(ValueIsOk(emboss_reserved_local_value.ValueOrDefault()));
return emboss_reserved_local_value.ValueOrDefault();
}
- $_logical_type_$ UncheckedRead() const {
+ ${logical_type} UncheckedRead() const {
// UncheckedRead() on a virtual still calls Ok() on its dependencies;
// i.e., it still does some bounds checking. This is because of a subtle
// case, illustrated by the example below:
@@ -646,52 +648,52 @@
void WriteToTextStream(Stream *emboss_reserved_local_stream,
const ::emboss::TextOutputOptions
&emboss_reserved_local_options) const {
- ::emboss::support::$_write_to_text_stream_function_$(
+ ::emboss::support::${write_to_text_stream_function}(
this, emboss_reserved_local_stream, emboss_reserved_local_options);
}
static constexpr bool IsAggregate() { return false; }
-$_write_methods_$
+${write_methods}
private:
- ::emboss::support::Maybe</**/ $_logical_type_$> MaybeRead() const {
-$_read_subexpressions_$
- return $_read_value_$;
+ ::emboss::support::Maybe</**/ ${logical_type}> MaybeRead() const {
+${read_subexpressions}
+ return ${read_value};
}
static constexpr bool ValueIsOk(
- $_logical_type_$ emboss_reserved_local_value) {
+ ${logical_type} emboss_reserved_local_value) {
(void)emboss_reserved_local_value; // Silence -Wunused-parameter
- return $_value_is_ok_$.ValueOr(false);
+ return ${value_is_ok}.ValueOr(false);
}
- const Generic$_parent_type_$View view_;
+ const Generic${parent_type}View view_;
};
- $_virtual_view_type_name_$ $_name_$() const;
- ::emboss::support::Maybe<bool> has_$_name_$() const;
+ ${virtual_view_type_name} ${name}() const;
+ ::emboss::support::Maybe<bool> has_${name}() const;
// ** structure_single_virtual_field_write_methods ** //////////////////////////
- bool TryToWrite($_logical_type_$ emboss_reserved_local_value) {
- const auto emboss_reserved_local_maybe_new_value = $_transform_$;
+ bool TryToWrite(${logical_type} emboss_reserved_local_value) {
+ const auto emboss_reserved_local_maybe_new_value = ${transform};
if (!CouldWriteValue(emboss_reserved_local_value)) return false;
- return view_.$_destination_$.TryToWrite(
+ return view_.${destination}.TryToWrite(
emboss_reserved_local_maybe_new_value.ValueOrDefault());
}
- void Write($_logical_type_$ emboss_reserved_local_value) {
+ void Write(${logical_type} emboss_reserved_local_value) {
const bool result = TryToWrite(emboss_reserved_local_value);
(void)result;
EMBOSS_CHECK(result);
}
- void UncheckedWrite($_logical_type_$ emboss_reserved_local_value) {
- view_.$_destination_$.UncheckedWrite(($_transform_$).ValueOrDefault());
+ void UncheckedWrite(${logical_type} emboss_reserved_local_value) {
+ view_.${destination}.UncheckedWrite((${transform}).ValueOrDefault());
}
- bool CouldWriteValue($_logical_type_$ emboss_reserved_local_value) {
+ bool CouldWriteValue(${logical_type} emboss_reserved_local_value) {
if (!ValueIsOk(emboss_reserved_local_value)) return false;
- const auto emboss_reserved_local_maybe_new_value = $_transform_$;
+ const auto emboss_reserved_local_maybe_new_value = ${transform};
if (!emboss_reserved_local_maybe_new_value.Known()) return false;
- return view_.$_destination_$.CouldWriteValue(
+ return view_.${destination}.CouldWriteValue(
emboss_reserved_local_maybe_new_value.ValueOrDefault());
}
template <class Stream>
@@ -703,60 +705,60 @@
// ** structure_single_virtual_field_method_definitions ** /////////////////////
template <class Storage>
-inline typename Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$
-Generic$_parent_type_$View<Storage>::$_name_$() const {
+inline typename Generic${parent_type}View<Storage>::${virtual_view_type_name}
+Generic${parent_type}View<Storage>::${name}() const {
return
- typename Generic$_parent_type_$View<Storage>::$_virtual_view_type_name_$(
+ typename Generic${parent_type}View<Storage>::${virtual_view_type_name}(
*this);
}
template <class Storage>
inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
- return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+ return ${field_exists};
}
// ** structure_single_field_indirect_method_declarations ** ///////////////////
- $_visibility_$:
+ ${visibility}:
// The "this->" is required for (some versions of?) GCC.
- auto $_name_$() const -> decltype(this->$_aliased_field_$) {
- return has_$_name_$().ValueOrDefault() ? $_aliased_field_$
- : decltype(this->$_aliased_field_$)();
+ auto ${name}() const -> decltype(this->${aliased_field}) {
+ return has_${name}().ValueOrDefault() ? ${aliased_field}
+ : decltype(this->${aliased_field})();
}
- ::emboss::support::Maybe<bool> has_$_name_$() const;
+ ::emboss::support::Maybe<bool> has_${name}() const;
// ** struct_single_field_indirect_method_definitions ** ///////////////////////
template <class Storage>
inline ::emboss::support::Maybe<bool>
-Generic$_parent_type_$View<Storage>::has_$_name_$() const {
- return $_field_exists_$;
+Generic${parent_type}View<Storage>::has_${name}() const {
+ return ${field_exists};
}
// ** structure_single_parameter_field_method_declarations ** //////////////////
private:
// TODO(bolms): Is there any harm if these are public methods?
- constexpr ::emboss::support::MaybeConstantView</**/ $_logical_type_$>
- $_name_$() const {
+ constexpr ::emboss::support::MaybeConstantView</**/ ${logical_type}>
+ ${name}() const {
return parameters_initialized_
- ? ::emboss::support::MaybeConstantView</**/ $_logical_type_$>(
- $_name_$_)
- : ::emboss::support::MaybeConstantView</**/ $_logical_type_$>();
+ ? ::emboss::support::MaybeConstantView</**/ ${logical_type}>(
+ ${name}_)
+ : ::emboss::support::MaybeConstantView</**/ ${logical_type}>();
}
- constexpr ::emboss::support::Maybe<bool> has_$_name_$() const {
+ constexpr ::emboss::support::Maybe<bool> has_${name}() const {
return ::emboss::support::Maybe<bool>(parameters_initialized_);
}
// ** enum_declaration ** //////////////////////////////////////////////////////
-enum class $_enum_$ : $_enum_type_$;
+enum class ${enum} : ${enum_type};
// ** enum_definition ** ///////////////////////////////////////////////////////
-enum class $_enum_$ : $_enum_type_$ {
-$_enum_values_$
+enum class ${enum} : ${enum_type} {
+${enum_values}
};
// This setup (ab)uses the fact that C++ templates can be defined in many
@@ -772,41 +774,41 @@
class EnumTraits;
template <>
-class EnumTraits<$_enum_$> final {
+class EnumTraits<${enum}> final {
public:
static bool TryToGetEnumFromName(const char *emboss_reserved_local_name,
- $_enum_$ *emboss_reserved_local_result) {
+ ${enum} *emboss_reserved_local_result) {
if (emboss_reserved_local_name == nullptr) return false;
// TODO(bolms): The generated code here would be much more efficient for
// large enums if the mapping were performed using a prefix trie rather than
// repeated strcmp().
-$_enum_from_name_cases_$
+${enum_from_name_cases}
return false;
}
static const char *TryToGetNameFromEnum(
- $_enum_$ emboss_reserved_local_value) {
+ ${enum} emboss_reserved_local_value) {
switch (emboss_reserved_local_value) {
-$_name_from_enum_cases_$
+${name_from_enum_cases}
default: return nullptr;
}
}
- static bool EnumIsKnown($_enum_$ emboss_reserved_local_value) {
+ static bool EnumIsKnown(${enum} emboss_reserved_local_value) {
switch (emboss_reserved_local_value) {
-$_enum_is_known_cases_$
+${enum_is_known_cases}
default:
return false;
}
}
static ::std::ostream &SendToOstream(::std::ostream &emboss_reserved_local_os,
- $_enum_$ emboss_reserved_local_value) {
+ ${enum} emboss_reserved_local_value) {
const char *emboss_reserved_local_name =
TryToGetNameFromEnum(emboss_reserved_local_value);
if (emboss_reserved_local_name == nullptr) {
emboss_reserved_local_os
- << static_cast</**/ ::std::underlying_type<$_enum_$>::type>(
+ << static_cast</**/ ::std::underlying_type<${enum}>::type>(
emboss_reserved_local_value);
} else {
emboss_reserved_local_os << emboss_reserved_local_name;
@@ -818,42 +820,42 @@
// These functions are intended to be found via ADL.
static inline bool TryToGetEnumFromName(
const char *emboss_reserved_local_name,
- $_enum_$ *emboss_reserved_local_result) {
- return EnumTraits<$_enum_$>::TryToGetEnumFromName(
+ ${enum} *emboss_reserved_local_result) {
+ return EnumTraits<${enum}>::TryToGetEnumFromName(
emboss_reserved_local_name, emboss_reserved_local_result);
}
static inline const char *TryToGetNameFromEnum(
- $_enum_$ emboss_reserved_local_value) {
- return EnumTraits<$_enum_$>::TryToGetNameFromEnum(
+ ${enum} emboss_reserved_local_value) {
+ return EnumTraits<${enum}>::TryToGetNameFromEnum(
emboss_reserved_local_value);
}
-static inline bool EnumIsKnown($_enum_$ emboss_reserved_local_value) {
- return EnumTraits<$_enum_$>::EnumIsKnown(emboss_reserved_local_value);
+static inline bool EnumIsKnown(${enum} emboss_reserved_local_value) {
+ return EnumTraits<${enum}>::EnumIsKnown(emboss_reserved_local_value);
}
static inline ::std::ostream &operator<<(
::std::ostream &emboss_reserved_local_os,
- $_enum_$ emboss_reserved_local_value) {
- return EnumTraits<$_enum_$>::SendToOstream(emboss_reserved_local_os,
+ ${enum} emboss_reserved_local_value) {
+ return EnumTraits<${enum}>::SendToOstream(emboss_reserved_local_os,
emboss_reserved_local_value);
}
// ** enum_from_name_case ** ///////////////////////////////////////////////////
- if (!strcmp("$_name_$", emboss_reserved_local_name)) {
- *emboss_reserved_local_result = $_enum_$::$_value_$;
+ if (!strcmp("${name}", emboss_reserved_local_name)) {
+ *emboss_reserved_local_result = ${enum}::${value};
return true;
}
// ** name_from_enum_case ** ///////////////////////////////////////////////////
- case $_enum_$::$_value_$: return "$_name_$";
+ case ${enum}::${value}: return "${name}";
// ** enum_is_known_case ** ////////////////////////////////////////////////////
- case $_enum_$::$_name_$: return true;
+ case ${enum}::${name}: return true;
// ** enum_value ** ////////////////////////////////////////////////////////////
- $_name_$ = $_value_$,
+ ${name} = ${value},
// ** enum_using_statement ** //////////////////////////////////////////////////
- using $_name_$ = $_component_$;
+ using ${name} = ${component};
diff --git a/compiler/back_end/util/code_template.py b/compiler/back_end/util/code_template.py
index bbea043..5374676 100644
--- a/compiler/back_end/util/code_template.py
+++ b/compiler/back_end/util/code_template.py
@@ -22,82 +22,25 @@
import string
-class _CppFormatter(string.Formatter):
- """Customized Formatter using $_name_$ instead of {name}.
-
- This class exists for the format_template() function; see its documentation
- for details.
- """
-
- def parse(self, format_string):
- """Overrides string.Formatter.parse.
-
- Arguments:
- format_string: a format string to be parsed.
-
- Yields:
- A sequence of 4-element tuples (literal, name, format_spec, conversion),
- where:
-
- literal: A literal string to include in the output. This will be
- output before the substitution, if any.
- name: The name of a substitution, or None if no substitution.
- format_spec: A format specification.
- conversion: A conversion specification.
-
- Consult the documentation for string.Formatter for the format of the
- format_spec and conversion elements.
- """
- # A replacement spec is $_field_name!conversion:format_spec_$, where
- # conversion and format_spec are optional. string.Formatter will take care
- # of parsing and interpreting the conversion and format_spec, so this method
- # just extracts them.
- delimiter_matches = re.finditer(
- r"""(?x)
- \$_
- (?P<field_name> ( [^!:_] | _[^$] )* )
- ( ! (?P<conversion> ( [^:_] | _[^$] )* ) )?
- ( : (?P<format_spec> ( [^_] | _[^$] )* ) )?
- _\$""", format_string)
- after_last_delimiter = 0
- for match in delimiter_matches:
- yield (format_string[after_last_delimiter:match.start()],
- match.group("field_name"),
- # A missing format_spec is indicated by ""...
- match.group("format_spec") or "",
- # ... but a missing conversion is indicated by None. Consistency!
- match.group("conversion") or None)
- after_last_delimiter = match.end()
- yield format_string[after_last_delimiter:], None, None, None
-
-
-_FORMATTER = _CppFormatter()
-
-
-def format_template(template, *args, **kwargs):
- """format_template acts like str.format, but uses $_name_$ instead of {name}.
+def format_template(template, **kwargs):
+ """format_template acts like str.format, but uses ${name} instead of {name}.
format_template acts like a str.format, except that instead of using { and }
- to delimit substitutions, format_template uses $_ and _$. This simplifies
+ to delimit substitutions, format_template uses ${name}. This simplifies
templates of source code in most languages, which frequently use "{" and "}",
- but very rarely use "$". The choice of "$_" and "_$" is conducive to the use
- of clang-format on templates.
+ but very rarely use "$".
- format_template does not currently have a way to put literal "$_..._$" into a
- format string.
-
- See the documentation for str.format and string.Formatter for details about
+ See the documentation for string.Template for details about
template strings and the format of substitutions.
Arguments:
template: A template to format.
- *args: Positional arguments for string.Formatter.format.
- **kwargs: Keyword arguments for string.Formatter.format.
+ **kwargs: Keyword arguments for string.Template.substitute.
Returns:
A formatted string.
"""
- return _FORMATTER.format(template, *args, **kwargs)
+ return template.substitute(**kwargs)
def parse_templates(text):
@@ -126,15 +69,18 @@
templates = {}
name = None
template = []
+ def finish_template(template):
+ return string.Template("\n".join(template))
+
for line in text.splitlines():
if delimiter_re.match(line):
if name:
- templates[name] = "\n".join(template)
+ templates[name] = finish_template(template)
name = delimiter_re.match(line).group(1)
template = []
else:
template.append(line)
if name:
- templates[name] = "\n".join(template)
+ templates[name] = finish_template(template)
return collections.namedtuple("Templates",
list(templates.keys()))(**templates)
diff --git a/compiler/back_end/util/code_template_test.py b/compiler/back_end/util/code_template_test.py
index 31e1400..c133096 100644
--- a/compiler/back_end/util/code_template_test.py
+++ b/compiler/back_end/util/code_template_test.py
@@ -14,48 +14,41 @@
"""Tests for code_template."""
+import string
import unittest
from compiler.back_end.util import code_template
+def _format_template_str(template: str, **kwargs) -> str:
+ return code_template.format_template(string.Template(template), **kwargs)
class FormatTest(unittest.TestCase):
"""Tests for code_template.format."""
def test_no_replacement_fields(self):
- self.assertEqual("foo", code_template.format_template("foo"))
- self.assertEqual("{foo}", code_template.format_template("{foo}"))
- self.assertEqual("$foo$", code_template.format_template("$foo$"))
- self.assertEqual("$_foo$", code_template.format_template("$_foo$"))
- self.assertEqual("$foo_$", code_template.format_template("$foo_$"))
+ self.assertEqual("foo", _format_template_str("foo"))
+ self.assertEqual("{foo}", _format_template_str("{foo}"))
+ self.assertEqual("${foo}", _format_template_str("$${foo}"))
def test_one_replacement_field(self):
- self.assertEqual("foo", code_template.format_template("$_bar_$", bar="foo"))
+ self.assertEqual("foo", _format_template_str("${bar}", bar="foo"))
self.assertEqual("bazfoo",
- code_template.format_template("baz$_bar_$", bar="foo"))
+ _format_template_str("baz${bar}", bar="foo"))
self.assertEqual("foobaz",
- code_template.format_template("$_bar_$baz", bar="foo"))
+ _format_template_str("${bar}baz", bar="foo"))
self.assertEqual("bazfooqux",
- code_template.format_template("baz$_bar_$qux", bar="foo"))
+ _format_template_str("baz${bar}qux", bar="foo"))
def test_one_replacement_field_with_formatting(self):
- self.assertEqual("1.000000",
- code_template.format_template("$_bar:.6f_$", bar=1))
- self.assertEqual("'foo'",
- code_template.format_template("$_bar!r_$", bar="foo"))
- self.assertEqual("==foo==",
- code_template.format_template("$_bar:=^7_$", bar="foo"))
- self.assertEqual("=='foo'==",
- code_template.format_template("$_bar!r:=^9_$", bar="foo"))
- self.assertEqual("xx=='foo'==yy",
- code_template.format_template("xx$_bar!r:=^9_$yy",
- bar="foo"))
+ # Basic string.Templates don't support formatting values.
+ self.assertRaises(ValueError,
+ _format_template_str, "${bar:.6f}", bar=1)
def test_one_replacement_field_value_missing(self):
- self.assertRaises(KeyError, code_template.format_template, "$_bar_$")
+ self.assertRaises(KeyError, _format_template_str, "${bar}")
def test_multiple_replacement_fields(self):
self.assertEqual(" aaa bbb ",
- code_template.format_template(" $_bar_$ $_baz_$ ",
+ _format_template_str(" ${bar} ${baz} ",
bar="aaa",
baz="bbb"))
@@ -63,36 +56,44 @@
class ParseTemplatesTest(unittest.TestCase):
"""Tests for code_template.parse_templates."""
+ def assertTemplatesEqual(self, expected, actual): # pylint:disable=invalid-name
+ """Compares the results of a parse_templates"""
+ # Extract the name and template from the result tuple
+ actual = {
+ k: v.template for k, v in actual._asdict().items()
+ }
+ self.assertEqual(expected, actual)
+
def test_handles_no_template_case(self):
- self.assertEqual({}, code_template.parse_templates("")._asdict())
- self.assertEqual({}, code_template.parse_templates(
- "this is not a template")._asdict())
+ self.assertTemplatesEqual({}, code_template.parse_templates(""))
+ self.assertTemplatesEqual({}, code_template.parse_templates(
+ "this is not a template"))
def test_handles_one_template_at_start(self):
- self.assertEqual({"foo": "bar"},
- code_template.parse_templates("** foo **\nbar")._asdict())
+ self.assertTemplatesEqual({"foo": "bar"},
+ code_template.parse_templates("** foo **\nbar"))
def test_handles_one_template_after_start(self):
- self.assertEqual(
+ self.assertTemplatesEqual(
{"foo": "bar"},
- code_template.parse_templates("text\n** foo **\nbar")._asdict())
+ code_template.parse_templates("text\n** foo **\nbar"))
def test_handles_delimiter_with_other_text(self):
- self.assertEqual(
+ self.assertTemplatesEqual(
{"foo": "bar"},
- code_template.parse_templates("text\n// ** foo ** ////\nbar")._asdict())
- self.assertEqual(
+ code_template.parse_templates("text\n// ** foo ** ////\nbar"))
+ self.assertTemplatesEqual(
{"foo": "bar"},
- code_template.parse_templates("text\n# ** foo ** #####\nbar")._asdict())
+ code_template.parse_templates("text\n# ** foo ** #####\nbar"))
def test_handles_multiple_delimiters(self):
- self.assertEqual({"foo": "bar",
+ self.assertTemplatesEqual({"foo": "bar",
"baz": "qux"}, code_template.parse_templates(
- "** foo **\nbar\n** baz **\nqux")._asdict())
+ "** foo **\nbar\n** baz **\nqux"))
def test_returns_object_with_attributes(self):
self.assertEqual("bar", code_template.parse_templates(
- "** foo **\nbar\n** baz **\nqux").foo)
+ "** foo **\nbar\n** baz **\nqux").foo.template)
if __name__ == "__main__":
unittest.main()