+++ /dev/null
-from django.contrib import admin
-
-from api import models
-
-class PullRequestAdmin(admin.ModelAdmin):
- list_display = ('comitter', 'timestamp', 'comment', 'document', 'source_revision')
-
-admin.site.register(models.PullRequest, PullRequestAdmin)
-admin.site.register(models.PartCache)
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-09-20 21:34:52$"
-__doc__ = "Micro-forms for the API."
-
-from django import forms
-from api.models import PullRequest
-from django.contrib.auth.models import User
-
-import re
-from django.utils import simplejson as json
-
-class MergeRequestForm(forms.Form):
- # should the target document revision be updated or shared
- type = forms.ChoiceField(choices=(('update', 'Update'), ('share', 'Share')) )
-
- #
- # if type == update:
- # * user's revision which is the base of the merge
- # if type == share:
- # * revision which will be pulled to the main branch
- #
- # NOTE: the revision doesn't have to be owned by the user
- # who requests the merge:
- # a) Every user can update his branch
- # b) Some users can push their changes
- # -> if they can't, they leave a PRQ
- # c) Some users can pull other people's changes
- # d) Some users can update branches owned by special
- # users associated with PRQ's
- revision = forms.RegexField('[0-9a-f]{40}')
-
- # any additional comments that user wants to add to the change
- message = forms.CharField(required=False)
-
-class DocumentUploadForm(forms.Form):
- ocr_file = forms.FileField(label='Source OCR file', required=False)
- ocr_data = forms.CharField(widget=forms.HiddenInput(), required=False)
-
- bookname = forms.RegexField(regex=r'[0-9\.\w_-]+', \
- label='Publication name', help_text='Example: słowacki__beniowski__pieśń_1')
-
- generate_dc = forms.BooleanField(required=False, \
- initial=True, label=u"Generate DublinCore template")
-
-
- def clean(self):
- clean_data = self.cleaned_data
-
- ocr_file = clean_data['ocr_file']
- ocr_data = clean_data['ocr_data']
-
- if not ocr_file and not ocr_data:
- raise forms.ValidationError(
- "You must either provide file descriptor or raw data." )
-
- return clean_data
-
-PRQ_USER_RE = re.compile(r"^\$prq-(\d{1,10})$", re.UNICODE)
-
-class DocumentRetrieveForm(forms.Form):
- revision = forms.RegexField(regex=r'latest|[0-9a-z]{40}', required=False)
- user = forms.CharField(required=False)
-
- def clean_user(self):
- # why, oh why doesn't django implement this!!!
- # value = super(DocumentRetrieveForm, self).clean_user()
- value = self.cleaned_data['user']
-
- if value.startswith('$'):
- # library user (... maybe later)
- if value == '$library':
- raise forms.ValidationError("Invalid user name '%s'" % value)
-
- m = PRQ_USER_RE.match(value)
-
- if m:
- try:
- return value
- except:
- raise forms.ValidationError("User doesn't exist.")
- raise forms.ValidationError("Invalid user name '%s'" % value)
- try:
- return value
- except:
- raise forms.ValidationError("User doesn't exist.")
-
-
-class TextRetrieveForm(DocumentRetrieveForm):
- chunk = forms.CharField(required=False)
- format = forms.CharField(required=False)
-
- def clean_format(self):
- value = self.cleaned_data['format']
- if not value:
- return 'raw'
-
- if value not in ('nl', 'raw'):
- raise forms.ValidationError("Invalid text format")
- return value
-
-class TextUpdateForm(DocumentRetrieveForm):
- message = forms.CharField(required=False)
- contents = forms.CharField(required=False)
- chunks = forms.CharField(required=False)
-
- format = forms.CharField(required=False)
-
- def clean_format(self):
- value = self.cleaned_data['format']
- if not value:
- return 'raw'
-
- if value not in ('nl', 'raw'):
- raise forms.ValidationError("Invalid text format")
- return value
-
- def clean_message(self):
- value = self.cleaned_data['message']
-
- if value:
- return u"$USER$ " + value
- else:
- return u"$AUTO$ XML content update."
-
- def clean_chunks(self):
- value = self.cleaned_data['chunks']
-
- try:
- return json.loads(value)
- except Exception, e:
- forms.ValidationError("Invalid JSON: " + e.message)
-
-
- def clean(self):
- if self.cleaned_data['contents'] and self.cleaned_data['chunks']:
- raise forms.ValidationError("Pass either contents or chunks - not both ")
-
- if not self.cleaned_data['contents'] and not self.cleaned_data['chunks']:
- raise forms.ValidationError("You must pass contents or chunks.")
-
- return self.cleaned_data
\ No newline at end of file
+++ /dev/null
-# -*- encoding: utf-8 -*-
-import os.path
-
-import logging
-log = logging.getLogger('platforma.api.library')
-
-from piston.handler import BaseHandler, AnonymousBaseHandler
-from piston.utils import rc
-
-from datetime import date
-
-from django.core.urlresolvers import reverse
-from django.db import IntegrityError
-
-import librarian
-import librarian.html
-import difflib
-import wlrepo
-
-from explorer.models import GalleryForDocument
-
-# internal imports
-import api.forms as forms
-import api.response as response
-from api.utils import validate_form, hglibrary, natural_order
-from api.models import PartCache, PullRequest
-
-from pygments import highlight
-from pygments.lexers import DiffLexer
-from pygments.formatters import HtmlFormatter
-
-#
-import settings
-
-
-def is_prq(username):
- return username.startswith('$prq-')
-
-def prq_for_user(username):
- try:
- return PullRequest.objects.get(id=int(username[5:]))
- except:
- return None
-
-def check_user(request, user):
- log.info("user: %r, perm: %r" % (request.user, request.user.get_all_permissions()) )
- #pull request
- if is_prq(user):
- if not request.user.has_perm('api.view_prq'):
- yield response.AccessDenied().django_response({
- 'reason': 'access-denied',
- 'message': "You don't have enough priviliges to view pull requests."
- })
- # other users
- elif request.user.username != user:
- if not request.user.has_perm('api.view_other_document'):
- yield response.AccessDenied().django_response({
- 'reason': 'access-denied',
- 'message': "You don't have enough priviliges to view other people's document."
- })
- pass
-
-#
-# Document List Handlers
-#
-# TODO: security check
-class BasicLibraryHandler(AnonymousBaseHandler):
- allowed_methods = ('GET',)
-
- @hglibrary
- def read(self, request, lib):
- """Return the list of documents."""
- document_list = [{
- 'url': reverse('document_view', args=[docid]),
- 'name': docid } for docid in lib.documents() ]
- return {'documents' : document_list}
-
-#
-# This handler controlls the document collection
-#
-class LibraryHandler(BaseHandler):
- allowed_methods = ('GET', 'POST')
- anonymous = BasicLibraryHandler
-
- @hglibrary
- def read(self, request, lib):
- """Return the list of documents."""
-
- documents = {}
-
- for docid in lib.documents():
- documents[docid] = {
- 'url': reverse('document_view', args=[docid]),
- 'name': docid,
- 'parts': []
- }
-
- parts = PartCache.objects.defer('part_id')\
- .values_list('part_id', 'document_id').distinct()
-
- document_tree = dict(documents)
-
- for part, docid in parts:
- # this way, we won't display broken links
- if not documents.has_key(part):
- log.info("NOT FOUND: %s", part)
- continue
-
- parent = documents[docid]
- child = documents[part]
-
- # not top-level anymore
- document_tree.pop(part)
- parent['parts'].append(child)
-
- for doc in documents.itervalues():
- doc['parts'].sort(key=natural_order(lambda d: d['name']))
-
- return {'documents': sorted(document_tree.itervalues(),
- key=natural_order(lambda d: d['name']) ) }
-
-
- @validate_form(forms.DocumentUploadForm, 'POST')
- @hglibrary
- def create(self, request, form, lib):
- """Create a new document."""
-
- if form.cleaned_data['ocr_data']:
- data = form.cleaned_data['ocr_data']
- else:
- data = request.FILES['ocr_file'].read().decode('utf-8')
-
- if data is None:
- return response.BadRequest().django_response('You must pass ocr_data or ocr_file.')
-
- if form.cleaned_data['generate_dc']:
- data = librarian.wrap_text(data, unicode(date.today()))
-
- docid = form.cleaned_data['bookname']
-
- try:
- lock = lib.lock()
- try:
- log.info("DOCID %s", docid)
- doc = lib.document_create(docid)
- # document created, but no content yet
- try:
- doc = doc.quickwrite('xml', data.encode('utf-8'),
- '$AUTO$ XML data uploaded.', user=request.user.username)
- except Exception,e:
- import traceback
- # rollback branch creation
- lib._rollback()
- raise wlrepo.LibraryException(traceback.format_exc())
-
- url = reverse('document_view', args=[doc.id])
-
- return response.EntityCreated().django_response(\
- body = {
- 'url': url,
- 'name': doc.id,
- 'revision': doc.revision },
- url = url )
- finally:
- lock.release()
- except wlrepo.LibraryException, e:
- import traceback
- return response.InternalError().django_response({
- "reason": traceback.format_exc()
- })
- except wlrepo.DocumentAlreadyExists:
- # Document is already there
- return response.EntityConflict().django_response({
- "reason": "already-exists",
- "message": "Document already exists." % docid
- })
-
-#
-# Document Handlers
-#
-
-class DiffHandler(BaseHandler):
- allowed_methods = ('GET',)
-
- @hglibrary
- def read(self, request, docid, lib):
- '''Return diff between source_revision and target_revision)'''
- revision = request.GET.get('revision')
- if not revision:
- return ''
- source_document = lib.document(docid)
- target_document = lib.document_for_revision(revision)
- print source_document, target_document
-
- diff = difflib.unified_diff(
- source_document.data('xml').splitlines(True),
- target_document.data('xml').splitlines(True),
- 'source',
- 'target')
-
- s = ''.join(list(diff))
- return highlight(s, DiffLexer(), HtmlFormatter(cssclass="pastie"))
-
-
-#
-# Document Meta Data
-#
-class DocumentHandler(BaseHandler):
- allowed_methods = ('GET', 'PUT')
-
- @validate_form(forms.DocumentRetrieveForm, 'GET')
- @hglibrary
- def read(self, request, form, docid, lib):
- """Read document's meta data"""
- log.info(u"User '%s' wants to edit %s(%s) as %s" % \
- (request.user.username, docid, form.cleaned_data['revision'], form.cleaned_data['user']) )
-
- user = form.cleaned_data['user'] or request.user.username
- rev = form.cleaned_data['revision'] or 'latest'
-
- for error in check_user(request, user):
- return error
-
- try:
- doc = lib.document(docid, user, rev=rev)
- except wlrepo.RevisionMismatch, e:
- # the document exists, but the revision is bad
- return response.EntityNotFound().django_response({
- 'reason': 'revision-mismatch',
- 'message': e.message,
- 'docid': docid,
- 'user': user,
- })
- except wlrepo.RevisionNotFound, e:
- # the user doesn't have this document checked out
- # or some other weird error occured
- # try to do the checkout
- try:
- if user == request.user.username:
- mdoc = lib.document(docid)
- doc = mdoc.take(user)
- elif is_prq(user):
- prq = prq_for_user(user)
- # commiter's document
- prq_doc = lib.document_for_revision(prq.source_revision)
- doc = prq_doc.take(user)
- else:
- return response.EntityNotFound().django_response({
- 'reason': 'document-not-found',
- 'message': e.message,
- 'docid': docid,
- 'user': user,
- })
- except wlrepo.RevisionNotFound, e:
- return response.EntityNotFound().django_response({
- 'reason': 'document-not-found',
- 'message': e.message,
- 'docid': docid,
- 'user': user
- })
-
- return {
- 'name': doc.id,
- 'user': user,
- 'html_url': reverse('dochtml_view', args=[doc.id]),
- 'text_url': reverse('doctext_view', args=[doc.id]),
- # 'dc_url': reverse('docdc_view', args=[doc.id]),
- 'gallery_url': reverse('docgallery_view', args=[doc.id]),
- 'merge_url': reverse('docmerge_view', args=[doc.id]),
- 'revision': doc.revision,
- 'timestamp': doc.revision.timestamp,
- # 'public_revision': doc.revision,
- # 'public_timestamp': doc.revision.timestamp,
- }
-
-
-# @hglibrary
-# def update(self, request, docid, lib):
-# """Update information about the document, like display not"""
-# return
-#
-#
-#
-class DocumentHTMLHandler(BaseHandler):
- allowed_methods = ('GET')
-
- @validate_form(forms.DocumentRetrieveForm, 'GET')
- @hglibrary
- def read(self, request, form, docid, lib, stylesheet='full'):
- """Read document as html text"""
- try:
- revision = form.cleaned_data['revision']
- user = form.cleaned_data['user'] or request.user.username
- document = lib.document_for_revision(revision)
-
- if document.id != docid:
- return response.BadRequest().django_response({
- 'reason': 'name-mismatch',
- 'message': 'Provided revision is not valid for this document'
- })
-
- if document.owner != user:
- return response.BadRequest().django_response({
- 'reason': 'user-mismatch',
- 'message': "Provided revision doesn't belong to user %s" % user
- })
-
- for error in check_user(request, user):
- return error
-
- return librarian.html.transform(document.data('xml'), is_file=False, \
- parse_dublincore=False, stylesheet=stylesheet,\
- options={
- "with-paths": 'boolean(1)',
- })
-
- except (wlrepo.EntryNotFound, wlrepo.RevisionNotFound), e:
- return response.EntityNotFound().django_response({
- 'reason': 'not-found', 'message': e.message})
- except librarian.ValidationError, e:
- return response.InternalError().django_response({
- 'reason': 'xml-non-valid', 'message': e.message or u''})
- except librarian.ParseError, e:
- return response.InternalError().django_response({
- 'reason': 'xml-parse-error', 'message': e.message or u'' })
-
-#
-# Image Gallery
-#
-
-class DocumentGalleryHandler(BaseHandler):
- allowed_methods = ('GET', 'POST')
-
-
- def read(self, request, docid):
- """Read meta-data about scans for gallery of this document."""
- galleries = []
- from urllib import quote
-
- for assoc in GalleryForDocument.objects.filter(document=docid):
- dirpath = os.path.join(settings.MEDIA_ROOT, assoc.subpath)
-
- if not os.path.isdir(dirpath):
- log.warn(u"[WARNING]: missing gallery %s", dirpath)
- continue
-
- gallery = {'name': assoc.name, 'pages': []}
-
- for file in os.listdir(dirpath):
- if not isinstance(file, unicode):
- try:
- file = file.decode('utf-8')
- except:
- log.warn(u"File %r in gallery %r is not unicode. Ommiting."\
- % (file, dirpath) )
- file = None
-
- if file is not None:
- name, ext = os.path.splitext(os.path.basename(file))
-
- if ext.lower() not in [u'.png', u'.jpeg', u'.jpg']:
- log.warn(u"Ignoring: %s %s", name, ext)
- url = None
-
- url = settings.MEDIA_URL + assoc.subpath + u'/' + file
-
- if url is None:
- url = settings.MEDIA_URL + u'/missing.png'
-
- gallery['pages'].append( quote(url.encode('utf-8')) )
-
- gallery['pages'].sort()
- galleries.append(gallery)
-
- return galleries
-
- def create(self, request, docid):
- if not request.user.is_superuser:
- return rc.FORBIDDEN
-
- new_path = request.POST.get('path')
-
- if new_path:
- gallery, created = GalleryForDocument.objects.get_or_create(
- document = docid,
- defaults = {
- 'subpath': new_path,
- }
- )
-
- if not created:
- gallery.subpath = new_path
- gallery.save()
-
- return rc.CREATED
-
- return rc.BAD_REQUEST
-
-#
-# Dublin Core handlers
-#
-# @requires librarian
-#
-#class DocumentDublinCoreHandler(BaseHandler):
-# allowed_methods = ('GET', 'POST')
-#
-# @hglibrary
-# def read(self, request, docid, lib):
-# """Read document as raw text"""
-# try:
-# revision = request.GET.get('revision', 'latest')
-#
-# if revision == 'latest':
-# doc = lib.document(docid)
-# else:
-# doc = lib.document_for_revision(revision)
-#
-#
-# if document.id != docid:
-# return response.BadRequest().django_response({'reason': 'name-mismatch',
-# 'message': 'Provided revision is not valid for this document'})
-#
-# bookinfo = dcparser.BookInfo.from_string(doc.data('xml'))
-# return bookinfo.serialize()
-# except (EntryNotFound, RevisionNotFound), e:
-# return response.EntityNotFound().django_response({
-# 'exception': type(e), 'message': e.message})
-#
-# @hglibrary
-# def create(self, request, docid, lib):
-# try:
-# bi_json = request.POST['contents']
-# revision = request.POST['revision']
-#
-# if request.POST.has_key('message'):
-# msg = u"$USER$ " + request.PUT['message']
-# else:
-# msg = u"$AUTO$ Dublin core update."
-#
-# current = lib.document(docid, request.user.username)
-# orig = lib.document_for_revision(revision)
-#
-# if current != orig:
-# return response.EntityConflict().django_response({
-# "reason": "out-of-date",
-# "provided": orig.revision,
-# "latest": current.revision })
-#
-# xmldoc = parser.WLDocument.from_string(current.data('xml'))
-# document.book_info = dcparser.BookInfo.from_json(bi_json)
-#
-# # zapisz
-# ndoc = current.quickwrite('xml', \
-# document.serialize().encode('utf-8'),\
-# message=msg, user=request.user.username)
-#
-# try:
-# # return the new revision number
-# return {
-# "document": ndoc.id,
-# "subview": "dc",
-# "previous_revision": current.revision,
-# "revision": ndoc.revision,
-# 'timestamp': ndoc.revision.timestamp,
-# "url": reverse("docdc_view", args=[ndoc.id])
-# }
-# except Exception, e:
-# if ndoc: lib._rollback()
-# raise e
-# except RevisionNotFound:
-# return response.EntityNotFound().django_response()
-
-class MergeHandler(BaseHandler):
- allowed_methods = ('POST',)
-
- @validate_form(forms.MergeRequestForm, 'POST')
- @hglibrary
- def create(self, request, form, docid, lib):
- """Create a new document revision from the information provided by user"""
- try:
- revision = form.cleaned_data['revision']
-
- # fetch the main branch document
- doc = lib.document(docid)
-
- # fetch the base document
- user_doc = lib.document_for_revision(revision)
- base_doc = user_doc.latest()
-
- if base_doc != user_doc:
- return response.EntityConflict().django_response({
- "reason": "out-of-date",
- "provided": str(user_doc.revision),
- "latest": str(base_doc.revision)
- })
-
- if form.cleaned_data['type'] == 'update':
- # update is always performed from the file branch
- # to the user branch
- user_doc_new = base_doc.update(request.user.username)
-
- if user_doc_new == user_doc:
- return response.SuccessAllOk().django_response({
- "result": "no-op"
- })
-
- # shared document is the same
- doc_new = doc
-
- if form.cleaned_data['type'] == 'share':
- if not base_doc.up_to_date():
- return response.BadRequest().django_response({
- "reason": "not-fast-forward",
- "message": "You must first update your branch to the latest version."
- })
-
- anwser, info = base_doc.would_share()
-
- if not anwser:
- return response.SuccessAllOk().django_response({
- "result": "no-op", "message": info
- })
-
- # check for unresolved conflicts
- if base_doc.has_conflict_marks():
- return response.BadRequest().django_response({
- "reason": "unresolved-conflicts",
- "message": "There are unresolved conflicts in your file. Fix them, and try again."
- })
-
- if not request.user.has_perm('api.share_document'):
- # User is not permitted to make a merge, right away
- # So we instead create a pull request in the database
- try:
- prq, created = PullRequest.objects.get_or_create(
- comitter = request.user,
- document = docid,
- status = "N",
- defaults = {
- 'source_revision': str(base_doc.revision),
- 'comment': form.cleaned_data['message'] or '$AUTO$ Document shared.',
- }
- )
-
- # there can't be 2 pending request from same user
- # for the same document
- if not created:
- prq.source_revision = str(base_doc.revision)
- prq.comment = prq.comment + 'u\n\n' + (form.cleaned_data['message'] or u'')
- prq.save()
-
- return response.RequestAccepted().django_response(\
- ticket_status=prq.status, \
- ticket_uri=reverse("pullrequest_view", args=[prq.id]) )
- except IntegrityError:
- return response.EntityConflict().django_response({
- 'reason': 'request-already-exist'
- })
-
- changed = base_doc.share(form.cleaned_data['message'])
-
- # update shared version if needed
- if changed:
- doc_new = doc.latest()
- else:
- doc_new = doc
-
- # the user wersion is the same
- user_doc_new = base_doc
-
- # The client can compare parent_revision to revision
- # to see if he needs to update user's view
- # Same goes for shared view
-
- return response.SuccessAllOk().django_response({
- "result": "success",
- "name": user_doc_new.id,
- "user": user_doc_new.owner,
-
- "revision": user_doc_new.revision,
- 'timestamp': user_doc_new.revision.timestamp,
-
- "parent_revision": user_doc.revision,
- "parent_timestamp": user_doc.revision.timestamp,
-
- "shared_revision": doc_new.revision,
- "shared_timestamp": doc_new.revision.timestamp,
-
- "shared_parent_revision": doc.revision,
- "shared_parent_timestamp": doc.revision.timestamp,
- })
- except wlrepo.OutdatedException, e:
- return response.BadRequest().django_response({
- "reason": "not-fast-forward",
- "message": e.message
- })
- except wlrepo.LibraryException, e:
- return response.InternalError().django_response({
- "reason": "merge-error",
- "message": e.message
- })
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-import logging
-log = logging.getLogger('platforma.api.manage')
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-09-25 15:49:50$"
-__doc__ = "Module documentation."
-
-from piston.handler import BaseHandler
-from wlrepo import UpdateException
-
-from api.utils import hglibrary
-from api.models import PullRequest
-from api.response import *
-import datetime
-
-class PullRequestListHandler(BaseHandler):
- allowed_methods = ('GET',)
-
- def read(self, request):
- if request.user.has_perm('change_pullrequest'):
- return PullRequest.objects.all()
- else:
- return PullRequest.objects.filter(commiter=request.user)
-
-
-class PullRequestHandler(BaseHandler):
- allowed_methods = ('GET', 'PUT')
-
- def read(self, request, prq_id):
- return PullRequest.objects.get(id=prq_id)
-
- def update(self, request, prq_id):
- """Change the status of request"""
-
- if not request.user.has_perm('change_pullrequest'):
- return AccessDenied().django_response("Insufficient priviliges")
-
- prq = PullRequest.objects.get(id=prq_id)
-
- if not prq:
- return EntityNotFound().django_response()
-
- action = request.PUT.get('action', None)
-
- if action == 'accept':
- return self.accept_merge(request.user, prq)
- elif action == 'reject' and prq.status in ['N', 'R']:
- return self.reject_merge(request.user, prq)
- else:
- return BadRequest().django_response()
-
-
- @hglibrary
- def accept_merge(self, user, prq, lib):
- if prq.status not in ['N', 'E']:
- return BadRequest().django_response({
- 'reason': 'invalid-state',
- 'message': "This pull request is alredy resolved. Can't accept."
- })
-
- src_doc = lib.document_for_revision( prq.source_revision )
-
- lock = lib.lock()
- try:
- if not src_doc.up_to_date():
- # This revision is no longer up to date, thus
- # it needs to be updated, before push:
- #
- # Q: where to put the updated revision ?
- # A: create a special user branch named prq-#prqid
- prq_doc = src_doc.take("$prq-%d" % prq.id)
-
- # This could be not the first time we try this,
- # so the prq_doc could already be there
- # and up to date
-
- try:
- prq_doc = prq_doc.update(user.username)
- prq.source_revision = str(prq_doc.revision)
- src_doc = prq_doc
- except UpdateException, e:
- # this can happen only if the merge program
- # is misconfigured - try returning an entity conflict
- # TODO: put some useful infor here
- prq.status = 'E'
- prq.save()
- return EntityConflict().django_response({
- 'reason': 'update-failed',
- 'message': e.message })
-
- # check if there are conflicts
- if src_doc.has_conflict_marks():
- prq.status = 'E'
- prq.save()
- # Now, the user must resolve the conflict
- return EntityConflict().django_response({
- "reason": "unresolved-conflicts",
- "message": "There are conflict in the document. Resolve the conflicts retry accepting."
- })
-
- # So, we have an up-to-date, non-conflicting document
- changed = src_doc.share(prq.comment)
-
- if not changed:
- # this is actually very bad, but not critical
- log.error("Unsynched pull request: %d" % prq.id)
-
- # sync state with repository
- prq.status = 'A'
- prq.merged_revision = str(src_doc.shared().revision)
- prq.merged_timestamp = datetime.datetime.now()
- prq.save()
-
- return SuccessAllOk().django_response({
- 'status': prq.status,
- 'merged_into': prq.merged_revision,
- 'merged_at': prq.merged_timestamp
- })
- finally:
- lock.release()
-
- def reject_merge(self, prq, lib):
- prq.status = 'R'
- prq.save()
-
- return SuccessAllOk().django_response({
- 'status': prq.status
- })
-
-
-
-
-
-
-
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-10-19 14:34:42$"
-__doc__ = "Module documentation."
-
-#import api.forms as forms
-#import api.response as response
-#
-#from api.utils import validate_form, hglibrary
-#from api.models import PartCache
-#
-
-#
-#from piston.handler import BaseHandler
-#
-#from wlrepo import *
-
-import re
-from library_handlers import *
-
-import librarian
-from librarian import parser
-
-#
-# Document Text View
-#
-
-XINCLUDE_REGEXP = r"""<(?:\w+:)?include\s+[^>]*?href=("|')wlrepo://(?P<link>[^\1]+?)\1\s*[^>]*?>"""
-#
-#
-#
-
-class DocumentTextHandler(BaseHandler):
- allowed_methods = ('GET', 'POST')
-
- @validate_form(forms.TextRetrieveForm, 'GET')
- @hglibrary
- def read(self, request, form, docid, lib):
- """Read document as raw text"""
- try:
- revision = form.cleaned_data['revision']
- chunk = form.cleaned_data['chunk']
- user = form.cleaned_data['user'] or request.user.username
- format = form.cleaned_data['format']
-
- document = lib.document_for_revision(revision)
-
- if document.id != docid:
- return response.BadRequest().django_response({
- 'reason': 'name-mismatch',
- 'message': 'Provided revision is not valid for this document'
- })
-
- if document.owner != user:
- return response.BadRequest().django_response({
- 'reason': 'user-mismatch',
- 'message': "Provided revision doesn't belong to user %s" % user
- })
-
- for error in check_user(request, user):
- return error
-
- if not chunk:
- return document.data('xml')
-
- xdoc = parser.WLDocument.from_string(document.data('xml'), parse_dublincore=False)
-
- xchunk = xdoc.chunk(chunk)
-
- if xchunk is None:
- return response.EntityNotFound().django_response({
- 'reason': 'no-chunk-in-document',
- 'path': chunk
- })
-
- return librarian.serialize_children(xchunk, format=format)
-
- except librarian.ParseError, e:
- return response.EntityNotFound().django_response({
- 'reason': 'invalid-document-state',
- 'exception': type(e),
- 'message': e.message
- })
- except (EntryNotFound, RevisionNotFound), e:
- return response.EntityNotFound().django_response({
- 'reason': 'not-found',
- 'exception': type(e), 'message': e.message
- })
-
- @validate_form(forms.TextUpdateForm, 'POST')
- @hglibrary
- def create(self, request, form, docid, lib):
- lock = lib.lock();
- try:
- revision = form.cleaned_data['revision']
- msg = form.cleaned_data['message']
- user = form.cleaned_data['user'] or request.user.username
-
- # do not allow changing not owned documents
- # (for now... )
-
- if user != request.user.username:
- return response.AccessDenied().django_response({
- 'reason': 'insufficient-priviliges',
- })
-
- current = lib.document(docid, user)
- orig = lib.document_for_revision(revision)
-
- if current != orig:
- return response.EntityConflict().django_response({
- "reason": "out-of-date",
- "provided_revision": orig.revision,
- "latest_revision": current.revision })
-
- if form.cleaned_data['contents']:
- data = form.cleaned_data['contents']
- else:
- chunks = form.cleaned_data['chunks']
- data = current.data('xml')
- log.info(data[:600])
- log.info(chunks)
-
- xdoc = parser.WLDocument.from_string(data, parse_dublincore=False)
- errors = xdoc.merge_chunks(chunks)
-
- if len(errors):
- return response.EntityConflict().django_response({
- "reason": "invalid-chunks",
- "message": "Unable to merge following parts into the document: %s " % ",".join(errors)
- })
-
- data = xdoc.serialize()
-
-
- # try to find any Xinclude tags
- includes = [m.groupdict()['link'] for m in (re.finditer(\
- XINCLUDE_REGEXP, data, flags=re.UNICODE) or []) ]
-
- log.info("INCLUDES: %s", includes)
-
- # TODO: provide useful routines to make this simpler
- def xml_update_action(lib, resolve):
- try:
- f = lib._fileopen(resolve('parts'), 'r')
- stored_includes = json.loads(f.read())
- f.close()
- except:
- stored_includes = []
-
- if stored_includes != includes:
- f = lib._fileopen(resolve('parts'), 'w+')
- f.write(json.dumps(includes))
- f.close()
-
- lib._fileadd(resolve('parts'))
-
- # update the parts cache
- PartCache.update_cache(docid, current.owner,\
- stored_includes, includes)
-
- # now that the parts are ok, write xml
- f = lib._fileopen(resolve('xml'), 'w+')
- f.write(data.encode('utf-8'))
- f.close()
-
- ndoc = None
- ndoc = current.invoke_and_commit(\
- xml_update_action, lambda d: (msg, user) )
-
- try:
- # return the new revision number
- return response.SuccessAllOk().django_response({
- "document": ndoc.id,
- "user": user,
- "subview": "xml",
- "previous_revision": current.revision,
- "revision": ndoc.revision,
- 'timestamp': ndoc.revision.timestamp,
- "url": reverse("doctext_view", args=[ndoc.id])
- })
- except Exception, e:
- if ndoc: lib._rollback()
- raise e
- except RevisionNotFound, e:
- return response.EntityNotFound(mimetype="text/plain").\
- django_response(e.message)
- finally:
- lock.release()
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-import logging
-log = logging.getLogger('platforma.api.toolbar')
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-09-25 15:55:33$"
-__doc__ = "Module documentation."
-
-from django.views.generic.simple import direct_to_template
-from piston.handler import BaseHandler
-from piston.utils import rc
-
-import settings
-
-import toolbar.models
-
-class ToolbarHandler(BaseHandler):
- allowed_methods = ('GET',)
-
- def read(self, request):
- groups = toolbar.models.ButtonGroup.objects.all()
- return [g.to_dict(with_buttons=True) for g in groups]
-
-class ScriptletsHandler(BaseHandler):
- allowed_methods = ('GET',)
-
- def read(self, request):
- scriptlets = toolbar.models.Scriptlet.objects.all()
-
- return direct_to_template(request, 'toolbar_api/scriptlets.js',
- extra_context = {'scriptlets': scriptlets },
- mimetype='text/javascript' )
\ No newline at end of file
+++ /dev/null
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-
+++ /dev/null
-# To change this template, choose Tools | Templates
-# and open the template in the editor.
-
-
+++ /dev/null
-#!/usr/bin/env python
-# -*- conding: utf-8 -*-
-__author__="lreqc"
-__date__ ="$2009-09-08 14:31:26$"
-
-from django.core.management.base import NoArgsCommand
-
-# from optparse import make_option
-
-class Command(NoArgsCommand):
-
- def handle(self, *args, **options):
- client = Client()
- if not options['username'] or not options['password']:
- raise CommandError("You must provide login data")
-
- client.login(username=options['username'], \
- password=options['password'])
-
- print options['username'], options['password']
-
- docid = args[0]
-
- url = reverse("document_view", args=[docid])
- print "Quering %s" % url
- resp = client.get(url)
-
- result = json.loads(resp.content)
- print result
-
- print "Current revision for '%s': %s" % (docid, result['user_revision'])
- url = reverse("docmerge_view", args=[docid])
- print "Sending POST to %s" % url
- resp = client.post(url, {
- 'type': 'share',
- 'target_revision': result['user_revision'],
- 'message': 'Sharing.. :)'
- })
-
- print resp.status_code, resp.content
+++ /dev/null
-#!/usr/bin/env python
-# -*- conding: utf-8 -*-
-__author__="lreqc"
-__date__ ="$2009-09-08 14:31:26$"
-
-from django.core.management.base import BaseCommand
-from django.utils import simplejson as json
-from django.test.client import Client
-from django.core.urlresolvers import reverse
-
-from optparse import make_option
-
-class Command(BaseCommand):
-
- option_list = BaseCommand.option_list + (
- make_option('-u', '--user', action='store', dest='username'),
- make_option('-p', '--password', action='store', dest='password'),
- )
-
- def handle(self, *args, **options):
- client = Client()
- if not options['username'] or not options['password']:
- raise CommandError("You must provide login data")
-
- client.login(username=options['username'], \
- password=options['password'])
-
- print options['username'], options['password']
-
- filename = args[0]
- docid = args[1]
-
- url = reverse("document_view", args=[docid])
- print "Quering %s" % url
- resp = client.get(url)
-
- result = json.loads(resp.content)
- print result
-
- print "Current revision for '%s': %s" % (docid, result['user_revision'])
- url = reverse("doctext_view", args=[ docid, result['user_revision'] ])
- print "Sending PUT to %s" % url
-
- resp = client.put(url, {
- 'contents': open(filename).read(),
- 'message': options['message'] or ''
-
- })
-
- print resp.status_code, resp.content
+++ /dev/null
-#!/usr/bin/env python
-# -*- conding: utf-8 -*-
-__author__="lreqc"
-__date__ ="$2009-09-08 14:31:26$"
-
-from django.core.management.base import BaseCommand
-from django.utils import simplejson as json
-from django.test.client import Client
-from django.core.urlresolvers import reverse
-
-from optparse import make_option
-
-class Command(BaseCommand):
-
- option_list = BaseCommand.option_list + (
- make_option('-u', '--user', action='store', dest='username'),
- make_option('-p', '--password', action='store', dest='password'),
- make_option('-m', '--message', action='store', dest='message'),
- )
-
- def handle(self, *args, **options):
- client = Client()
- if not options['username'] or not options['password']:
- raise CommandError("You must provide login data")
-
- client.login(username=options['username'], \
- password=options['password'])
-
- print options['username'], options['password']
-
- filename = args[0]
- docid = args[1]
-
- url = reverse("document_view", args=[docid])
- print "Quering %s" % url
- resp = client.get(url)
-
- result = json.loads(resp.content)
- print result
-
- print "Current revision for '%s': %s" % (docid, result['user_revision'])
- url = reverse("doctext_view", args=[ docid, result['user_revision'] ])
- print "Sending PUT to %s" % url
-
- resp = client.put(url, {
- 'contents': open(filename).read(),
- 'message': options['message'] or ''
-
- })
-
- print resp.status_code, resp.content
+++ /dev/null
-#!/usr/bin/env python
-# -*- conding: utf-8 -*-
-__author__="lreqc"
-__date__ ="$2009-09-08 14:31:26$"
-
-from django.core.management.base import BaseCommand
-from django.utils import simplejson as json
-from django.test.client import Client
-from django.core.urlresolvers import reverse
-
-from optparse import make_option
-
-class Command(BaseCommand):
-
- option_list = BaseCommand.option_list + (
- make_option('-u', '--user', action='store', dest='username'),
- make_option('-p', '--password', action='store', dest='password'),
- make_option('-d', '--dublin-core', action='store_true', dest='dc'),
- )
-
- def handle(self, *args, **options):
- client = Client()
- if not options['username'] or not options['password']:
- raise CommandError("You must provide login data")
-
- client.login(username=options['username'], \
- password=options['password'])
-
- print options['username'], options['password']
-
- filename = args[0]
- bookname = args[1]
-
- print "Uploading '%s' as document '%s'" % (filename, bookname)
- print options['dc']
- print "With DC template" if options['dc'] is not None else ""
-
- print client.post( reverse("document_list_view"),\
- {
- 'bookname': bookname,
- 'ocr_file': open(filename),
- 'generate_dc': options['dc'] or False } )
-
+++ /dev/null
-from django.db import models
-from django.contrib.auth.models import User
-
-# Create your models here.
-class PartCache(models.Model):
- document_id = models.CharField(max_length=255)
- user_id = models.CharField(max_length=64, blank=True)
- part_id = models.CharField(max_length=255)
-
- @classmethod
- def update_cache(me, docid, userid, old, new):
- old = set(old)
- new = set(new)
-
- related = me.objects.filter(user_id=userid, document_id=docid)
-
- missing = old.difference(new)
- related.filter(part_id__in=missing).delete()
-
- created = new.difference(old)
-
- for part in created:
- me.objects.create(user_id=userid, document_id=docid, part_id=part)
-
-
-class PullRequest(models.Model):
- REQUEST_STATUSES = {
- "N": "New",
- "E": "Edited/Conflicting",
- "R": "Rejected",
- "A": "Accepted & merged",
- }
-
- comitter = models.ForeignKey(User) # the user who request the pull
- comment = models.TextField() # addtional comments to the request
-
- timestamp = models.DateTimeField(auto_now_add=True)
-
- # document to merge
- document = models.CharField(max_length=255)
-
- # revision to be merged into the main branch
- source_revision = models.CharField(max_length=40, unique=True)
- target_revision = models.CharField(max_length=40, blank=True)
-
- # current status
- status = models.CharField(max_length=1, choices=REQUEST_STATUSES.items())
-
- # comment to the status change of request (if applicable)
- response_comment = models.TextField(blank=True)
-
- # revision number in which the changes were merged (if any)
- merged_revision = models.CharField(max_length=40, blank=True, null=True)
- merge_timestamp = models.DateTimeField(blank=True, null=True)
-
- def __unicode__(self):
- return unicode(self.comitter) + u':' + self.document
-
-
- class Meta:
- permissions = (
- ("view_prq", "Can view pull request's contents."),
- )
-
-
-# This is actually an abstract Model, but if we declare
-# it as so Django ignores the permissions :(
-class Document(models.Model):
- class Meta:
- permissions = (
- ("share_document", "Can share documents without pull requests."),
- ("view_other_document", "Can view other's documents."),
- )
\ No newline at end of file
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-09-25 15:53:00$"
-__doc__ = "Module documentation."
-
-from piston.resource import Resource
-from api.utils import DjangoAuth
-
-authdata = {'authentication': DjangoAuth()}
-
-#
-# Library resources
-#
-
-import api.handlers.library_handlers as dh
-from api.handlers.text_handler import DocumentTextHandler
-
-library_resource = Resource(dh.LibraryHandler, **authdata)
-document_resource = Resource(dh.DocumentHandler, **authdata)
-document_text_resource = Resource(DocumentTextHandler, **authdata)
-document_html_resource = Resource(dh.DocumentHTMLHandler, **authdata)
-# document_dc_resource = Resource(dh.DocumentDublinCoreHandler, **authdata)
-document_gallery = Resource(dh.DocumentGalleryHandler, **authdata)
-document_merge = Resource(dh.MergeHandler, **authdata)
-diff_resource = Resource(dh.DiffHandler, **authdata)
-
-import api.handlers.manage_handlers as mh
-
-pullrequest_collection = Resource(mh.PullRequestListHandler, **authdata)
-pullrequest_rsrc = Resource(mh.PullRequestHandler, **authdata)
-
-#
-# Toolbar resources
-#
-import api.handlers.toolbar_handlers as th
-toolbar_buttons = Resource(th.ToolbarHandler, **authdata)
-scriptlets = Resource(th.ScriptletsHandler, **authdata)
-
-
-
-__all__ = [
- 'library_resource',
- 'document_resource',
- 'document_text_resource',
- 'document_html_resource',
-# 'document_dc_resource',
- 'document_gallery',
- 'document_merge',
- 'toolbar_buttons',
- 'scriptlets',
- 'pullrequest_collection',
- 'pullrequest_rsrc',
- 'diff_resource',
-]
\ No newline at end of file
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-__author__= "Łukasz Rekucki"
-__date__ = "$2009-09-26 00:32:18$"
-__doc__ = "Extensible HTTP Responses."
-
-from django.http import HttpResponse
-from django.utils import simplejson as json
-
-MIME_PLAIN = 'text/plain'
-MIME_JSON = 'application/json'
-
-class ResponseObject(object):
-
- def __init__(self, code, mimetype=MIME_JSON):
- self._code = code
- self._mime = mimetype
-
- def django_response(self, body=None):
- if body is None:
- data = ''
- elif self._mime == MIME_JSON:
- data = json.dumps(body, default=lambda o: repr(o) )
- else:
- # data = u"%s\n%s" % (self.MESSAGE, unicode(body))
- data = unicode(body).encode('utf-8')
-
- return HttpResponse(content=data, status=self._code, \
- content_type=self._mime+'; charset=utf-8' )
-
-class SuccessAllOk(ResponseObject):
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 200, **kwargs)
-
-class EntityCreated(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 201, **kwargs)
-
- def django_response(self, url, body):
- response = ResponseObject.django_response(self, body)
- response['Location'] = url
- return response
-
-class RequestAccepted(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 202, **kwargs)
-
- def django_response(self, ticket_status, ticket_uri):
- return ResponseObject.django_response(self, {
- 'result': 'accepted',
- 'status': ticket_status,
- 'refer_to': ticket_uri })
-
-class SuccessNoContent(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 204, **kwargs)
-
- def django_response(self):
- return ResponseObject.django_response(self, body=None)
-
-#
-# Client errors
-#
-
-class BadRequest(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 400, **kwargs)
-
-class AccessDenied(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 403, **kwargs)
-
-
-class EntityNotFound(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 404, **kwargs)
-
-class EntityGone(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 410, **kwargs)
-
-
-class EntityConflict(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 409, **kwargs)
-
-
-#
-# Server side errors
-#
-class InternalError(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 500, **kwargs)
-
-class NotImplemented(ResponseObject):
-
- def __init__(self, **kwargs):
- ResponseObject.__init__(self, 501, **kwargs)
\ No newline at end of file
+++ /dev/null
-from django.test import TestCase
-from django.test.client import Client
-from django.core.urlresolvers import reverse
-
-from django.utils import simplejson as json
-
-from django.contrib.auth.models import User
-
-import settings
-from os.path import join, dirname
-from StringIO import StringIO
-import shutil
-import tempfile
-
-REPO_TEMPLATES = join(dirname(__file__), 'data')
-
-def temprepo(name):
- from functools import wraps
-
- def decorator(func):
-
-
- @wraps(func)
- def decorated(self, *args, **kwargs):
- clean = False
- try:
- temp = tempfile.mkdtemp("-test", func.__name__)
- shutil.copytree(join(REPO_TEMPLATES, name), join(temp, 'repo'), False)
- settings.REPOSITORY_PATH = join(temp, 'repo')
- func(self, *args, **kwargs)
- clean = True
- finally:
- if not clean and self.response:
- print "RESULT", func.__name__, ">>>"
- print self.response.content
- print "<<<"
- else:
- shutil.rmtree(temp, True)
-
- settings.REPOSITORY_PATH = ''
-
- return decorated
- return decorator
-
-
-class SimpleTest(TestCase):
-
- def setUp(self):
- self.response = None
- u = User.objects.create_user('admin', 'test@localhost', 'admin')
- u.save()
-
- @temprepo('clean')
- def test_documents_get_anonymous(self):
- self.response = self.client.get( reverse("document_list_view") )
- self.assert_json_response({
- u'documents': [],
- })
-
- @temprepo('clean')
- def test_documents_get_with_login(self):
- self.assertTrue(self.client.login(username='admin', password='admin'))
-
- self.response = self.client.get( reverse("document_list_view") )
- self.assert_json_response({
- u'documents': [],
- })
-
- @temprepo('clean')
- def test_document_creation(self):
- self.assertTrue(self.client.login(username='admin', password='admin'))
-
- infile = tempfile.NamedTemporaryFile("w+")
- infile.write('012340123456789')
- infile.flush()
- infile.seek(0)
-
- self.response = self.client.post( reverse("document_list_view"),
- data = {
- 'bookname': 'testbook',
- 'ocr_file': infile,
- 'generate_dc': False,
- })
-
- r = self.assert_json_response( {
- 'url': reverse('document_view', args=['testbook']),
- 'name': 'testbook',
- # can't test revision number, 'cause it's random
- }, code=201)
-
- created_rev = r['revision']
- self.response = self.client.get(r['url'])
-
- result = self.assert_json_response({
- u'public_revision': created_rev,
- # u'size': 15,
- })
-
-
- @temprepo('simple')
- def test_document_meta_get_with_login(self):
- self.assertTrue(self.client.login(username='admin', password='admin'))
-
- self.response = self.client.get( reverse("document_list_view") )
- self.assert_json_response({
- # u'latest_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
- u'documents': [
- {u'url': u'/api/documents/sample', u'name': u'sample', u'parts': []},
- {u'url': u'/api/documents/sample_pl', u'name': u'sample_pl', u'parts': []}
- ],
- })
-
- self.response = self.client.get( \
- reverse("document_view", args=['sample']) )
-
- self.assert_json_response({
- #u'latest_shared_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
- #u'text_url': reverse("doctext_view", args=[u'sample']),
- #u'dc_url': reverse("docdc_view", args=[u'sample']),
- # u'parts_url': reverse("docparts_view", args=[u'sample']),
- u'name': u'sample',
- # u'size': 20,
- })
-
-
- @temprepo('simple')
- def test_document_text_with_login(self):
- self.assertTrue(self.client.login(username='admin', password='admin'))
-
- self.response = self.client.get( \
- reverse("document_view", args=['sample']) )
-
- resp = self.assert_json_response({
- #u'latest_shared_rev': u'f94a263812dbe46a3a13d5209bb119988d0078d5',
- #u'text_url': reverse("doctext_view", args=[u'sample']),
- #u'dc_url': reverse("docdc_view", args=[u'sample']),
- # u'parts_url': reverse("docparts_view", args=[u'sample']),
- u'name': u'sample',
- # u'size': 20,
- })
-
- self.response = self.client.get(resp['text_url'])
- self.assertEqual(self.response.status_code, 200)
- self.assertEqual(self.response.content, "Ala ma kota\n")
-
-
- @temprepo('simple')
- def test_document_text_save(self):
- self.assertTrue(self.client.login(username='admin', password='admin'))
- TEXT = u"Ala ma kota i psa"
-
- self.response = self.client.get(
- reverse("document_view", args=['sample']) )
-
- resp = self.assert_json_response()
-
- self.response = self.client.post(resp['text_url'], {
- 'revision': resp['user_revision'] ,'contents': TEXT })
- result = self.assert_json_response(must_have={u'document': u'sample'} )
-
- #self.response = self.client.get(result['url'])
- #self.assertEqual(self.response.content, TEXT)
-
- def assert_json_response(self, must_have={}, exclude=[], code=200):
- self.assertEqual(self.response.status_code, code)
- result = json.loads(self.response.content)
-
- for (k,v) in must_have.items():
- self.assertTrue(result.has_key(k), "Required field '%s' missing in response." % k)
- self.assertEqual(result[k], v)
-
- if exclude is True:
- for (k,v) in result.items():
- self.assertTrue(must_have.has_key(k))
- self.assertEqual(must_have[k], v)
-
- for key in exclude:
- self.assertFalse(result.has_key(key))
-
- return result
-
\ No newline at end of file
+++ /dev/null
-revlogv1
-store
-fncache
+++ /dev/null
-data/$meta.i
-data/.hgignore.i
-data/.hgtags.i
+++ /dev/null
-default
\ No newline at end of file
+++ /dev/null
-d5e516ebd357bca24c6afb737e97db3b3d4f111a $branchbase
+++ /dev/null
-65046aefea667e38c7a01d7ca62412d7e81f68bc 2
-d5e516ebd357bca24c6afb737e97db3b3d4f111a default
-00e4aa6f4f53f31020e4d3e0579cb3c0fa0bd056 $doc:sample
-65046aefea667e38c7a01d7ca62412d7e81f68bc $doc:sample_pl
+++ /dev/null
-revlogv1
-store
-fncache
+++ /dev/null
-data/$meta.i
-data/.hgignore.i
-data/sample.parts.i
-data/sample.xml.i
-data/sample_pl.xml.i
-data/.hgtags.i
+++ /dev/null
-default
\ No newline at end of file
+++ /dev/null
-d5e516ebd357bca24c6afb737e97db3b3d4f111a $branchbase
+++ /dev/null
-__author__="lreqc"
-__date__ ="$2009-09-17 16:16:54$"
-
-from django.conf.urls.defaults import *
-from api.resources import *
-
-FORMAT = r"\.(?P<emitter_format>xml|json|yaml)"
-DOC = r'(?P<docid>[^/]+)'
-# REVISION = r'(?P<revision>latest|[0-9a-f]{40})'
-
-def urlpath(*args, **kwargs):
- format = kwargs.get('format', True)
- return r'^' + (r'/'.join(args)) + (FORMAT if format else '') + '$'
-
-urlpatterns = patterns('',
-# url(r'^hello$', hello_resource, {'emitter_format': 'json'}),
-# url(r'^hello\.(?P<emitter_format>.+)$', hello_resource),
-
- # HTML Renderer service
- url(r'^render$', 'api.views.render'),
-
- # Toolbar
- url(r'^toolbar/buttons$', toolbar_buttons, {'emitter_format': 'json'},
- name="toolbar_buttons"
- ),
-
- url(r'^toolbar/scriptlets$', scriptlets, {'emitter_format': 'json'},
- name="toolbar_scriptlets"
- ),
-
- # Pull requests
- url(r"^pull-requests$", pullrequest_collection,
- {'emitter_format': 'json'}, name="pullrequest_list" ),
-
- url(r"^pull-requests/(?P<prq_id>\d+)$", pullrequest_rsrc,
- {'emitter_format': 'json'}, name="pullrequest_view" ),
-
- # Documents
- url(r'^documents$', library_resource,
- {'emitter_format': 'json'}, name="document_list_view"),
-
- url(urlpath(r'documents'), library_resource,
- name="document_list_view_withformat"),
-
- #url(urlpath(r'documents', DOC),
- # document_resource, name="document_view_withformat"),
-
- url(urlpath(r'documents', DOC, format=False),
- document_resource, {'emitter_format': 'json'},
- name="document_view"),
-
- url(urlpath(r'documents', DOC, 'gallery', format=False),
- document_gallery, {'emitter_format': 'json'},
- name="docgallery_view"),
-
- # XML
- url(urlpath(r'documents', DOC, 'text', format=False),
- document_text_resource, {'emitter_format': 'raw'},
- name="doctext_view"),
-
- # HTML
- url(urlpath(r'documents', DOC, 'html', format=False),
- document_html_resource, {'emitter_format': 'raw'},
- name="dochtml_view"),
-
- # DC
- #url(urlpath(r'documents', DOC, 'dc'),
- # document_dc_resource,
- # name="docdc_view_withformat"),
-
-# url(urlpath(r'documents', DOC, 'dc', format=False),
-# document_dc_resource, {'emitter_format': 'json'},
-# name="docdc_view"),
-
- # MERGE
- url(urlpath(r'documents', DOC, 'revision', format=False),
- document_merge, {'emitter_format': 'json'}, name="docmerge_view"),
-
- url(r'documents/(?P<docid>[^/]+)/diff$',
- diff_resource, {'emitter_format': 'raw'}, name="diff_resource"),
-
-
-# url(r'^documents/(?P<docid>[^/]+)/parts$',
-# document_resource, {'emitter_format': 'json'},
-# name="docparts_view"),
-
- # url(r'^posts/(?P<post_slug>[^/]+)/$', blogpost_resource),
- # url(r'^other/(?P<username>[^/]+)/(?P<data>.+)/$', arbitrary_resource),
-)
-
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-__author__ = "Łukasz Rekucki"
-__date__ = "$2009-09-20 21:48:03$"
-__doc__ = "Module documentation."
-
-
-from functools import wraps
-from piston.emitters import Emitter
-from piston.utils import rc
-
-import api.response
-
-import wlrepo
-import settings
-
-class TextEmitter(Emitter):
- def render(self, request):
- return unicode(self.construct())
-
-Emitter.register('raw', TextEmitter, 'text/plain; charset=utf-8')
-Emitter.register('rawhtml', TextEmitter, 'text/html; charset=utf-8')
-Emitter.register('rawxml', TextEmitter, 'application/xml; charset=utf-8')
-
-class DjangoAuth(object):
-
- def is_authenticated(self, request):
- return request.user.is_authenticated()
-
- def challenge(self):
- return rc.FORBIDDEN
-
-
-def validate_form(formclass, source='GET'):
-
- def decorator(func):
- @wraps(func)
- def decorated(self, request, *args, **kwargs):
- form = formclass(getattr(request, source), request.FILES)
-
- if not form.is_valid():
- errorlist = [{'field': k, 'errors': str(e)} for k, e in form.errors.items()]
- return api.response.BadRequest().django_response(errorlist)
-
- kwargs['form'] = form
- return func(self, request, * args, ** kwargs)
- return decorated
- return decorator
-
-def hglibrary(func):
- @wraps(func)
- def decorated(self, *args, **kwargs):
- l = wlrepo.open_library(settings.REPOSITORY_PATH, 'hg')
- kwargs['lib'] = l
- return func(self, *args, **kwargs)
- return decorated
-
-
-
-import re
-import locale
-
-NAT_EXPR = re.compile(r'(\d+)', re.LOCALE | re.UNICODE)
-def natural_order(get_key=lambda x: x):
-
- def getter(key):
- nkey = get_key(key)
- if not isinstance(nkey, unicode):
- ukey = nkey.decode('utf-8')
- else:
- ukey = nkey
-
- parts = enumerate( NAT_EXPR.split(ukey))
- return [int(x) if n%2 else locale.strxfrm(x.encode('utf-8')) for (n,x) in parts ]
-
- return getter
-
+++ /dev/null
-# Create your views here.
-
-import logging
-log = logging.getLogger('platforma.render')
-
-from django.http import HttpResponse
-import librarian
-from librarian import html
-from lxml import etree
-from StringIO import StringIO
-import re
-
-LINE_SWAP_EXPR = re.compile(r'/\s', re.MULTILINE | re.UNICODE);
-
-def render(request):
- style_filename = html.get_stylesheet('partial')
-
- data = request.POST['fragment']
- path = request.POST['chunk']
-
- base, me = path.rsplit('/', 1)
- match = re.match(r'([^\[]+)\[(\d+)\]', me)
- tag, pos = match.groups()
-
- style = etree.parse(style_filename)
-
- data = u'<chunk><%s>%s</%s></chunk>' % (tag, LINE_SWAP_EXPR.sub(u'<br />\n', data), tag)
- log.info(data)
- doc = etree.parse( StringIO(data) )
-
- opts = {
- 'with-paths': 'boolean(1)',
- 'base-path': "'%s'" % base,
- 'base-offset': pos,
- }
-
- result = doc.xslt(style, **opts)
- return HttpResponse( librarian.serialize_children(result.getroot()[0]) )
\ No newline at end of file