def execute(self): context = self.context if JvmToolMixin.get_registered_tools(): # Map of scope -> (map of key -> callback). callback_product_map = (context.products.get_data( 'jvm_build_tools_classpath_callbacks') or defaultdict(dict)) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task.ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for scope, key, main, custom_rules in JvmToolMixin.get_registered_tools( ): option = key.replace('-', '_') deplist = self.context.options.for_scope(scope)[option] callback_product_map[scope][ key] = self.cached_bootstrap_classpath_callback( key, scope, deplist, main=main, custom_rules=custom_rules) context.products.safe_create_data( 'jvm_build_tools_classpath_callbacks', lambda: callback_product_map)
def execute(self): registered_tools = JvmToolMixin.get_registered_tools() if registered_tools: # Map of scope -> (map of key -> callback). callback_product_map = self.context.products.get_data('jvm_build_tools_classpath_callbacks', init_func=lambda: defaultdict(dict)) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task._ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for jvm_tool in registered_tools: dep_spec = jvm_tool.dep_spec(self.context.options) callback = self.cached_bootstrap_classpath_callback(dep_spec, jvm_tool) callback_product_map[jvm_tool.scope][jvm_tool.key] = callback if self.get_options().eager: with self.context.new_workunit('eager'): for scope, callbacks_by_key in callback_product_map.items(): for key, callback in callbacks_by_key.items(): try: callback() except self.ToolUnderspecified: pass # We don't want to fail for placeholder registrations
def execute(self): registered_tools = JvmToolMixin.get_registered_tools() if registered_tools: # Map of scope -> (map of key -> callback). callback_product_map = self.context.products.get_data( "jvm_build_tools_classpath_callbacks", init_func=lambda: defaultdict(dict)) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task._ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for jvm_tool in registered_tools: dep_spec = jvm_tool.dep_spec(self.context.options) callback = self.cached_bootstrap_classpath_callback( dep_spec, jvm_tool) callback_product_map[jvm_tool.scope][jvm_tool.key] = callback if self.get_options().eager: with self.context.new_workunit("eager"): for scope, callbacks_by_key in callback_product_map.items( ): for key, callback in callbacks_by_key.items(): try: callback() except self.ToolUnderspecified: pass # We don't want to fail for placeholder registrations
def get_alternate_target_roots(cls, options, address_mapper, build_graph): processed = set() for jvm_tool in JvmToolMixin.get_registered_tools(): dep_spec = jvm_tool.dep_spec(options) dep_address = Address.parse(dep_spec) # Some JVM tools are requested multiple times, we only need to handle them once. if dep_address not in processed: processed.add(dep_address) try: if build_graph.resolve_address(dep_address): # The user has defined a tool classpath override - we let that stand. continue except AddressLookupError as e: if jvm_tool.classpath is None: raise cls._tool_resolve_error(e, dep_spec, jvm_tool) else: if not jvm_tool.is_default(options): # The user specified a target spec for this jvm tool that doesn't actually exist. # We want to error out here instead of just silently using the default option while # appearing to respect their config. raise cls.ToolResolveError(dedent(""" Failed to resolve target for tool: {tool}. This target was obtained from option {option} in scope {scope}. Make sure you didn't make a typo in the tool's address. You specified that the tool should use the target found at "{tool}". This target has a default classpath configured, so you can simply remove: [{scope}] {option}: {tool} from pants.ini (or any other config file) to use the default tool. The default classpath is: {default_classpath} Note that tool target addresses in pants.ini should be specified *without* quotes. """).strip().format(tool=dep_spec, option=jvm_tool.key, scope=jvm_tool.scope, default_classpath=':'.join(map(str, jvm_tool.classpath or ())))) if jvm_tool.classpath: tool_classpath_target = JarLibrary(name=dep_address.target_name, address=dep_address, build_graph=build_graph, jars=jvm_tool.classpath) else: # The tool classpath is empty by default, so we just inject a dummy target that # ivy resolves as the empty list classpath. JarLibrary won't do since it requires # one or more jars, so we just pick a target type ivy has no resolve work to do for. tool_classpath_target = Target(name=dep_address.target_name, address=dep_address, build_graph=build_graph) build_graph.inject_target(tool_classpath_target, synthetic=True) # We use the trick of not returning alternate roots, but instead just filling the dep_spec # holes with a JarLibrary built from a tool's default classpath JarDependency list if there is # no over-riding targets present. This means we do modify the build_graph, but we at least do # it at a time in the engine lifecycle cut out for handling that. return None
def _alternate_target_roots(cls, options, address_mapper, build_graph): processed = set() for jvm_tool in JvmToolMixin.get_registered_tools(): dep_spec = jvm_tool.dep_spec(options) dep_address = Address.parse(dep_spec) # Some JVM tools are requested multiple times, we only need to handle them once. if dep_address not in processed: processed.add(dep_address) try: if build_graph.resolve_address(dep_address): # The user has defined a tool classpath override - we let that stand. continue except AddressLookupError as e: if jvm_tool.classpath is None: raise cls._tool_resolve_error(e, dep_spec, jvm_tool) else: if not jvm_tool.is_default(options): # The user specified a target spec for this jvm tool that doesn't actually exist. # We want to error out here instead of just silently using the default option while # appearing to respect their config. raise cls.ToolResolveError(dedent(""" Failed to resolve target for tool: {tool}. This target was obtained from option {option} in scope {scope}. Make sure you didn't make a typo in the tool's address. You specified that the tool should use the target found at "{tool}". This target has a default classpath configured, so you can simply remove: [{scope}] {option}: {tool} from pants.ini (or any other config file) to use the default tool. The default classpath is: {default_classpath} Note that tool target addresses in pants.ini should be specified *without* quotes. """).strip().format(tool=dep_spec, option=jvm_tool.key, scope=jvm_tool.scope, default_classpath=':'.join(map(str, jvm_tool.classpath or ())))) if jvm_tool.classpath: tool_classpath_target = JarLibrary(name=dep_address.target_name, address=dep_address, build_graph=build_graph, jars=jvm_tool.classpath) else: # The tool classpath is empty by default, so we just inject a dummy target that # ivy resolves as the empty list classpath. JarLibrary won't do since it requires # one or more jars, so we just pick a target type ivy has no resolve work to do for. tool_classpath_target = Target(name=dep_address.target_name, address=dep_address, build_graph=build_graph) build_graph.inject_target(tool_classpath_target, synthetic=True) # We use the trick of not returning alternate roots, but instead just filling the dep_spec # holes with a JarLibrary built from a tool's default classpath JarDependency list if there is # no over-riding targets present. This means we do modify the build_graph, but we at least do # it at a time in the engine lifecycle cut out for handling that. return None
def execute(self): context = self.context if JvmToolMixin.get_registered_tools(): # Map of scope -> (map of key -> callback). callback_product_map = (context.products.get_data('jvm_build_tools_classpath_callbacks') or defaultdict(dict)) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task.ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for scope, key, main, custom_rules in JvmToolMixin.get_registered_tools(): option = key.replace('-', '_') deplist = self.context.options.for_scope(scope)[option] callback_product_map[scope][key] = self.cached_bootstrap_classpath_callback( key, scope, deplist, main=main, custom_rules=custom_rules) context.products.safe_create_data('jvm_build_tools_classpath_callbacks', lambda: callback_product_map)
def execute(self): registered_tools = JvmToolMixin.get_registered_tools() if registered_tools: # Map of scope -> (map of key -> callback). callback_product_map = self.context.products.get_data('jvm_build_tools_classpath_callbacks', init_func=lambda: defaultdict(dict)) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task._ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for jvm_tool in registered_tools: dep_spec = jvm_tool.dep_spec(self.context.options) callback = self.cached_bootstrap_classpath_callback(dep_spec, jvm_tool) callback_product_map[jvm_tool.scope][jvm_tool.key] = callback
def execute(self): registered_tools = JvmToolMixin.get_registered_tools() if registered_tools: # Map of scope -> (map of key -> callback). callback_product_map = self.context.products.get_data( "jvm_build_tools_classpath_callbacks", init_func=lambda: defaultdict(dict) ) # We leave a callback in the products map because we want these Ivy calls # to be done lazily (they might never actually get executed) and we want # to hit Task.invalidated (called in Task.ivy_resolve) on the instance of # BootstrapJvmTools rather than the instance of whatever class requires # the bootstrap tools. It would be awkward and possibly incorrect to call # self.invalidated twice on a Task that does meaningful invalidation on its # targets. -pl for jvm_tool in registered_tools: dep_spec = jvm_tool.dep_spec(self.context.options) callback = self.cached_bootstrap_classpath_callback(dep_spec, jvm_tool) callback_product_map[jvm_tool.scope][jvm_tool.key] = callback
def execute(self): registered_tools = JvmToolMixin.get_registered_tools() if registered_tools: # Map of scope -> (map of key -> callback). callback_product_map = self.context.products.get_data( "jvm_build_tools_classpath_callbacks", init_func=lambda: defaultdict(dict)) # We leave a callback in the products map because we want these resolver calls # to be done lazily (they might never actually get executed). for jvm_tool in registered_tools: dep_spec = jvm_tool.dep_spec(self.context.options) callback = self.cached_bootstrap_classpath_callback( dep_spec, jvm_tool) callback_product_map[jvm_tool.scope][jvm_tool.key] = callback if self.get_options().eager: with self.context.new_workunit("eager"): for scope, callbacks_by_key in callback_product_map.items( ): for key, callback in callbacks_by_key.items(): try: callback() except self.ToolUnderspecified: pass # We don't want to fail for placeholder registrations
def _alternate_target_roots(cls, options, address_mapper, build_graph): processed = set() for jvm_tool in JvmToolMixin.get_registered_tools(): dep_spec = jvm_tool.dep_spec(options) dep_address = Address.parse(dep_spec) # Some JVM tools are requested multiple times, we only need to handle them once. if dep_address not in processed: processed.add(dep_address) try: if build_graph.contains_address(dep_address) or address_mapper.resolve(dep_address): # The user has defined a tool classpath override - we let that stand. continue except AddressLookupError as e: if jvm_tool.classpath is None: raise cls._tool_resolve_error(e, dep_spec, jvm_tool) else: if jvm_tool.classpath: tool_classpath_target = JarLibrary( name=dep_address.target_name, address=dep_address, build_graph=build_graph, jars=jvm_tool.classpath, ) else: # The tool classpath is empty by default, so we just inject a dummy target that # ivy resolves as the empty list classpath. JarLibrary won't do since it requires # one or more jars, so we just pick a target type ivy has no resolve work to do for. tool_classpath_target = Target( name=dep_address.target_name, address=dep_address, build_graph=build_graph ) build_graph.inject_target(tool_classpath_target) # We use the trick of not returning alternate roots, but instead just filling the dep_spec # holes with a JarLibrary built from a tool's default classpath JarDependency list if there is # no over-riding targets present. This means we do modify the build_graph, but we at least do # it at a time in the engine lifecycle cut out for handling that. return None