def project_config(cwd): """Returns a path for the googkit.cfg that is project config file. Raise a GoogkitError if the project config file is not found. See also: googkit.lib.Config#load() """ proj_root = project_root(cwd) if proj_root is None: raise GoogkitError('Project directory is not found.') project_config = os.path.join(proj_root, PROJECT_CONFIG) if not os.path.exists(project_config): raise GoogkitError('Project config file is not found.') return project_config
def load(tree): """Loads googkit plugins to the specified instance of CommandTree. """ base_dir = googkit.lib.path.plugin() for filename in os.listdir(base_dir): plugin_dir = os.path.join(base_dir, filename) if not os.path.isdir(plugin_dir): continue init_path = os.path.join(plugin_dir, INIT_FILE) if not os.path.exists(init_path): continue command_path = os.path.join(plugin_dir, COMMAND_FILE) if not os.path.exists(command_path): continue module_name = 'plugins.{filename}.command'.format(filename=filename) module = __import__(module_name, fromlist=['command']) if not hasattr(module, 'register'): raise GoogkitError( _('No register method found for plugin: {module}').format( module=module_name)) module.register(tree)
def download_closure_compiler(self): """Downloads Closure Compiler resources to the compiler root that defined in a config file. """ tmp_path = tempfile.mkdtemp() compiler_zip = os.path.join(tmp_path, 'compiler.zip') compiler_zip_url = self.config.compiler_zip() logging.info(_('Downloading Closure Compiler...')) try: request.urlretrieve(compiler_zip_url, compiler_zip) except IOError as e: raise GoogkitError( _('Dowloading Closure Compiler failed: {message}').format( massage=str(e))) compiler_root = self.config.compiler_root() os.path.join('tools', 'sub', 'unzip.py') with zipfile.ZipFile(compiler_zip) as z: z.extractall(compiler_root) shutil.rmtree(tmp_path) logging.info(_('Done.'))
def plugin(): """Returns a path for the plugin directory. Raise a GoogkitError if the plugin directory is not found. """ plugin_dir = os.path.join(googkit_root(), SCRIPT_DIR, PLUGIN_DIR) if not os.path.isdir(plugin_dir): msg = 'Plugins directory is not found: {path}'.format(path=plugin_dir) raise GoogkitError(msg) return plugin_dir
def locale(): """Returns a path for the locale directory has localized messages. Raise a GoogkitError if the locale directory is not found. """ locale_dir = os.path.join(googkit_root(), LOCALE_DIR) if not os.path.isdir(locale_dir): msg = 'Locale directory is not found: {path}'.format(path=locale_dir) raise GoogkitError(msg) return locale_dir
def _load_config(self): default_config = googkit.lib.path.default_config() user_config = googkit.lib.path.user_config() project_config = googkit.lib.path.project_config(self.env.cwd) if project_config is None: raise GoogkitError(_('No config file found.')) config = Config() config.load(project_config, user_config, default_config) return config
def default_config(): """Returns a path for the default project config file. Raise a GoogkitError if the default config file is not found. See also: googkit.lib.Config#load() """ path = os.path.join(googkit_root(), DEFAULT_CONFIG) if not os.path.exists(path): msg = 'Default config file is not found: {path}'.format(path=path) raise GoogkitError(msg) return path
def copy_template(self, dst_dir): """Copy template files (include default googkit.cfg, demonstration files) to the specified directory. """ template_dir = googkit.lib.path.template() conflicted = set(os.listdir(dst_dir)) & set(os.listdir(template_dir)) if conflicted: raise GoogkitError( _('Conflicted files: {files}').format( files=', '.join(conflicted))) distutils.dir_util.copy_tree(template_dir, dst_dir)
def template(): """Returns a path for the project template directory. The template directory should be created when a project is initialised, and it should have demonstration files. Raise a GoogkitError if the template directory is not found. """ template_dir = os.path.join(googkit_root(), TEMPLATE_DIR) if not os.path.isdir(template_dir): msg = 'Template directory is not found: {path}'.format( path=template_dir) raise GoogkitError(msg) return template_dir
def _clone(repos, target_path): # git-clone on Windows expected unix-like path args = [_git_cmd(), 'clone', repos, request.pathname2url(target_path)] popen_args = { 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, } proc = subprocess.Popen(args, **popen_args) result = proc.communicate() if proc.returncode != 0: raise GoogkitError(_('Git clone failed: {message}').format( message=result[1].decode())) logging.debug(result[0].decode())
def _pull(repos, target_path): args = [_git_cmd(), 'pull'] popen_args = { 'cwd': target_path, 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, } proc = subprocess.Popen(args, **popen_args) result = proc.communicate() if proc.returncode != 0: raise GoogkitError(_('Git pull failed: {message}').format( message=result[1].decode())) logging.debug(result[0].decode())
def download_closure_library(self): """Downloads Closure Library resources to the library root that defined in a config file. """ library_repos = self.config.library_repos() library_root = self.config.library_root() logging.info(_('Downloading Closure Library...')) try: googkit.lib.clone.run(library_repos, library_root) except GoogkitError as e: raise GoogkitError( _('Dowloading Closure Library failed: {message}').format( message=str(e))) logging.info('Done.')
def _build(self, builder_args, project_root): builder = self.config.closurebuilder() cmd = ['python', builder] + [str(arg) for arg in builder_args] popen_args = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE} builder_proc = subprocess.Popen(cmd, **popen_args) result = builder_proc.communicate() if builder_proc.returncode != 0: raise GoogkitError( _('Compilation failed:\n{message}').format( message=result[1].decode())) else: logging.debug(result[1].decode())
def update_deps(self): """Updates module dependencies by using depswriter.py. """ config = self.config js_dev_dir = config.js_dev_dir() deps_js = config.deps_js() base_js_dir = os.path.dirname(config.base_js()) js_dev_dir_rel = os.path.relpath(js_dev_dir, base_js_dir) args_format = { 'deps_js': deps_js, 'js_dev': js_dev_dir, 'js_dev_rel': js_dev_dir_rel, } args = [ 'python', config.depswriter(), '--root_with_prefix="{js_dev} {js_dev_rel}"'.format(**args_format), '--output_file="{deps_js}"'.format(**args_format) ] popen_args = { 'shell': True, 'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE, } # depswriter.py doesn't work with arguments including white-space. # For example, # it works: # # $ python depswriter.py --root_with_prefix="path path" # # but it doesn't work: # # $ python depswriter.py "--root_with_prefix=\"path path\"" proc = subprocess.Popen(' '.join(args), **popen_args) result = proc.communicate() if proc.returncode != 0: raise GoogkitError( _('Updating dependencies failed: {message}').format( message=result[1].decode())) logging.debug('Updated ' + deps_js)
def lint(self): """Lints project resouces by using Closure Linter. """ if googkit.lib.file.which('gjslint') is None: raise GoogkitError(_('Required command not found: gjslint')) paths = self._sources() args = OptionBuilder() flagfile = self.config.linter_flagfile() if os.path.exists(flagfile): args.add('--flagfile', flagfile) cmd = ['gjslint'] + [str(arg) for arg in args] + paths popen_args = {'stdout': subprocess.PIPE, 'stderr': subprocess.PIPE} proc = subprocess.Popen(cmd, **popen_args) result = proc.communicate() logging.info(result[0].decode())
def test_run_with_exception(self): MockCmd = mock.MagicMock() MockCmd.needs_project_config.return_value = False mock_cmd = MockCmd.return_value mock_cmd.run.side_effect = GoogkitError('DUMMY') with mock.patch('os.chdir'), \ mock.patch('sys.argv', new=['/DUMMY.py', 'dummy1', 'dummy2']), \ mock.patch('sys.stdout'), \ mock.patch('googkit.lib.path.project_root', return_value='/dir1/dir2'), \ mock.patch('googkit.Help'), \ mock.patch('googkit.Environment', return_value='dummy_env'), \ mock.patch('googkit.CommandTree') as MockTree, \ mock.patch('googkit.lib.plugin.load'), \ mock.patch('logging.basicConfig') as mock_basic_cfg, \ mock.patch('logging.error') as mock_error: MockTree.return_value.command_class.return_value = MockCmd with self.assertRaises(SystemExit): googkit.main() mock_basic_cfg.assert_called_once_with(level=logging.INFO, format='%(message)s') self.assertTrue(mock_error.called)
def test_init(self): message = 'Yeah' error = GoogkitError(message) self.assertTrue(isinstance(error, Exception)) self.assertEqual(str(error), message)