Beispiel #1
0
def push(ctx, force, draft):
    output.showCommandHeader('push', ctx)

    try:
        config_file_data = config_file.readRaw()

        if 'push' not in config_file_data['app']:
            click.echo(
                'In order to Push you need to have a push configuration set in your config file'
            )
            return
    except config_file.ApplangaConfigFileNotValidException as e:
        click.secho('There was a problem with the config file:\n%s\n' % str(e),
                    err=True,
                    fg='red')
        return

    try:
        file_responses = api.uploadFiles(
            config_file_data['app']['push']['source'],
            force=force,
            draft=draft,
            debug=ctx.obj['DEBUG'])
    except api.ApplangaRequestException as e:
        click.secho('There was a problem with pushing files:\n%s\n' % str(e),
                    err=True,
                    fg='red')
        return

    if len(file_responses) == 0:
        click.secho('No file to upload got found.', err=True, fg='red')

    for upload_data in file_responses:
        language = upload_data[
            'language'] if 'language' in upload_data else 'language missing'
        click.echo('\nUpload   :  %s\nLanguage :  %s' %
                   (upload_data['path'], language))
        click.echo('=' * 60)

        if 'error' in upload_data:
            # There was a problem with the import
            click.echo('Result: "Error"')
            click.secho('There was a problem with importing file:\n%s\n' %
                        upload_data['error'],
                        err=True,
                        fg='red')
            continue

        # Import was successful
        response_json = upload_data['response'].json()
        click.echo(
            'Result: "Success"\n\n - Entries in file: %d\n - Added:           %d\n - Updated:         %d\n - Tag updates:     %d\n'
            % (response_json['total'], response_json['added'],
               response_json['updated'], response_json['tagUpdates']))
Beispiel #2
0
def makeRequest(data={},
                api_path=None,
                access_token=None,
                upload_file=None,
                method='GET',
                debug=False,
                base_path=constants.API_BASE_PATH):
    """Makes a request to Applanga API.

    Args:
        data: Data to send to API.
        api_path: Path to append to API URL.
        access_token: The access token to use.
        upload_file: File to upload with request.
        method: Request method to use.
        debug: Display debug output.
        base_url: Api base path if specified will overwrite default '/v1/api'

    Returns:
        API response

    """

    config_file_data = None
    if access_token is None:
        # No access_token given so try to get from config file and stop when
        # nothing gets returned
        try:
            config_file_data = config_file.readRaw()
        except config_file.ApplangaConfigFileNotValidException as e:
            raise ApplangaRequestException(str(e))

        access_token = config_file_data['app']['access_token']

    if not access_token:
        if not config_file_data:
            raise ApplangaRequestException('Access token is missing')

    # App id is part of access token. Extract it to additionally also send
    # separate as parameter as needed by API.
    app_id = access_token.split('!')[0]

    headers = {
        'Authorization': 'Bearer ' + access_token,
        'CLI-Version': constants.VERSION_NUMBER
    }

    url = constants.APPLANGA_HOST

    env_api_base_url = os.environ.get('APPLANGA_API_HOST')

    if env_api_base_url:
        url = env_api_base_url

    url = url + base_path

    if api_path is not None:
        url += api_path

    data['app'] = app_id

    if debug:
        click.secho('\nStart request:', fg=constants.DEBUG_TEXT_COLOR)
        click.secho('  URL: %s' % (url), fg=constants.DEBUG_TEXT_COLOR)
        click.secho('  Method: %s' % (method), fg=constants.DEBUG_TEXT_COLOR)
        click.secho('  Headers: %s' % (headers), fg=constants.DEBUG_TEXT_COLOR)
        click.secho('  Data: %s' % (data), fg=constants.DEBUG_TEXT_COLOR)

    if method == 'GET':
        try:
            response = requests.get(url, params=data, headers=headers)
        except requests.exceptions.ConnectionError as e:
            raise ApplangaRequestException(
                'Problem connecting to server. Please check your internet connection.'
            )
    else:
        if upload_file:
            try:
                with open(upload_file, 'rb') as upload_file_content:
                    try:
                        response = requests.post(
                            url,
                            params=data,
                            headers=headers,
                            files={upload_file: upload_file_content})
                    except requests.exceptions.ConnectionError as e:
                        raise ApplangaRequestException(
                            'Problem connecting to server. Please check your internet connection.'
                        )

            except IOError as e:
                click.echo(e)
                raise ApplangaRequestException(
                    'Problem with accessing file to upload. The file does probably not exist or there are problems with the access rights.'
                )

        else:
            response = requests.post(url, params=data, headers=headers)

    if debug:
        click.secho('\nRequest response: %s' % response.text,
                    fg=constants.DEBUG_TEXT_COLOR)
        click.secho('  Status code: %s' % (response.status_code),
                    fg=constants.DEBUG_TEXT_COLOR)

    if response.status_code != 200:
        # Request was not successful so raise exception
        exception_text = response.text

        try:
            response_data = response.json()
            if 'message' in response_data:
                # There is a message so return it
                exception_text = response_data['message']
        except ValueError as e:
            exception_text = response.text

        raise ApplangaRequestException('API response: ' + exception_text)

    # Request was successful so return
    return response
Beispiel #3
0
def pull(ctx):
    output.showCommandHeader('pull', ctx)

    try:
        config_file_data = config_file.readRaw()

        if 'pull' not in config_file_data['app']:
            click.echo(
                'In order to Pull you need to have a pull configuration set in your config file'
            )
            return
    except config_file.ApplangaConfigFileNotValidException as e:
        click.secho('There was a problem with the config file:\n%s\n' % str(e),
                    err=True,
                    fg='red')
        return

    all_app_languages = []
    for target in config_file_data['app']['pull']['target']:
        if 'language' not in target:
            if '<language>' not in target['path']:
                # If also no placeholder is defined then there is no need to
                # query languages from API
                continue

            try:
                all_app_languages = api.getAllAppLanguages(
                    debug=ctx.obj['DEBUG'])
            except api.ApplangaRequestException as e:
                click.echo('Result: "Error"')
                click.secho(
                    'There was a problem getting the app languages:\n%s\n' %
                    str(e),
                    err=True,
                    fg='red')
                return

            break

    request_languages = []
    for target in config_file_data['app']['pull']['target']:

        if 'language' in target:
            # Language is defined in config
            request_languages = [target['language']]
        elif '<language>' in target['path']:
            # Language placeholder is defined in path so download all languages
            request_languages = list(all_app_languages)
        else:
            # No language defined so error
            click.echo('\nDownload :  %s\nLanguage :  %s' %
                       (target['path'], 'missing'))
            click.echo('=' * 60)
            click.echo('Result: "Error"')
            click.secho(
                'You either need to use the <language> wildcard inside the path string or set it explicitly per file via the "language" property. \nFor more informations and examples on how todo that please refer to the Applanga CLI Integration Documentation.\n',
                err=True,
                fg='red')
            continue

        # Remove all the languages on the exclude list
        exclude_languages = []
        if 'exclude_languages' in target:
            exclude_languages = target['exclude_languages']

        request_languages = [
            x for x in request_languages if x not in exclude_languages
        ]

        # Go through all the languages that should be downloaded
        for language in request_languages:
            target['language'] = language

            click.echo('\nDownload :  %s\nLanguage :  %s' %
                       (target['path'], language))
            click.echo('=' * 60)

            try:
                file_written = api.downloadFile(target, debug=ctx.obj['DEBUG'])
                click.echo('Result: "Success"')
                click.echo('Wrote file: %s' % file_written)

            except api.ApplangaRequestException as e:
                click.echo('Result: "Error"')
                click.secho(
                    'There was a problem with downloading file:\n%s\n' %
                    str(e),
                    err=True,
                    fg='red')
                return
Beispiel #4
0
def downloadFile(file_data, debug=False):
    """Downloads file from Applanga.

    Args:
        file_data: Data about the files to download.
        debug: Display debug output.

    Returns:
        Path of file which got downloaded

    """

    # Make sure it contains all the data that is needed
    if 'language' not in file_data:
        raise ApplangaRequestException(
            'Request is incomplete. The language is missing.')
    if 'file_format' not in file_data:
        raise ApplangaRequestException(
            'Request is incomplete. The file_format is missing.')
    if 'path' not in file_data:
        raise ApplangaRequestException(
            'Request is incomplete. The path is missing.')

    request_options = {}
    request_options['exportOnlyWithTranslation'] = True

    if 'export_empty' in file_data:
        if file_data['export_empty'] == True:
            request_options['exportOnlyWithTranslation'] = False

    if 'convert_placeholder' in file_data:
        if file_data['convert_placeholder'] == True:
            request_options['convertPlaceholder'] = True

    if 'ignore_duplicates' in file_data:
        request_options[
            'ignoreDuplicates'] = file_data['ignore_duplicates'] is True

    if file_data['file_format'] in [
            'nested_json', 'react_nested_json', 'ruby_on_rails_yaml',
            'symfony_yaml', 'symfony2_yaml', 'ember_i18n_json_module',
            'node_2_json', 'go_i18n_json'
    ] and 'disable_plurals' in file_data:
        request_options[
            'disablePlurals'] = file_data['disable_plurals'] is True

    if 'includeMetadata' in file_data:
        request_options['includeMetadata'] = file_data['includeMetadata']

    if 'includeInvisibleId' in file_data:
        request_options['includeInvisibleId'] = file_data['includeInvisibleId']

    try:
        # Request the file from server
        request_data = {
            'file-format': file_data['file_format'],
            'language': file_data['language'],
            'options': json.dumps(request_options)
        }
        if 'tag' in file_data:
            request_data['tag'] = file_data['tag']

        response = makeRequest(data=request_data,
                               api_path='/files',
                               debug=debug)

    except ApplangaRequestException as e:
        raise ApplangaRequestException(str(e))

    language = file_data['language']

    language_ = language.replace('-', '_')
    if 'android_xml' == file_data['file_format'] and len(language) == 5:
        language = language.replace('-', '-r')

    if 'arb' == file_data['file_format'] and len(language) >= 5:
        language = language_

    try:
        config_file_data = config_file.readRaw()
        languageMapping = config_file_data['languageMap']
        if languageMapping[language]:
            language = languageMapping[language]
    except Exception as e:
        pass

    #if we detect a language folder with an _ locale but non with - we store the files int the _ folder
    file_path = file_data['path'].replace('<language>', language)
    file_path_ = file_data['path'].replace('<language>', language_)
    if not os.path.exists(os.path.dirname(file_path)) and os.path.exists(
            os.path.dirname(file_path_)):
        file_path = file_path_

    try:
        # Makes sure that the directory we want to write into exists
        if not os.path.exists(os.path.dirname(file_path)):
            try:
                os.makedirs(os.path.dirname(file_path))
            except OSError as e:
                if e.errno != os.errno.EEXIST:
                    raise

        open(file_path, 'wb').write(response.content)
        return file_path
    except FileNotFoundError as e:
        raise ApplangaRequestException('Could not write file "%s": %s' %
                                       (file_path, str(e)))
Beispiel #5
0
def getFiles(source):
    """Looks and retruns files which match path in given source block.

    Args:
        source: The source block dictionary with path property.

    Returns:
        The found files with language and skipped ones for which no language could be found.

    """

    return_files = {}
    skipped_files = []

    path = source['path']

    source_language = None
    language_regex_path = None
    search_path = path
    uses_placeholder = False

    if 'language' in source:
        # Language is given as parameter
        source_language = source['language']
    else:
        # Language is in path
        search_path = path.replace('<language>', '*')
        language_regex_path = re.escape(path).replace(r'\*', '.*').replace(
            re.escape('<language>'), r'([a-zA-Z]{2}([\-\_][a-zA-Z]{2,4})?)')
        uses_placeholder = True

    files = glob2.glob(search_path)

    # Go through all matched files of the current source block and add them
    # according to their language
    for file in files:
        file_language = None

        if language_regex_path:
            # If a regex is defined try to get language from path
            file_match = re.search(language_regex_path, file)
            if file_match and len(file_match.groups()):
                file_language = file_match.group(1)

        if not file_language:
            # If no language got found in path use the one from source
            # block if defined
            file_language = source_language

        if file_language:
            try:
                config_file_data = config_file.readRaw()
                reversedDir = dict(
                    map(reversed, config_file_data['languageMap'].items()))
                file_language = reversedDir[file_language]
            except (config_file.ApplangaConfigFileNotValidException,
                    KeyError) as e:
                pass

            # Make sure the language name is in the correct format
            file_language = convertLanguageName(file_language)

            if file_language == None:
                skipped_files.append(file)
                continue

            # Remove all the languages on the exclude list
            if 'exclude_languages' in source:
                if file_language in source['exclude_languages']:
                    continue

            return_files[file] = {'language': file_language}

            # Add other properties which got defined for file
            if 'tag' in source:
                return_files[file]['tag'] = source['tag']
            if 'file_format' in source:
                return_files[file]['file_format'] = source['file_format']

            if 'disable_plurals' in source:
                return_files[file]['disable_plurals'] = source[
                    'disable_plurals']

    return {
        'skipped': skipped_files,
        'found': return_files,
        'uses_placeholder': uses_placeholder
    }