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']))
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
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
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)))
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 }