def _get_python3_reqs(reqs): """Filters out the reqs that are less than our minimum version.""" results = [] for req in reqs: if not req.markers: results.append(req) else: req_markers = markers.Marker(req.markers) if req_markers.evaluate({ 'python_version': MIN_PY_VERSION, }): results.append(req) return results
def _find_constraint(req, constraints): """Return the constraint matching the markers for req. Given a requirement, find the constraint with matching markers. If none match, find a constraint without any markers at all. Otherwise return None. """ if req.markers: req_markers = markers.Marker(req.markers) for constraint_setting, _ in constraints: if constraint_setting.markers == req.markers: return constraint_setting if not constraint_setting.markers: # There is no point in performing the complex # comparison for a constraint that has no markers, so # we skip it here. If we find no closer match then the # loop at the end of the function will look for a # constraint without a marker and use that. continue # NOTE(dhellmann): This is a very naive attempt to check # marker compatibility that relies on internal # implementation details of the packaging library. The # best way to ensure the constraint and requirements match # is to use the same marker string in the corresponding # lines. c_markers = markers.Marker(constraint_setting.markers) env = { str(var): str(val) for var, op, val in c_markers._markers # WARNING: internals } if req_markers.evaluate(env): return constraint_setting # Try looking for a constraint without any markers. for constraint_setting, _ in constraints: if not constraint_setting.markers: return constraint_setting return None
def collect_extensions(parent='.') -> Iterator[WinExt]: """Collect all directories that contain a 'module.yml' recursively. The 'include' directory of each module is added by default to the include path, and 'include' directories from other extensions are added to the include path if they are listed in the 'modules' """ # This is somewhat confusing, because the 'modules' key in the yaml # files specifies the dependencies for that module, the the 'modules' # variable contains the actual module configurations. modules = {} dependencies = {} build_order = ('.i', '.mc', '.rc', '.cpp') for dir in find_directories(parent): yml = os.path.join(parent, dir, 'module.yml') with open(yml) as fh: cfg = yaml.load(fh) if yml is None: raise ValueError('Invalid configuration file') name = dir.replace(os.sep, '.') modules[name] = cfg # Module configuration dependencies[name] = set(cfg.setdefault('modules', [])) # Module dependencies external_modules = [] for name in toposort_flatten(dependencies): src = os.path.join(parent, name.replace('.', os.sep), 'src') sources = [] try: files = os.listdir(src) except FileNotFoundError: external_modules += [ name ] # Add this to external_modules for later generation continue for item in build_order: # Add all sources present in the 'src' directory for fname in files: if fname.endswith(item): sources.append(os.path.join(src, fname)) include_dirs = [] f = set() q = deque([name]) i = 0 # Simple dependency resolver algorithm: while q: i += 1 assert i < 500 # To avoid infinite loop dep = q.popleft().replace('.', os.sep) # Take one module include_dirs.extend([ # Add the include directories os.path.join(parent, dep, 'src'), os.path.join(parent, dep, 'include') ]) f.add(dep.replace(os.sep, '.')) # Add the module's dependencies to the set q.extend([d for d in dependencies[name] if d not in f ]) # Queue modules not already in the set for processing cfg = modules[name] del cfg['modules'] # Remove the 'modules' (depenencies) key # If the cfg has environment_markers, then parse it # NOTE: currently does not support removing dependencies if 'environment_markers' in cfg: marker = markers.Marker(cfg['environment_markers']) if not marker.evaluate(): print('skipping: {} due to environment failure'.format(name)) continue else: del cfg['environment_markers'] if sys.version_info < (3, 5): cfg.setdefault('extra_link_args', []).append(get_link_arg()) with suppress(KeyError): for i, depend in enumerate(cfg['depends']): cfg['depends'][i] = os.path.join(name, 'include', depend) for config_option in ['export_symbol_file', 'pch_header']: with suppress(KeyError): cfg[config_option] = os.path.join( name.replace('.', os.sep), 'include', cfg[config_option]) build_temp_library_dirs = set( [os.path.join(os.path.dirname(d), 'src') for d in include_dirs]) cfg.setdefault('libraries', []).extend( set([ get_implib_basename(os.path.dirname(d)) for d in include_dirs[2:] ])) yield WinExt( name, sources=sources, include_dirs=copy(include_dirs), external_modules=copy(external_modules), build_temp_library_dirs=list(build_temp_library_dirs), **cfg) print('collected: {}'.format(name))
def marker(self): """Return environment marker.""" if not self._marker: assert markers, 'Package packaging is needed for environment markers' self._marker = markers.Marker(self.raw) return self._marker