comparison MoinMoin/items/content.py @ 1649:5dc142ab43d2

Keep itemtype and contenttype in Item and Content subclasses. Class decorators named @register are provided as helpers in items and items.content modules.
author Cheer Xiao <xiaqqaix@gmail.com>
date Wed, 08 Aug 2012 22:51:16 +0800
parents 1a2c53092ea1
children fa66e4447d63
comparison
equal deleted inserted replaced
1648:1a2c53092ea1 1649:5dc142ab43d2
98 """ 98 """
99 return self._register(self.Entry(factory, content_type, priority)) 99 return self._register(self.Entry(factory, content_type, priority))
100 100
101 101
102 content_registry = RegistryContent() 102 content_registry = RegistryContent()
103
104 def register(cls):
105 content_registry.register(cls._factory, Type(cls.contenttype))
106 return cls
103 107
104 108
105 def conv_serialize(doc, namespaces, method='polyglot'): 109 def conv_serialize(doc, namespaces, method='polyglot'):
106 out = array('u') 110 out = array('u')
107 flaskg.clock.start('conv_serialize') 111 flaskg.clock.start('conv_serialize')
239 query = And(terms) 243 query = And(terms)
240 revs = flaskg.storage.search(query, sortedby=NAME_EXACT, limit=None) 244 revs = flaskg.storage.search(query, sortedby=NAME_EXACT, limit=None)
241 return [rev.meta[NAME] for rev in revs] 245 return [rev.meta[NAME] for rev in revs]
242 246
243 247
248 @register
244 class NonExistentContent(Content): 249 class NonExistentContent(Content):
245 """Dummy Content to use with NonExistent.""" 250 """Dummy Content to use with NonExistent."""
251 contenttype = 'application/x-nonexistent'
252
246 def do_get(self, force_attachment=False, mimetype=None): 253 def do_get(self, force_attachment=False, mimetype=None):
247 abort(404) 254 abort(404)
248 255
249 def _convert(self, doc): 256 def _convert(self, doc):
250 abort(404) 257 abort(404)
251 258
252 259
253 content_registry.register(NonExistentContent._factory, Type('application/x-nonexistent')) 260 @register
254
255
256 class Binary(Content): 261 class Binary(Content):
257 """ An arbitrary binary item, fallback class for every item mimetype. """ 262 """ An arbitrary binary item, fallback class for every item mimetype. """
263 contenttype = '*/*'
258 264
259 # XXX reads item rev data into memory! 265 # XXX reads item rev data into memory!
260 def get_data(self): 266 def get_data(self):
261 if self.rev is not None: 267 if self.rev is not None:
262 return self.rev.data.read() 268 return self.rev.data.read()
339 return send_file(file=file_to_send, 345 return send_file(file=file_to_send,
340 mimetype=content_type, 346 mimetype=content_type,
341 as_attachment=as_attachment, attachment_filename=filename, 347 as_attachment=as_attachment, attachment_filename=filename,
342 cache_timeout=10, # wiki data can change rapidly 348 cache_timeout=10, # wiki data can change rapidly
343 add_etags=True, etag=hash, conditional=True) 349 add_etags=True, etag=hash, conditional=True)
344
345 content_registry.register(Binary._factory, Type('*/*'))
346 350
347 351
348 class RenderableBinary(Binary): 352 class RenderableBinary(Binary):
349 """ Base class for some binary stuff that renders with a object tag. """ 353 """ Base class for some binary stuff that renders with a object tag. """
350 354
419 self.item._save(meta, data, name=self.name, action=u'SAVE', comment='') 423 self.item._save(meta, data, name=self.name, action=u'SAVE', comment='')
420 data.close() 424 data.close()
421 os.remove(temp_fname) 425 os.remove(temp_fname)
422 426
423 427
428 @register
424 class ApplicationXTar(TarMixin, Application): 429 class ApplicationXTar(TarMixin, Application):
425 """ 430 """
426 Tar items 431 Tar items
427 """ 432 """
428 433 contenttype = 'application/x-tar'
429 content_registry.register(ApplicationXTar._factory, Type('application/x-tar')) 434
430 content_registry.register(ApplicationXTar._factory, Type('application/x-gtar')) 435
436 @register
437 class ApplicationXGTar(ApplicationXTar):
438 """
439 Compressed tar items
440 """
441 contenttype = 'application/x-gtar'
431 442
432 443
433 class ZipMixin(object): 444 class ZipMixin(object):
434 """ 445 """
435 ZipMixin offers additional functionality for zip-like items to list and 446 ZipMixin offers additional functionality for zip-like items to list and
455 466
456 def put_member(self, name, content, content_length, expected_members): 467 def put_member(self, name, content, content_length, expected_members):
457 raise NotImplementedError 468 raise NotImplementedError
458 469
459 470
471 @register
460 class ApplicationZip(ZipMixin, Application): 472 class ApplicationZip(ZipMixin, Application):
461 """ 473 """
462 Zip items 474 Zip items
463 """ 475 """
464 476 contenttype = 'application/zip'
465 content_registry.register(ApplicationZip._factory, Type('application/zip')) 477
466 478
467 479 @register
468 class PDF(Application): 480 class PDF(Application):
469 """ PDF """ 481 """ PDF """
470 482 contenttype = 'application/pdf'
471 content_registry.register(PDF._factory, Type('application/pdf')) 483
472 484
473 485 @register
474 class Video(Binary): 486 class Video(Binary):
475 """ Base class for video/* """ 487 """ Base class for video/* """
476 488 contenttype = 'video/*'
477 content_registry.register(Video._factory, Type('video/*')) 489
478 490
479 491 @register
480 class Audio(Binary): 492 class Audio(Binary):
481 """ Base class for audio/* """ 493 """ Base class for audio/* """
482 494 contenttype = 'audio/*'
483 content_registry.register(Audio._factory, Type('audio/*')) 495
484 496
485 497 @register
486 class Image(Binary): 498 class Image(Binary):
487 """ Base class for image/* """ 499 """ Base class for image/* """
488 500 contenttype = 'image/*'
489 content_registry.register(Image._factory, Type('image/*'))
490 501
491 502
492 class RenderableImage(RenderableBinary): 503 class RenderableImage(RenderableBinary):
493 """ Base class for renderable Image mimetypes """ 504 """ Base class for renderable Image mimetypes """
494 505
495 506
507 @register
496 class SvgImage(RenderableImage): 508 class SvgImage(RenderableImage):
497 """ SVG images use <object> tag mechanism from RenderableBinary base class """ 509 """ SVG images use <object> tag mechanism from RenderableBinary base class """
498 510 contenttype = 'image/svg+xml'
499 content_registry.register(SvgImage._factory, Type('image/svg+xml'))
500 511
501 512
502 class RenderableBitmapImage(RenderableImage): 513 class RenderableBitmapImage(RenderableImage):
503 """ PNG/JPEG/GIF images use <img> tag (better browser support than <object>) """ 514 """ PNG/JPEG/GIF images use <img> tag (better browser support than <object>) """
504 # if mimetype is also transformable, please register in TransformableImage ONLY! 515 # if mimetype is also transformable, please register in TransformableImage ONLY!
655 return Response(data, headers=headers) 666 return Response(data, headers=headers)
656 667
657 def _render_data_diff_text(self, oldrev, newrev): 668 def _render_data_diff_text(self, oldrev, newrev):
658 return super(TransformableBitmapImage, self)._render_data_diff_text(oldrev, newrev) 669 return super(TransformableBitmapImage, self)._render_data_diff_text(oldrev, newrev)
659 670
660 content_registry.register(TransformableBitmapImage._factory, Type('image/png')) 671
661 content_registry.register(TransformableBitmapImage._factory, Type('image/jpeg')) 672 @register
662 content_registry.register(TransformableBitmapImage._factory, Type('image/gif')) 673 class PNG(TransformableBitmapImage):
663 674 """ PNG image. """
664 675 contenttype = 'image/png'
676
677
678 @register
679 class JPEG(TransformableBitmapImage):
680 """ JPEG image. """
681 contenttype = 'image/jpeg'
682
683
684 @register
685 class GIF(TransformableBitmapImage):
686 """ GIF image. """
687 contenttype = 'image/gif'
688
689
690 @register
665 class Text(Binary): 691 class Text(Binary):
666 """ Base class for text/* """ 692 """ Base class for text/* """
693 contenttype = 'text/*'
667 694
668 class ModifyForm(Binary.ModifyForm): 695 class ModifyForm(Binary.ModifyForm):
669 template = 'modify_text.html' 696 template = 'modify_text.html'
670 data_text = String.using(strip=False, optional=True).with_properties(placeholder=L_("Type your text here")) 697 data_text = String.using(strip=False, optional=True).with_properties(placeholder=L_("Type your text here"))
671 rows = ROWS_DATA 698 rows = ROWS_DATA
744 # TODO: Real output format 771 # TODO: Real output format
745 html_conv = reg.get(type_moin_document, Type('application/x-xhtml-moin-page')) 772 html_conv = reg.get(type_moin_document, Type('application/x-xhtml-moin-page'))
746 doc = html_conv(doc) 773 doc = html_conv(doc)
747 return conv_serialize(doc, {html.namespace: ''}) 774 return conv_serialize(doc, {html.namespace: ''})
748 775
749 content_registry.register(Text._factory, Type('text/*'))
750
751 776
752 class MarkupItem(Text): 777 class MarkupItem(Text):
753 """ 778 """
754 some kind of item with markup 779 some kind of item with markup
755 (internal links and transcluded items) 780 (internal links and transcluded items)
756 """ 781 """
757 782
758 783
784 @register
759 class MoinWiki(MarkupItem): 785 class MoinWiki(MarkupItem):
760 """ MoinMoin wiki markup """ 786 """ MoinMoin wiki markup """
761 787 contenttype = 'text/x.moin.wiki'
762 content_registry.register(MoinWiki._factory, Type('text/x.moin.wiki')) 788
763 789
764 790 @register
765 class CreoleWiki(MarkupItem): 791 class CreoleWiki(MarkupItem):
766 """ Creole wiki markup """ 792 """ Creole wiki markup """
767 793 contenttype = 'text/x.moin.creole'
768 content_registry.register(CreoleWiki._factory, Type('text/x.moin.creole')) 794
769 795
770 796 @register
771 class MediaWiki(MarkupItem): 797 class MediaWiki(MarkupItem):
772 """ MediaWiki markup """ 798 """ MediaWiki markup """
773 799 contenttype = 'text/x-mediawiki'
774 content_registry.register(MediaWiki._factory, Type('text/x-mediawiki')) 800
775 801
776 802 @register
777 class ReST(MarkupItem): 803 class ReST(MarkupItem):
778 """ ReStructured Text markup """ 804 """ ReStructured Text markup """
779 805 contenttype = 'text/x-rst'
780 content_registry.register(ReST._factory, Type('text/x-rst')) 806
781 807
782 808 @register
783 class HTML(Text): 809 class HTML(Text):
784 """ 810 """
785 HTML markup 811 HTML markup
786 812
787 Note: As we use html_in converter to convert this to DOM and later some 813 Note: As we use html_in converter to convert this to DOM and later some
788 output converterter to produce output format (e.g. html_out for html 814 output converterter to produce output format (e.g. html_out for html
789 output), all(?) unsafe stuff will get lost. 815 output), all(?) unsafe stuff will get lost.
790 816
791 Note: If raw revision data is accessed, unsafe stuff might be present! 817 Note: If raw revision data is accessed, unsafe stuff might be present!
792 """ 818 """
819 contenttype = 'text/html'
820
793 class ModifyForm(Text.ModifyForm): 821 class ModifyForm(Text.ModifyForm):
794 template = "modify_text_html.html" 822 template = "modify_text_html.html"
795 823
796 content_registry.register(HTML._factory, Type('text/html')) 824
797 825 @register
798
799 class DocBook(MarkupItem): 826 class DocBook(MarkupItem):
800 """ DocBook Document """ 827 """ DocBook Document """
828 contenttype = 'application/docbook+xml'
829
801 def _convert(self, doc): 830 def _convert(self, doc):
802 from emeraldtree import ElementTree as ET 831 from emeraldtree import ElementTree as ET
803 from MoinMoin.converter import default_registry as reg 832 from MoinMoin.converter import default_registry as reg
804 833
805 doc = self._expand_document(doc) 834 doc = self._expand_document(doc)
839 mimetype=content_type, 868 mimetype=content_type,
840 as_attachment=as_attachment, attachment_filename=None, 869 as_attachment=as_attachment, attachment_filename=None,
841 cache_timeout=10, # wiki data can change rapidly 870 cache_timeout=10, # wiki data can change rapidly
842 add_etags=False, etag=None, conditional=True) 871 add_etags=False, etag=None, conditional=True)
843 872
844 content_registry.register(DocBook._factory, Type('application/docbook+xml'))
845
846 873
847 class Draw(TarMixin, Image): 874 class Draw(TarMixin, Image):
848 """ 875 """
849 Base class for *Draw that use special Java/Javascript applets to modify and store data in a tar file. 876 Base class for *Draw that use special Java/Javascript applets to modify and store data in a tar file.
850 """ 877 """
854 881
855 def handle_post(): 882 def handle_post():
856 raise NotImplementedError 883 raise NotImplementedError
857 884
858 885
886 @register
859 class TWikiDraw(Draw): 887 class TWikiDraw(Draw):
860 """ 888 """
861 drawings by TWikiDraw applet. It creates three files which are stored as tar file. 889 drawings by TWikiDraw applet. It creates three files which are stored as tar file.
862 """ 890 """
891 contenttype = 'application/x-twikidraw'
863 892
864 class ModifyForm(Draw.ModifyForm): 893 class ModifyForm(Draw.ModifyForm):
865 template = "modify_twikidraw.html" 894 template = "modify_twikidraw.html"
866 help = "" 895 help = ""
867 896
914 943
915 return Markup(image_map + u'<img src="{0}" alt="{1}" usemap="#{2}" />'.format(png_url, title, mapid)) 944 return Markup(image_map + u'<img src="{0}" alt="{1}" usemap="#{2}" />'.format(png_url, title, mapid))
916 else: 945 else:
917 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, title)) 946 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, title))
918 947
919 content_registry.register(TWikiDraw._factory, Type('application/x-twikidraw')) 948
920 949 @register
921
922 class AnyWikiDraw(Draw): 950 class AnyWikiDraw(Draw):
923 """ 951 """
924 drawings by AnyWikiDraw applet. It creates three files which are stored as tar file. 952 drawings by AnyWikiDraw applet. It creates three files which are stored as tar file.
925 """ 953 """
954 contenttype = 'application/x-anywikidraw'
926 955
927 class ModifyForm(Draw.ModifyForm): 956 class ModifyForm(Draw.ModifyForm):
928 template = "modify_anywikidraw.html" 957 template = "modify_anywikidraw.html"
929 help = "" 958 help = ""
930 def _load(self, item): 959 def _load(self, item):
983 title = _('Clickable drawing: %(filename)s', filename=self.name) 1012 title = _('Clickable drawing: %(filename)s', filename=self.name)
984 return Markup(image_map + u'<img src="{0}" alt="{1}" usemap="#{2}" />'.format(png_url, title, mapid)) 1013 return Markup(image_map + u'<img src="{0}" alt="{1}" usemap="#{2}" />'.format(png_url, title, mapid))
985 else: 1014 else:
986 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, title)) 1015 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, title))
987 1016
988 content_registry.register(AnyWikiDraw._factory, Type('application/x-anywikidraw')) 1017
989 1018 @register
990
991 class SvgDraw(Draw): 1019 class SvgDraw(Draw):
992 """ drawings by svg-edit. It creates two files (svg, png) which are stored as tar file. """ 1020 """ drawings by svg-edit. It creates two files (svg, png) which are stored as tar file. """
1021 contenttype = 'application/x-svgdraw'
993 1022
994 class ModifyForm(Draw.ModifyForm): 1023 class ModifyForm(Draw.ModifyForm):
995 template = "modify_svg-edit.html" 1024 template = "modify_svg-edit.html"
996 help = "" 1025 help = ""
997 1026
1014 # of items and also rendering them with the code in base class could work 1043 # of items and also rendering them with the code in base class could work
1015 item_name = self.name 1044 item_name = self.name
1016 drawing_url = url_for('frontend.get_item', item_name=item_name, member='drawing.svg', rev=self.rev.revid) 1045 drawing_url = url_for('frontend.get_item', item_name=item_name, member='drawing.svg', rev=self.rev.revid)
1017 png_url = url_for('frontend.get_item', item_name=item_name, member='drawing.png', rev=self.rev.revid) 1046 png_url = url_for('frontend.get_item', item_name=item_name, member='drawing.png', rev=self.rev.revid)
1018 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, drawing_url)) 1047 return Markup(u'<img src="{0}" alt="{1}" />'.format(png_url, drawing_url))
1019
1020 content_registry.register(SvgDraw._factory, Type('application/x-svgdraw'))