def error_contacting_app(request, url, app, exception): """Handle the case, where an app did not respond. This view is called, if there was a HTTP error, when contacting the remote tx app. """ if all([exception.status_code, exception.content]): log_msg = ( "Error visiting URL %s for app %s: status code " "was %s and error_message %s" % ( url, app.name, exception.status_code, exception.content ) ) view_msg = _("TxApp responded with an error: %s" % exception.content) else: log_msg = "Error contacting remote server: url is %s" % url view_msg = _("Error contacting app.") logger.error(log_msg) return render_to_response( 'txapp_error.html', { 'app_name': app.name, 'error_message': view_msg }, context_instance=RequestContext(request) )
def team_request_deny(request, project_slug, language_code): team_request = get_object_or_404(TeamRequest, project__slug=project_slug, language__code=language_code) project = team_request.project if request.POST: try: team_request.delete() messages.success(request, _( "You rejected the request by '%(user)s' for a '%(team)s' team." ) % {'team':team_request.language.name, 'user':team_request.user}) # ActionLog & Notification # TODO: Use signals nt = 'project_team_request_denied' context = {'team_request': team_request, 'performer': request.user} # Logging action action_logging(request.user, [project], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for(project, signal=nt, extra_context=context) # Send notification for maintainers and the user notification.send(set(itertools.chain(project.maintainers.all(), [team_request.user])), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def create(self): """ Create a new translation supplied as a string. Returns: A dict with information for the request. Raises: BadRequestError: There was a problem with the request. NoContentError: There was no content string in the request. """ if 'content' not in self.data: raise NoContentError("No content found.") parser = parser_for( mimetype=get_mimetype_from_method(self.resource.i18n_type) ) if parser is None: raise BadRequestError("Mimetype not supported") file_ = tempfile.NamedTemporaryFile( mode='wb', suffix=get_file_extension_for_method(self.resource.i18n_type), delete=False, ) try: file_.write(self.data['content'].encode('UTF-8')) file_.close() try: parser.contents_check(file_.name) except (FileCheckError, ParseError), e: raise BadRequestError(e.message) except Exception, e: logger.error(e.message, exc_info=True) raise BadRequestError("A strange error has happened.")
def _update(self, request, project_slug, resource_slug, lang_code=None): # Permissions handling try: resource = Resource.objects.get( slug=resource_slug, project__slug=project_slug ) except Resource.DoesNotExist: return rc.NOT_FOUND if lang_code == "source": language = resource.source_language else: try: language = Language.objects.by_code_or_alias(lang_code) except Language.DoesNotExist: logger.error("Weird! Selected language code (%s) does " "not match with any language in the database." % lang_code) return BAD_REQUEST( "Selected language code (%s) does not match with any" "language in the database." % lang_code ) team = Team.objects.get_or_none(resource.project, lang_code) check = ProjectPermission(request.user) if (not check.submit_translations(team or resource.project) or\ not resource.accept_translations) and not\ check.maintain(resource.project): return rc.FORBIDDEN try: t = Translation.get_object("create", request, resource, language) res = t.create() except BadRequestError, e: return BAD_REQUEST(unicode(e))
def get(self, start=None, end=None, pseudo_type=None): """ Return the requested translation in a json string. If self.language is None, return all translations. Args: start: Start for pagination. end: End for pagination. Returns: A dict with the translation(s). Raises: BadRequestError: There was a problem with the request. """ try: template = _compile_translation_template( self.resource, self.language, pseudo_type ) except Exception, e: logger.error(e.message, exc_info=True) raise BadRequestError( "Error compiling the translation file: %s" % e )
def create(self): """ Create a new translation supplied as a string. Returns: A dict with information for the request. Raises: BadRequestError: There was a problem with the request. NoContentError: There was no content string in the request. """ if 'content' not in self.data: raise NoContentError("No content found.") parser = registry.appropriate_handler(self.resource, language=self.language) if parser is None: raise BadRequestError("I18n type is not supported: %s" % i18n_type) file_ = tempfile.NamedTemporaryFile( mode='wb', suffix=registry.extensions_for(self.resource.i18n_method)[0], delete=False, ) try: file_.write(self.data['content'].encode('UTF-8')) file_.close() try: parser.bind_file(file_.name) parser.is_content_valid() except (FileCheckError, ParseError), e: raise BadRequestError(unicode(e)) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("A strange error has happened.")
def project_hub_join_withdraw(request, project_slug): # project_slug here refers to outsourced_project_slug. It was kept like # it to keep consistency across url regexes. hub_request = get_object_or_404(HubRequest, project__slug=project_slug) if request.POST: try: _hub_request = copy.copy(hub_request) hub_request.delete() messages.success(request, _("Request to join '%s' project hub " "was withdrawn") % _hub_request.project_hub) # ActionLog & Notification # TODO: Use signals nt = 'project_hub_join_withdrawn' context = {'hub_request': _hub_request, 'performer': request.user, 'sender': request.user} # Logging action action_logging(request.user, [_hub_request.project, hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(_hub_request.project_hub.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % e.message)
def create(self, request, project_slug, api_version=1): """ Create resource for project by UUID of StorageFile. """ if "application/json" in request.content_type: if "uuid" in request.data: uuid = request.data["uuid"] project = Project.objects.get(slug=project_slug) try: storagefile = StorageFile.objects.get(uuid=uuid) except StorageFile.DoesNotExist, e: transaction.rollback() return BAD_REQUEST("Specified uuid is invalid.") resource_slug = None if "slug" in request.data: resource_slug = request.data["slug"] if len(resource_slug) > 51: transaction.rollback() return BAD_REQUEST("Resouce slug is too long " "(Max. 50 chars).") try: resource, created = Resource.objects.get_or_create( slug=resource_slug or slugify(storagefile.name), source_language=storagefile.language, project=project, ) except DatabaseError, e: transaction.rollback() logger.error(e.message, exc_info=True) return BAD_REQUEST(e.message) except IntegrityError, e: transaction.rollback() logger.error(e.message, exc_info=True) return BAD_REQUEST(e.message)
def team_join_withdraw(request, project_slug, language_code): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project access_request = get_object_or_404(TeamAccessRequest, team__pk=team.pk, user__pk=request.user.pk) if request.POST: try: access_request.delete() messages.success(request,_( "You withdrew your request to join the '%s' team." ) % team.language.name) # ActionLog & Notification # TODO: Use signals nt = 'project_team_join_withdrawn' context = {'access_request': access_request, 'performer': request.user,} # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for(project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators notification.send(set(itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def create(self): """ Create a new translation supplied as a string. Returns: A dict with information for the request. Raises: BadRequestError: There was a problem with the request. NoContentError: There was no content string in the request. """ if 'content' not in self.data: raise NoContentError("No content found.") parser = registry.appropriate_handler( self.resource, language=self.language ) if parser is None: raise BadRequestError("I18n type is not supported: %s" % i18n_type) file_ = tempfile.NamedTemporaryFile( mode='wb', suffix=registry.extensions_for(self.resource.i18n_method)[0], delete=False, ) try: file_.write(self.data['content'].encode('UTF-8')) file_.close() try: parser.bind_file(file_.name) parser.is_content_valid() except (FileCheckError, ParseError), e: raise BadRequestError(unicode(e)) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("A strange error has happened.")
def redis_exception_handler(func): """Decorator to handle redis backend exceptions.""" def wrapper(*args, **kwargs): try: return func(*args, **kwargs) except ConnectionError, e: logger.critical("Cannot connect to redis: %s" % e, exc_info=True) except Exception, e: logger.error("Error from redis: %s" % e, exc_info=True)
def team_join_approve(request, project_slug, language_code, username): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project user = get_object_or_404(User, username=username) access_request = get_object_or_404(TeamAccessRequest, team__pk=team.pk, user__pk=user.pk) if request.POST: if user in team.members.all() or \ user in team.coordinators.all(): messages.warning( request, _("User '%(user)s' is already on the '%(team)s' team.") % { 'user': user, 'team': team.language.name }) access_request.delete() try: team.members.add(user) team.save() messages.success( request, _("You added '%(user)s' to the '%(team)s' team.") % { 'user': user, 'team': team.language.name }) access_request.delete() # ActionLog & Notification # TODO: Use signals nt = 'project_team_join_approved' context = { 'access_request': access_request, 'sender': request.user } # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for( project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators and the user notification.send( set( itertools.chain(project.maintainers.all(), team.coordinators.all(), [access_request.user])), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def wrapper(*args, **kwargs): if settings.HAYSTACK_SEARCH_ENGINE == 'solr': try: soldadmin = SolrCoreAdmin(SearchQuerySet().query.backend.conn.url) soldadmin.status() func(*args, **kwargs) except Exception, e: logger.error('Error contacting SOLR backend: %s' % getattr(e, 'reason', str(e))) raise HaystackError('Error contacting SOLR backend.')
def parse_file(self, is_source=False, lang_rules=None): """ Parse an INI file and create a stringset with all entries in the file. """ stringset = StringSet() suggestions = StringSet() fh = codecs.open(self.filename, "r", "utf-8") try: buf = fh.read() finally: fh.close() for line in buf.split('\n'): # Skip empty lines and comments if not line or line.startswith(self.comment_chars): continue try: source, trans = line.split('=', 1) except ValueError: # Maybe abort instead of skipping? logger.error('Could not parse line "%s". Skipping...' % line) continue # In versions >=1.6 translations are surrounded by double quotes. So remove them # Normally, if the translation starts with '"', it is a 1.6-file and must # end with '"', since translations starting with '"' are not allowed in 1.5. # But, let's check both the first and last character of the translation to be safe. if trans.startswith('"') and trans.endswith('"'): trans = trans[1:-1] # We use empty context context = "" if is_source: source_len = len(source) new_line = line[:source_len] + re.sub( re.escape(trans), "%(hash)s_tr" % {'hash': hash_tag(source, context)}, line[source_len:] ) # this looks fishy buf = re.sub(re.escape(line), new_line, buf) stringset.strings.append(GenericTranslation(source, trans, rule=5, context=context, pluralized=False, fuzzy=False, obsolete=False)) self.stringset=stringset self.suggestions=suggestions if is_source: self.template = str(buf.encode('utf-8'))
def save_web_hook(sender, **kwargs): """Save a web hook, after saving a project (if defined).""" project = kwargs["instance"] form = kwargs["form"] url = form.cleaned_data["webhook"] if url: try: hook, created = WebHook.objects.get_or_create(project=project, kind="p", defaults={"url": url}) if not created: hook.url = url hook.save() except Exception, e: logger.error("Error saving hook for project %s: %s" % (project, e))
def visit_url(sender, **kwargs): """Visit the URL for the project. Send the slug of the project, the slug of the resource and the language of the translation as identifiers. Send the translation percentage as information. Args: sender: The rlstats object itself. Returns: True of False for success (or not). """ # TODO make it a celery task # TODO increase the timeout in celery stats = sender resource = stats.resource project = resource.project language = stats.language if 'post_function' in kwargs: post_function = kwargs['post_function'] else: post_function = requests.post hooks = WebHook.objects.filter(project=project) if not hooks: logger.debug("Project %s has no web hooks" % project.slug) return event_info = { 'project': project.slug, 'resource': resource.slug, 'language': language.code, 'percent': stats.translated_perc, } logger.debug("POST data for %s: %s" % (stats.resource.project.slug, event_info)) for hook in hooks: res = post_function(hook.url, data=event_info, allow_redirects=False, timeout=2.0) if res.ok: logger.debug("POST for project %s successful." % project) else: msg = "Error visiting webhook %s: HTTP code is %s" % ( hook, res.status_code) logger.error(msg)
def save_web_hook(sender, **kwargs): """Save a web hook, after saving a project (if defined).""" project = kwargs['instance'] form = kwargs['form'] url = form.cleaned_data['webhook'] if url: try: hook, created = WebHook.objects.get_or_create( project=project, kind='p', defaults={'url': url}) if not created: hook.url = url hook.save() except Exception, e: logger.error("Error saving hook for project %s: %s" % (project, e))
def visit_url(sender, **kwargs): """Visit the URL for the project. Send the slug of the project, the slug of the resource and the language of the translation as identifiers. Send the translation percentage as information. Args: sender: The rlstats object itself. Returns: True of False for success (or not). """ # TODO make it a celery task # TODO increase the timeout in celery stats = sender resource = stats.resource project = resource.project language = stats.language if 'post_function' in kwargs: post_function = kwargs['post_function'] else: post_function = requests.post hooks = WebHook.objects.filter(project=project) if not hooks: logger.debug("Project %s has no web hooks" % project.slug) return event_info = { 'project': project.slug, 'resource': resource.slug, 'language': language.code, 'percent': stats.translated_perc, } logger.debug( "POST data for %s: %s" % (stats.resource.project.slug, event_info) ) for hook in hooks: res = post_function(hook.url, data=event_info, allow_redirects=False, timeout=2.0) if res.ok: logger.debug("POST for project %s successful." % project) else: msg = "Error visiting webhook %s: HTTP code is %s" % ( hook, res.status_code) logger.error(msg)
def team_leave(request, project_slug, language_code): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project if request.POST: try: if (team.members.filter(username=request.user.username).exists() or team.reviewers.filter( username=request.user.username).exists()): team.members.remove(request.user) team.reviewers.remove(request.user) messages.info( request, _("You left the '%s' team.") % team.language.name) # ActionLog & Notification # TODO: Use signals nt = 'project_team_left' context = { 'team': team, 'performer': request.user, 'sender': request.user } # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for( project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators notification.send( set( itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) else: messages.info( request, _("You are not in the '%s' team.") % team.language.name) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def get_translation_file(request, project_slug, resource_slug, lang_code, **kwargs): """ View to export all translations of a resource for the requested language and give the translation file back to the user. """ resource = get_object_or_404(Resource, project__slug = project_slug, slug = resource_slug) language = get_object_or_404(Language, code=lang_code) try: fb = FormatsBackend(resource, language) template = fb.compile_translation(**kwargs) except Exception, e: messages.error(request, "Error compiling translation file.") logger.error("Error compiling '%s' file for '%s': %s" % (language, resource, str(e))) return HttpResponseRedirect(reverse('resource_detail', args=[resource.project.slug, resource.slug]),)
def file_extension_for(self, resource, language): """Return the filename extension that should be used for the specific resource-language pair. """ resource_method = resource.i18n_method try: if resource_method != 'PO': return self.extensions_for(resource_method)[0] if language is None: return self.extensions_for('POT')[0] return self.extensions_for(resource_method)[0] except IndexError, e: msg = "No extensions for resource %s: %s" logger.error(msg % (resource, e), exc_info=True) raise
def import_translation(self, content): """Parse a translation file for a resource. Args: content: The content to parse. Returns: A two element tuple(pair). The first element is the number of strings added and the second one is the number of those upadted. """ handler = self._get_handler(self.resource, self.language) if handler is None: msg = "Files of type %s are not supported." logger.error(msg % self.resource.i18n_method) raise FormatsBackendError(msg % self.resource.i18n_method) return self._import_content(handler, content, False)
def import_translation(self, content): """Parse a translation file for a resource. Args: content: The content to parse. Returns: A two element tuple(pair). The first element is the number of strings added and the second one is the number of those upadted. """ handler = self._get_handler(self.resource, self.language) if handler is None: msg = _("Invalid i18n method used: %s") logger.error(msg % self.resource.i18n_method) raise FormatsBackendError(msg) return self._import_content(handler, content, False)
def get_pot_file(request, project_slug, resource_slug): """ View to download the pot file of the resource. """ resource = get_object_or_404(Resource, project__slug=project_slug, slug=resource_slug) try: fb = FormatsBackend(resource, None) template = fb.compile_translation() except Exception, e: messages.error(request, _("Error compiling the pot file.")) logger.error("Error compiling the pot file for %s: %s" % (resource, e)) return HttpResponseRedirect( reverse('resource_detail', args=[resource.project.slug, resource.slug]))
def get(self, pseudo_type, mode=None): """ Return the requested translation as a file. Returns: The compiled template. Raises: BadRequestError: There was a problem with the request. """ try: fb = FormatsBackend(self.resource, self.language) return fb.compile_translation(pseudo_type, mode=mode) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("Error compiling the translation file: %s" %e )
def create(self): """ Creates a new translation from file. Returns: A dict with information for the translation. Raises: BadRequestError: There was a problem with the request. NoContentError: There was no file in the request. """ if not self.request.FILES: raise NoContentError("No file has been uploaded.") submitted_file = self.request.FILES.values()[0] name = str(submitted_file.name) size = submitted_file.size try: file_ = tempfile.NamedTemporaryFile( mode='wb', suffix=name[name.rfind('.'):], delete=False ) for chunk in submitted_file.chunks(): file_.write(chunk) file_.close() parser = registry.appropriate_handler( self.resource, language=self.language, filename=name ) parser.bind_file(file_.name) if parser is None: raise BadRequestError("Unknown file type") if size == 0: raise BadRequestError("Empty file") try: parser.is_content_valid() logger.debug("Uploaded file %s" % file_.name) except (FileCheckError, ParseError), e: raise BadRequestError("Error uploading file: %s" % e) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("A strange error happened.")
def get(self, pseudo_type, mode=None): """ Return the requested translation as a file. Returns: The compiled template. Raises: BadRequestError: There was a problem with the request. """ try: fb = FormatsBackend(self.resource, self.language) return fb.compile_translation(pseudo_type, mode=mode) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("Error compiling the translation file: %s" % e)
def get(self, pseudo_type): """ Return the requested translation as a file. Returns: The compiled template. Raises: BadRequestError: There was a problem with the request. """ try: template = _compile_translation_template( self.resource, self.language, pseudo_type ) except Exception, e: logger.error(e.message, exc_info=True) return BadRequestError("Error compiling the translation file: %s" %e )
def get_pot_file(request, project_slug, resource_slug): """ View to download the pot file of the resource. """ resource = get_object_or_404( Resource, project__slug=project_slug, slug=resource_slug ) try: template = _compile_translation_template(resource, None) except Exception, e: messages.error(request, _("Error compiling the pot file.")) logger.error( "Error compiling the pot file for %s: %s" % (resource, e.message) ) return HttpResponseRedirect(reverse( 'resource_detail', args=[resource.project.slug, resource.slug] ))
def team_request_approve(request, project_slug, language_code): team_request = get_object_or_404(TeamRequest, project__slug=project_slug, language__code=language_code) project = team_request.project if request.POST: try: team = Team(project=team_request.project, language=team_request.language, creator=request.user) team.save() team.coordinators.add(team_request.user) team.save() team_request.delete() messages.success( request, _("You approved the '%(team)s' team requested by '%(user)s'.") % { 'team': team.language.name, 'user': team_request.user }) # ActionLog & Notification # TODO: Use signals nt = 'project_team_added' context = {'team': team, 'sender': request.user} # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for( project, signal=nt, extra_context=context) # Send notification for maintainers and coordinators notification.send( set( itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def project_hub_join_approve(request, project_slug, outsourced_project_slug): hub_request = get_object_or_404(HubRequest, project__slug=outsourced_project_slug, project_hub__slug=project_slug) outsourced_project = hub_request.project if request.POST: try: outsourced_project.outsource = hub_request.project_hub outsourced_project.anyone_submit = False outsourced_project.save() _hub_request = copy.copy(hub_request) hub_request.delete() messages.success( request, _("You added '%(project)s' to the " "'%(project_hub)s' project hub") % { 'project': outsourced_project, 'project_hub': hub_request.project_hub }) # ActionLog & Notification nt = 'project_hub_join_approved' context = {'hub_request': hub_request, 'sender': request.user} # Logging action action_logging(request.user, [outsourced_project, hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(outsourced_project.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e)) project_outsourced_changed.send(sender=hub_request.project_hub)
def team_join_approve(request, project_slug, language_code, username): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project user = get_object_or_404(User, username=username) access_request = get_object_or_404(TeamAccessRequest, team__pk=team.pk, user__pk=user.pk) if request.POST: if user in team.members.all() or \ user in team.coordinators.all(): messages.warning(request, _("User '%(user)s' is already on the '%(team)s' team.") % {'user':user, 'team':team.language.name}) access_request.delete() try: team.members.add(user) team.save() messages.success(request, _("You added '%(user)s' to the '%(team)s' team.") % {'user':user, 'team':team.language.name}) access_request.delete() # ActionLog & Notification # TODO: Use signals nt = 'project_team_join_approved' context = {'access_request': access_request, 'sender': request.user} # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for(project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators and the user notification.send(set(itertools.chain(project.maintainers.all(), team.coordinators.all(), [access_request.user])), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def add_edit_developer_comment_extra(request, project_slug, *args, **kwargs): """ View for handling AJAX calls from Lotte in order to add/edit the developer comment for a source entity. Only maintainers can edit it. """ # Permissions handling project = get_object_or_404(Project, slug=project_slug) check = ProjectPermission(request.user) if not check.maintain(project): content = {'error': True, 'message': _('Permission error.')} elif not request.POST: content = {'error': True, 'message': _('Bad request.')} else: previous_comment = None try: se = SourceEntity.objects.get(id=request.POST.get( 'source_entity_id', None), resource__project=project) previous_comment_extra = se.developer_comment_extra se.developer_comment_extra = request.POST.get('comment_extra', '') se.save() content = { 'error': False, 'comment': se.developer_comment, 'comment_extra': se.developer_comment_extra, } except SourceEntity.DoesNotExist: content = { 'error': True, 'message': _('No such Source Entity for the given project.'), } except Exception, e: logger.error('Lotte: Error while editing developer comment: %s' % (e.message or str(e))) content = { 'error': True, 'message': _('Ops! Something weird happened. The admins ' 'were notified about it.'), }
def project_hub_join_deny(request, project_slug, outsourced_project_slug): hub_request = get_object_or_404(HubRequest, project__slug=outsourced_project_slug, project_hub__slug=project_slug) outsourced_project = hub_request.project if request.POST: try: _hub_request = copy.copy(hub_request) hub_request.delete() messages.info( request, _("You rejected the request of " "'%(project)s' to join the '%(project_hub)s' project hub") % { 'project': outsourced_project, 'project_hub': _hub_request.project_hub }) # ActionLog & Notification # TODO: Use signals nt = 'project_hub_join_denied' context = {'hub_request': hub_request, 'sender': request.user} # Logging action action_logging(request.user, [outsourced_project, _hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(outsourced_project.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % e.message) project_outsourced_changed.send(sender=hub_request.project_hub)
def team_request_deny(request, project_slug, language_code): team_request = get_object_or_404(TeamRequest, project__slug=project_slug, language__code=language_code) project = team_request.project if request.POST: try: team_request.delete() messages.success( request, _("You rejected the request by '%(user)s' for a '%(team)s' team." ) % { 'team': team_request.language.name, 'user': team_request.user }) # ActionLog & Notification # TODO: Use signals nt = 'project_team_request_denied' context = { 'team_request': team_request, 'performer': request.user, 'sender': request.user } # Logging action action_logging(request.user, [project], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for( project, signal=nt, extra_context=context) # Send notification for maintainers and the user notification.send( set( itertools.chain(project.maintainers.all(), [team_request.user])), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def team_join_withdraw(request, project_slug, language_code): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project access_request = get_object_or_404(TeamAccessRequest, team__pk=team.pk, user__pk=request.user.pk) if request.POST: try: access_request.delete() messages.success( request, _("You withdrew your request to join the '%s' team.") % team.language.name) # ActionLog & Notification # TODO: Use signals nt = 'project_team_join_withdrawn' context = { 'access_request': access_request, 'performer': request.user, 'sender': request.user } # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for( project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators notification.send( set( itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def create(self): """ Creates a new translation from file. Returns: A dict with information for the translation. Raises: BadRequestError: There was a problem with the request. NoContentError: There was no file in the request. """ if not self.request.FILES: raise NoContentError("No file has been uploaded.") submitted_file = self.request.FILES.values()[0] name = str(submitted_file.name) size = submitted_file.size try: file_ = tempfile.NamedTemporaryFile(mode='wb', suffix=name[name.rfind('.'):], delete=False) for chunk in submitted_file.chunks(): file_.write(chunk) file_.close() parser = registry.appropriate_handler(self.resource, language=self.language, filename=name) parser.bind_file(file_.name) if parser is None: raise BadRequestError("Unknown file type") if size == 0: raise BadRequestError("Empty file") try: parser.is_content_valid() logger.debug("Uploaded file %s" % file_.name) except (FileCheckError, ParseError), e: raise BadRequestError("Error uploading file: %s" % e) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("A strange error happened.")
class DTDHandler(SimpleCompilerFactory, Handler): """ Handler for DTD translation files. """ default_encoding = 'UTF-8' format_encoding = 'UTF-8' name = "DTD file handler" format = "DTD (*.dtd)" method_name = "DTD" HandlerParseError = DTDParseError HandlerCompileError = DTDCompileError def _escape(self, s): """Escape format content. HTML escape quotes, ampersands and angle brackets single quotes are omitted, because double quotes around the value are forced in template """ return xml_escape(s, {'"': '"', '%': '%'}) def _unescape(self, s): """ Unescape entities for easy editing """ return xml_unescape( s, { '"': '"', ''': "'", '%': '%', ''': "'", '%': '%', ''': "'", }) def _get_content_from_file(self, filename, encoding): fh = open(filename, "r") try: text = fh.read().decode(encoding) fh.close() except UnicodeDecodeError as e: logger.warning( "Unicode decode error in DTDHandler.parse_file(): %s" % unicode(e), exc_info=True) raise self.HandlerParseError(unicode(e)) except IOError, e: logger.warning( "Error opening file %s with encoding %s: %s" %\ (filename, encoding, e.message), exc_info=True ) raise FormatError(e.message) except Exception, e: logger.error("Unhandled exception in DTDHandler.parse_file(): %s" % unicode(e), exc_info=True) raise self.HandlerParseError(unicode(e))
def add_edit_developer_comment_extra(request, project_slug, *args, **kwargs): """ View for handling AJAX calls from Lotte in order to add/edit the developer comment for a source entity. Only maintainers can edit it. """ # Permissions handling project = get_object_or_404(Project, slug=project_slug) check = ProjectPermission(request.user) if not check.maintain(project): content = {'error': True, 'message': _('Permission error.')} elif not request.POST: content = {'error': True, 'message': _('Bad request.')} else: previous_comment = None try: se = SourceEntity.objects.get( id=request.POST.get('source_entity_id', None), resource__project=project) previous_comment_extra = se.developer_comment_extra se.developer_comment_extra = request.POST.get('comment_extra', '') se.save() content = { 'error': False, 'comment': se.developer_comment, 'comment_extra': se.developer_comment_extra, } except SourceEntity.DoesNotExist: content = { 'error': True, 'message': _('No such Source Entity for the given project.'), } except Exception, e: logger.error('Lotte: Error while editing developer comment: %s' % (e.message or str(e))) content = { 'error': True, 'message': _('Ops! Something weird happened. The admins ' 'were notified about it.'), }
def error_contacting_app(request, url, app, exception): """Handle the case, where an app did not respond. This view is called, if there was a HTTP error, when contacting the remote tx app. """ if all([exception.status_code, exception.content]): log_msg = ("Error visiting URL %s for app %s: status code " "was %s and error_message %s" % (url, app.name, exception.status_code, exception.content)) view_msg = _("TxApp responded with an error: %s" % exception.content) else: log_msg = "Error contacting remote server: url is %s" % url view_msg = _("Error contacting app.") logger.error(log_msg) return render_to_response('txapp_error.html', { 'app_name': app.name, 'error_message': view_msg }, context_instance=RequestContext(request))
def team_leave(request, project_slug, language_code): team = get_object_or_404(Team, project__slug=project_slug, language__code=language_code) project = team.project if request.POST: try: if (team.members.filter(username=request.user.username).exists() or team.reviewers.filter(username=request.user.username).exists()): team.members.remove(request.user) team.reviewers.remove(request.user) messages.info(request, _( "You left the '%s' team." ) % team.language.name) # ActionLog & Notification # TODO: Use signals nt = 'project_team_left' context = {'team': team, 'performer': request.user, 'sender': request.user} # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for(project, signal=nt, extra_context=context) # Send notification for maintainers, coordinators notification.send(set(itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) else: messages.info(request, _( "You are not in the '%s' team." ) % team.language.name) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def import_source(self, content, filename=None): """Parse some content which is of a particular i18n type and save it to the database. Args: content: The content to parse. filename: The filename of the uploaded content (if any). Returns: A two-element tuple (pair). The first element is the number of strings added and the second one is the number of those updated. """ if self.language is None: msg = _("No language specified, when importing source file.") logger.error(msg) raise FormatsBackendError(msg) handler = self._get_handler(self.resource, self.language, filename=filename) if handler is None: msg = "Files of type %s are not supported." logger.error(msg % self.resource.i18n_method) raise FormatsBackendError(msg % self.resource.i18n_method) return self._import_content(handler, content, True)
def project_hub_join_approve(request, project_slug, outsourced_project_slug): hub_request = get_object_or_404(HubRequest, project__slug=outsourced_project_slug, project_hub__slug=project_slug) outsourced_project = hub_request.project if request.POST: try: outsourced_project.outsource = hub_request.project_hub outsourced_project.anyone_submit = False outsourced_project.save() _hub_request = copy.copy(hub_request) hub_request.delete() messages.success(request, _("You added '%(project)s' to the " "'%(project_hub)s' project hub")% { 'project':outsourced_project, 'project_hub':hub_request.project_hub}) # ActionLog & Notification nt = 'project_hub_join_approved' context = {'hub_request': hub_request, 'sender': request.user} # Logging action action_logging(request.user, [outsourced_project, hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(outsourced_project.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e)) project_outsourced_changed.send(sender=hub_request.project_hub)
def get_translation_file(request, project_slug, resource_slug, lang_code, **kwargs): """ View to export all translations of a resource for the requested language and give the translation file back to the user. """ resource = get_object_or_404(Resource, project__slug=project_slug, slug=resource_slug) language = get_object_or_404(Language, code=lang_code) try: fb = FormatsBackend(resource, language) template = fb.compile_translation(**kwargs) except Exception, e: messages.error(request, "Error compiling translation file.") logger.error("Error compiling '%s' file for '%s': %s" % (language, resource, str(e))) return HttpResponseRedirect( reverse('resource_detail', args=[resource.project.slug, resource.slug]), )
def _get_formatted_message(label, context): """ Return a message that is a rendered template with the given context using the default language of the system. """ current_language = get_language() # Setting the environment to the default language activate(settings.LANGUAGE_CODE) c = Context(context) template = 'notification/%s/notice.html' % label try: msg = loader.get_template(template).render(c) except TemplateDoesNotExist: logger.error("Template '%s' doesn't exist." % template) msg = None # Reset environment to original language activate(current_language) return msg
def team_request_approve(request, project_slug, language_code): team_request = get_object_or_404(TeamRequest, project__slug=project_slug, language__code=language_code) project = team_request.project if request.POST: try: team = Team(project=team_request.project, language=team_request.language, creator=request.user) team.save() team.coordinators.add(team_request.user) team.save() team_request.delete() messages.success(request, _( "You approved the '%(team)s' team requested by '%(user)s'." ) % {'team':team.language.name, 'user':team_request.user}) # ActionLog & Notification # TODO: Use signals nt = 'project_team_added' context = {'team': team, 'sender': request.user} # Logging action action_logging(request.user, [project, team], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for those that are observing this project txnotification.send_observation_notices_for(project, signal=nt, extra_context=context) # Send notification for maintainers and coordinators notification.send(set(itertools.chain(project.maintainers.all(), team.coordinators.all())), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % str(e))
def forwards(self, orm): "Write your forwards methods here." for se in orm.SourceEntity.objects.all(): old_hash = se.string_hash try: if se.context == 'None' or not se.context: se.context = "" se.save() except utils.IntegrityError: logger.error( "Failed to update one of the source entities" " for resource %s. Please re-upload the source file for that" " resource." % '.'.join([se.resource.project.slug, se.resource.slug])) continue new_hash = se.string_hash template = orm.Template.objects.get(resource=se.resource) template.content = re.sub(str(old_hash), str(new_hash), template.content) template.save()
def get(self, start=None, end=None, pseudo_type=None, mode=None): """ Return the requested translation in a json string. If self.language is None, return all translations. Args: start: Start for pagination. end: End for pagination. pseudo_type: The pseudo_type requested. mode: The mode for the compilation. Returns: A dict with the translation(s). Raises: BadRequestError: There was a problem with the request. """ try: fb = FormatsBackend(self.resource, self.language) template = fb.compile_translation(pseudo_type, mode=mode) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError("Error compiling the translation file: %s" % e)
def project_hub_join_withdraw(request, project_slug): # project_slug here refers to outsourced_project_slug. It was kept like # it to keep consistency across url regexes. hub_request = get_object_or_404(HubRequest, project__slug=project_slug) if request.POST: try: _hub_request = copy.copy(hub_request) hub_request.delete() messages.success( request, _("Request to join '%s' project hub " "was withdrawn") % _hub_request.project_hub) # ActionLog & Notification # TODO: Use signals nt = 'project_hub_join_withdrawn' context = { 'hub_request': _hub_request, 'performer': request.user, 'sender': request.user } # Logging action action_logging(request.user, [_hub_request.project, hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(_hub_request.project_hub.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % e.message)
def project_hub_join_deny(request, project_slug, outsourced_project_slug): hub_request = get_object_or_404(HubRequest, project__slug=outsourced_project_slug, project_hub__slug=project_slug) outsourced_project = hub_request.project if request.POST: try: _hub_request = copy.copy(hub_request) hub_request.delete() messages.info(request, _("You rejected the request of " "'%(project)s' to join the '%(project_hub)s' project hub")% { 'project': outsourced_project, 'project_hub':_hub_request.project_hub}) # ActionLog & Notification # TODO: Use signals nt = 'project_hub_join_denied' context = {'hub_request': hub_request, 'sender': request.user} # Logging action action_logging(request.user, [outsourced_project, _hub_request.project_hub], nt, context=context) if settings.ENABLE_NOTICES: # Send notification for maintainers, coordinators and the user notification.send(outsourced_project.maintainers.all(), nt, context) except IntegrityError, e: transaction.rollback() logger.error("Something weird happened: %s" % e.message) project_outsourced_changed.send(sender=hub_request.project_hub)
def _update(self, request, project_slug, resource_slug, lang_code=None): # Permissions handling try: resource = Resource.objects.select_related('project').get( slug=resource_slug, project__slug=project_slug) except Resource.DoesNotExist: return rc.NOT_FOUND source_push = False if lang_code == "source": language = resource.source_language source_push = True else: try: language = Language.objects.by_code_or_alias(lang_code) except Language.DoesNotExist: logger.error("Weird! Selected language code (%s) does " "not match with any language in the database." % lang_code) return BAD_REQUEST( "Selected language code (%s) does not match with any" "language in the database." % lang_code) team = Team.objects.get_or_none(resource.project, lang_code) check = ProjectPermission(request.user) if source_push and not check.maintain(resource.project): return rc.FORBIDDEN elif (not check.submit_translations(team or resource.project) or\ not resource.accept_translations) and not\ check.maintain(resource.project): return rc.FORBIDDEN try: t = Translation.get_object("create", request, resource, language) res = t.create() except BadRequestError, e: return BAD_REQUEST(unicode(e))
def get(self, start=None, end=None, pseudo_type=None, mode=None): """ Return the requested translation in a json string. If self.language is None, return all translations. Args: start: Start for pagination. end: End for pagination. pseudo_type: The pseudo_type requested. mode: The mode for the compilation. Returns: A dict with the translation(s). Raises: BadRequestError: There was a problem with the request. """ try: fb = FormatsBackend(self.resource, self.language) template = fb.compile_translation(pseudo_type, mode=mode) except Exception, e: logger.error(unicode(e), exc_info=True) raise BadRequestError( "Error compiling the translation file: %s" % e )
def update_source_file(self, fake=False): """ Fetch source file from remote url and import it, updating existing entries. """ try: source_file = urllib2.urlopen(self.source_file_url) except: logger.error("Could not pull source file for resource %s (%s)" % (self.resource.full_name, self.source_file_url)) raise filename = '' if source_file.info().has_key('Content-Disposition'): # If the response has Content-Disposition, we try to take # filename from it content = source_file.info()['Content-Disposition'] if 'filename' in content: filename = content.split('filename')[1] filename = filename.replace('"', '').replace("'", "").replace( "=", "").replace('/', '-').strip() if filename == '': parts = urlparse.urlsplit(self.source_file_url) #FIXME: This still might end empty filename = parts.path.split('/')[-1] try: if not self.resource.i18n_method: msg = "No i18n method defined for resource %s" logger.error(msg % self.resource) return parser = registry.appropriate_handler( self.resource, language=self.resource.source_language, filename=filename) language = self.resource.source_language content = source_file.read() parser.bind_content(content) parser.set_language(language) parser.bind_resource(self.resource) parser.is_content_valid() parser.parse_file(is_source=True) strings_added, strings_updated = 0, 0 if not fake: strings_added, strings_updated = parser.save2db(is_source=True) except Exception, e: logger.error( "Error importing source file for resource %s.%s (%s): %s" % (self.resource.project.slug, self.resource.slug, self.source_file_url, str(e))) raise
else: # In cases of pluralized translations, sometimes only one # translation will exist and the rest plural forms will be # empty. If the user wants to delete all of them, we need # to let by the ones that don't already have a translation. if not source_string.source_entity.pluralized: raise LotteBadRequestError( _("The translation string is empty")) except LotteBadRequestError, e: logger.debug("%s" % e, exc_info=True) raise # catch-all. if we don't save we _MUST_ inform the user except Exception, e: msg = _("Error occurred while trying to save translation: %s" % unicode(e)) logger.error(msg, exc_info=True) raise LotteBadRequestError(msg) return warnings def _add_copyright(source_string, target_language, user): from transifex.addons.copyright.handlers import lotte_copyrights lotte_save_translation.connect(lotte_copyrights) lotte_save_translation.send(None, resource=source_string.resource, language=target_language, user=user) # Restrict access only for private projects since this is used to fetch stuff # Allow even anonymous access on public projects
def push_translation(request, project_slug, lang_code, *args, **kwargs): """ Client pushes an id and a translation string. Id is considered to be of the source translation string and the string is in the target_lang. FIXME: Document in detail the form of the 'strings' POST variable. """ logger.debug("POST data when saving translation: %s" % request.POST) # Permissions handling # Project should always be available project = get_object_or_404(Project, slug=project_slug) team = Team.objects.get_or_none(project, lang_code) check = ProjectPermission(request.user) if not check.submit_translations(team or project) and not\ check.maintain(project): return permission_denied(request) if not request.POST: return HttpResponseBadRequest() data = simplejson.loads(request.raw_post_data) strings = data["strings"] try: target_language = Language.objects.by_code_or_alias(lang_code) except Language.DoesNotExist: raise Http404 # This dictionary will hold the results of the save operation and will map # status code for each translation pushed, to indicate the result on each # translation push separately. push_response_dict = {} # Form the strings dictionary, get as Json object # The fields are the following: # id-> source_entity id # translations-> translation strings (includes all plurals) # context-> source_entity context # occurrence-> occurrence (not yet well supported) # Iterate through all the row data that have been sent. for row in strings: source_id = int(row['id']) try: source_string = Translation.objects.select_related(depth=1).get( id=source_id) except Translation.DoesNotExist: # TODO: Log or inform here push_response_dict[source_id] = { 'status': 400, 'message': _("Source string cannot be identified in the DB") } # If the source_string cannot be identified in the DB then go to next # translation pair. continue if not source_string.resource.accept_translations: push_response_dict[source_id] = { 'status': 400, 'message': _("The resource of this source string is not " "accepting translations.") } # If the translated source string is pluralized check that all the # source language supported rules have been filled in, else return error # and donot save the translations. if source_string.source_entity.pluralized: error_flag = False for rule in target_language.get_pluralrules(): if rule in row[ 'translations'] and row['translations'][rule] != "": continue else: error_flag = True if error_flag: error_flag = False # Check also if all of them are "". If yes, delete all the plurals! for rule in target_language.get_pluralrules(): if rule in row['translations'] and row['translations'][ rule] == "": continue else: error_flag = True if error_flag: push_response_dict[source_id] = { 'status': 400, 'message': (_("Cannot save unless plural translations are either " "completely specified or entirely empty!")) } # Skip the save as we hit on an error. continue try: msgs = _save_translation(source_string, row['translations'], target_language, request.user) if not msgs: push_response_dict[source_id] = {'status': 200} else: push_response_dict[source_id] = { 'status': 200, 'message': msgs[-1] } except LotteBadRequestError, e: push_response_dict[source_id] = { 'status': 400, 'message': e.message } except Exception, e: logger.error("Unexpected exception raised: %s" % e.message, exc_info=True) push_response_dict[source_id] = { 'status': 400, 'message': e.message }
msg = _("Error creating resource: %s") logger.warning(msg % e) raise ResourceBackendError(msg % e) # save source entities try: fb = FormatsBackend(r, source_language, user) except AttributeError, e: raise ResourceBackendError( _("The content type of the request is not valid.")) try: return fb.import_source(content, filename=extra_data.get('filename')) except FormatsBackendError, e: raise ResourceBackendError(unicode(e)) except Exception, e: logger.error("Unexamined exception raised: %s" % e, exc_info=True) raise ResourceBackendError(unicode(e)) class FormatsBackend(object): """Backend for formats operations.""" def __init__(self, resource, language, user=None): """Initializer. Args: resource: The resource the translations will belong to. language: The language of the translation. """ self.resource = resource self.language = language self.user = user