-
Notifications
You must be signed in to change notification settings - Fork 4.6k
Alternative module configuration syntax #43955
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,15 @@ | ||
| import FWCore.ParameterSet.Config as cms | ||
| from FWCore.Modules.modules import EventContentAnalyzer, EmptySource | ||
|
|
||
| process = cms.Process("EMPTY") | ||
|
|
||
| process.test = cms.EDAnalyzer("EventContentAnalyzer", listPathStatus = cms.untracked.bool(True)) | ||
| process.test = EventContentAnalyzer(listPathStatus = True) | ||
|
|
||
| process.e = cms.EndPath(process.test) | ||
|
|
||
| #process.out = cms.OutputModule("AsciiOutputModule") | ||
| #process.e2 = cms.EndPath(process.out) | ||
|
|
||
| process.source = cms.Source("EmptySource") | ||
| process.source = EmptySource() | ||
|
|
||
| process.maxEvents.input = 1 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,31 @@ | ||
| import FWCore.ParameterSet.Config as cms | ||
| from FWCore.Framework.modules import AddIntsProducer, IntProductFilter | ||
| from FWCore.Modules.modules import AsciiOutputModule | ||
| from FWCore.Integration.modules import DelayedReaderThrowingSource | ||
|
|
||
| process = cms.Process("TEST") | ||
|
|
||
| process.source = cms.Source("DelayedReaderThrowingSource", labels = cms.untracked.vstring("test", "test2", "test3")) | ||
| process.source = DelayedReaderThrowingSource( labels = ["test", "test2", "test3"]) | ||
|
|
||
| process.getter = cms.EDProducer("AddIntsProducer", labels = cms.VInputTag(cms.InputTag("test","","INPUTTEST"))) | ||
| process.onPath = cms.EDProducer("AddIntsProducer", labels = cms.VInputTag(cms.InputTag("test2", "", "INPUTTEST"), cms.InputTag("getter", "other"))) | ||
| process.f1 = cms.EDFilter("IntProductFilter", label = cms.InputTag("onPath"), shouldProduce = cms.bool(True)) | ||
| process.f2 = cms.EDFilter("IntProductFilter", label = cms.InputTag("onPath"), shouldProduce = cms.bool(True)) | ||
| process.inFront = cms.EDFilter("IntProductFilter", label = cms.InputTag("test3")) | ||
| process.getter = AddIntsProducer(labels = [("test","","INPUTTEST")]) | ||
| process.onPath = AddIntsProducer(labels = [("test2", "", "INPUTTEST"), ("getter", "other")]) | ||
| process.f1 = IntProductFilter( label = "onPath", shouldProduce = True) | ||
| process.f2 = IntProductFilter( label = "onPath", shouldProduce = True) | ||
| process.inFront = IntProductFilter( label = "test3") | ||
|
|
||
| process.p1 = cms.Path(process.inFront+process.onPath+process.f1+process.f2) | ||
| process.p3 = cms.Path(process.onPath+process.f1, cms.Task(process.getter)) | ||
|
|
||
| process.p2 = cms.Path(process.onPath+process.f2) | ||
|
|
||
|
|
||
| #process.dump = cms.EDAnalyzer("EventContentAnalyzer") | ||
| #from FWCore.Modules.modules import EventContentAnalyzer import * | ||
| #process.dump = EventContentAnalyzer() | ||
| #process.p = cms.Path(process.dump) | ||
|
|
||
| process.out = cms.OutputModule("AsciiOutputModule") | ||
| process.out = AsciiOutputModule() | ||
| process.e = cms.EndPath(process.out, cms.Task(process.getter)) | ||
|
|
||
| process.maxEvents.input = 1 | ||
|
|
||
| #process.add_(cms.Service("Tracer")) | ||
| #from FWCore.Services.modules import Tracer | ||
| #process.add_(Tracer()) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| import os | ||
| from os.path import sep, join | ||
| import importlib | ||
|
|
||
| class _ModuleProxy (object): | ||
| def __init__(self, package, name): | ||
| self._package = package | ||
| self._name = name | ||
| self._caller = None | ||
| def __call__(self,**kwargs): | ||
| if not self._caller: | ||
| self._caller = getattr(importlib.import_module(self._package+'.'+self._name),self._name) | ||
| return self._caller(**kwargs) | ||
|
|
||
|
|
||
| def _setupProxies(fullName): | ||
| _cmssw_package_name='.'.join(fullName.split(sep)[-3:-1]) | ||
| basename = fullName.split(sep)[-1] | ||
| pathname = fullName[:-1*len(basename)] | ||
| proxies = dict() | ||
| for filename in ( x for x in os.listdir(pathname) if (len(x) > 3 and x[-3:] == '.py' and x != basename and ((len(x) < 6) or (x[-6:] != 'cfi.py')))): | ||
| name = filename[:-3] | ||
| proxies[name] = _ModuleProxy(_cmssw_package_name, name) | ||
| return proxies |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -147,6 +147,54 @@ namespace edm { | |
| std::cref(baseType_), | ||
| std::cref(pluginName_), | ||
| std::ref(usedCfiFileNames))); | ||
| if (defaultDescDefined_) { | ||
| writeClassFile(defaultDesc_); | ||
| } else if (descriptions_.size() == 1) { | ||
| writeClassFile(descriptions_.begin()->second); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this mean if the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is correct. |
||
| } | ||
|
|
||
| void ConfigurationDescriptions::writeClassFile(ParameterSetDescription const& iDesc) const { | ||
| std::string pluginName = pluginName_; | ||
| auto found = pluginName.find("::"); | ||
| while (found != std::string::npos) { | ||
| pluginName.replace(found, 2, "_"); | ||
| found = pluginName.find("::"); | ||
| } | ||
| //Symbols that can appear in our plugin names but can't in python function names | ||
| const std::string toReplace("@<>,"); | ||
| found = pluginName.find_first_of(toReplace); | ||
| while (found != std::string::npos) { | ||
| pluginName.replace(found, 1, "_"); | ||
| found = pluginName.find_first_of(toReplace, found); | ||
| } | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IIUC this means that a plugin with a name
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is how the name would be modified. |
||
|
|
||
| std::string fileName = pluginName + ".py"; | ||
| std::ofstream outFile(fileName.c_str()); | ||
| if (outFile.fail()) { | ||
| edm::Exception ex(edm::errors::LogicError, "Creating class file failed.\n"); | ||
| ex << "Opening a file '" << fileName << "' failed.\n"; | ||
| ex << "Error code from errno " << errno << ": " << std::strerror(errno) << "\n"; | ||
|
|
||
| ex.addContext("Executing function ConfigurationDescriptions::writeDefault"); | ||
| throw ex; | ||
| } | ||
| outFile << "import FWCore.ParameterSet.Config as cms\n\n"; | ||
| outFile << "def " << pluginName | ||
| << "(**kwargs):\n" | ||
| " mod = cms." | ||
| << baseType_ << "('" << pluginName_ << "'"; | ||
|
|
||
| bool startWithComma = true; | ||
| int indentation = 4; | ||
| iDesc.writeCfi(outFile, startWithComma, indentation); | ||
|
|
||
| outFile << ")\n" | ||
| " for k,v in kwargs.items():\n" | ||
| " setattr(mod, k, v)\n" | ||
| " return mod\n"; | ||
|
|
||
| outFile.close(); | ||
| } | ||
|
|
||
| void ConfigurationDescriptions::writeCfiForLabel(std::pair<std::string, ParameterSetDescription> const& labelAndDesc, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -120,6 +120,9 @@ namespace edm { | |
|
|
||
| void ParameterDescriptionBase::writeCfi_( | ||
| std::ostream& os, bool optional, bool& startWithComma, int indentation, bool& wroteSomething) const { | ||
| if (label().empty() or label()[0] == '@') { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change was related to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes |
||
| return; | ||
| } | ||
| wroteSomething = true; | ||
| if (startWithComma) | ||
| os << ","; | ||
|
|
||
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 something I was thinking about ages ago, when I was spending too much of my time looking after the HLT configurations, and I'm glad to see it being implemented !
Looking at the example, the main concern I have is for
InputTags andVInputTags: writing or readingI think it's very easy to get confused about
getterandotherbeing two components on anInputTaginstead of two separateInputTags.Some other confusing exmples:
this is a
VInputTagwith only oneInputTag?this is a
VInputTagwith twoInputTags ?this is a
VInputTagwith twoInputTags ?this is a
VInputTagwith twoInputTags ?this is a
VInputTagwith twoInputTags ?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.
@fwyzard Thanks for the feedback! All the examples are already possible since this code just reuses what is already available. The reduced syntax can already be used in
E.g.
That being said, the reduced syntax also excepts the explicit type information as well
As for some of your explicit examples, I'm curious why you ask if the following are
VInputTagswith two entries, rather than (the correct) aVInputTagswith 1 entry.or even
which does require one to understand that
(...,)in python is just a way to express atuplewith a single entry.All the above are standard python for a container with 1 entry.
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.
These two cases could be interpreted as ambiguous for understanding the type of
labels(InputTagvsVInputTag) only from the assignment.The same syntax would work for
InputTag(with module and instance labels) and for 2-elementVInputTagThe same syntax would work for
InputTag(with module labels) and for 1-elementVInputTag.(for reference, the sequence-syntax for assining
InputTagwas added in #29992, #29846)