def merge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate( self.layout.hidden_file_paths, ignore) # check for dir conflicts conflicts = tree.find_dir_conflicts(view_dst, ignore_file) merge_map = tree.get_file_map(view_dst, ignore_file) if not self.ignore_conflicts: conflicts.extend(pkg.view_file_conflicts(self, merge_map)) if conflicts: raise MergeConflictError(conflicts[0]) # merge directories with the tree tree.merge_directories(view_dst, ignore_file) pkg.add_files_to_view(self, merge_map)
def remove_files_from_view(self, view, merge_map): ignore_namespace = False if self.py_namespace: ext_map = view.extensions_layout.extension_map(self.extendee_spec) remaining_namespaces = set(spec.package.py_namespace for name, spec in ext_map.items() if name != self.name) if self.py_namespace in remaining_namespaces: namespace_init = match_predicate( r'site-packages/{0}/__init__.py'.format(self.py_namespace)) ignore_namespace = True bin_dir = self.spec.prefix.bin global_view = ( self.extendee_spec.prefix == view.get_projection_for_spec( self.spec)) to_remove = [] for src, dst in merge_map.items(): if ignore_namespace and namespace_init(dst): continue if global_view or not path_contains_subdirectory(src, bin_dir): to_remove.append(dst) else: os.remove(dst) view.remove_files(to_remove)
def test_match_predicate(): matcher = match_predicate(lambda x: True) assert matcher('foo') assert matcher('bar') assert matcher('baz') matcher = match_predicate(['foo', 'bar']) assert matcher('foo') assert matcher('bar') assert not matcher('baz') matcher = match_predicate(r'^(foo|bar)$') assert matcher('foo') assert matcher('bar') assert not matcher('baz') with pytest.raises(ValueError): matcher = match_predicate(object()) matcher('foo')
def perl_ignore(self, ext_pkg, args): """Add some ignore files to activate/deactivate args.""" ignore_arg = args.get('ignore', lambda f: False) # Many perl packages describe themselves in a perllocal.pod file, # so the files conflict when multiple packages are activated. # We could merge the perllocal.pod files in activated packages, # but this is unnecessary for correct operation of perl. # For simplicity, we simply ignore all perllocal.pod files: patterns = [r'perllocal\.pod$'] return match_predicate(ignore_arg, patterns)
def unmerge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate(self.layout.hidden_file_regexes, ignore) merge_map = tree.get_file_map(view_dst, ignore_file) pkg.remove_files_from_view(self, merge_map) # now unmerge the directory tree tree.unmerge_directories(view_dst, ignore_file)
def python_ignore(self, ext_pkg, args): """Add some ignore files to activate/deactivate args.""" ignore_arg = args.get('ignore', lambda f: False) # Always ignore easy-install.pth, as it needs to be merged. patterns = [r'easy-install\.pth$'] # Ignore pieces of setuptools installed by other packages. if ext_pkg.name != 'py-setuptools': patterns.append(r'/site[^/]*\.pyc?$') patterns.append(r'setuptools\.pth') patterns.append(r'bin/easy_install[^/]*$') patterns.append(r'setuptools.*egg$') return match_predicate(ignore_arg, patterns)
def unmerge(self, spec, ignore=None): pkg = spec.package view_source = pkg.view_source() view_dst = pkg.view_destination(self) tree = LinkTree(view_source) ignore = ignore or (lambda f: False) ignore_file = match_predicate( self.layout.hidden_file_paths, ignore) merge_map = tree.get_file_map(view_dst, ignore_file) pkg.remove_files_from_view(self, merge_map) # now unmerge the directory tree tree.unmerge_directories(view_dst, ignore_file)
def view_file_conflicts(self, view, merge_map): """Report all file conflicts, excepting special cases for python. Specifically, this does not report errors for duplicate __init__.py files for packages in the same namespace. """ conflicts = list(dst for src, dst in merge_map.items() if os.path.exists(dst)) if conflicts and self.py_namespace: ext_map = view.extensions_layout.extension_map(self.extendee_spec) namespaces = set(x.package.py_namespace for x in ext_map.values()) namespace_re = (r'site-packages/{0}/__init__.py'.format( self.py_namespace)) find_namespace = match_predicate(namespace_re) if self.py_namespace in namespaces: conflicts = list(x for x in conflicts if not find_namespace(x)) return conflicts
def view_file_conflicts(self, view, merge_map): """Report all file conflicts, excepting special cases for python. Specifically, this does not report errors for duplicate __init__.py files for packages in the same namespace. """ conflicts = list(dst for src, dst in merge_map.items() if os.path.exists(dst)) if conflicts and self.py_namespace: ext_map = view.extensions_layout.extension_map(self.extendee_spec) namespaces = set( x.package.py_namespace for x in ext_map.values()) namespace_re = ( r'site-packages/{0}/__init__.py'.format(self.py_namespace)) find_namespace = match_predicate(namespace_re) if self.py_namespace in namespaces: conflicts = list( x for x in conflicts if not find_namespace(x)) return conflicts
def remove_files_from_view(self, view, merge_map): ignore_namespace = False if self.py_namespace: ext_map = view.extensions_layout.extension_map(self.extendee_spec) remaining_namespaces = set( spec.package.py_namespace for name, spec in ext_map.items() if name != self.name) if self.py_namespace in remaining_namespaces: namespace_init = match_predicate( r'site-packages/{0}/__init__.py'.format(self.py_namespace)) ignore_namespace = True bin_dir = self.spec.prefix.bin global_view = self.extendee_spec.prefix == view.root for src, dst in merge_map.items(): if ignore_namespace and namespace_init(dst): continue if global_view or not path_contains_subdirectory(src, bin_dir): view.remove_file(src, dst) else: os.remove(dst)
def python_ignore(self, ext_pkg, args): """Add some ignore files to activate/deactivate args.""" ignore_arg = args.get('ignore', lambda f: False) # Always ignore easy-install.pth, as it needs to be merged. patterns = [r'site-packages/easy-install\.pth$'] # Ignore pieces of setuptools installed by other packages. # Must include directory name or it will remove all site*.py files. if ext_pkg.name != 'py-setuptools': patterns.extend([ r'bin/easy_install[^/]*$', r'site-packages/setuptools[^/]*\.egg$', r'site-packages/setuptools\.pth$', r'site-packages/site[^/]*\.pyc?$', r'site-packages/__pycache__/site[^/]*\.pyc?$' ]) if ext_pkg.name != 'py-pygments': patterns.append(r'bin/pygmentize$') if ext_pkg.name != 'py-numpy': patterns.append(r'bin/f2py[0-9.]*$') return match_predicate(ignore_arg, patterns)
def python_ignore(self, ext_pkg, args): """Add some ignore files to activate/deactivate args.""" ignore_arg = args.get('ignore', lambda f: False) # Always ignore easy-install.pth, as it needs to be merged. patterns = [r'site-packages/easy-install\.pth$'] # Ignore pieces of setuptools installed by other packages. # Must include directory name or it will remove all site*.py files. if ext_pkg.name != 'py-setuptools': patterns.extend([ r'bin/easy_install[^/]*$', r'site-packages/setuptools[^/]*\.egg$', r'site-packages/setuptools\.pth$', r'site-packages/site[^/]*\.pyc?$', r'site-packages/__pycache__/site[^/]*\.pyc?$' ]) if ext_pkg.name != 'py-pygments': patterns.append(r'bin/pygmentize$') if ext_pkg.name != 'py-numpy': patterns.append(r'bin/f2py3?$') return match_predicate(ignore_arg, patterns)