Source code for vsgen.project

# -*- coding: utf-8 -*-
"""
This module provides the neccessary defintions to support a base project file defintion.
"""

import os
import fnmatch
import itertools
import uuid


[docs]class VSGProject(object): """ VSGProject encapsulates the data and logic needed to act as a base project. :ivar uuid GUID: The GUID of the project; if not provided one is generated automatically. :ivar str FileName: The absolute filename of the project file; if not provided the value is "" :ivar str Name: The display name of the project; if not provide the value is "". :ivar str WorkingDirectory: The absolute directory that will be the working directory of the project; if not provide the value is "" :ivar str OutputPath: The absolute directory that will be the output directory of the project; if not provide the value is "". :ivar str RootNamespace: The name of the root namespace of the project; if not provide the value is "". `Ignored`. :ivar str ProjectHome: The absolute directory of the project's source root folder; if not provide the value is "" :ivar str StartupFile: The absolute path to the Startup file; if not provide the value is "" :ivar list CompileFiles: The list of absolute files that will comprise the projects compile group; if not provide the value is []. :ivar list ContentFiles: The list of absolute files that will comprise the projects content group; if not provide the value is []. :ivar list Directories: The list of absolute directories that will comprise the projects directory group; if not provide the value is []. :ivar list DirectoryInFilter: A list of fnmatch expressions to match directories to be included during the item generation step; if not provided the value is []. :ivar list DirectoryExFilter: A list of fnmatch expressions to match directories to be excludes during the item generation step; if not provided the value is []. :ivar list CompileInFilter: A list of fnmatch expressions to match compile files to be included during the item generation step; if not provide the value is []. :ivar list CompileExFilter: A list of fnmatch expressions to match compile files to be excluded during the item generation step; if not provide the value is []. :ivar list ContentInFilter: A list of fnmatch expressions to match content files to be included during the item generation step; if not provide the value is []. :ivar list ContentExFilter: A list of fnmatch expressions to match content files to be excluded during the item generation step; if not provide the value is []. :ivar float VSVersion: The Visual Studio version; if not provide the value is ``None``. """ __project_type__ = None def __init__(self, **kwargs): """ Constructor. :param kwargs: List of arbitrary keyworded arguments to be processed as instance variable data """ super(VSGProject, self).__init__() self._import(kwargs) def _import(self, datadict): """ Internal method to import instance variables data from a dictionary :param dict datadict: The dictionary containing variables values. """ self.GUID = datadict.get("GUID", uuid.uuid1()) self.FileName = datadict.get("FileName", "") self.Name = datadict.get("Name", "") self.WorkingDirectory = datadict.get("WorkingDirectory", "") self.OutputPath = datadict.get("OutputPath", "") self.RootNamespace = datadict.get("RootNamespace", "") self.ProjectHome = datadict.get("ProjectHome", "") self.StartupFile = datadict.get("StartupFile", "") self.CompileFiles = datadict.get("CompileFiles", []) self.ContentFiles = datadict.get("ContentFiles", []) self.Directories = datadict.get("Directories", []) self.DirectoryInFilter = datadict.get("DirectoryInFilter", []) self.DirectoryExFilter = datadict.get("DirectoryExFilter", []) self.CompileInFilter = datadict.get("CompileInFilter", []) self.CompileExFilter = datadict.get("CompileExFilter", []) self.ContentInFilter = datadict.get("ContentInFilter", []) self.ContentExFilter = datadict.get("ContentExFilter", []) self.VSVersion = datadict.get("VSVersion", None)
[docs] @classmethod def from_section(cls, config, section, **kwargs): """ Creates a :class:`~vsgen.project.VSGProject` from a :class:`~configparser.ConfigParser` section. :param ConfigParser config: A :class:`~configparser.ConfigParser` instance. :param str section: A :class:`~configparser.ConfigParser` section key. :param kwargs: List of additional keyworded arguments to be passed into the :class:`~vsgen.project.VSGProject`. :return: A valid :class:`~vsgen.project.VSGProject` instance if succesful; None otherwise. """ p = cls(**kwargs) p.Name = config.get(section, 'name', fallback=p.Name) p.FileName = config.getfile(section, 'filename', fallback=p.FileName) p.SearchPath = config.getdirs(section, 'search_path', fallback=p.SearchPath) p.OutputPath = config.getdir(section, 'output_path', fallback=p.OutputPath) p.WorkingDirectory = config.getdir(section, 'working_directory', fallback=p.WorkingDirectory) p.RootNamespace = config.get(section, 'root_namespace', fallback=p.RootNamespace) p.ProjectHome = config.getdir(section, 'project_home', fallback=p.ProjectHome) p.StartupFile = config.getfile(section, 'startup_file', fallback=p.StartupFile) p.CompileFiles = config.getlist(section, 'compile_files', fallback=p.CompileFiles) p.ContentFiles = config.getlist(section, 'content_files', fallback=p.ContentFiles) p.CompileInFilter = config.getlist(section, 'compile_in_filter', fallback=p.CompileInFilter) p.CompileExFilter = config.getlist(section, 'compile_ex_filter', fallback=p.CompileExFilter) p.ContentInFilter = config.getlist(section, 'content_in_filter', fallback=p.ContentInFilter) p.ContentExFilter = config.getlist(section, 'content_ex_filter', fallback=p.ContentExFilter) p.DirectoryInFilter = config.getlist(section, 'directory_in_filter', fallback=p.DirectoryInFilter) p.DirectoryExFilter = config.getlist(section, 'directory_ex_filter', fallback=p.DirectoryExFilter) root_path = config.get(section, 'root_path', fallback="") p.insert_files(root_path) return p
@property def ProjectHomeRelative(self): """ Returns the :attr:`ProjectHome` relative to :attr:`FileName` directory. """ return os.path.relpath(self.ProjectHome, os.path.dirname(self.FileName)) @property def StartupFileRelative(self): """ Returns the :attr:`StartupFile` relative to :attr:`ProjectHome` directory. """ return os.path.relpath(self.StartupFile, self.ProjectHome) if self.StartupFile else self.StartupFile @property def WorkingDirectoryRelative(self): """ Returns the :attr:`WorkingDirectory` relative to :attr:`ProjectHome` directory. """ return os.path.relpath(self.WorkingDirectory, self.ProjectHome) @property def OutputPathRelative(self): """ Returns the :attr:`OutputPath` relative to :attr:`ProjectHome` directory. """ return os.path.relpath(self.OutputPath, self.ProjectHome) @property def ContentFilesRelative(self): """ Returns a generator iterating over the each file in :attr:`ContentFiles` relative to :attr:`ProjectHome` directory. """ return (os.path.relpath(path, self.ProjectHome) for path in sorted(self.ContentFiles, key=self.lower)) @property def CompileFilesRelative(self): """ Returns a generator iterating over the each file in :attr:`ContentFiles` relative to :attr:`ProjectHome` directory. """ return (os.path.relpath(path, self.ProjectHome) for path in sorted(self.CompileFiles, key=self.lower)) @property def DirectoriesRelative(self): """ Returns a generator iterating over the each directory referenced by the project, relative to :attr:`ProjectHome` directory. """ # Acquire all directories directories = itertools.chain(self.Directories, (os.path.dirname(f) for f in itertools.chain(self.ContentFiles, self.CompileFiles))) directories = set(os.path.relpath(d, self.ProjectHome) for d in directories) # We need separate entries for parent directories of directories in the list for path in set(directories): subpath = os.path.dirname(path) while subpath: directories.add(subpath) subpath = os.path.dirname(subpath) return sorted(directories)
[docs] def insert_files(self, rootpath, directoryInFilter=None, directoryExFilter=None, compileInFilter=None, compileExFilter=None, contentInFilter=None, contentExFilter=None): """ Inserts files by recursive traversing the rootpath and inserting files according the addition filter parameters. :param str rootpath: The absolute path to the root directory. :param list directoryInFilter: A list of fnmatch expressions to match directories to be included. A `None` value will default to :attr:`DirectoryInFilter`. :param list directoryExFilter: A list of fnmatch expressions to match directories to be excluded. A `None` value will default to :attr:`DirectoryExFilter`. :param list compileInFilter: A list of fnmatch expressions to match compile files to be included. A `None` value will default to :attr:`CompileInFilter`. :param list compileExFilter: A list of fnmatch expressions to match compile files to be excludes. A `None` value will default to :attr:`CompileExFilter`. :param list contentInFilter: A list of fnmatch expressions to match content files to be includes. A `None` value will default to :attr:`ContentInFilter`. :param list contentExFilter: A list of fnmatch expressions to match content files to be excludes. A `None` value will default to :attr:`ContentExFilter`. """ # Overrides directoryInFilter = self.DirectoryInFilter if directoryInFilter is None else directoryInFilter directoryExFilter = self.DirectoryExFilter if directoryExFilter is None else directoryExFilter compileInFilter = self.CompileInFilter if compileInFilter is None else compileInFilter compileExFilter = self.CompileExFilter if compileExFilter is None else compileExFilter contentInFilter = self.ContentInFilter if contentInFilter is None else contentInFilter contentExFilter = self.ContentExFilter if contentExFilter is None else contentExFilter def filter(text, filters, explicit): """ Convience filter function :param text text: The target text. :param list filters: The collection of fnmatch expressions :param bool explicit: Flag denoting an the empty filter collection return match failure. """ if explicit: return any(fnmatch.fnmatch(text, f) for f in filters) return not filters or any(fnmatch.fnmatch(text, f) for f in filters) for root, dirnames, filenames in os.walk(rootpath): searchdir = os.path.normpath(os.path.normcase(root)) # If the root dir matches an excluded directory, stop any further searches if filter(searchdir, directoryExFilter, True): dirnames[:] = [] elif filter(searchdir, directoryInFilter, False): for filepath in [os.path.join(root, filename) for filename in filenames]: if filter(filepath, compileInFilter, False) and not filter(filepath, compileExFilter, True): self.CompileFiles.append(filepath) elif filter(filepath, contentInFilter, False) and not filter(filepath, contentExFilter, True): self.ContentFiles.append(filepath)