X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/b2711d07638204cb78be7e7a54e265d816ae31ac..5274191c1e165a615645a4c10c8ca0220d347a3b:/third_party/transifex-client/txclib/commands.py?ds=sidebyside diff --git a/third_party/transifex-client/txclib/commands.py b/third_party/transifex-client/txclib/commands.py deleted file mode 100644 index 282287fc..00000000 --- a/third_party/transifex-client/txclib/commands.py +++ /dev/null @@ -1,576 +0,0 @@ -# -*- coding: utf-8 -*- -""" -In this file we have all the top level commands for the transifex client. -Since we're using a way to automatically list them and execute them, when -adding code to this file you must take care of the following: - * Added functions must begin with 'cmd_' followed by the actual name of the - command being used in the command line (eg cmd_init) - * The description for each function that we display to the user is read from - the func_doc attribute which reads the doc string. So, when adding - docstring to a new function make sure you add an oneliner which is - descriptive and is meant to be seen by the user. - * When including libraries, it's best if you include modules instead of - functions because that way our function resolution will work faster and the - chances of overlapping are minimal - * All functions should use the OptionParser and should have a usage and - descripition field. -""" -import os -import re, shutil -import sys -from optparse import OptionParser, OptionGroup -import ConfigParser - - -from txclib import utils, project -from txclib.utils import parse_json, compile_json, relpath -from txclib.config import OrderedRawConfigParser -from txclib.exceptions import UnInitializedError -from txclib.parsers import delete_parser, help_parser, parse_csv_option, \ - status_parser, pull_parser, set_parser, push_parser, init_parser -from txclib.log import logger - - -def cmd_init(argv, path_to_tx): - "Initialize a new transifex project." - parser = init_parser() - (options, args) = parser.parse_args(argv) - if len(args) > 1: - parser.error("Too many arguments were provided. Aborting...") - if args: - path_to_tx = args[0] - else: - path_to_tx = os.getcwd() - - if os.path.isdir(os.path.join(path_to_tx,".tx")): - logger.info("tx: There is already a tx folder!") - reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ") - while (reinit != 'y' and reinit != 'Y' and reinit != 'N' and reinit != 'n' and reinit != ''): - reinit = raw_input("Do you want to delete it and reinit the project? [y/N]: ") - if not reinit or reinit in ['N', 'n', 'NO', 'no', 'No']: - return - # Clean the old settings - # FIXME: take a backup - else: - rm_dir = os.path.join(path_to_tx, ".tx") - shutil.rmtree(rm_dir) - - logger.info("Creating .tx folder...") - os.mkdir(os.path.join(path_to_tx,".tx")) - - # Handle the credentials through transifexrc - home = os.path.expanduser("~") - txrc = os.path.join(home, ".transifexrc") - config = OrderedRawConfigParser() - - default_transifex = "https://www.transifex.com" - transifex_host = options.host or raw_input("Transifex instance [%s]: " % default_transifex) - - if not transifex_host: - transifex_host = default_transifex - if not transifex_host.startswith(('http://', 'https://')): - transifex_host = 'https://' + transifex_host - - config_file = os.path.join(path_to_tx, ".tx", "config") - if not os.path.exists(config_file): - # The path to the config file (.tx/config) - logger.info("Creating skeleton...") - config = OrderedRawConfigParser() - config.add_section('main') - config.set('main', 'host', transifex_host) - # Touch the file if it doesn't exist - logger.info("Creating config file...") - fh = open(config_file, 'w') - config.write(fh) - fh.close() - - prj = project.Project(path_to_tx) - prj.getset_host_credentials(transifex_host, user=options.user, - password=options.password) - prj.save() - logger.info("Done.") - - -def cmd_set(argv, path_to_tx): - "Add local or remote files under transifex" - parser = set_parser() - (options, args) = parser.parse_args(argv) - - # Implement options/args checks - # TODO !!!!!!! - if options.local: - try: - expression = args[0] - except IndexError: - parser.error("Please specify an expression.") - if not options.resource: - parser.error("Please specify a resource") - if not options.source_language: - parser.error("Please specify a source language.") - if not '' in expression: - parser.error("The expression you have provided is not valid.") - if not utils.valid_slug(options.resource): - parser.error("Invalid resource slug. The format is "\ - ". and the valid characters include [_-\w].") - _auto_local(path_to_tx, options.resource, - source_language=options.source_language, - expression = expression, source_file=options.source_file, - execute=options.execute, regex=False) - if options.execute: - _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx) - _set_mode(options.resource, options.mode, path_to_tx) - _set_type(options.resource, options.i18n_type, path_to_tx) - return - - if options.remote: - try: - url = args[0] - except IndexError: - parser.error("Please specify an remote url") - _auto_remote(path_to_tx, url) - _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx) - _set_mode(options.resource, options.mode, path_to_tx) - return - - if options.is_source: - resource = options.resource - if not resource: - parser.error("You must specify a resource name with the" - " -r|--resource flag.") - - lang = options.language - if not lang: - parser.error("Please specify a source language.") - - if len(args) != 1: - parser.error("Please specify a file.") - - if not utils.valid_slug(resource): - parser.error("Invalid resource slug. The format is "\ - ". and the valid characters include [_-\w].") - - file = args[0] - # Calculate relative path - path_to_file = relpath(file, path_to_tx) - _set_source_file(path_to_tx, resource, options.language, path_to_file) - elif options.resource or options.language: - resource = options.resource - lang = options.language - - if len(args) != 1: - parser.error("Please specify a file") - - # Calculate relative path - path_to_file = relpath(args[0], path_to_tx) - - try: - _go_to_dir(path_to_tx) - except UnInitializedError, e: - utils.logger.error(e) - return - - if not utils.valid_slug(resource): - parser.error("Invalid resource slug. The format is "\ - ". and the valid characters include [_-\w].") - _set_translation(path_to_tx, resource, lang, path_to_file) - - _set_mode(options.resource, options.mode, path_to_tx) - _set_type(options.resource, options.i18n_type, path_to_tx) - _set_minimum_perc(options.resource, options.minimum_perc, path_to_tx) - - logger.info("Done.") - return - - -def _auto_local(path_to_tx, resource, source_language, expression, execute=False, - source_file=None, regex=False): - """Auto configure local project.""" - # The path everything will be relative to - curpath = os.path.abspath(os.curdir) - - # Force expr to be a valid regex expr (escaped) but keep intact - expr_re = utils.regex_from_filefilter(expression, curpath) - expr_rec = re.compile(expr_re) - - if not execute: - logger.info("Only printing the commands which will be run if the " - "--execute switch is specified.") - - # First, let's construct a dictionary of all matching files. - # Note: Only the last matching file of a language will be stored. - translation_files = {} - for root, dirs, files in os.walk(curpath): - for f in files: - f_path = os.path.abspath(os.path.join(root, f)) - match = expr_rec.match(f_path) - if match: - lang = match.group(1) - f_path = os.path.abspath(f_path) - if lang == source_language and not source_file: - source_file = f_path - else: - translation_files[lang] = f_path - - if not source_file: - raise Exception("Could not find a source language file. Please run" - " set --source manually and then re-run this command or provide" - " the source file with the -s flag.") - if execute: - logger.info("Updating source for resource %s ( %s -> %s )." % (resource, - source_language, relpath(source_file, path_to_tx))) - _set_source_file(path_to_tx, resource, source_language, - relpath(source_file, path_to_tx)) - else: - logger.info('\ntx set --source -r %(res)s -l %(lang)s %(file)s\n' % { - 'res': resource, - 'lang': source_language, - 'file': relpath(source_file, curpath)}) - - prj = project.Project(path_to_tx) - root_dir = os.path.abspath(path_to_tx) - - if execute: - try: - prj.config.get("%s" % resource, "source_file") - except ConfigParser.NoSectionError: - raise Exception("No resource with slug \"%s\" was found.\nRun 'tx set --auto" - "-local -r %s \"expression\"' to do the initial configuration." % resource) - - # Now let's handle the translation files. - if execute: - logger.info("Updating file expression for resource %s ( %s )." % (resource, - expression)) - # Eval file_filter relative to root dir - file_filter = relpath(os.path.join(curpath, expression), - path_to_tx) - prj.config.set("%s" % resource, "file_filter", file_filter) - else: - for (lang, f_path) in sorted(translation_files.items()): - logger.info('tx set -r %(res)s -l %(lang)s %(file)s' % { - 'res': resource, - 'lang': lang, - 'file': relpath(f_path, curpath)}) - - if execute: - prj.save() - - -def _auto_remote(path_to_tx, url): - """ - Initialize a remote release/project/resource to the current directory. - """ - logger.info("Auto configuring local project from remote URL...") - - type, vars = utils.parse_tx_url(url) - prj = project.Project(path_to_tx) - username, password = prj.getset_host_credentials(vars['hostname']) - - if type == 'project': - logger.info("Getting details for project %s" % vars['project']) - proj_info = utils.get_details('project_details', - username, password, - hostname = vars['hostname'], project = vars['project']) - resources = [ '.'.join([vars['project'], r['slug']]) for r in proj_info['resources'] ] - logger.info("%s resources found. Configuring..." % len(resources)) - elif type == 'release': - logger.info("Getting details for release %s" % vars['release']) - rel_info = utils.get_details('release_details', - username, password, hostname = vars['hostname'], - project = vars['project'], release = vars['release']) - resources = [] - for r in rel_info['resources']: - if r.has_key('project'): - resources.append('.'.join([r['project']['slug'], r['slug']])) - else: - resources.append('.'.join([vars['project'], r['slug']])) - logger.info("%s resources found. Configuring..." % len(resources)) - elif type == 'resource': - logger.info("Getting details for resource %s" % vars['resource']) - resources = [ '.'.join([vars['project'], vars['resource']]) ] - else: - raise("Url '%s' is not recognized." % url) - - for resource in resources: - logger.info("Configuring resource %s." % resource) - proj, res = resource.split('.') - res_info = utils.get_details('resource_details', - username, password, hostname = vars['hostname'], - project = proj, resource=res) - try: - source_lang = res_info['source_language_code'] - i18n_type = res_info['i18n_type'] - except KeyError: - raise Exception("Remote server seems to be running an unsupported version" - " of Transifex. Either update your server software of fallback" - " to a previous version of transifex-client.") - prj.set_remote_resource( - resource=resource, - host = vars['hostname'], - source_lang = source_lang, - i18n_type = i18n_type) - - prj.save() - - -def cmd_push(argv, path_to_tx): - "Push local files to remote server" - parser = push_parser() - (options, args) = parser.parse_args(argv) - force_creation = options.force_creation - languages = parse_csv_option(options.languages) - resources = parse_csv_option(options.resources) - skip = options.skip_errors - prj = project.Project(path_to_tx) - if not (options.push_source or options.push_translations): - parser.error("You need to specify at least one of the -s|--source," - " -t|--translations flags with the push command.") - - prj.push( - force=force_creation, resources=resources, languages=languages, - skip=skip, source=options.push_source, - translations=options.push_translations, - no_interactive=options.no_interactive - ) - logger.info("Done.") - - -def cmd_pull(argv, path_to_tx): - "Pull files from remote server to local repository" - parser = pull_parser() - (options, args) = parser.parse_args(argv) - if options.fetchall and options.languages: - parser.error("You can't user a language filter along with the"\ - " -a|--all option") - languages = parse_csv_option(options.languages) - resources = parse_csv_option(options.resources) - skip = options.skip_errors - minimum_perc = options.minimum_perc or None - - try: - _go_to_dir(path_to_tx) - except UnInitializedError, e: - utils.logger.error(e) - return - - # instantiate the project.Project - prj = project.Project(path_to_tx) - prj.pull( - languages=languages, resources=resources, overwrite=options.overwrite, - fetchall=options.fetchall, fetchsource=options.fetchsource, - force=options.force, skip=skip, minimum_perc=minimum_perc, - mode=options.mode - ) - logger.info("Done.") - - -def _set_source_file(path_to_tx, resource, lang, path_to_file): - """Reusable method to set source file.""" - proj, res = resource.split('.') - if not proj or not res: - raise Exception("\"%s.%s\" is not a valid resource identifier. It should" - " be in the following format project_slug.resource_slug." % - (proj, res)) - if not lang: - raise Exception("You haven't specified a source language.") - - try: - _go_to_dir(path_to_tx) - except UnInitializedError, e: - utils.logger.error(e) - return - - if not os.path.exists(path_to_file): - raise Exception("tx: File ( %s ) does not exist." % - os.path.join(path_to_tx, path_to_file)) - - # instantiate the project.Project - prj = project.Project(path_to_tx) - root_dir = os.path.abspath(path_to_tx) - - if root_dir not in os.path.normpath(os.path.abspath(path_to_file)): - raise Exception("File must be under the project root directory.") - - logger.info("Setting source file for resource %s.%s ( %s -> %s )." % ( - proj, res, lang, path_to_file)) - - path_to_file = relpath(path_to_file, root_dir) - - prj = project.Project(path_to_tx) - - # FIXME: Check also if the path to source file already exists. - try: - try: - prj.config.get("%s.%s" % (proj, res), "source_file") - except ConfigParser.NoSectionError: - prj.config.add_section("%s.%s" % (proj, res)) - except ConfigParser.NoOptionError: - pass - finally: - prj.config.set("%s.%s" % (proj, res), "source_file", - path_to_file) - prj.config.set("%s.%s" % (proj, res), "source_lang", - lang) - - prj.save() - - -def _set_translation(path_to_tx, resource, lang, path_to_file): - """Reusable method to set translation file.""" - - proj, res = resource.split('.') - if not project or not resource: - raise Exception("\"%s\" is not a valid resource identifier. It should" - " be in the following format project_slug.resource_slug." % - resource) - - try: - _go_to_dir(path_to_tx) - except UnInitializedError, e: - utils.logger.error(e) - return - - # Warn the user if the file doesn't exist - if not os.path.exists(path_to_file): - logger.info("Warning: File '%s' doesn't exist." % path_to_file) - - # instantiate the project.Project - prj = project.Project(path_to_tx) - root_dir = os.path.abspath(path_to_tx) - - if root_dir not in os.path.normpath(os.path.abspath(path_to_file)): - raise Exception("File must be under the project root directory.") - - if lang == prj.config.get("%s.%s" % (proj, res), "source_lang"): - raise Exception("tx: You cannot set translation file for the source language." - " Source languages contain the strings which will be translated!") - - logger.info("Updating translations for resource %s ( %s -> %s )." % (resource, - lang, path_to_file)) - path_to_file = relpath(path_to_file, root_dir) - prj.config.set("%s.%s" % (proj, res), "trans.%s" % lang, - path_to_file) - - prj.save() - - -def cmd_status(argv, path_to_tx): - "Print status of current project" - parser = status_parser() - (options, args) = parser.parse_args(argv) - resources = parse_csv_option(options.resources) - prj = project.Project(path_to_tx) - resources = prj.get_chosen_resources(resources) - resources_num = len(resources) - for idx, res in enumerate(resources): - p, r = res.split('.') - logger.info("%s -> %s (%s of %s)" % (p, r, idx + 1, resources_num)) - logger.info("Translation Files:") - slang = prj.get_resource_option(res, 'source_lang') - sfile = prj.get_resource_option(res, 'source_file') or "N/A" - lang_map = prj.get_resource_lang_mapping(res) - logger.info(" - %s: %s (%s)" % (utils.color_text(slang, "RED"), - sfile, utils.color_text("source", "YELLOW"))) - files = prj.get_resource_files(res) - fkeys = files.keys() - fkeys.sort() - for lang in fkeys: - local_lang = lang - if lang in lang_map.values(): - local_lang = lang_map.flip[lang] - logger.info(" - %s: %s" % (utils.color_text(local_lang, "RED"), - files[lang])) - logger.info("") - - -def cmd_help(argv, path_to_tx): - """List all available commands""" - parser = help_parser() - (options, args) = parser.parse_args(argv) - if len(args) > 1: - parser.error("Multiple arguments received. Exiting...") - - # Get all commands - fns = utils.discover_commands() - - # Print help for specific command - if len(args) == 1: - try: - fns[argv[0]](['--help'], path_to_tx) - except KeyError: - utils.logger.error("Command %s not found" % argv[0]) - # or print summary of all commands - - # the code below will only be executed if the KeyError exception is thrown - # becuase in all other cases the function called with --help will exit - # instead of return here - keys = fns.keys() - keys.sort() - - logger.info("Transifex command line client.\n") - logger.info("Available commands are:") - for key in keys: - logger.info(" %-15s\t%s" % (key, fns[key].func_doc)) - logger.info("\nFor more information run %s command --help" % sys.argv[0]) - - -def cmd_delete(argv, path_to_tx): - "Delete an accessible resource or translation in a remote server." - parser = delete_parser() - (options, args) = parser.parse_args(argv) - languages = parse_csv_option(options.languages) - resources = parse_csv_option(options.resources) - skip = options.skip_errors - force = options.force_delete - prj = project.Project(path_to_tx) - prj.delete(resources, languages, skip, force) - logger.info("Done.") - - -def _go_to_dir(path): - """Change the current working directory to the directory specified as - argument. - - Args: - path: The path to chdor to. - Raises: - UnInitializedError, in case the directory has not been initialized. - """ - if path is None: - raise UnInitializedError( - "Directory has not been initialzied. " - "Did you forget to run 'tx init' first?" - ) - os.chdir(path) - - -def _set_minimum_perc(resource, value, path_to_tx): - """Set the minimum percentage in the .tx/config file.""" - args = (resource, 'minimum_perc', value, path_to_tx, 'set_min_perc') - _set_project_option(*args) - - -def _set_mode(resource, value, path_to_tx): - """Set the mode in the .tx/config file.""" - args = (resource, 'mode', value, path_to_tx, 'set_default_mode') - _set_project_option(*args) - - -def _set_type(resource, value, path_to_tx): - """Set the i18n type in the .tx/config file.""" - args = (resource, 'type', value, path_to_tx, 'set_i18n_type') - _set_project_option(*args) - - -def _set_project_option(resource, name, value, path_to_tx, func_name): - """Save the option to the project config file.""" - if value is None: - return - if not resource: - logger.debug("Setting the %s for all resources." % name) - resources = [] - else: - logger.debug("Setting the %s for resource %s." % (name, resource)) - resources = [resource, ] - prj = project.Project(path_to_tx) - getattr(prj, func_name)(resources, value) - prj.save()