Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/python/__version__.py.in
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
DESTINATION ${CMAKE_INSTALL_DOCDIR})

find_package(fmt 9 REQUIRED)

#--- project specific subdirectories -------------------------------------------
add_subdirectory(src)

Expand All @@ -188,8 +190,6 @@ if(BUILD_TESTING)
add_subdirectory(tests)
endif()

find_package(fmt 9 REQUIRED)

add_subdirectory(tools)
add_subdirectory(python)

Expand Down
1 change: 1 addition & 0 deletions cmake/podioConfig.cmake.in
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ if(NOT "@REQUIRE_PYTHON_VERSION@" STREQUAL "")
else()
find_dependency(Python3 COMPONENTS Interpreter Development)
endif()
find_dependency(fmt @fmt_VERSION@)

SET(ENABLE_SIO @ENABLE_SIO@)
if(ENABLE_SIO)
Expand Down
5 changes: 5 additions & 0 deletions include/podio/ObjectID.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef PODIO_OBJECTID_H
#define PODIO_OBJECTID_H

#include <fmt/ostream.h>

#include <cstdint>
#include <functional>
#include <iomanip>
Expand Down Expand Up @@ -60,4 +62,7 @@ struct std::hash<podio::ObjectID> {
}
};

template <>
struct fmt::formatter<podio::ObjectID> : fmt::ostream_formatter {};

#endif
5 changes: 5 additions & 0 deletions include/podio/UserDataCollection.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "podio/detail/Pythonizations.h"
#include "podio/utilities/TypeHelpers.h"

#include <fmt/ostream.h>

#define PODIO_ADD_USER_TYPE(type) \
template <> \
consteval const char* userDataTypeName<type>() { \
Expand Down Expand Up @@ -354,4 +356,7 @@ constexpr std::string_view UserDataCollection<BasicType, U>::dataTypeName;

} // namespace podio

template <typename BasicType>
struct fmt::formatter<podio::UserDataCollection<BasicType>> : fmt::ostream_formatter {};

#endif
9 changes: 7 additions & 2 deletions include/podio/detail/Link.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
#include "nlohmann/json.hpp"
#endif

#include <fmt/ostream.h>

#include <functional>
#include <ostream>
#include <type_traits>
Expand Down Expand Up @@ -348,8 +350,8 @@ class LinkT {
podio::utils::MaybeSharedPtr<LinkObjT> m_obj{nullptr};
};

template <typename FromT, typename ToT>
std::ostream& operator<<(std::ostream& os, const Link<FromT, ToT>& link) {
template <typename FromT, typename ToT, bool Mutable>
std::ostream& operator<<(std::ostream& os, const LinkT<FromT, ToT, Mutable>& link) {
if (!link.isAvailable()) {
return os << "[not available]";
}
Expand Down Expand Up @@ -382,4 +384,7 @@ struct std::hash<podio::LinkT<FromT, ToT, Mutable>> {
}
};

template <typename FromT, typename ToT, bool Mutable>
struct fmt::formatter<podio::LinkT<FromT, ToT, Mutable>> : fmt::ostream_formatter {};

#endif // PODIO_DETAIL_LINK_H
5 changes: 5 additions & 0 deletions include/podio/detail/LinkCollectionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
#include "nlohmann/json.hpp"
#endif

#include <fmt/ostream.h>

#include <iomanip>
#include <memory>
#include <mutex>
Expand Down Expand Up @@ -460,4 +462,7 @@ void to_json(nlohmann::json& j, const podio::LinkCollection<FromT, ToT>& collect

} // namespace podio

template <typename FromT, typename ToT>
struct fmt::formatter<podio::LinkCollection<FromT, ToT>> : fmt::ostream_formatter {};

#endif // PODIO_DETAIL_LINKCOLLECTIONIMPL_H
5 changes: 5 additions & 0 deletions python/templates/Collection.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <memory>
#include <cstddef>

#include <fmt/ostream.h>

namespace podio {
struct RelationNames;
}
Expand Down Expand Up @@ -280,6 +282,9 @@ void to_json(nlohmann::json& j, const {{ class.bare_type }}Collection& collectio

{{ utils.namespace_close(class.namespace) }}

template <>
struct fmt::formatter<{% if class.namespace %}{{ class.namespace }}::{% endif %}{{ class.bare_type }}Collection> : fmt::ostream_formatter {};

{{ workarounds.ld_library_path(class, "Collection", ["valueTypeName", "dataTypeName"]) }}

#endif
7 changes: 7 additions & 0 deletions python/templates/Component.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
{% if generate_current_version %}
#include <ostream>

#include <fmt/ostream.h>

#if defined(PODIO_JSON_OUTPUT) && !defined(__CLING__)
#include "nlohmann/json_fwd.hpp"
#endif
Expand Down Expand Up @@ -58,4 +60,9 @@ public:

{{ utils.namespace_close(class.namespace) }}

{% if generate_current_version %}
template <>
struct fmt::formatter<{{ class.full_type }}> : fmt::ostream_formatter {};
{% endif %}

#endif
5 changes: 5 additions & 0 deletions python/templates/Interface.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "podio/utilities/TypeHelpers.h"
#include "podio/detail/OrderKey.h"

#include <fmt/ostream.h>

#include <memory>
#include <ostream>
#include <stdexcept>
Expand Down Expand Up @@ -196,4 +198,7 @@ struct std::hash<{{ class.full_type }}> {
}
};

template <>
struct fmt::formatter<{{ class.full_type }}> : fmt::ostream_formatter {};

#endif
3 changes: 3 additions & 0 deletions python/templates/MutableObject.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,7 @@ private:

{{ macros.std_hash(class, prefix='Mutable') }}

{{ macros.ostream_formatter(class, prefix='Mutable') }}


#endif
4 changes: 4 additions & 0 deletions python/templates/Object.h.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "podio/utilities/MaybeSharedPtr.h"
#include "podio/detail/OrderKey.h"

#include <fmt/ostream.h>

#include <ostream>
#include <cstdint>

Expand Down Expand Up @@ -79,6 +81,8 @@ std::ostream& operator<<(std::ostream& o, const {{ class.bare_type }}& value);

{{ macros.std_hash(class) }}

{{ macros.ostream_formatter(class) }}

{{ workarounds.ld_library_path(class) }}

#endif
6 changes: 6 additions & 0 deletions python/templates/macros/declarations.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,9 @@ struct std::hash<{{ namespace }}{{ prefix }}{{ class.bare_type }}> {
}
};
{% endmacro %}

{% macro ostream_formatter(class, prefix='') %}
{% set namespace = class.namespace + '::' if class.namespace else '' %}
template <>
struct fmt::formatter<{{ namespace }}{{ prefix }}{{ class.bare_type }}> : fmt::ostream_formatter {};
{% endmacro %}
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ SET(core_headers
PODIO_ADD_LIB_AND_DICT(podio "${core_headers}" "${core_sources}" selection.xml)
target_compile_options(podio PRIVATE -pthread)
target_link_libraries(podio PRIVATE Python3::Python)
target_link_libraries(podio PUBLIC fmt::fmt)
# For Frame.h
if (ROOT_VERSION VERSION_LESS 6.36)
target_compile_definitions(podio PUBLIC PODIO_ROOT_OLDER_6_36=1)
Expand Down
11 changes: 11 additions & 0 deletions tests/unittests/interface_types.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,3 +195,14 @@ TEST_CASE("InterfaceType extension model", "[interface-types][extension]") {
REQUIRE(wrapper.isA<iextension::AnotherHit>());
REQUIRE(wrapper.as<iextension::AnotherHit>().energy() == 4.2f);
}

TEST_CASE("InterfaceType formatting", "[interface-types][basics][formatting]") {
auto iface = iextension::EnergyInterface::makeEmpty();
auto formatted = fmt::format("{}", iface);
REQUIRE(formatted == "[not available]");

iface = ExampleCluster{};
formatted = fmt::format("{}", iface);
REQUIRE_FALSE(formatted.empty());
REQUIRE(formatted != "[not available]");
}
31 changes: 31 additions & 0 deletions tests/unittests/links.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "nlohmann/json.hpp"
#endif

#include <fmt/format.h>

#include <map>
#include <set>
#include <type_traits>
Expand Down Expand Up @@ -299,6 +301,22 @@ TEST_CASE("Links templated accessors", "[links]") {
}
}
// NOLINTEND(clang-analyzer-cplusplus.NewDeleteLeaks)

TEST_CASE("Link formatting", "[links]") {
TestL link;
auto formatted = fmt::format("{}", link);
REQUIRE_FALSE(formatted.empty());
REQUIRE(formatted != "[not available]");

auto emptyLink = TestL::makeEmpty();
auto emptyFmt = fmt::format("{}", emptyLink);
REQUIRE(emptyFmt == "[not available]");

TestMutL mutLink;
formatted = fmt::format("{}", mutLink);
REQUIRE(formatted != "[not avialable]");
}

TEST_CASE("LinkCollection collection concept", "[links][concepts]") {
STATIC_REQUIRE(podio::CollectionType<TestLColl>);
STATIC_REQUIRE(std::is_same_v<std::ranges::range_value_t<TestLColl>, TestL>);
Expand Down Expand Up @@ -443,6 +461,19 @@ TEST_CASE("LinkCollection basics", "[links]") {
}
}

TEST_CASE("LinkCollection formatting", "[links][formatting]") {
podio::LinkCollection<ExampleHit, ExampleCluster> links;

auto formatted = fmt::format("{}", links);
REQUIRE_FALSE(formatted.empty());

links.create();
links.create();

auto formatted2 = fmt::format("{}", links);
REQUIRE(formatted2.size() > formatted.size());
}

auto createLinkCollections(const size_t nElements = 3u) {
auto colls = std::make_tuple(TestLColl(), ExampleHitCollection(), ExampleClusterCollection());

Expand Down
55 changes: 55 additions & 0 deletions tests/unittests/unittest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
// podio specific includes
#include "podio/Frame.h"
#include "podio/GenericParameters.h"
#include "podio/ObjectID.h"
#include "podio/ROOTLegacyReader.h"
#include "podio/ROOTReader.h"
#include "podio/ROOTWriter.h"
Expand Down Expand Up @@ -60,12 +61,26 @@
#include "datamodel/MutableExampleWithArray.h"
#include "datamodel/MutableExampleWithComponent.h"
#include "datamodel/MutableExampleWithExternalExtraCode.h"
#include "datamodel/NamespaceInNamespaceStruct.h"
#include "datamodel/StructWithExtraCode.h"
#include "datamodel/datamodel.h"
#include "extension_model/extension_model.h"

#include "podio/UserDataCollection.h"

#include <fmt/format.h>

TEST_CASE("ObjectID formatting", "[basics][formatting]") {
auto objId = podio::ObjectID{};
auto formatted = fmt::format("{}", objId);
REQUIRE(formatted == "ffffffff|-1");

objId.collectionID = 42;
objId.index = 123;
formatted = fmt::format("{}", objId);
REQUIRE(formatted == fmt::format("{:8x}|123", 42));
}

TEST_CASE("AutoDelete", "[basics][memory-management]") {
auto coll = EventInfoCollection();
auto hit1 = MutableEventInfo();
Expand Down Expand Up @@ -138,6 +153,30 @@ TEST_CASE("makeEmpty", "[basics]") {
REQUIRE(hit.energy() == 0);
}

TEST_CASE("Object formatting", "[basics][formatting]") {
ExampleCluster cluster;
auto formatted = fmt::format("{}", cluster);
REQUIRE_FALSE(formatted.empty());
REQUIRE(formatted != "[not avaialble]");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

My only comment would be that these tests are not very demanding but having to deal with multiline strings is a bit annoying.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yeah, they basically make sure things compile, not whether they make sense from an output point of view. We didn't have too many for operator<< either, apart from the ones in https://github.com/AIDASoft/podio/blob/master/tests/ostream_operator.cpp which also essentially make sure things compile and don't crash at runtime, but do not make any checks on the outputs themselves.


cluster = ExampleCluster::makeEmpty();
formatted = fmt::format("{}", cluster);
REQUIRE(formatted == "[not available]");

auto mutCluster = MutableExampleCluster{};
formatted = fmt::format("{}", mutCluster);
REQUIRE_FALSE(formatted.empty());
REQUIRE(formatted != "[not available]");

auto typeWithComponent = ExampleWithArrayComponent{};
formatted = fmt::format("{}", typeWithComponent);
REQUIRE_FALSE(formatted.empty());

auto nspComp = ex2::NamespaceInNamespaceStruct{};
formatted = fmt::format("{}", nspComp);
REQUIRE_FALSE(formatted.empty());
}

TEST_CASE("Cyclic", "[basics][relations][memory-management]") {
auto coll1 = ExampleForCyclicDependency1Collection();
auto start = coll1.create();
Expand Down Expand Up @@ -413,6 +452,9 @@ TEST_CASE("UserDataCollection print", "[basics]") {
coll.print(sstr);

REQUIRE(sstr.str() == "[1, 2, 3]");

auto formatted = fmt::format("{}", coll);
REQUIRE_FALSE(formatted.empty());
}

TEST_CASE("UserDataCollection access", "[basics]") {
Expand Down Expand Up @@ -637,6 +679,19 @@ TEST_CASE("Equality", "[basics]") {
REQUIRE(clu != cluster);
}

TEST_CASE("Collection formatting", "[basics]") {
ExampleClusterCollection clusters;
auto cluster = clusters.create();
cluster.energy(42.5f);
auto formatted = fmt::format("{}", clusters);
REQUIRE_FALSE(formatted.empty());

ExampleWithComponentCollection components;
auto comp = components.create();
formatted = fmt::format("{}", components);
REQUIRE_FALSE(formatted.empty());
}

TEST_CASE("UserInitialization", "[basics][code-gen]") {
ExampleWithUserInitCollection coll;
// Default initialization values should work even through the create factory
Expand Down
Loading