# -*- coding: ascii -*- # # Copyright 2007, 2008, 2009, 2010, 2011 # Andr\xe9 Malo or his licensors, as applicable # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. """ =================== Data distribution =================== This module provides tools to simplify data distribution. """ __author__ = u"Andr\xe9 Malo" __docformat__ = "restructuredtext en" from distutils import filelist as _filelist import os as _os import posixpath as _posixpath import sys as _sys from _setup import commands as _commands def splitpath(path): """ Split a path """ drive, path = '', _os.path.normpath(path) try: splitunc = _os.path.splitunc except AttributeError: pass else: drive, path = splitunc(path) if not drive: drive, path = _os.path.splitdrive(path) elems = [] try: sep = _os.path.sep except AttributeError: sep = _os.path.join('1', '2')[1:-1] while 1: prefix, path = _os.path.split(path) elems.append(path) if prefix in ('', sep): drive = _os.path.join(drive, prefix) break path = prefix elems.reverse() return drive, elems def finalizer(installer): """ Finalize install_data """ data_files = [] for item in installer.data_files: if not isinstance(item, Data): data_files.append(item) continue data_files.extend(item.flatten(installer)) installer.data_files = data_files class Data(object): """ File list container """ def __init__(self, files, target=None, preserve=0, strip=0, prefix=None): """ Initialization """ self._files = files self._target = target self._preserve = preserve self._strip = strip self._prefix = prefix self.fixup_commands() def fixup_commands(self): pass def from_templates(cls, *templates, **kwargs): """ Initialize from template """ files = _filelist.FileList() for tpl in templates: for line in tpl.split(';'): files.process_template_line(line.strip()) files.sort() files.remove_duplicates() result = [] for filename in files.files: _, elems = splitpath(filename) if '.svn' in elems or '.git' in elems: continue result.append(filename) return cls(result, **kwargs) from_templates = classmethod(from_templates) def flatten(self, installer): """ Flatten the file list to (target, file) tuples """ # pylint: disable = W0613 if self._prefix: _, prefix = splitpath(self._prefix) telems = prefix else: telems = [] tmap = {} for fname in self._files: (_, name), target = splitpath(fname), telems if self._preserve: if self._strip: name = name[max(0, min(self._strip, len(name) - 1)):] if len(name) > 1: target = telems + name[:-1] tmap.setdefault(_posixpath.join(*target), []).append(fname) return tmap.items() class Documentation(Data): """ Documentation container """ def fixup_commands(self): _commands.add_option('install_data', 'without-docs', help_text='Do not install documentation files', inherit='install', ) _commands.add_finalizer('install_data', 'documentation', finalizer) def flatten(self, installer): """ Check if docs should be installed at all """ if installer.without_docs: return [] return Data.flatten(self, installer) class Manpages(Documentation): """ Manpages container """ def dispatch(cls, files): """ Automatically dispatch manpages to their target directories """ mpmap = {} for manpage in files: normalized = _os.path.normpath(manpage) _, ext = _os.path.splitext(normalized) if ext.startswith(_os.path.extsep): ext = ext[len(_os.path.extsep):] mpmap.setdefault(ext, []).append(manpage) return [cls(manpages, prefix=_posixpath.join( 'share', 'man', 'man%s' % section, )) for section, manpages in mpmap.items()] dispatch = classmethod(dispatch) def flatten(self, installer): """ Check if manpages are suitable """ if _sys.platform == 'win32': return [] return Documentation.flatten(self, installer)