def get_ep(self, group, name, dist=None): """ Get an entry point. :param group: the group name :param name: the entry point name :param dist: if not given, search in all dists if no dist was given, and the search turned up more than one entry point with the same name, returns a list of entrypoints else, returns an entry point """ if not dist: specs = [] for dist_name in self._epmap.keys(): spc = self.get_ep(group, name, dist=dist_name) if spc: specs.append(spc) if len(specs) > 1: return specs elif len(specs) == 1: return specs[0] else: distribution_map = self._epmap.get(dist, {}) group_map = distribution_map.get(group, {}) spec = group_map.get(name) if spec: return EntryPoint.parse(spec) return None
def get_dist_map(self, dist=None): """Return the entry map of a given distribution.""" if not dist: return self._epmap.copy() dmap = self._epmap.get(dist, {}).copy() for gname in dmap: for epname in dmap[gname]: dmap[gname][epname] = EntryPoint.parse(dmap[gname][epname]) return dmap
def iter_group(self, group): """ iterate over entry points within a given group """ from reentry.entrypoint import EntryPoint for dist in self.epmap: for _, entry_point_spec in six.iteritems(self.epmap[dist].get( group, {})): yield EntryPoint.parse(entry_point_spec)
def get_dist_map(self, dist): """ Return the entry map of a given distribution """ from reentry.entrypoint import EntryPoint dmap = self.epmap.get(dist, {}).copy() for gname in dmap: for epname in dmap[gname]: dmap[gname][epname] = EntryPoint.parse(dmap[gname][epname]) return dmap
def scan_install_dist(self, dist): """Add a distribution during it's install.""" distname = dist.get_name() entrypoint_map = {} dist_map = {} if hasattr(dist, 'entry_points'): dist_map = dist.entry_points or {} for group, entrypoint_list in dist_map.items(): entrypoint_map[group] = {} for entrypoint_string in entrypoint_list: entry_point = EntryPoint.parse(entrypoint_string) entrypoint_map[group][entry_point.name] = entrypoint_string return distname, entrypoint_map
def get_map(self, dist=None, group=None, name=None): """See BackendInterface docs.""" # sanitize dist kwarg dist_list = self._dist_list_from_arg(dist) # sanitize groups kwarg group_list = self._group_list_from_arg(group) # sanitize name kwarg name_list = _listify(name) filtered_entry_points = self._filter_entry_points(dist_list, group_list, name_list) entry_point_map = {} for entry_point, ep_info in six.iteritems(filtered_entry_points): if not ep_info['group'] in entry_point_map: entry_point_map[ep_info['group']] = {} entry_point_map[ep_info['group']][ep_info['name']] = EntryPoint.parse(entry_point) return entry_point_map
def iter_group(self, group): """Iterate over entry points within a given group.""" for dist in self._epmap: for _, entry_point_spec in six.iteritems(self._epmap[dist].get( group, {})): yield EntryPoint.parse(entry_point_spec)
def infer_calculation_entry_point(type_strings): """Try to infer a calculation entry point name for all the calculation type strings that are found in the database. Before the plugin system was introduced, the `type` column of the node table was a string based on the base node type with the module path and class name appended. For example, for the `PwCalculation` class, which was a sub class of `JobCalculation`, would get `calculation.job.quantumespresso.pw.PwCalculation.` as its `type` string. At this point, the `JobCalculation` also still fullfilled the role of both the `Process` class as well as the `Node` class. In the migration for `v1.0.0`, this had to be migrated, where the `type` became that of the actual node i.e. `node.process.calculation.calcjob.CalcJobNode.` which would lose the information of which actual sub class it represented. This information should be stored in the `process_type` column, where the value is the name of the entry point of that calculation class. This function will, for a given set of calculation type strings of pre v1.0.0, try to map them on the known entry points for the calculation category. This is the union of those entry points registered at the AiiDA registry (see the mapping above) and those available in the environment in which this function is ran. If a type string cannot be mapped onto an entry point name, a fallback `process_type` string will be generated which is based on part of the old `type` string. For example, `calculation.job.unknown.UnknownCalculation.` would get the process type string `~unknown.UnknownCalculation`. The function will return a mapping of type strings onto their inferred process type strings. :param type_strings: a set of type strings whose entry point is to be inferred :return: a mapping of current node type string to the inferred entry point name """ from reentry.entrypoint import EntryPoint from aiida.plugins.entry_point import get_entry_points prefix_calc_job = 'calculation.job.' entry_point_group = 'aiida.calculations' entry_point_names = [] mapping_node_type_to_entry_point = {} # Build the list of known entry points, joining those present in the environment with the hard-coded set from taken # from the aiida-registry. Note that if entry points with the same name are found in both sets, the entry point # from the local environment is kept as leading. entry_points_local = get_entry_points(group=entry_point_group) entry_points_registry = [EntryPoint.parse(entry_point) for entry_point in registered_calculation_entry_points] entry_points = entry_points_local entry_point_names = [entry_point.name for entry_point in entry_points] for entry_point in entry_points_registry: if entry_point.name not in entry_point_names: entry_point_names.append(entry_point.name) for type_string in type_strings: # If it does not start with the calculation job prefix, it cannot possibly reference a calculation plugin if not type_string.startswith(prefix_calc_job): continue plugin_string = type_string[len(prefix_calc_job):] plugin_parts = [part for part in plugin_string.split('.') if part] plugin_class = plugin_parts.pop() inferred_entry_point_name = '.'.join(plugin_parts) if inferred_entry_point_name in entry_point_names: entry_point_string = '{entry_point_group}:{entry_point_name}'.format( entry_point_group=entry_point_group, entry_point_name=inferred_entry_point_name ) elif inferred_entry_point_name: entry_point_string = '{plugin_name}.{plugin_class}'.format( plugin_name=inferred_entry_point_name, plugin_class=plugin_class ) else: # If there is no inferred entry point name, i.e. there is no module name, use an empty string as fall back # This should only be the case for the type string `calculation.job.JobCalculation.` entry_point_string = '' mapping_node_type_to_entry_point[type_string] = entry_point_string return mapping_node_type_to_entry_point