-
Notifications
You must be signed in to change notification settings - Fork 95
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
Add ParserConfig class to encapsulate file path settings #439
Conversation
The error message assumes model uri's always start with "model://". This is no longer the case. Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Codecov Report
@@ Coverage Diff @@
## master #439 +/- ##
==========================================
+ Coverage 87.60% 87.75% +0.14%
==========================================
Files 63 64 +1
Lines 9616 9668 +52
==========================================
+ Hits 8424 8484 +60
+ Misses 1192 1184 -8
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't feel confident enough in the code base to approve/request changes yet, so I'll leave that to other reviewers. But I did have a few comments.
My main question is whether the DefaultConfig()
should be a mutable singleton. Typically a default cannot be changed by client code, so I would expect the API to return a static const ParserConfig &
. What were the tradeoffs compared to passing around a reference to a config object in the parsing code, with sdf::Root::Load()
and related functions taking a default argument?
If the mutable singleton is the best approach here, what would you think about changing it's name to GlobalConfig()
?
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the mutable singleton is the best approach here, what would you think about changing it's name to GlobalConfig()?
I thought a mutable singleton was needed to maintain backward compatibility. The functions sdf::setFindFileCallback
and sdf::addURIPath
used to modify the globals g_findFileCB
and g_uriPathMap
respectively. Now they modify the singleton. But I do agree that GlobalConfig
is a much better name. Renamed in deda523
@osrf-jenkins run tests please |
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
@@ -40,22 +40,60 @@ namespace sdf | |||
// | |||
class Root; | |||
|
|||
/// \brief Init based on the installed sdf_format.xml file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW This is a large amount of combinatorics... But I don't have a better solution.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah :(. I think there are some redundancies that we can deprecate, but we still end up with a lot of functions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First pass done, PTAL!
// Forward declare private data class. | ||
class ParserConfigPrivate; | ||
|
||
/// This class contains configuration options for the libsdformat parser. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In addition to below comment (how path resolution works), it's unclear to me what the precedence is for these different attributes (e.g. does callback override search paths, or the other way around).
Is there documentation that this can forward-reference, or should it be written here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay! Thanks!
@@ -64,6 +65,21 @@ namespace sdf | |||
bool _searchLocalPath = true, | |||
bool _useCallback = false); | |||
|
|||
/// \brief Find the absolute path of a file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This new function, and the old flavor, don't fully specify how the searching actually takes place. (I understand it's implementation specific, but still.)
From _useCallback
, I infer that "normal mechanism" means _searchLocalPath
, but I don't know it for sure.
Can you make this text more concise, and tell what the priorities are?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know about more concise, but I listed the search order in 6f53a9f. How does that look?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooh, that's excellent! Thank you!
|
||
/// \brief Get the URI scheme to search directories map | ||
/// \return Immutable reference to the URI scheme to search directories map | ||
public: const SchemeToPathMap &URIPathMap() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit It smells weird to be able to look at all paths, add a new path, but not remove a path. (assymmetry)
Is it hard to add that here?
Or perhaps the right workflow is to just reassign? e.g. just clear it out.
So if I wanted to remove or reorder a path, I would just do something like Parser::GLobalConfig() = my_new_config
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was trying to make this PR replicate existing functionality without adding any new features other than being able to specify a non-global config. It would be easy to add a function to remove a URI scheme, but adding a path to an existing URI scheme or reordering paths seem best suited for a future PR, IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Aye, makes sense to me.
@@ -0,0 +1,240 @@ | |||
/* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there any tests which explicitly show shadowing / prioritization?
e.g. both a search path and a callback could resolve the same file (possibly to different places), but only one of them wins out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added test in 8977cd1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a SDFPtr readFile(const std::string &)
at parser.hh:105 that didn't get overloaded
also, #474 was just merged, so you can use ImplPtr in ParserConfig
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
I was trying to have one less overload by only overloading the signature that also contains an Here's a list of all the functions in bool init(SDFPtr _sdf);
bool initFile(const std::string &_filename, SDFPtr _sdf);
bool initFile(const std::string &_filename, const ParserConfig &_config, SDFPtr _sdf);
bool initFile(const std::string &_filename, ElementPtr _sdf);
bool initFile(const std::string &_filename, const ParserConfig &_config, ElementPtr _sdf);
bool initString(const std::string &_xmlString, SDFPtr _sdf);
bool initString(const std::string &_xmlString, const ParserConfig &_config, SDFPtr _sdf);
sdf::SDFPtr readFile(const std::string &_filename);
sdf::SDFPtr readFile(const std::string &_filename, Errors &_errors);
sdf::SDFPtr readFile(const std::string &_filename, const ParserConfig &_config, Errors &_errors);
bool readFile(const std::string &_filename, SDFPtr _sdf);
bool readFile(const std::string &_filename, SDFPtr _sdf, Errors &_errors);
bool readFile(const std::string &_filename, const ParserConfig &_config, SDFPtr _sdf, Errors &_errors);
bool readFileWithoutConversion(const std::string &_filename, SDFPtr _sdf, Errors &_errors);
bool readFileWithoutConversion(const std::string &_filename, const ParserConfig &_config, SDFPtr _sdf, Errors &_errors);
bool readString(const std::string &_xmlString, SDFPtr _sdf);
bool readString(const std::string &_xmlString, SDFPtr _sdf, Errors &_errors);
bool readString(const std::string &_xmlString, const ParserConfig &_config, SDFPtr _sdf, Errors &_errors);
bool readString(const std::string &_xmlString, ElementPtr _sdf);
bool readString(const std::string &_xmlString, ElementPtr _sdf, Errors &_errors);
bool readString(const std::string &_xmlString, const ParserConfig &_config, ElementPtr _sdf, Errors &_errors);
bool readStringWithoutConversion( const std::string &_xmlString, SDFPtr _sdf, Errors &_errors);
bool readStringWithoutConversion(const std::string &_xmlString, const ParserConfig &_config, SDFPtr _sdf, Errors &_errors);
bool convertFile(const std::string &_filename, const std::string &_version, SDFPtr _sdf);
bool convertFile(const std::string &_filename, const std::string &_version, const ParserConfig &_config, SDFPtr _sdf);
bool convertString(const std::string &_sdfString, const std::string &_version, SDFPtr _sdf);
bool convertString(const std::string &_sdfString, const std::string &_version, const ParserConfig &_config, SDFPtr _sdf); It's interesting that we have |
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
that sounds fine to me
I would be ok with that. It's not the safest API since it doesn't have any way to report errors |
I've reported the windows compiler warning to the ign-utils repository gazebosim/gz-utils#9 |
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
@osrf-jenkins run tests please |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is looking good to me; I just have two small suggestions for extra test expectations
|
||
ASSERT_TRUE(sdf::ParserConfig::GlobalConfig().FindFileCallback()); | ||
EXPECT_EQ("test/dir2", | ||
sdf::ParserConfig::GlobalConfig().FindFileCallback()("empty")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do you feel about adding some expectations about sdf::findFile
?
diff --git a/test/integration/parser_config.cc b/test/integration/parser_config.cc
index d6bd2fb3..3f9780ac 100644
--- a/test/integration/parser_config.cc
+++ b/test/integration/parser_config.cc
@@ -51,6 +51,9 @@ TEST(ParserConfig, GlobalConfig)
ASSERT_TRUE(sdf::ParserConfig::GlobalConfig().FindFileCallback());
EXPECT_EQ("test/dir2",
sdf::ParserConfig::GlobalConfig().FindFileCallback()("empty"));
+ // sdf::findFile requires explicitly enabling callbacks
+ EXPECT_EQ("test/dir2", sdf::findFile("empty", false, true));
+ EXPECT_EQ("test/dir2", sdf::findFile("empty", true, true));
}
/////////////////////////////////////////////////
EXPECT_EQ(it->second.front(), testDir); | ||
|
||
ASSERT_TRUE(config.FindFileCallback()); | ||
EXPECT_EQ("test/dir2", config.FindFileCallback()("empty")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how do you feel about calling sdf::findFile
here as well?
diff --git a/test/integration/parser_config.cc b/test/integration/parser_config.cc
@@ -79,6 +82,8 @@ TEST(ParserConfig, NonGlobalConfig)
ASSERT_TRUE(config.FindFileCallback());
EXPECT_EQ("test/dir2", config.FindFileCallback()("empty"));
+ EXPECT_EQ("test/dir2", sdf::findFile("empty", false, true, config));
+ EXPECT_EQ("test/dir2", sdf::findFile("empty", true, true, config));
EXPECT_TRUE(sdf::ParserConfig::GlobalConfig().URIPathMap().empty());
EXPECT_FALSE(sdf::ParserConfig::GlobalConfig().FindFileCallback());
Signed-off-by: Addisu Z. Taddese <addisu@openrobotics.org>
@osrf-jenkins run tests please |
Toward #373
This adds a new
ParserConfig
object that contains configuration options for the libsdformat parser. This replaces the old globalsg_uriPathMap
andg_findFileCB
. To do this in a backward compatible way, theParserConfig
class provides a singleton object that calls tosdf::setSdfFindCallback
andsdf::addURIPath
use.New overloads of the main SDFormat file and string loading APIs allow users to pass in a
ParserConfig
object. If omitted, these APIs will default to the singletonParserConfig
object.