def make_request(method, host, url, username, password, fields=None): if host.lower().startswith('https://'): connection = urllib3.connection_from_url(host, cert_reqs=ssl.CERT_REQUIRED, ca_certs=certs_file()) else: connection = urllib3.connection_from_url(host) headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format( username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True) r = None try: r = connection.request(method, url, headers=headers, fields=fields) data = r.data charset = determine_charset(r) if isinstance(data, bytes): data = data.decode(charset) if r.status < 200 or r.status >= 400: if r.status == 404: raise HttpNotFound(data) else: raise Exception(data) return data, charset except SSLError: logger.error("Invalid SSL certificate") raise finally: if not r is None: r.close()
def _delete_resource(self, project_details, resource, stats, *args): """Delete a resource from Transifex.""" project_slug, resource_slug = resource.split('.') project_resource_slugs = [ r['slug'] for r in project_details['resources'] ] logger.info("Deleting resource %s:" % resource) if resource_slug not in project_resource_slugs: if not self.skip: msg = "Skipping: %s : Resource does not exist." logger.info(msg % resource) return if not self.force: slang = self.get_resource_option(resource, 'source_lang') for language in stats: if language == slang: continue if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping: %s : Unable to delete resource because it " "has a not empty %s translation.\nPlease use -f or " "--force option to delete this resource.") logger.info(msg % (resource, language)) return try: self.do_url_request('delete_resource', method="DELETE") self.config.remove_section(resource) self.save() msg = "Deleted resource %s of project %s." logger.info(msg % (resource_slug, project_slug)) except Exception, e: msg = "Unable to delete resource %s of project %s." logger.error(msg % (resource_slug, project_slug)) if not self.skip: raise
def get_details(api_call, username, password, *args, **kwargs): """ Get the tx project info through the API. This function can also be used to check the existence of a project. """ url = (API_URLS[api_call] % (kwargs)).encode('UTF-8') conn = urllib3.connection_from_url(kwargs['hostname']) headers = urllib3.util.make_headers( basic_auth='{0}:{1}'.format(username, password), accept_encoding=True, user_agent=user_agent_identifier(), ) try: r = conn.request('GET', url, headers=headers) if r.status < 200 or r.status >= 400: raise Exception(r.data) remote_project = parse_json(r.data) return remote_project except ssl.SSLError: logger.error("Invalid SSL certificate") raise except Exception, e: logger.debug(unicode(e)) raise
def _init(self, path_to_tx=None): instructions = "Run 'tx init' to initialize your project first!" try: self.root = self._get_tx_dir_path(path_to_tx) self.config_file = self._get_config_file_path(self.root) self.config = self._read_config_file(self.config_file) local_txrc_file = self._get_transifex_file(os.getcwd()) if os.path.exists(local_txrc_file): self.txrc_file = local_txrc_file else: self.txrc_file = self._get_transifex_file() self.txrc = self._get_transifex_config([ self.txrc_file, ]) except ProjectNotInit as e: logger.error('\n'.join([six.u(str(e)), instructions])) raise host = self.config.get('main', 'host') if host.lower().startswith('https://'): self.conn = urllib3.connection_from_url(host, cert_reqs=CERT_REQUIRED, ca_certs=web.certs_file()) else: self.conn = urllib3.connection_from_url(host)
def _delete_translation(self, project_details, resource, stats, language): """Delete a specific translation from the specified resource.""" project_slug, resource_slug = resource.split('.') if language not in stats: if not self.skip: msg = "Skipping %s: Translation does not exist." logger.warning(msg % (language)) return if not self.force: teams = project_details['teams'] if language in teams: msg = ( "Skipping %s: Unable to delete translation because it is " "associated with a team.\nPlease use -f or --force option " "to delete this translation.") logger.warning(msg % language) return if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping %s: Unable to delete translation because it " "is not empty.\nPlease use -f or --force option to delete " "this translation.") logger.warning(msg % language) return try: self.do_url_request('delete_translation', language=language, method="DELETE") msg = "Deleted language %s from resource %s of project %s." logger.info(msg % (language, resource_slug, project_slug)) except Exception, e: msg = "Unable to delete translation %s" logger.error(msg % language) if not self.skip: raise
def _init(self, path_to_tx=None): instructions = "Run 'tx init' to initialize your project first!" try: self.root = self._get_tx_dir_path(path_to_tx) self.config_file = self._get_config_file_path(self.root) self.config = self._read_config_file(self.config_file) local_txrc_file = self._get_transifex_file(os.getcwd()) if os.path.exists(local_txrc_file): self.txrc_file = local_txrc_file else: self.txrc_file = self._get_transifex_file() self.txrc = self._get_transifex_config([self.txrc_file, ]) except ProjectNotInit as e: logger.error('\n'.join([six.u(str(e)), instructions])) raise host = self.config.get('main', 'host') if host.lower().startswith('https://'): self.conn = urllib3.connection_from_url( host, cert_reqs=ssl.CERT_REQUIRED, ca_certs=certs_file() ) else: self.conn = urllib3.connection_from_url(host)
def make_request(method, host, url, username, password, fields=None): if host.lower().startswith('https://'): connection = urllib3.connection_from_url( host, cert_reqs=ssl.CERT_REQUIRED, ca_certs=certs_file() ) else: connection = urllib3.connection_from_url(host) headers = urllib3.util.make_headers( basic_auth='{0}:{1}'.format(username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True ) r = None try: r = connection.request(method, url, headers=headers, fields=fields) data = r.data charset = determine_charset(r) if isinstance(data, bytes): data = data.decode(charset) if r.status < 200 or r.status >= 400: if r.status == 404: raise HttpNotFound(data) else: raise Exception(data) return data, charset except SSLError: logger.error("Invalid SSL certificate") raise finally: if not r is None: r.close()
def _create_resource(self, resource, pslug, fileinfo, filename, **kwargs): """Create a resource. Args: resource: The full resource name. pslug: The slug of the project. fileinfo: The information of the resource. filename: The name of the file. Raises: URLError, in case of a problem. """ multipart = True method = "POST" api_call = 'create_resource' host = self.url_info['host'] try: username = self.txrc.get(host, 'username') passwd = self.txrc.get(host, 'password') token = self.txrc.get(host, 'token') hostname = self.txrc.get(host, 'hostname') except ConfigParser.NoSectionError: raise Exception("No user credentials found for host %s. Edit" " ~/.transifexrc and add the appropriate info in there." % host) # Create the Url kwargs['hostname'] = hostname kwargs.update(self.url_info) kwargs['project'] = pslug url = (API_URLS[api_call] % kwargs).encode('UTF-8') headers = None i18n_type = self._get_option(resource, 'type') if i18n_type is None: logger.error( "Please define the resource type in .tx/config (eg. type = PO)." " More info: http://bit.ly/txcl-rt" ) headers = urllib3.util.make_headers( basic_auth='{0}:{1}'.format(username, passwd), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True ) data = { "slug": fileinfo.split(';')[0], "name": fileinfo.split(';')[0], "uploaded_file": (filename, open(filename, 'rb').read()), "i18n_type": i18n_type } try: r = self.conn.request(method, url, fields=data, headers=headers) except ssl.SSLError: logger.error("Invalid SSL certificate") r.close() return r.data
def _extension_for(self, i18n_type): """Return the extension used for the specified type.""" try: res = parse_json(self.do_url_request('formats')) return res[i18n_type]['file-extensions'].split(',')[0] except Exception,e: logger.error(e) return ''
def _extension_for(self, i18n_type): """Return the extension used for the specified type.""" try: res = parse_json(self.do_url_request('formats')) return res[i18n_type]['file-extensions'].split(',')[0] except Exception, e: logger.error(e) return ''
def get_projects_for_org(self, organization): try: projects = self.api.get('projects', organization=organization) except Exception as e: logger.error(e) raise # return project list sorted by name return sorted([p for p in projects if not p['archived']], key=lambda x: x['name'])
def get_organizations(self): try: organizations = self.api.get('organizations') except Exception as e: logger.error(e) raise # return org list sorted by name return sorted([(o['slug'], o['name']) for o in organizations], key=lambda x: x[1])
def _init(self, path_to_tx=None): instructions = "Run 'tx init' to initialize your project first!" try: self.root = self._get_tx_dir_path(path_to_tx) self.config_file = self._get_config_file_path(self.root) self.config = self._read_config_file(self.config_file) self.txrc_file = self._get_transifex_file() self.txrc = self._get_transifex_config(self.txrc_file) except ProjectNotInit, e: logger.error('\n'.join([unicode(e), instructions])) raise
def get_organizations(self): try: organizations = self.api.get('organizations') except Exception as e: logger.error(e) raise # return org list sorted by name return sorted( [(o['slug'], o['name']) for o in organizations], key=lambda x: x[1] )
def get_projects_for_org(self, organization): try: projects = self.api.get('projects', organization=organization) except Exception as e: logger.error(e) raise # return project list sorted by name return sorted( [p for p in projects if not p['archived']], key=lambda x: x['name'] )
def _get_stats_for_resource(self): """Get the statistics information for a resource.""" try: r = self.do_url_request('resource_stats') logger.debug("Statistics response is %s" % r) stats = parse_json(r) except ssl.SSLError: logger.error("Invalid SSL certificate") raise except Exception, e: logger.debug(unicode(e)) raise
def __init__(self, token=None, username=None, password=None, path_to_tx=None, host=None): self.hostnames = self.map_paths_to_hostnames(path_to_tx, host) if token: self.token = token self.username = self.USERNAME elif username and password: self.token = password self.username = username else: logger.error("Authorization credentials are missing. Make sure " "that you have run `tx init` to setup your " "credentials.")
def get_formats(self, filename): _, extension = os.path.splitext(filename) try: formats = self.api.get('formats') except Exception as e: logger.error(e) raise def display_format(v): return '{} - {}'.format(v['description'], v['file-extensions']) formats = [(k, display_format(v)) for k, v in formats.items() if extension in v['file-extensions']] return sorted(formats, key=lambda x: x[0])
def get_formats(self, filename): _, extension = os.path.splitext(filename) try: formats = self.api.get('formats') except Exception as e: logger.error(e) raise def display_format(v): return '{} - {}'.format(v['description'], v['file-extensions']) formats = [(k, display_format(v)) for k, v in formats.items() if extension in v['file-extensions']] if not formats: raise Exception(messages.TEXTS['formats']['empty']) return sorted(formats, key=lambda x: x[0])
def get_branch_from_options(options, project_root): """ Returns the branch name that needs to be used in command based on parser options. options: optparse parser options as returned from `parse()` project_root: project root directory """ if not options.branch: return if options.branch != '-1': return options.branch branch = utils.get_current_branch(project_root) if not branch: logger.error("You specified the --branch option but current " "directory does not seem to belong in any git repo.") sys.exit(1) return branch
def perform_single_request(method, url, headers, fields, manager, skip_decode, callback=None, callback_args=None): callback_args = callback_args or {} response = None try: encoded_request = encode_args(manager.request) response = encoded_request(method, url, headers=headers, fields=fields) r_value = parse_tx_response(response, skip_decode) except SSLError: logger.error("Invalid SSL certificate") raise except HTTPError: logger.error("HTTP error") raise except Exception as e: logger.error(str(e)) if isinstance(current_thread(), _MainThread): raise return finally: if response is not None: response.close() if callback is not None: callback_args.update({"data": r_value[0], "charset": r_value[1]}) callback(**callback_args) return r_value
def main(argv=None): """ Here we parse the flags (short, long) and we instantiate the classes. """ parser = tx_main_parser() options, rest = parser.parse_known_args() if not options.command: parser.print_help() sys.exit(1) utils.DISABLE_COLORS = options.color_disable # set log level if options.quiet: set_log_level('WARNING') elif options.debug: set_log_level('DEBUG') web.cacerts_file = options.cacert # find .tx path_to_tx = options.root_dir or utils.find_dot_tx() cmd = options.command try: utils.exec_command(cmd, rest, path_to_tx) except SSLError as e: logger.error("SSL error %s" % e) except utils.UnknownCommandError: logger.error("Command %s not found" % cmd) except AuthenticationError: authentication_failed_message = """ Error: Authentication failed. Please make sure your credentials are valid. For more information, visit: https://docs.transifex.com/client/client-configuration#-transifexrc. """ logger.error(authentication_failed_message) except Exception as e: import traceback if options.trace: traceback.print_exc() else: msg = "Unknown error" if not str(e) else str(e) logger.error(msg) # The else statement will be executed only if the command raised no # exceptions. If an exception was raised, we want to return a non-zero exit # code else: return sys.exit(1)
def main(argv=None): """ Here we parse the flags (short, long) and we instantiate the classes. """ parser = tx_main_parser() options, rest = parser.parse_known_args() if not options.command: parser.print_help() sys.exit(1) utils.DISABLE_COLORS = options.color_disable # set log level if options.quiet: set_log_level('WARNING') elif options.debug: set_log_level('DEBUG') # find .tx path_to_tx = options.root_dir or utils.find_dot_tx() cmd = options.command try: utils.exec_command(cmd, rest, path_to_tx) except SSLError as e: logger.error("SSL error %s" % e) except utils.UnknownCommandError: logger.error("Command %s not found" % cmd) except AuthenticationError: authentication_failed_message = """ Error: Authentication failed. Please make sure your credentials are valid. For more information, visit: https://docs.transifex.com/client/client-configuration#-transifexrc. """ logger.error(authentication_failed_message) except Exception as e: import traceback if options.trace: traceback.print_exc() else: msg = "Unknown error" if not str(e) else str(e) logger.error(msg) # The else statement will be executed only if the command raised no # exceptions. If an exception was raised, we want to return a non-zero exit # code else: return sys.exit(1)
def _delete_translation(self, project_details, resource, stats, language): """Delete a specific translation from the specified resource.""" project_slug, resource_slug = resource.split('.', 1) if language not in stats: if not self.skip: msg = "Skipping %s: Translation does not exist." logger.warning(msg % (language)) return if not self.force: teams = project_details['teams'] if language in teams: msg = ( "Skipping %s: Unable to delete translation because it is " "associated with a team.\nPlease use -f or --force option " "to delete this translation." ) logger.warning(msg % language) return if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping %s: Unable to delete translation because it " "is not empty.\nPlease use -f or --force option to delete " "this translation." ) logger.warning(msg % language) return try: self.do_url_request( 'delete_translation', language=language, method="DELETE" ) msg = "Deleted language %s from resource %s of project %s." logger.info(msg % (language, resource_slug, project_slug)) except Exception as e: msg = "Unable to delete translation %s" logger.error(msg % language) if isinstance(e, SSLError) or not self.skip: raise
def _delete_resource(self, project_details, resource, stats, *args): """Delete a resource from Transifex.""" project_slug, resource_slug = resource.split('.', 1) project_resource_slugs = [ r['slug'] for r in project_details['resources'] ] logger.info("Deleting resource %s:" % resource) if resource_slug not in project_resource_slugs: if not self.skip: msg = "Skipping: %s : Resource does not exist." logger.info(msg % resource) return if not self.force: slang = self.get_resource_option(resource, 'source_lang') for language in stats: if language == slang: continue if int(stats[language]['translated_entities']) > 0: msg = ( "Skipping: %s : Unable to delete resource because it " "has a not empty %s translation.\nPlease use -f or " "--force option to delete this resource." ) logger.info(msg % (resource, language)) return try: self.do_url_request('delete_resource', method="DELETE") self.config.remove_section(resource) self.save() msg = "Deleted resource %s of project %s." logger.info(msg % (resource_slug, project_slug)) except Exception as e: msg = "Unable to delete resource %s of project %s." logger.error(msg % (resource_slug, project_slug)) if isinstance(e, SSLError) or not self.skip: raise
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """ Push all the resources """ resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = input("Warning: By using --force, the uploaded" " files will overwrite remote translations, even if they" " are newer than your uploaded files.\nAre you sure you" " want to continue? [y/N] ") if not answer in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile is None: logger.error("You don't seem to have a proper source file" " mapping for resource %s. Try without the --source" " option or set a source file first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource(resource, project_slug, fileinfo, filename) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[( "%s;%s" % (resource_slug, slang) , self.get_full_path(sfile) )], ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception as e: if isinstance(e, SSLError): raise code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue if translations: # Check if given language codes exist if not languages: push_languages = list(files.keys()) else: push_languages = [] f_langs = list(files.keys()) for l in languages: if l in list(lang_map.keys()): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for language code '%s'." logger.error(msg % color_text(l,"RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, } if not self._should_push_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info(msg % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (color_text(remote_lang, "RED"), local_file) ) try: self.do_url_request( 'push_translation', multipart=True, method='PUT', files=[( "%s;%s" % (resource_slug, remote_lang), self.get_full_path(local_file) )], language=remote_lang ) logger.debug("Translation %s pushed." % remote_lang) except HttpNotFound: if not source: logger.error("Resource hasn't been created. Try pushing source file.") except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e)
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None, pseudo=False): """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) if mode == 'reviewed': url = 'pull_reviewed_file' elif mode == 'translator': url = 'pull_translator_file' elif mode == 'developer': url = 'pull_developer_file' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) if mode is None: mode = self._get_option(resource, 'mode') self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() try: file_filter = self.config.get(resource, 'file_filter') except configparser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if pseudo: pseudo_file = self._get_pseudo_file( slang, resource, file_filter ) if self._should_download(slang, stats, local_file=pseudo_file): logger.info("Pulling pseudo file for resource %s (%s)." % ( resource, color_text(pseudo_file, "RED") )) self._download_pseudo( project_slug, resource_slug, pseudo_file ) if not languages: continue if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, stats, force ) if new_translations: msg = "New translations found for the following languages: %s" logger.info(msg % ', '.join(new_translations)) existing, new = self._languages_to_pull( languages, files, lang_map, stats, force ) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.add(slang) elif slang not in new_translations: new_translations.add(slang) if pull_languages: logger.debug("Pulling languages for: %s" % pull_languages) msg = "Pulling translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in pull_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'mode': mode, } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info( msg % (color_text(remote_lang, "RED"), local_file) ) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning( " -> %s: %s" % (color_text(remote_lang, "RED"), local_file) ) try: r, charset = self.do_url_request(url, language=remote_lang) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) continue base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r.encode(charset)) fd.close() if new_translations: msg = "Pulling new translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in new_translations: if lang in list(lang_map.keys()): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = os.path.relpath( os.path.join( self.root, native_path( file_filter.replace('<lang>', local_lang) ) ), os.curdir ) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = os.path.relpath(os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) if lang != slang: satisfies_min = self._satisfies_min_translated( stats[remote_lang], mode ) if not satisfies_min: msg = "Skipping language %s due to used options." logger.info(msg % lang) continue logger.warning( " -> %s: %s" % (color_text(remote_lang, "RED"), local_file) ) r, charset = self.do_url_request(url, language=remote_lang) base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r.encode(charset)) fd.close()
def ERRMSG(msg, verbosity=1): """ STDERR logging function """ logger.error('%s' % msg)
def make_request(method, host, url, username, password, fields=None, skip_decode=False, get_params={}): # Initialize http and https pool managers num_pools = 1 managers = {} if host.lower().startswith("http://"): scheme = "http" if "http_proxy" in os.environ: proxy_url = urllib3.util.url.parse_url(os.environ["http_proxy"]) managers["http"] = urllib3.ProxyManager( proxy_url=proxy_url.url, proxy_headers=urllib3.util.make_headers( user_agent=user_agent_identifier(), proxy_basic_auth=proxy_url.auth), num_pools=num_pools) else: managers["http"] = urllib3.PoolManager(num_pools=num_pools) elif host.lower().startswith("https://"): scheme = "https" if "https_proxy" in os.environ: proxy_url = urllib3.util.url.parse_url(os.environ["https_proxy"]) managers["https"] = urllib3.ProxyManager( proxy_url=proxy_url.url, proxy_headers=urllib3.util.make_headers( user_agent=user_agent_identifier(), proxy_basic_auth=proxy_url.auth), num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file()) else: managers["https"] = urllib3.PoolManager(num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file()) else: raise Exception("Unknown scheme") charset = None headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format( username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True) response = None try: manager = managers[scheme] # All arguments must be bytes, not unicode encoded_request = encode_args(manager.request) response = encoded_request(method, urljoin(host, url), headers=dict(headers), fields=fields) data = response.data if not skip_decode: charset = determine_charset(response) if isinstance(data, bytes): data = data.decode(charset) if response.status < 200 or response.status >= 400: if response.status == 401: raise AuthenticationError(data) elif response.status == 403: raise HttpNotAuthorized(data) elif response.status == 404: raise HttpNotFound(data) elif response.status >= 500: msg = "Failed to connect. Server responded with HTTP code {}" raise TXConnectionError(msg.format(response.status), code=response.status) else: raise Exception("Error received from server: {}".format(data)) return data, charset except SSLError: logger.error("Invalid SSL certificate") raise finally: if response is not None: response.close()
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None): """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) if mode == 'reviewed': url = 'pull_reviewed_file' elif mode == 'translator': url = 'pull_translator_file' elif mode == 'developer': url = 'pull_developer_file' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.') files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) verify_ssl(host) logger.debug("Language mapping is: %s" % lang_map) if mode is None: mode = self._get_option(resource, 'mode') self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() try: file_filter = self.config.get(resource, 'file_filter') except ConfigParser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, stats, force) if new_translations: msg = "New translations found for the following languages: %s" logger.info(msg % ', '.join(new_translations)) existing, new = self._languages_to_pull(languages, files, lang_map, stats, force) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.add(slang) elif slang not in new_translations: new_translations.add(slang) if pull_languages: logger.debug("Pulling languages for: %s" % pull_languages) msg = "Pulling translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in pull_languages: local_lang = lang if lang in lang_map.values(): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'mode': mode, } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info(msg % (color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning(" -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) try: r = self.do_url_request(url, language=remote_lang) except Exception, e: if not skip: raise e else: logger.error(e) continue base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close() if new_translations: msg = "Pulling new translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in new_translations: if lang in lang_map.keys(): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = os.path.relpath( os.path.join( self.root, native_path( file_filter.replace('<lang>', local_lang))), os.curdir.decode('utf-8')) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = os.path.relpath( os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) if lang != slang: satisfies_min = self._satisfies_min_translated( stats[remote_lang], mode) if not satisfies_min: msg = "Skipping language %s due to used options." logger.info(msg % lang) continue logger.warning( " -> %s: %s" % (color_text(remote_lang, "RED"), local_file)) r = self.do_url_request(url, language=remote_lang) base_dir = os.path.split(local_file)[0] mkdir_p(base_dir) fd = open(local_file, 'wb') fd.write(r) fd.close()
def _create_resource(self, resource, pslug, fileinfo, filename, **kwargs): """Create a resource. Args: resource: The full resource name. pslug: The slug of the project. fileinfo: The information of the resource. filename: The name of the file. Raises: URLError, in case of a problem. """ multipart = True method = "POST" api_call = 'create_resource' host = self.url_info['host'] try: username = self.txrc.get(host, 'username') passwd = self.txrc.get(host, 'password') token = self.txrc.get(host, 'token') hostname = self.txrc.get(host, 'hostname') except ConfigParser.NoSectionError: raise Exception("No user credentials found for host %s. Edit" " ~/.transifexrc and add the appropriate info in there." % host) # Create the Url kwargs['hostname'] = hostname kwargs.update(self.url_info) kwargs['project'] = pslug url = (API_URLS[api_call] % kwargs).encode('UTF-8') opener = None headers = None req = None i18n_type = self._get_option(resource, 'type') if i18n_type is None: logger.error( "Please define the resource type in .tx/config (eg. type = PO)." " More info: http://bit.ly/txcl-rt" ) opener = urllib2.build_opener(MultipartPostHandler) data = { "slug": fileinfo.split(';')[0], "name": fileinfo.split(';')[0], "uploaded_file": open(filename,'rb'), "i18n_type": i18n_type } urllib2.install_opener(opener) req = RequestWithMethod(url=url, data=data, method=method) base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) try: fh = urllib2.urlopen(req) except urllib2.HTTPError, e: if e.code in [401, 403, 404]: raise e else: # For other requests, we should print the message as well raise Exception("Remote server replied: %s" % e.read())
def make_request(method, host, url, username, password, fields=None, skip_decode=False): # Initialize http and https pool managers num_pools = 1 managers = {} if host.lower().startswith("http://"): scheme = "http" if "http_proxy" in os.environ: proxy_url = os.environ["http_proxy"] managers["http"] = urllib3.ProxyManager( proxy_url=proxy_url, proxy_headers={"User-Agent": user_agent_identifier()}, num_pools=num_pools) else: managers["http"] = urllib3.PoolManager(num_pools=num_pools) elif host.lower().startswith("https://"): scheme = "https" if "https_proxy" in os.environ: proxy_url = os.environ["https_proxy"] managers["https"] = urllib3.ProxyManager( proxy_url=proxy_url, proxy_headers={"User-Agent": user_agent_identifier()}, num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file()) else: managers["https"] = urllib3.PoolManager(num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file()) else: raise Exception("Unknown scheme") charset = None headers = urllib3.util.make_headers(basic_auth='{0}:{1}'.format( username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True) response = None try: manager = managers[scheme] response = manager.request(method, host + url, headers=dict(headers), fields=fields) data = response.data if not skip_decode: charset = determine_charset(response) if isinstance(data, bytes): data = data.decode(charset) if response.status < 200 or response.status >= 400: if response.status == 401: raise HttpNotAuthorized(data) elif response.status == 404: raise HttpNotFound(data) else: raise Exception(data) return data, charset except SSLError: logger.error("Invalid SSL certificate") raise finally: if response is not None: response.close()
continue if translations: # Check if given language codes exist if not languages: push_languages = files.keys() else: push_languages = [] f_langs = files.keys() for l in languages: if l in lang_map.keys(): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for language code '%s'." logger.error(msg % color_text(l,"RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in lang_map.values(): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats,
def make_request(method, host, url, username, password, fields=None, skip_decode=False): # Initialize http and https pool managers num_pools = 1 managers = {} if host.lower().startswith("http://"): scheme = "http" if "http_proxy" in os.environ: proxy_url = os.environ["http_proxy"] managers["http"] = urllib3.ProxyManager( proxy_url=proxy_url, proxy_headers={"User-Agent": user_agent_identifier()}, num_pools=num_pools ) else: managers["http"] = urllib3.PoolManager(num_pools=num_pools) elif host.lower().startswith("https://"): scheme = "https" if "https_proxy" in os.environ: proxy_url = os.environ["https_proxy"] managers["https"] = urllib3.ProxyManager( proxy_url=proxy_url, proxy_headers={"User-Agent": user_agent_identifier()}, num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file() ) else: managers["https"] = urllib3.PoolManager( num_pools=num_pools, cert_reqs=CERT_REQUIRED, ca_certs=certs_file() ) else: raise Exception("Unknown scheme") charset = None headers = urllib3.util.make_headers( basic_auth='{0}:{1}'.format(username, password), accept_encoding=True, user_agent=user_agent_identifier(), keep_alive=True ) response = None try: manager = managers[scheme] # All arguments must be bytes, not unicode encoded_request = encode_args(manager.request) response = encoded_request( method, host + url, headers=dict(headers), fields=fields ) data = response.data if not skip_decode: charset = determine_charset(response) if isinstance(data, bytes): data = data.decode(charset) if response.status < 200 or response.status >= 400: if response.status == 401: raise HttpNotAuthorized(data) elif response.status == 404: raise HttpNotFound(data) else: raise Exception(data) return data, charset except SSLError: logger.error("Invalid SSL certificate") raise finally: if response is not None: response.close()
continue if translations: # Check if given language codes exist if not languages: push_languages = files.keys() else: push_languages = [] f_langs = files.keys() for l in languages: if l in lang_map.keys(): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for language code '%s'." logger.error(msg % color_text(l, "RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in lang_map.values(): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats,
def _create_resource(self, resource, pslug, fileinfo, filename, **kwargs): """Create a resource. Args: resource: The full resource name. pslug: The slug of the project. fileinfo: The information of the resource. filename: The name of the file. Raises: URLError, in case of a problem. """ multipart = True method = "POST" api_call = 'create_resource' host = self.url_info['host'] try: username = self.txrc.get(host, 'username') passwd = self.txrc.get(host, 'password') token = self.txrc.get(host, 'token') hostname = self.txrc.get(host, 'hostname') except ConfigParser.NoSectionError: raise Exception( "No user credentials found for host %s. Edit" " ~/.transifexrc and add the appropriate info in there." % host) # Create the Url kwargs['hostname'] = hostname kwargs.update(self.url_info) kwargs['project'] = pslug url = (API_URLS[api_call] % kwargs).encode('UTF-8') opener = None headers = None req = None i18n_type = self._get_option(resource, 'type') if i18n_type is None: logger.error( "Please define the resource type in .tx/config (eg. type = PO)." " More info: http://bit.ly/txcl-rt") opener = urllib2.build_opener(MultipartPostHandler) data = { "slug": fileinfo.split(';')[0], "name": fileinfo.split(';')[0], "uploaded_file": open(filename, 'rb'), "i18n_type": i18n_type } urllib2.install_opener(opener) req = RequestWithMethod(url=url, data=data, method=method) base64string = base64.encodestring('%s:%s' % (username, passwd))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) try: fh = urllib2.urlopen(req) except urllib2.HTTPError, e: if e.code in [401, 403, 404]: raise e else: # For other requests, we should print the message as well raise Exception("Remote server replied: %s" % e.read())
def pull(self, languages=[], resources=[], overwrite=True, fetchall=False, fetchsource=False, force=False, skip=False, minimum_perc=0, mode=None, pseudo=False): """Pull all translations file from transifex server.""" self.minimum_perc = minimum_perc resource_list = self.get_chosen_resources(resources) skip_decode = False if mode == 'reviewed': url = 'pull_reviewed_file' elif mode == 'translator': url = 'pull_translator_file' elif mode == 'developer': url = 'pull_developer_file' elif mode == 'onlytranslated': url = 'pull_onlytranslated_file' elif mode == 'onlyreviewed': url = 'pull_onlyreviewed_file' else: url = 'pull_file' for resource in resource_list: logger.debug("Handling resource %s" % resource) self.resource = resource project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) if mode is None: mode = self._get_option(resource, 'mode') self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.debug("URL data are: %s" % self.url_info) stats = self._get_stats_for_resource() details_response, _ = self.do_url_request('resource_details') details = utils.parse_json(details_response) if details['i18n_type'] in self.SKIP_DECODE_I18N_TYPES: skip_decode = True try: file_filter = self.config.get(resource, 'file_filter') except configparser.NoOptionError: file_filter = None # Pull source file pull_languages = set([]) new_translations = set([]) if pseudo: pseudo_file = self._get_pseudo_file(slang, resource, file_filter) if self._should_download(slang, stats, local_file=pseudo_file): logger.info( "Pulling pseudo file for resource %s (%s)." % (resource, utils.color_text(pseudo_file, "RED"))) self._download_pseudo(project_slug, resource_slug, pseudo_file) if not languages: continue if fetchall: new_translations = self._new_translations_to_add( files, slang, lang_map, stats, force) if new_translations: msg = ("New translations found " "for the following languages:%s") logger.info(msg % ', '.join(new_translations)) existing, new = self._languages_to_pull(languages, files, lang_map, stats, force) pull_languages |= existing new_translations |= new logger.debug("Adding to new translations: %s" % new) if fetchsource: if sfile and slang not in pull_languages: pull_languages.add(slang) elif slang not in new_translations: new_translations.add(slang) if pull_languages: logger.debug("Pulling languages for: %s" % pull_languages) msg = "Pulling translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in pull_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang if languages and lang not in pull_languages: logger.debug("Skipping language %s" % lang) continue if lang != slang: local_file = files.get(lang, None) or files[lang_map[lang]] else: local_file = sfile logger.debug("Using file %s" % local_file) kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, 'mode': mode, } if not self._should_update_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info( msg % (utils.color_text(remote_lang, "RED"), local_file)) continue if not overwrite: local_file = ("%s.new" % local_file) logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file)) try: r, charset = self.do_url_request(url, language=remote_lang, skip_decode=skip_decode) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) continue self._save_file(local_file, charset, r) if new_translations: msg = "Pulling new translations for resource %s (source: %s)" logger.info(msg % (resource, sfile)) for lang in new_translations: if lang in list(lang_map.keys()): local_lang = lang_map[lang] else: local_lang = lang remote_lang = lang if file_filter: local_file = os.path.relpath( os.path.join( self.root, native_path( file_filter.replace('<lang>', local_lang))), os.curdir) else: trans_dir = os.path.join(self.root, ".tx", resource) if not os.path.exists(trans_dir): os.mkdir(trans_dir) local_file = os.path.relpath( os.path.join(trans_dir, '%s_translation' % local_lang, os.curdir)) if lang != slang: satisfies_min = self._satisfies_min_translated( stats[remote_lang], mode) if not satisfies_min: msg = "Skipping language %s due to used options." logger.info(msg % lang) continue logger.warning( " -> %s: %s" % (utils.color_text(remote_lang, "RED"), local_file)) r, charset = self.do_url_request(url, language=remote_lang, skip_decode=skip_decode) self._save_file(local_file, charset, r)
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """ Push all the resources """ resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.', 1) files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = input( "Warning: By using --force, the uploaded" " files will overwrite remote translations, even if they" " are newer than your uploaded files.\nAre you sure you" " want to continue? [y/N] ") if not answer in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile is None: logger.error( "You don't seem to have a proper source file" " mapping for resource %s. Try without the --source" " option or set a source file first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource(resource, project_slug, fileinfo, filename) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[("%s;%s" % (resource_slug, slang), self.get_full_path(sfile))], ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception as e: if isinstance(e, SSLError): raise code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue if translations: # Check if given language codes exist if not languages: push_languages = list(files.keys()) else: push_languages = [] f_langs = list(files.keys()) for l in languages: if l in list(lang_map.keys()): l = lang_map[l] push_languages.append(l) if l not in f_langs: msg = "Warning: No mapping found for language code '%s'." logger.error(msg % color_text(l, "RED")) logger.debug("Languages to push are %s" % push_languages) # Push translation files one by one for lang in push_languages: local_lang = lang if lang in list(lang_map.values()): remote_lang = lang_map.flip[lang] else: remote_lang = lang local_file = files[local_lang] kwargs = { 'lang': remote_lang, 'stats': stats, 'local_file': local_file, 'force': force, } if not self._should_push_translation(**kwargs): msg = "Skipping '%s' translation (file: %s)." logger.info(msg % (color_text(lang, "RED"), local_file)) continue msg = "Pushing '%s' translations (file: %s)" logger.warning( msg % (color_text(remote_lang, "RED"), local_file)) try: self.do_url_request( 'push_translation', multipart=True, method='PUT', files=[("%s;%s" % (resource_slug, remote_lang), self.get_full_path(local_file))], language=remote_lang) logger.debug("Translation %s pushed." % remote_lang) except HttpNotFound: if not source: logger.error( "Resource hasn't been created. Try pushing source file." ) except Exception as e: if isinstance(e, SSLError) or not skip: raise else: logger.error(e)
def main(argv=None): """ Here we parse the flags (short, long) and we instantiate the classes. """ if argv is None: argv = sys.argv[1:] usage = "usage: %prog [options] command [cmd_options]" description = "This is the Transifex command line client which"\ " allows you to manage your translations locally and sync"\ " them with the master Transifex server.\nIf you'd like to"\ " check the available commands issue `%prog help` or if you"\ " just want help with a specific command issue `%prog help"\ " command`" parser = OptionParser(usage=usage, version=txclib.__version__, description=description) parser.disable_interspersed_args() parser.add_option("-d", "--debug", action="store_true", dest="debug", default=False, help=("enable debug messages")) parser.add_option("-q", "--quiet", action="store_true", dest="quiet", default=False, help="don't print status messages to stdout") parser.add_option("-r", "--root", action="store", dest="root_dir", type="string", default=None, help="change root directory (default is cwd)") parser.add_option("--traceback", action="store_true", dest="trace", default=False, help="print full traceback on exceptions") parser.add_option("--disable-colors", action="store_true", dest="color_disable", default=(os.name == 'nt' or not sys.stdout.isatty()), help="disable colors in the output of commands") (options, args) = parser.parse_args() if len(args) < 1: parser.error("No command was given") utils.DISABLE_COLORS = options.color_disable # set log level if options.quiet: set_log_level('WARNING') elif options.debug: set_log_level('DEBUG') # find .tx path_to_tx = options.root_dir or utils.find_dot_tx() cmd = args[0] try: utils.exec_command(cmd, args[1:], path_to_tx) except SSLError as e: logger.error("SSl error %s" % e) sys.exit(1) except utils.UnknownCommandError: logger.error("tx: Command %s not found" % cmd) except SystemExit: sys.exit() except: import traceback if options.trace: traceback.print_exc() else: formatted_lines = traceback.format_exc().splitlines() logger.error(formatted_lines[-1]) sys.exit(1)
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """ Push all the resources """ resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.') files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_resource_option(resource, 'source_file') lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = raw_input("Warning: By using --force, the uploaded" " files will overwrite remote translations, even if they" " are newer than your uploaded files.\nAre you sure you" " want to continue? [y/N] ") if not answer in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile == None: logger.error("You don't seem to have a proper source file" " mapping for resource %s. Try without the --source" " option or set a source file first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource(resource, project_slug, fileinfo, filename) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[( "%s;%s" % (resource_slug, slang) , self.get_full_path(sfile) )], ) except Exception, e: if not skip: raise e else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception, e: code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue
def main(): """ Here we parse the flags (short, long) and we instantiate the classes. """ usage = "usage: %prog [options] command [cmd_options]" description = "This is the Transifex command line client which"\ " allows you to manage your translations locally and sync"\ " them with the master Transifex server.\nIf you'd like to"\ " check the available commands issue `%prog help` or if you"\ " just want help with a specific command issue `%prog help"\ " command`" argv = sys.argv[1:] parser = OptionParser( usage=usage, version=get_version(), description=description ) parser.disable_interspersed_args() parser.add_option( "-d", "--debug", action="store_true", dest="debug", default=False, help=("enable debug messages") ) parser.add_option( "-q", "--quiet", action="store_true", dest="quiet", default=False, help="don't print status messages to stdout" ) parser.add_option( "-r", "--root", action="store", dest="root_dir", type="string", default=None, help="change root directory (default is cwd)" ) parser.add_option( "--traceback", action="store_true", dest="trace", default=False, help="print full traceback on exceptions" ) parser.add_option( "--disable-colors", action="store_true", dest="color_disable", default=(os.name == 'nt' or not sys.stdout.isatty()), help="disable colors in the output of commands" ) (options, args) = parser.parse_args() if len(args) < 1: parser.error("No command was given") utils.DISABLE_COLORS = options.color_disable # set log level if options.quiet: set_log_level('WARNING') elif options.debug: set_log_level('DEBUG') # find .tx path_to_tx = options.root_dir or utils.find_dot_tx() cmd = args[0] try: utils.exec_command(cmd, args[1:], path_to_tx) except utils.UnknownCommandError: logger.error("tx: Command %s not found" % cmd) except SystemExit: sys.exit() except: import traceback if options.trace: traceback.print_exc() else: formatted_lines = traceback.format_exc().splitlines() logger.error(formatted_lines[-1]) sys.exit(1)
def push(self, source=False, translations=False, force=False, resources=[], languages=[], skip=False, no_interactive=False): """ Push all the resources """ resource_list = self.get_chosen_resources(resources) self.skip = skip self.force = force for resource in resource_list: push_languages = [] project_slug, resource_slug = resource.split('.') files = self.get_resource_files(resource) slang = self.get_resource_option(resource, 'source_lang') sfile = self.get_source_file(resource) lang_map = self.get_resource_lang_mapping(resource) host = self.get_resource_host(resource) verify_ssl(host) logger.debug("Language mapping is: %s" % lang_map) logger.debug("Using host %s" % host) self.url_info = { 'host': host, 'project': project_slug, 'resource': resource_slug } logger.info("Pushing translations for resource %s:" % resource) stats = self._get_stats_for_resource() if force and not no_interactive: answer = raw_input( "Warning: By using --force, the uploaded" " files will overwrite remote translations, even if they" " are newer than your uploaded files.\nAre you sure you" " want to continue? [y/N] ") if not answer in ["", 'Y', 'y', "yes", 'YES']: return if source: if sfile is None: logger.error( "You don't seem to have a proper source file" " mapping for resource %s. Try without the --source" " option or set a source file first and then try again." % resource) continue # Push source file try: logger.warning("Pushing source file (%s)" % sfile) if not self._resource_exists(stats): logger.info("Resource does not exist. Creating...") fileinfo = "%s;%s" % (resource_slug, slang) filename = self.get_full_path(sfile) self._create_resource(resource, project_slug, fileinfo, filename) self.do_url_request( 'push_source', multipart=True, method="PUT", files=[("%s;%s" % (resource_slug, slang), self.get_full_path(sfile))], ) except Exception, e: if not skip: raise else: logger.error(e) else: try: self.do_url_request('resource_details') except Exception, e: code = getattr(e, 'code', None) if code == 404: msg = "Resource %s doesn't exist on the server." logger.error(msg % resource) continue