mirror of
https://github.com/gryf/.vim.git
synced 2025-12-17 19:40:29 +01:00
Added unittest for vimblogger_ft, corrected documentation, make pygment optional
This commit is contained in:
82
doc/tags
82
doc/tags
@@ -27,10 +27,6 @@
|
|||||||
'snippets' snipMate.txt /*'snippets'*
|
'snippets' snipMate.txt /*'snippets'*
|
||||||
.snippet snipMate.txt /*.snippet*
|
.snippet snipMate.txt /*.snippet*
|
||||||
.snippets snipMate.txt /*.snippets*
|
.snippets snipMate.txt /*.snippets*
|
||||||
:AcpDisable acp.txt /*:AcpDisable*
|
|
||||||
:AcpEnable acp.txt /*:AcpEnable*
|
|
||||||
:AcpLock acp.txt /*:AcpLock*
|
|
||||||
:AcpUnlock acp.txt /*:AcpUnlock*
|
|
||||||
:CVSEdit vcscommand.txt /*:CVSEdit*
|
:CVSEdit vcscommand.txt /*:CVSEdit*
|
||||||
:CVSEditors vcscommand.txt /*:CVSEditors*
|
:CVSEditors vcscommand.txt /*:CVSEditors*
|
||||||
:CVSUnedit vcscommand.txt /*:CVSUnedit*
|
:CVSUnedit vcscommand.txt /*:CVSUnedit*
|
||||||
@@ -40,6 +36,8 @@
|
|||||||
:CVSWatchOn vcscommand.txt /*:CVSWatchOn*
|
:CVSWatchOn vcscommand.txt /*:CVSWatchOn*
|
||||||
:CVSWatchRemove vcscommand.txt /*:CVSWatchRemove*
|
:CVSWatchRemove vcscommand.txt /*:CVSWatchRemove*
|
||||||
:CVSWatchers vcscommand.txt /*:CVSWatchers*
|
:CVSWatchers vcscommand.txt /*:CVSWatchers*
|
||||||
|
:Date: vimblogger_ft.txt /*:Date:*
|
||||||
|
:DeleteBlogArticle vimblogger_ft.txt /*:DeleteBlogArticle*
|
||||||
:DelimitMateReload delimitMate.txt /*:DelimitMateReload*
|
:DelimitMateReload delimitMate.txt /*:DelimitMateReload*
|
||||||
:DelimitMateSwitch delimitMate.txt /*:DelimitMateSwitch*
|
:DelimitMateSwitch delimitMate.txt /*:DelimitMateSwitch*
|
||||||
:DelimitMateTest delimitMate.txt /*:DelimitMateTest*
|
:DelimitMateTest delimitMate.txt /*:DelimitMateTest*
|
||||||
@@ -77,9 +75,15 @@
|
|||||||
:FufTag fuf.txt /*:FufTag*
|
:FufTag fuf.txt /*:FufTag*
|
||||||
:FufTagWithCursorWord fuf.txt /*:FufTagWithCursorWord*
|
:FufTagWithCursorWord fuf.txt /*:FufTagWithCursorWord*
|
||||||
:FufTaggedFile fuf.txt /*:FufTaggedFile*
|
:FufTaggedFile fuf.txt /*:FufTaggedFile*
|
||||||
|
:Id: vimblogger_ft.txt /*:Id:*
|
||||||
:Loremipsum loremipsum.txt /*:Loremipsum*
|
:Loremipsum loremipsum.txt /*:Loremipsum*
|
||||||
:Loreplace loremipsum.txt /*:Loreplace*
|
:Loreplace loremipsum.txt /*:Loreplace*
|
||||||
:Mark mark.txt /*:Mark*
|
:Mark mark.txt /*:Mark*
|
||||||
|
:Modified: vimblogger_ft.txt /*:Modified:*
|
||||||
|
:PreviewBlogArticle vimblogger_ft.txt /*:PreviewBlogArticle*
|
||||||
|
:SendBlogArticle vimblogger_ft.txt /*:SendBlogArticle*
|
||||||
|
:Tags: vimblogger_ft.txt /*:Tags:*
|
||||||
|
:Title: vimblogger_ft.txt /*:Title:*
|
||||||
:VCSAdd vcscommand.txt /*:VCSAdd*
|
:VCSAdd vcscommand.txt /*:VCSAdd*
|
||||||
:VCSAnnotate vcscommand.txt /*:VCSAnnotate*
|
:VCSAnnotate vcscommand.txt /*:VCSAnnotate*
|
||||||
:VCSBlame vcscommand.txt /*:VCSBlame*
|
:VCSBlame vcscommand.txt /*:VCSBlame*
|
||||||
@@ -122,9 +126,16 @@
|
|||||||
:VimwikiToggleListItem vimwiki.txt /*:VimwikiToggleListItem*
|
:VimwikiToggleListItem vimwiki.txt /*:VimwikiToggleListItem*
|
||||||
:VimwikiUISelect vimwiki.txt /*:VimwikiUISelect*
|
:VimwikiUISelect vimwiki.txt /*:VimwikiUISelect*
|
||||||
:VimwikiVSplitLink vimwiki.txt /*:VimwikiVSplitLink*
|
:VimwikiVSplitLink vimwiki.txt /*:VimwikiVSplitLink*
|
||||||
|
AnsiEsc AnsiEsc.txt /*AnsiEsc*
|
||||||
|
AnsiEsc-contents AnsiEsc.txt /*AnsiEsc-contents*
|
||||||
|
AnsiEsc-copyright AnsiEsc.txt /*AnsiEsc-copyright*
|
||||||
|
AnsiEsc-history AnsiEsc.txt /*AnsiEsc-history*
|
||||||
|
AnsiEsc-manual AnsiEsc.txt /*AnsiEsc-manual*
|
||||||
|
AnsiEsc.txt AnsiEsc.txt /*AnsiEsc.txt*
|
||||||
ExtractSnips() snipMate.txt /*ExtractSnips()*
|
ExtractSnips() snipMate.txt /*ExtractSnips()*
|
||||||
ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()*
|
ExtractSnipsFile() snipMate.txt /*ExtractSnipsFile()*
|
||||||
Filename() snipMate.txt /*Filename()*
|
Filename() snipMate.txt /*Filename()*
|
||||||
|
Id vimblogger_ft.txt /*Id*
|
||||||
ResetSnippets() snipMate.txt /*ResetSnippets()*
|
ResetSnippets() snipMate.txt /*ResetSnippets()*
|
||||||
ShowMarksClearAll showmarks.txt /*ShowMarksClearAll*
|
ShowMarksClearAll showmarks.txt /*ShowMarksClearAll*
|
||||||
ShowMarksClearMark showmarks.txt /*ShowMarksClearMark*
|
ShowMarksClearMark showmarks.txt /*ShowMarksClearMark*
|
||||||
@@ -156,21 +167,6 @@ VCSCommandSplit vcscommand.txt /*VCSCommandSplit*
|
|||||||
VCSCommandVCSTypeOverride vcscommand.txt /*VCSCommandVCSTypeOverride*
|
VCSCommandVCSTypeOverride vcscommand.txt /*VCSCommandVCSTypeOverride*
|
||||||
VimwikiWeblinkHandler vimwiki.txt /*VimwikiWeblinkHandler*
|
VimwikiWeblinkHandler vimwiki.txt /*VimwikiWeblinkHandler*
|
||||||
abc fuf.txt /*abc*
|
abc fuf.txt /*abc*
|
||||||
acp acp.txt /*acp*
|
|
||||||
acp-about acp.txt /*acp-about*
|
|
||||||
acp-author acp.txt /*acp-author*
|
|
||||||
acp-changelog acp.txt /*acp-changelog*
|
|
||||||
acp-commands acp.txt /*acp-commands*
|
|
||||||
acp-contact acp.txt /*acp-contact*
|
|
||||||
acp-installation acp.txt /*acp-installation*
|
|
||||||
acp-introduction acp.txt /*acp-introduction*
|
|
||||||
acp-options acp.txt /*acp-options*
|
|
||||||
acp-perl-omni acp.txt /*acp-perl-omni*
|
|
||||||
acp-snipMate acp.txt /*acp-snipMate*
|
|
||||||
acp-thanks acp.txt /*acp-thanks*
|
|
||||||
acp-usage acp.txt /*acp-usage*
|
|
||||||
acp.txt acp.txt /*acp.txt*
|
|
||||||
autocomplpop acp.txt /*autocomplpop*
|
|
||||||
b:VCSCommandCommand vcscommand.txt /*b:VCSCommandCommand*
|
b:VCSCommandCommand vcscommand.txt /*b:VCSCommandCommand*
|
||||||
b:VCSCommandOriginalBuffer vcscommand.txt /*b:VCSCommandOriginalBuffer*
|
b:VCSCommandOriginalBuffer vcscommand.txt /*b:VCSCommandOriginalBuffer*
|
||||||
b:VCSCommandSourceFile vcscommand.txt /*b:VCSCommandSourceFile*
|
b:VCSCommandSourceFile vcscommand.txt /*b:VCSCommandSourceFile*
|
||||||
@@ -204,6 +200,7 @@ delimitMateSyntax delimitMate.txt /*delimitMateSyntax*
|
|||||||
delimitMateTodo delimitMate.txt /*delimitMateTodo*
|
delimitMateTodo delimitMate.txt /*delimitMateTodo*
|
||||||
delimitMateVisualWrapping delimitMate.txt /*delimitMateVisualWrapping*
|
delimitMateVisualWrapping delimitMate.txt /*delimitMateVisualWrapping*
|
||||||
delimitMate_WithinEmptyPair delimitMate.txt /*delimitMate_WithinEmptyPair*
|
delimitMate_WithinEmptyPair delimitMate.txt /*delimitMate_WithinEmptyPair*
|
||||||
|
docinfo vimblogger_ft.txt /*docinfo*
|
||||||
ds surround.txt /*ds*
|
ds surround.txt /*ds*
|
||||||
fuf fuf.txt /*fuf*
|
fuf fuf.txt /*fuf*
|
||||||
fuf#setOneTimeVariables() fuf.txt /*fuf#setOneTimeVariables()*
|
fuf#setOneTimeVariables() fuf.txt /*fuf#setOneTimeVariables()*
|
||||||
@@ -272,32 +269,14 @@ fuf-usage fuf.txt /*fuf-usage*
|
|||||||
fuf-vimrc-example fuf.txt /*fuf-vimrc-example*
|
fuf-vimrc-example fuf.txt /*fuf-vimrc-example*
|
||||||
fuf.txt fuf.txt /*fuf.txt*
|
fuf.txt fuf.txt /*fuf.txt*
|
||||||
fuzzyfinder fuf.txt /*fuzzyfinder*
|
fuzzyfinder fuf.txt /*fuzzyfinder*
|
||||||
g:acp_behavior acp.txt /*g:acp_behavior*
|
g:blogger_browser vimblogger_ft.txt /*g:blogger_browser*
|
||||||
g:acp_behavior-command acp.txt /*g:acp_behavior-command*
|
g:blogger_confirm_del vimblogger_ft.txt /*g:blogger_confirm_del*
|
||||||
g:acp_behavior-completefunc acp.txt /*g:acp_behavior-completefunc*
|
g:blogger_draft vimblogger_ft.txt /*g:blogger_draft*
|
||||||
g:acp_behavior-meets acp.txt /*g:acp_behavior-meets*
|
g:blogger_login vimblogger_ft.txt /*g:blogger_login*
|
||||||
g:acp_behavior-onPopupClose acp.txt /*g:acp_behavior-onPopupClose*
|
g:blogger_maxarticles vimblogger_ft.txt /*g:blogger_maxarticles*
|
||||||
g:acp_behavior-repeat acp.txt /*g:acp_behavior-repeat*
|
g:blogger_name vimblogger_ft.txt /*g:blogger_name*
|
||||||
g:acp_behaviorCssOmniPropertyLength acp.txt /*g:acp_behaviorCssOmniPropertyLength*
|
g:blogger_pass vimblogger_ft.txt /*g:blogger_pass*
|
||||||
g:acp_behaviorCssOmniValueLength acp.txt /*g:acp_behaviorCssOmniValueLength*
|
g:blogger_stylesheets vimblogger_ft.txt /*g:blogger_stylesheets*
|
||||||
g:acp_behaviorFileLength acp.txt /*g:acp_behaviorFileLength*
|
|
||||||
g:acp_behaviorHtmlOmniLength acp.txt /*g:acp_behaviorHtmlOmniLength*
|
|
||||||
g:acp_behaviorKeywordCommand acp.txt /*g:acp_behaviorKeywordCommand*
|
|
||||||
g:acp_behaviorKeywordIgnores acp.txt /*g:acp_behaviorKeywordIgnores*
|
|
||||||
g:acp_behaviorKeywordLength acp.txt /*g:acp_behaviorKeywordLength*
|
|
||||||
g:acp_behaviorPerlOmniLength acp.txt /*g:acp_behaviorPerlOmniLength*
|
|
||||||
g:acp_behaviorPythonOmniLength acp.txt /*g:acp_behaviorPythonOmniLength*
|
|
||||||
g:acp_behaviorRubyOmniMethodLength acp.txt /*g:acp_behaviorRubyOmniMethodLength*
|
|
||||||
g:acp_behaviorRubyOmniSymbolLength acp.txt /*g:acp_behaviorRubyOmniSymbolLength*
|
|
||||||
g:acp_behaviorSnipmateLength acp.txt /*g:acp_behaviorSnipmateLength*
|
|
||||||
g:acp_behaviorUserDefinedFunction acp.txt /*g:acp_behaviorUserDefinedFunction*
|
|
||||||
g:acp_behaviorUserDefinedMeets acp.txt /*g:acp_behaviorUserDefinedMeets*
|
|
||||||
g:acp_behaviorXmlOmniLength acp.txt /*g:acp_behaviorXmlOmniLength*
|
|
||||||
g:acp_completeOption acp.txt /*g:acp_completeOption*
|
|
||||||
g:acp_completeoptPreview acp.txt /*g:acp_completeoptPreview*
|
|
||||||
g:acp_enableAtStartup acp.txt /*g:acp_enableAtStartup*
|
|
||||||
g:acp_ignorecaseOption acp.txt /*g:acp_ignorecaseOption*
|
|
||||||
g:acp_mappingDriven acp.txt /*g:acp_mappingDriven*
|
|
||||||
g:fuf_abbrevMap fuf.txt /*g:fuf_abbrevMap*
|
g:fuf_abbrevMap fuf.txt /*g:fuf_abbrevMap*
|
||||||
g:fuf_autoPreview fuf.txt /*g:fuf_autoPreview*
|
g:fuf_autoPreview fuf.txt /*g:fuf_autoPreview*
|
||||||
g:fuf_bookmarkdir_keyDelete fuf.txt /*g:fuf_bookmarkdir_keyDelete*
|
g:fuf_bookmarkdir_keyDelete fuf.txt /*g:fuf_bookmarkdir_keyDelete*
|
||||||
@@ -440,18 +419,6 @@ mark-usage mark.txt /*mark-usage*
|
|||||||
mark.txt mark.txt /*mark.txt*
|
mark.txt mark.txt /*mark.txt*
|
||||||
mark.vim mark.txt /*mark.vim*
|
mark.vim mark.txt /*mark.vim*
|
||||||
multi_snip snipMate.txt /*multi_snip*
|
multi_snip snipMate.txt /*multi_snip*
|
||||||
project project.txt /*project*
|
|
||||||
project-adding-mappings project.txt /*project-adding-mappings*
|
|
||||||
project-example project.txt /*project-example*
|
|
||||||
project-flags project.txt /*project-flags*
|
|
||||||
project-inheritance project.txt /*project-inheritance*
|
|
||||||
project-invoking project.txt /*project-invoking*
|
|
||||||
project-mappings project.txt /*project-mappings*
|
|
||||||
project-plugin project.txt /*project-plugin*
|
|
||||||
project-settings project.txt /*project-settings*
|
|
||||||
project-syntax project.txt /*project-syntax*
|
|
||||||
project-tips project.txt /*project-tips*
|
|
||||||
project.txt project.txt /*project.txt*
|
|
||||||
py2stdlib py2stdlib.txt /*py2stdlib*
|
py2stdlib py2stdlib.txt /*py2stdlib*
|
||||||
py2stdlib-__future__ py2stdlib.txt /*py2stdlib-__future__*
|
py2stdlib-__future__ py2stdlib.txt /*py2stdlib-__future__*
|
||||||
py2stdlib-__main__ py2stdlib.txt /*py2stdlib-__main__*
|
py2stdlib-__main__ py2stdlib.txt /*py2stdlib-__main__*
|
||||||
@@ -903,6 +870,7 @@ vcscommand-ssh-wrapper vcscommand.txt /*vcscommand-ssh-wrapper*
|
|||||||
vcscommand-statusline vcscommand.txt /*vcscommand-statusline*
|
vcscommand-statusline vcscommand.txt /*vcscommand-statusline*
|
||||||
vcscommand.txt vcscommand.txt /*vcscommand.txt*
|
vcscommand.txt vcscommand.txt /*vcscommand.txt*
|
||||||
vgS surround.txt /*vgS*
|
vgS surround.txt /*vgS*
|
||||||
|
vimblogger_ft.txt vimblogger_ft.txt /*vimblogger_ft.txt*
|
||||||
vimwiki vimwiki.txt /*vimwiki*
|
vimwiki vimwiki.txt /*vimwiki*
|
||||||
vimwiki-calendar vimwiki.txt /*vimwiki-calendar*
|
vimwiki-calendar vimwiki.txt /*vimwiki-calendar*
|
||||||
vimwiki-changelog vimwiki.txt /*vimwiki-changelog*
|
vimwiki-changelog vimwiki.txt /*vimwiki-changelog*
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ Other requirements:
|
|||||||
- Python (tested with version 2.6, should work also in others)
|
- Python (tested with version 2.6, should work also in others)
|
||||||
- gdata http://code.google.com/p/gdata-python-client
|
- gdata http://code.google.com/p/gdata-python-client
|
||||||
- docutils http://docutils.sourceforge.net
|
- docutils http://docutils.sourceforge.net
|
||||||
- pygments http://pygments.org
|
- pygments http://pygments.org (optional)
|
||||||
- Blogger account
|
- Blogger account
|
||||||
|
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
@@ -138,22 +138,22 @@ tincidunt, luctus a, sodales eget, leo. Sed ligula augue, cursus et.
|
|||||||
----->8-----
|
----->8-----
|
||||||
|
|
||||||
reST document (optionally) starts with *docinfo* section (first several
|
reST document (optionally) starts with *docinfo* section (first several
|
||||||
lines, that are starting from *:* character) separaded from other
|
lines, that are starting from ":" character) separaded from other
|
||||||
content with one empty line.
|
content with one empty line.
|
||||||
|
|
||||||
Docinfo items holds article attributes, and are updated automatically
|
Docinfo items holds article attributes, and are updated automatically
|
||||||
every each of upload to blogger, which is triggered by
|
every each of upload to blogger, which is triggered by
|
||||||
*:SendBlogArticle* command.
|
":SendBlogArticle" command.
|
||||||
|
|
||||||
*:Id:*
|
*:Id:*
|
||||||
Holds article id on blogger side. If not defined, new article will
|
Holds article id on blogger side. If not defined, new article will
|
||||||
be created (even if there is already existing one with the very same
|
be created (even if there is already existing one with the very same
|
||||||
content). If wrong id is entered (or an Id of deleted article),
|
content). If wrong Id is entered (or an Id of deleted article),
|
||||||
exception will be raised, and no action on blogger side will be
|
exception will be raised, and no action on blogger side will be
|
||||||
performed.
|
performed.
|
||||||
|
|
||||||
*:Title:*
|
*:Title:*
|
||||||
Holds article title. Can be changed when *:Id:* is obtained.
|
Holds article title. Can be changed when |:Id:| is obtained.
|
||||||
|
|
||||||
*:Date:*
|
*:Date:*
|
||||||
This is published date in RFC 3339
|
This is published date in RFC 3339
|
||||||
@@ -173,8 +173,9 @@ All other items are ignored.
|
|||||||
After docinfo block, article body should be placed using markup for
|
After docinfo block, article body should be placed using markup for
|
||||||
reStructuredText.
|
reStructuredText.
|
||||||
|
|
||||||
Additionally, there is sourcecode directive, simple syntax highlighter
|
Additionally, if pytgments is installed, there is sourcecode directive, simple
|
||||||
using Pygments module. Very simple usage could be as follows:
|
syntax highlighter using Pygments module. Very simple usage could be as
|
||||||
|
follows:
|
||||||
|
|
||||||
-----8<-----
|
-----8<-----
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
@@ -184,7 +185,7 @@ using Pygments module. Very simple usage could be as follows:
|
|||||||
|
|
||||||
----->8-----
|
----->8-----
|
||||||
|
|
||||||
Note: All headings for generated HTML by *:SendBlogArticle* will be
|
Note: All headings for generated HTML by |:SendBlogArticle| will be
|
||||||
shifted by 3, so the first heading will become <h3>, second <h4> and so
|
shifted by 3, so the first heading will become <h3>, second <h4> and so
|
||||||
on, to fit into blogger template (well, most of them). Remember, that
|
on, to fit into blogger template (well, most of them). Remember, that
|
||||||
HTML allow up to 6 level of headings, while reST doesn't have this
|
HTML allow up to 6 level of headings, while reST doesn't have this
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
# module vimblogger
|
# module rst2blogger
|
||||||
|
|||||||
@@ -1,46 +1,12 @@
|
|||||||
# vim: fileencoding=utf8
|
"""
|
||||||
#
|
File: blogger.py
|
||||||
# Blogger interface to make easy way to create/update articles for specified
|
Author: Roman 'gryf' Dobosz
|
||||||
# blog.
|
Description: This is blogger activity connected module. It is using gdata[1]
|
||||||
#
|
blogger module to provide add/modify/delete articles interface.
|
||||||
# It is assumed one way communication only, so you may create or update an
|
|
||||||
# article from reST source files. There is no way to recreate article from
|
[1] http://code.google.com/p/gdata-python-client
|
||||||
# html to reST format.
|
"""
|
||||||
#
|
|
||||||
# requirements:
|
|
||||||
#
|
|
||||||
# - Vim compiled with +python
|
|
||||||
# - python 2.x (tested with 2.6)
|
|
||||||
# - modules
|
|
||||||
# - gdata (http://code.google.com/p/gdata-python-client)
|
|
||||||
# - docutils (http://docutils.sourceforge.net)
|
|
||||||
#
|
|
||||||
# USE CASES:
|
|
||||||
# 1. Create new post
|
|
||||||
#
|
|
||||||
# use reST template:
|
|
||||||
# ===8<---
|
|
||||||
# :Title: Blog post title
|
|
||||||
# :Date: optional publish date (for example: 2010-11-28 18:47:05),
|
|
||||||
# default: now()
|
|
||||||
# :Modified: optional, default: None
|
|
||||||
# :Tags: comma separated blog tags
|
|
||||||
#
|
|
||||||
# .. more
|
|
||||||
#
|
|
||||||
# --->8===
|
|
||||||
#
|
|
||||||
# All four docinfo are optional, however it is nice to give at least a title
|
|
||||||
# to the article :)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# which is provided under templates directory or as a
|
|
||||||
# snipMate shoortcut (see .vim/snippets/rst.snippets)
|
|
||||||
#
|
|
||||||
|
|
||||||
#-----------------------------------------------------------------------------
|
|
||||||
#
|
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -51,6 +17,7 @@ from gdata.blogger.data import BlogPost
|
|||||||
|
|
||||||
class VimBlogger(object):
|
class VimBlogger(object):
|
||||||
"""
|
"""
|
||||||
|
Communicate with blogger through gdata.blogger modules
|
||||||
"""
|
"""
|
||||||
DATE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})"
|
DATE_PATTERN = re.compile(r"^(\d{4}-\d{2}-\d{2})"
|
||||||
"T(\d{2}:\d{2}:\d{2})(\.\d{3})?[+-]"
|
"T(\d{2}:\d{2}:\d{2})(\.\d{3})?[+-]"
|
||||||
@@ -59,12 +26,9 @@ class VimBlogger(object):
|
|||||||
TIME_FORMAT = "%H:%M:%S"
|
TIME_FORMAT = "%H:%M:%S"
|
||||||
TZ_FORMAT = "%H:%M"
|
TZ_FORMAT = "%H:%M"
|
||||||
|
|
||||||
# TODO: dodać usuwanie artykułów (prosta lista, wybieramy art,
|
|
||||||
# potwierdzamy)
|
|
||||||
# TODO: Dokumentacja jako vimdoc!
|
|
||||||
|
|
||||||
def __init__(self, blogname, login, password):
|
def __init__(self, blogname, login, password):
|
||||||
"""
|
"""
|
||||||
|
Initialization.
|
||||||
"""
|
"""
|
||||||
self.draft = True
|
self.draft = True
|
||||||
self.blog_id = None
|
self.blog_id = None
|
||||||
@@ -79,7 +43,6 @@ class VimBlogger(object):
|
|||||||
"""
|
"""
|
||||||
Return list of articles
|
Return list of articles
|
||||||
"""
|
"""
|
||||||
|
|
||||||
feed = self.client.get_posts(self.blog_id)
|
feed = self.client.get_posts(self.blog_id)
|
||||||
posts = []
|
posts = []
|
||||||
|
|
||||||
@@ -91,7 +54,6 @@ class VimBlogger(object):
|
|||||||
self._extract_date(entry.published.text)))
|
self._extract_date(entry.published.text)))
|
||||||
return posts
|
return posts
|
||||||
|
|
||||||
|
|
||||||
def create_article(self, html_doc, attrs=None):
|
def create_article(self, html_doc, attrs=None):
|
||||||
"""
|
"""
|
||||||
Create new article
|
Create new article
|
||||||
@@ -118,7 +80,7 @@ class VimBlogger(object):
|
|||||||
new_post.published = atom.data.Published(text=attrs['date'])
|
new_post.published = atom.data.Published(text=attrs['date'])
|
||||||
|
|
||||||
if self.draft:
|
if self.draft:
|
||||||
new_post.control = atom.data.Control(\
|
new_post.control = atom.data.Control(\
|
||||||
draft=atom.data.Draft(text='yes'))
|
draft=atom.data.Draft(text='yes'))
|
||||||
|
|
||||||
return self.client.post(new_post, BLOG_POST_URL % self.blog_id)
|
return self.client.post(new_post, BLOG_POST_URL % self.blog_id)
|
||||||
@@ -137,7 +99,7 @@ class VimBlogger(object):
|
|||||||
post = self._get_post(attrs['id'])
|
post = self._get_post(attrs['id'])
|
||||||
post.content = atom.data.Content(text=html_doc, type="html")
|
post.content = atom.data.Content(text=html_doc, type="html")
|
||||||
|
|
||||||
# update publish date
|
# update published date
|
||||||
if 'date' in attrs and attrs['date'] and \
|
if 'date' in attrs and attrs['date'] and \
|
||||||
self._check_date(attrs['date']):
|
self._check_date(attrs['date']):
|
||||||
post.published = atom.data.Published(text=attrs['date'])
|
post.published = atom.data.Published(text=attrs['date'])
|
||||||
@@ -168,9 +130,9 @@ class VimBlogger(object):
|
|||||||
self.client.delete(post)
|
self.client.delete(post)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _get_post(self, post_id):
|
def _get_post(self, post_id):
|
||||||
"""
|
"""
|
||||||
|
Return post with specified ID
|
||||||
"""
|
"""
|
||||||
post_href = self.blog.get_post_link().href
|
post_href = self.blog.get_post_link().href
|
||||||
return self.client.get_feed(post_href + "/%s" % post_id,
|
return self.client.get_feed(post_href + "/%s" % post_id,
|
||||||
@@ -227,18 +189,13 @@ class VimBlogger(object):
|
|||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _update_date(self, post, attrs):
|
|
||||||
"""
|
|
||||||
Update articles published date
|
|
||||||
"""
|
|
||||||
|
|
||||||
def _authorize(self, login, password):
|
def _authorize(self, login, password):
|
||||||
"""
|
"""
|
||||||
Try to authorize in Google service.
|
Try to authorize in Google service.
|
||||||
Authorization is kept in client object. In case of wrong credentials,
|
Authorization is kept in client object. In case of wrong credentials,
|
||||||
exception is thrown.
|
exception is thrown.
|
||||||
"""
|
"""
|
||||||
source = 'Blogger_Python_Sample-2.0'
|
source = 'Vim rst2blogger interface'
|
||||||
service = 'blogger'
|
service = 'blogger'
|
||||||
|
|
||||||
self.client.client_login(login,
|
self.client.client_login(login,
|
||||||
@@ -255,4 +212,3 @@ class VimBlogger(object):
|
|||||||
self.blog_id = blog.get_blog_id()
|
self.blog_id = blog.get_blog_id()
|
||||||
self.blog = blog
|
self.blog = blog
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,11 @@
|
|||||||
# vim: fileencoding=utf8
|
# vim: fileencoding=utf8
|
||||||
|
"""
|
||||||
|
File: main.py
|
||||||
|
Author: Roman 'gryf' Dobosz
|
||||||
|
Description: main file to provide fuctionality between vim and moudles rest
|
||||||
|
and blogger
|
||||||
|
"""
|
||||||
|
|
||||||
import webbrowser
|
import webbrowser
|
||||||
from xml.dom import minidom
|
from xml.dom import minidom
|
||||||
from xml.parsers.expat import ExpatError
|
from xml.parsers.expat import ExpatError
|
||||||
@@ -35,7 +42,7 @@ class Rst2Blogger(object):
|
|||||||
systems' web browser
|
systems' web browser
|
||||||
"""
|
"""
|
||||||
bufcontent = "\n".join(self.buff)
|
bufcontent = "\n".join(self.buff)
|
||||||
name = vim.current.buffer.name
|
name = self.buff.name
|
||||||
|
|
||||||
name = name[:-4] + ".html"
|
name = name[:-4] + ".html"
|
||||||
html = blogPreview(bufcontent, self.stylesheets)
|
html = blogPreview(bufcontent, self.stylesheets)
|
||||||
@@ -51,7 +58,10 @@ class Rst2Blogger(object):
|
|||||||
return "Generated HTML has been written to %s" % name
|
return "Generated HTML has been written to %s" % name
|
||||||
|
|
||||||
def post(self):
|
def post(self):
|
||||||
bufcontent = "\n".join(vim.current.buffer)
|
"""
|
||||||
|
Do post article
|
||||||
|
"""
|
||||||
|
bufcontent = "\n".join(self.buff)
|
||||||
html, attrs = blogArticleString(bufcontent)
|
html, attrs = blogArticleString(bufcontent)
|
||||||
|
|
||||||
parse_msg = self._check_html(html, True)
|
parse_msg = self._check_html(html, True)
|
||||||
@@ -60,7 +70,8 @@ class Rst2Blogger(object):
|
|||||||
return "There are errors in generated document"
|
return "There are errors in generated document"
|
||||||
|
|
||||||
if not self.password:
|
if not self.password:
|
||||||
self.password = vim.eval('inputsecret("Enter your gmail password: ")')
|
self.password = \
|
||||||
|
vim.eval('inputsecret("Enter your gmail password: ")')
|
||||||
|
|
||||||
blog = VimBlogger(self.blogname, self.login, self.password)
|
blog = VimBlogger(self.blogname, self.login, self.password)
|
||||||
blog.draft = self.draft > 0
|
blog.draft = self.draft > 0
|
||||||
@@ -74,9 +85,6 @@ class Rst2Blogger(object):
|
|||||||
msg = "New article with id %s has been created" % \
|
msg = "New article with id %s has been created" % \
|
||||||
post.get_post_id()
|
post.get_post_id()
|
||||||
|
|
||||||
if not post:
|
|
||||||
return "There is something fishy with creating new article."
|
|
||||||
|
|
||||||
for item, value in (('id', post.get_post_id()),
|
for item, value in (('id', post.get_post_id()),
|
||||||
('date', post.published.text),
|
('date', post.published.text),
|
||||||
('title', post.title.text),
|
('title', post.title.text),
|
||||||
@@ -92,14 +100,15 @@ class Rst2Blogger(object):
|
|||||||
delete
|
delete
|
||||||
"""
|
"""
|
||||||
if not self.password:
|
if not self.password:
|
||||||
self.password = vim.eval('inputsecret("Enter your gmail password: ")')
|
self.password = \
|
||||||
|
vim.eval('inputsecret("Enter your gmail password: ")')
|
||||||
blog = VimBlogger(self.blogname, self.login, self.password)
|
blog = VimBlogger(self.blogname, self.login, self.password)
|
||||||
|
|
||||||
posts = blog.get_articles(self.maxarticles)
|
posts = blog.get_articles(self.maxarticles)
|
||||||
|
|
||||||
msg = u"inputlist(["
|
msg = u"inputlist(["
|
||||||
for index, entries in enumerate(posts):
|
for index, entries in enumerate(posts):
|
||||||
line = "%2d %s %s" % (index+1,
|
line = "%2d %s %s" % (index + 1,
|
||||||
entries[1],
|
entries[1],
|
||||||
entries[2])
|
entries[2])
|
||||||
msg += u'"' + line.replace('"', '\\"') + u'",'
|
msg += u'"' + line.replace('"', '\\"') + u'",'
|
||||||
@@ -109,8 +118,9 @@ class Rst2Blogger(object):
|
|||||||
|
|
||||||
choice = int(vim.eval(msg))
|
choice = int(vim.eval(msg))
|
||||||
if choice:
|
if choice:
|
||||||
art = posts[choice-1]
|
art = posts[choice - 1]
|
||||||
msg = 'confirm("You are about to delete article \'%s\'. Are you sure?"'
|
msg = 'confirm("You are about to delete article \'%s\'. '
|
||||||
|
msg += 'Are you sure?"'
|
||||||
msg = unicode(msg % art[1]).encode(self.vim_encoding)
|
msg = unicode(msg % art[1]).encode(self.vim_encoding)
|
||||||
msg += ', "&No\n&Yes")'
|
msg += ', "&No\n&Yes")'
|
||||||
|
|
||||||
@@ -120,14 +130,10 @@ class Rst2Blogger(object):
|
|||||||
choice = 2
|
choice = 2
|
||||||
|
|
||||||
if choice == 2:
|
if choice == 2:
|
||||||
result = blog.delete_article(art[0])
|
blog.delete_article(art[0])
|
||||||
if result is None:
|
return "Article deleted"
|
||||||
return "Article deleted"
|
|
||||||
else:
|
|
||||||
return result
|
|
||||||
return "No articles deleted"
|
return "No articles deleted"
|
||||||
|
|
||||||
|
|
||||||
def _update_docinfo(self, attr, val):
|
def _update_docinfo(self, attr, val):
|
||||||
"""
|
"""
|
||||||
Update current buffer with attributes value
|
Update current buffer with attributes value
|
||||||
@@ -183,6 +189,9 @@ class Rst2Blogger(object):
|
|||||||
returns empty string if parses succeed, else exception message.
|
returns empty string if parses succeed, else exception message.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# minidom doesn't understand html entities like ' ' For checking
|
||||||
|
# purpose it is perfectly ok, to switch them with '&'
|
||||||
|
html = html.replace(" ", "&")
|
||||||
if add_container:
|
if add_container:
|
||||||
html = "<div>" + html + "</div>"
|
html = "<div>" + html + "</div>"
|
||||||
|
|
||||||
@@ -193,5 +202,3 @@ class Rst2Blogger(object):
|
|||||||
message = str(ex)
|
message = str(ex)
|
||||||
|
|
||||||
return message
|
return message
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
"""
|
||||||
|
File: rest.py
|
||||||
|
Author: Roman 'gryf' Dobosz
|
||||||
|
Description: This module is responsible for conversion between reST and HTML
|
||||||
|
with some goods added.
|
||||||
|
"""
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
from docutils import core
|
from docutils import core
|
||||||
@@ -5,35 +12,40 @@ from docutils import nodes
|
|||||||
from docutils.parsers.rst import directives, Directive
|
from docutils.parsers.rst import directives, Directive
|
||||||
from docutils.writers.html4css1 import Writer, HTMLTranslator
|
from docutils.writers.html4css1 import Writer, HTMLTranslator
|
||||||
|
|
||||||
from pygments import highlight
|
try:
|
||||||
from pygments.lexers import get_lexer_by_name, TextLexer
|
from pygments import highlight
|
||||||
from pygments.formatters import HtmlFormatter
|
from pygments.lexers import get_lexer_by_name, TextLexer
|
||||||
|
from pygments.formatters import HtmlFormatter
|
||||||
|
|
||||||
|
class Pygments(Directive):
|
||||||
|
"""
|
||||||
|
Source code syntax highlighting.
|
||||||
|
"""
|
||||||
|
required_arguments = 1
|
||||||
|
optional_arguments = 0
|
||||||
|
final_argument_whitespace = True
|
||||||
|
has_content = True
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
self.assert_has_content()
|
||||||
|
try:
|
||||||
|
lexer = get_lexer_by_name(self.arguments[0])
|
||||||
|
except ValueError:
|
||||||
|
# no lexer found - use the text one instead of an exception
|
||||||
|
lexer = TextLexer()
|
||||||
|
# take an arbitrary option if more than one is given
|
||||||
|
formatter = HtmlFormatter(noclasses=True)
|
||||||
|
parsed = highlight(u'\n'.join(self.content), lexer, formatter)
|
||||||
|
return [nodes.raw('', parsed, format='html')]
|
||||||
|
|
||||||
|
directives.register_directive('sourcecode', Pygments)
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Attrs(object):
|
class Attrs(object):
|
||||||
ATTRS = {}
|
ATTRS = {}
|
||||||
|
|
||||||
class Pygments(Directive):
|
|
||||||
"""
|
|
||||||
Source code syntax highlighting.
|
|
||||||
"""
|
|
||||||
required_arguments = 1
|
|
||||||
optional_arguments = 0
|
|
||||||
final_argument_whitespace = True
|
|
||||||
has_content = True
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
self.assert_has_content()
|
|
||||||
try:
|
|
||||||
lexer = get_lexer_by_name(self.arguments[0])
|
|
||||||
except ValueError:
|
|
||||||
# no lexer found - use the text one instead of an exception
|
|
||||||
lexer = TextLexer()
|
|
||||||
# take an arbitrary option if more than one is given
|
|
||||||
formatter = HtmlFormatter(noclasses=True)
|
|
||||||
parsed = highlight(u'\n'.join(self.content), lexer, formatter)
|
|
||||||
return [nodes.raw('', parsed, format='html')]
|
|
||||||
|
|
||||||
directives.register_directive('sourcecode', Pygments)
|
|
||||||
|
|
||||||
class CustomHTMLTranslator(HTMLTranslator):
|
class CustomHTMLTranslator(HTMLTranslator):
|
||||||
"""
|
"""
|
||||||
@@ -41,7 +53,6 @@ class CustomHTMLTranslator(HTMLTranslator):
|
|||||||
There are couple of customizations for docinfo fields behaviour and
|
There are couple of customizations for docinfo fields behaviour and
|
||||||
abbreviations and acronyms.
|
abbreviations and acronyms.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, document):
|
def __init__(self, document):
|
||||||
"""
|
"""
|
||||||
Set some nice defaults for articles translations
|
Set some nice defaults for articles translations
|
||||||
@@ -143,6 +154,7 @@ class CustomHTMLTranslator(HTMLTranslator):
|
|||||||
else:
|
else:
|
||||||
self.body.append(self.starttag(node, 'abbr', ''))
|
self.body.append(self.starttag(node, 'abbr', ''))
|
||||||
|
|
||||||
|
|
||||||
class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
||||||
"""
|
"""
|
||||||
Special subclass for generating only body of an article
|
Special subclass for generating only body of an article
|
||||||
@@ -154,7 +166,7 @@ class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
|||||||
CustomHTMLTranslator.__init__(self, document)
|
CustomHTMLTranslator.__init__(self, document)
|
||||||
self.head = []
|
self.head = []
|
||||||
self.meta = []
|
self.meta = []
|
||||||
self.head_prefix = ['','','','','']
|
self.head_prefix = ['', '', '', '', '']
|
||||||
self.body_prefix = []
|
self.body_prefix = []
|
||||||
self.body_suffix = []
|
self.body_suffix = []
|
||||||
self.stylesheet = []
|
self.stylesheet = []
|
||||||
@@ -173,11 +185,13 @@ class NoHeaderHTMLTranslator(CustomHTMLTranslator):
|
|||||||
"""
|
"""
|
||||||
Attrs.ATTRS['date'] = node.astext()
|
Attrs.ATTRS['date'] = node.astext()
|
||||||
|
|
||||||
|
|
||||||
class PreviewHTMLTranslator(CustomHTMLTranslator):
|
class PreviewHTMLTranslator(CustomHTMLTranslator):
|
||||||
"""
|
"""
|
||||||
Class for display article in the browser as a preview.
|
Class for display article in the browser as a preview.
|
||||||
"""
|
"""
|
||||||
CSS = []
|
CSS = []
|
||||||
|
|
||||||
def __init__(self, document):
|
def __init__(self, document):
|
||||||
"""
|
"""
|
||||||
Alter levels for the heading tags, define custom, blog specific
|
Alter levels for the heading tags, define custom, blog specific
|
||||||
@@ -193,7 +207,6 @@ class PreviewHTMLTranslator(CustomHTMLTranslator):
|
|||||||
for css in self.default_stylesheets]
|
for css in self.default_stylesheets]
|
||||||
self.body_ = []
|
self.body_ = []
|
||||||
|
|
||||||
|
|
||||||
def depart_docinfo(self, node):
|
def depart_docinfo(self, node):
|
||||||
"""
|
"""
|
||||||
Overwrite body with some custom one. body_ will hold the first heading
|
Overwrite body with some custom one. body_ will hold the first heading
|
||||||
@@ -203,7 +216,7 @@ class PreviewHTMLTranslator(CustomHTMLTranslator):
|
|||||||
|
|
||||||
def visit_field(self, node):
|
def visit_field(self, node):
|
||||||
"""
|
"""
|
||||||
Additional 'keyword' for the ODF metadata
|
Make title visible as a heading
|
||||||
"""
|
"""
|
||||||
key, node_ = [n.astext() for n in node]
|
key, node_ = [n.astext() for n in node]
|
||||||
key = key.lower()
|
key = key.lower()
|
||||||
@@ -212,6 +225,7 @@ class PreviewHTMLTranslator(CustomHTMLTranslator):
|
|||||||
self.body_.append('<h1 class="post-title entry-title">'
|
self.body_.append('<h1 class="post-title entry-title">'
|
||||||
'<a href="#">%s</a></h1>\n' % self.encode(node_))
|
'<a href="#">%s</a></h1>\n' % self.encode(node_))
|
||||||
|
|
||||||
|
|
||||||
class BlogBodyWriter(Writer):
|
class BlogBodyWriter(Writer):
|
||||||
"""
|
"""
|
||||||
Custom Writer class for generating HTML partial with the article
|
Custom Writer class for generating HTML partial with the article
|
||||||
@@ -224,6 +238,7 @@ class BlogBodyWriter(Writer):
|
|||||||
self.document.settings.output_encoding = "utf-8"
|
self.document.settings.output_encoding = "utf-8"
|
||||||
Writer.translate(self)
|
Writer.translate(self)
|
||||||
|
|
||||||
|
|
||||||
class BlogPreviewWriter(Writer):
|
class BlogPreviewWriter(Writer):
|
||||||
"""
|
"""
|
||||||
Custom Writer class for generating full HTML of the article
|
Custom Writer class for generating full HTML of the article
|
||||||
@@ -253,6 +268,7 @@ def blogPreview(string, stylesheets=None):
|
|||||||
html_output = html_output.replace("<!-- more -->", "\n<!-- more -->\n")
|
html_output = html_output.replace("<!-- more -->", "\n<!-- more -->\n")
|
||||||
return html_output
|
return html_output
|
||||||
|
|
||||||
|
|
||||||
def blogArticleString(string):
|
def blogArticleString(string):
|
||||||
"""
|
"""
|
||||||
Returns partial HTML of the article, and attribute dictionary
|
Returns partial HTML of the article, and attribute dictionary
|
||||||
@@ -269,4 +285,3 @@ def blogArticleString(string):
|
|||||||
attrs[key] = Attrs.ATTRS[key]
|
attrs[key] = Attrs.ATTRS[key]
|
||||||
|
|
||||||
return html_output, attrs
|
return html_output, attrs
|
||||||
|
|
||||||
|
|||||||
1
ftplugin/rst/rst2blogger/tests/__init__.py
Normal file
1
ftplugin/rst/rst2blogger/tests/__init__.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# module rst2blogger.tests
|
||||||
267
ftplugin/rst/rst2blogger/tests/shared.py
Normal file
267
ftplugin/rst/rst2blogger/tests/shared.py
Normal file
@@ -0,0 +1,267 @@
|
|||||||
|
# vim: set fileencoding=utf-8
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
from tempfile import mkstemp
|
||||||
|
|
||||||
|
|
||||||
|
LOGIN = "John"
|
||||||
|
PASS = "secret"
|
||||||
|
REST_ARTICLE = u""":Title: Title — This is a test
|
||||||
|
:Date: 2010-12-12T12:36:36+01:00
|
||||||
|
:Tags: this is a test, Blogger, rest
|
||||||
|
|
||||||
|
.. meta::
|
||||||
|
:description: meta are completely ignored in blogger parsers
|
||||||
|
|
||||||
|
`Amet`, convallis sollicitudin, commodo a, purus. Nulla vitae eros a diam
|
||||||
|
blandit **mollis**. Proin luctus ``ls --color ~/`` feugiat eros.
|
||||||
|
|
||||||
|
.. more
|
||||||
|
|
||||||
|
Pellentesque habitant morbi tristique senectus et *netus* et malesuada fames
|
||||||
|
ac turpis egestas. Duis ultricies urna: ``easy_install pygments``. Etiam enim
|
||||||
|
urna, pharetra suscipit, varius et, congue quis, odio. Donec `NES <Nintendo
|
||||||
|
Entertainment System>`:acronym: lobortis, elit bibendum euismod faucibus,
|
||||||
|
velit nibh egestas libero, vitae pellentesque elit augue ut massa.
|
||||||
|
|
||||||
|
test empty `acronym`:acronym: and `abbrev`:abbreviation:
|
||||||
|
|
||||||
|
Section 1
|
||||||
|
---------
|
||||||
|
|
||||||
|
Nulla consequat erat at massa. Vivamus id mi. Morbi purus enim, dapibus a,
|
||||||
|
facilisis non, tincidunt at, enim. Vestibulum ante ipsum primis in faucibus
|
||||||
|
orci luctus et ultrices posuere cubilia Curae; `WTF? <What the
|
||||||
|
fcuk?>`:abbreviation: Duis imperdiet eleifend arcu. Cras magna ligula,
|
||||||
|
consequat at, tempor non, posuere.
|
||||||
|
|
||||||
|
Subsection 1.1
|
||||||
|
..............
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
import vim
|
||||||
|
print vim.current.buffer.name
|
||||||
|
|
||||||
|
.. sourcecode:: unknown_lexer
|
||||||
|
|
||||||
|
Cras dignissim vulputate metus.
|
||||||
|
Phasellus eu quam. Quisque interdum cursus purus. In.
|
||||||
|
|
||||||
|
End.
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
class Eval(object):
|
||||||
|
"""
|
||||||
|
Communication class
|
||||||
|
"""
|
||||||
|
value = ""
|
||||||
|
blog = None
|
||||||
|
gdata_delete = 0
|
||||||
|
|
||||||
|
|
||||||
|
class Dummy(sys.__class__):
|
||||||
|
"""
|
||||||
|
Dummy class, for faking modules and other objects, not directly needed
|
||||||
|
"""
|
||||||
|
def __getattr__(self, attrname):
|
||||||
|
""" The dummy class should have no attribute """
|
||||||
|
if attrname == 'util':
|
||||||
|
return Dummy("util")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# fake vim module.
|
||||||
|
sys.modules["vim"] = Dummy("vim")
|
||||||
|
|
||||||
|
|
||||||
|
class MockBuffer(list):
|
||||||
|
"""
|
||||||
|
Vim buffer-like class
|
||||||
|
"""
|
||||||
|
def append(self, val, line=None):
|
||||||
|
"""
|
||||||
|
Override append method to mimic vim.buffer append behaviour
|
||||||
|
"""
|
||||||
|
if line is None:
|
||||||
|
super(MockBuffer, self).append(val)
|
||||||
|
else:
|
||||||
|
super(MockBuffer, self).insert(line, val)
|
||||||
|
|
||||||
|
|
||||||
|
class Mock(object):
|
||||||
|
"""
|
||||||
|
Generic all-purpose mock class
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
import vim
|
||||||
|
vim.command = lambda x: None
|
||||||
|
vim.current = Mock()
|
||||||
|
vim.current.buffer = MockBuffer(REST_ARTICLE.split("\n"))
|
||||||
|
fdesc, vim.current.buffer.name = mkstemp()
|
||||||
|
vim.current.buffer.name += ".rst"
|
||||||
|
os.close(fdesc) # close descriptor, only filename is needed
|
||||||
|
|
||||||
|
|
||||||
|
def mock_vim_eval(string):
|
||||||
|
ints = ("g:blogger_draft", "g:blogger_maxarticles",
|
||||||
|
"g:blogger_confirm_del")
|
||||||
|
if string in ints:
|
||||||
|
return "0"
|
||||||
|
elif string == "g:blogger_stylesheets":
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return Eval.value
|
||||||
|
vim.eval = mock_vim_eval
|
||||||
|
|
||||||
|
|
||||||
|
class MockBlog(object):
|
||||||
|
"""
|
||||||
|
Mock blog class
|
||||||
|
"""
|
||||||
|
def __init__(self, name, id):
|
||||||
|
self.name = name
|
||||||
|
self.id = id
|
||||||
|
|
||||||
|
def get_blog_name(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
def get_blog_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
def get_post_link(self):
|
||||||
|
link = Mock()
|
||||||
|
link.href = "http://www.mock.org"
|
||||||
|
return link
|
||||||
|
|
||||||
|
def get_post_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
|
||||||
|
class MockPost(object):
|
||||||
|
"""
|
||||||
|
Mock class imitating posts
|
||||||
|
"""
|
||||||
|
def __init__(self):
|
||||||
|
self.category = Mock()
|
||||||
|
self.category = []
|
||||||
|
self.id = None
|
||||||
|
self.title = Mock()
|
||||||
|
self.title.text = ""
|
||||||
|
self.published = Mock()
|
||||||
|
self.published.text = ""
|
||||||
|
|
||||||
|
def add_label(self, label):
|
||||||
|
item = Mock()
|
||||||
|
item.term = label
|
||||||
|
self.category.append(item)
|
||||||
|
|
||||||
|
def get_post_id(self):
|
||||||
|
return self.id
|
||||||
|
|
||||||
|
|
||||||
|
class MockBlogFeed(object):
|
||||||
|
"""
|
||||||
|
Mock class for feed objects
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.entry = []
|
||||||
|
if Eval.blog:
|
||||||
|
for bid, bname in {1: 'one', 3: 'test', 7: 'blog_name'}.items():
|
||||||
|
blog = MockBlog(bname, bid)
|
||||||
|
self.entry.append(blog)
|
||||||
|
|
||||||
|
|
||||||
|
class MockPostFeed(object):
|
||||||
|
"""
|
||||||
|
Mock class for feed objects
|
||||||
|
"""
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
self.entry = []
|
||||||
|
|
||||||
|
|
||||||
|
from atom.data import Id, Updated
|
||||||
|
from gdata.blogger.client import BloggerClient
|
||||||
|
|
||||||
|
BloggerClient.get_blogs = lambda x: MockBlogFeed()
|
||||||
|
|
||||||
|
from gdata.client import BadAuthentication
|
||||||
|
|
||||||
|
|
||||||
|
def mock_client_login(self, login, password, source=None, service=None):
|
||||||
|
"""
|
||||||
|
Mock method for client login.
|
||||||
|
"""
|
||||||
|
if login != LOGIN or password != PASS:
|
||||||
|
raise BadAuthentication("Incorrect username or password")
|
||||||
|
BloggerClient.client_login = mock_client_login
|
||||||
|
|
||||||
|
|
||||||
|
def mock_client_post(self, post, url=None):
|
||||||
|
"""
|
||||||
|
Mimic post method
|
||||||
|
"""
|
||||||
|
if Eval.value == 10:
|
||||||
|
return None
|
||||||
|
new_id = Id(text='1234567890')
|
||||||
|
post.id = new_id
|
||||||
|
date = datetime.utcnow()
|
||||||
|
milli = str(date.microsecond)[:3]
|
||||||
|
date = date.strftime("%Y-%m-%dT%H:%M:%S")
|
||||||
|
date = date + ".%s+00:00" % milli
|
||||||
|
post.updated = Updated(text=date)
|
||||||
|
return post
|
||||||
|
BloggerClient.post = mock_client_post
|
||||||
|
BloggerClient.update = mock_client_post
|
||||||
|
|
||||||
|
|
||||||
|
def mock_client_delete(self, post):
|
||||||
|
"""
|
||||||
|
Mock delete method
|
||||||
|
"""
|
||||||
|
if not post:
|
||||||
|
raise AttributeError("%s object has no attribute 'etag'" % type(post))
|
||||||
|
if Eval.gdata_delete:
|
||||||
|
return "404 Mock"
|
||||||
|
return None
|
||||||
|
BloggerClient.delete = mock_client_delete
|
||||||
|
|
||||||
|
|
||||||
|
def mock_client_get_posts(self, blog_id):
|
||||||
|
"""
|
||||||
|
Mock get_posts method
|
||||||
|
"""
|
||||||
|
posts = (('title1', 1, "2000-01-01T00:04:00.001+01:00"),
|
||||||
|
('title2', 2, "2001-01-01T00:02:19.001+01:00"),
|
||||||
|
('title3', 3, "2002-01-01T00:01:00.001+01:00"),
|
||||||
|
('title4', 4, "2006-01-01T00:02:00.001+02:00"))
|
||||||
|
feed = MockPostFeed()
|
||||||
|
for p in posts:
|
||||||
|
a = MockPost()
|
||||||
|
a.id = p[1]
|
||||||
|
a.title.text = p[0]
|
||||||
|
a.published.text = p[2]
|
||||||
|
feed.entry.append(a)
|
||||||
|
return feed
|
||||||
|
BloggerClient.get_posts = mock_client_get_posts
|
||||||
|
|
||||||
|
|
||||||
|
def mock_client_get_feed(self, uri, desired_class=None):
|
||||||
|
"""
|
||||||
|
Mock get_feed method
|
||||||
|
"""
|
||||||
|
post = MockPost()
|
||||||
|
post.add_label('test1')
|
||||||
|
return post
|
||||||
|
BloggerClient.get_feed = mock_client_get_feed
|
||||||
|
|
||||||
|
|
||||||
|
from gdata.blogger.data import BlogPost
|
||||||
|
|
||||||
|
|
||||||
|
def mock_get_post_id(self):
|
||||||
|
return self.id.text
|
||||||
|
BlogPost.get_post_id = mock_get_post_id
|
||||||
514
ftplugin/rst/rst2blogger/tests/test_blogger.py
Normal file
514
ftplugin/rst/rst2blogger/tests/test_blogger.py
Normal file
@@ -0,0 +1,514 @@
|
|||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
this_dir = os.path.abspath(os.path.join(this_dir, "../.."))
|
||||||
|
sys.path.insert(0, this_dir)
|
||||||
|
|
||||||
|
from rst2blogger.tests import shared
|
||||||
|
from rst2blogger.blogger import VimBlogger
|
||||||
|
|
||||||
|
|
||||||
|
class TestCheckDates(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Tests for method VimBlogger._check_date
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimb = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
|
||||||
|
def test_happy_case_CET(self):
|
||||||
|
"""
|
||||||
|
Test on good date string on Central and East Europe
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_happy_case_HST(self):
|
||||||
|
"""
|
||||||
|
Test on good date string on Hawaii Time Zone
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001-10:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_happy_case_GMT(self):
|
||||||
|
"""
|
||||||
|
Test UTC date string
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001-00:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_without_milliseconds(self):
|
||||||
|
"""
|
||||||
|
Test on date string without milliseconds
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_tz_format(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong timezone format (hour have no leading 0)
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001+1:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
# Test date with wrong timezone format (minute have only one digit)
|
||||||
|
date = "2000-01-01T00:00:00.001+01:0"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
# Test date with wrong timezone format (hours and minutes hasn't been
|
||||||
|
# separated by colon)
|
||||||
|
date = "2000-01-01T00:00:00.001+0100"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_milliseconds(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong format of milliseconds (.01 instead of .010)
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.01+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
# Test date with wrong format of milliseconds (.1 instead of .100)
|
||||||
|
date = "2000-01-01T00:00:00.1+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
# Test date with spolied format (dot for milliseconds, but no digits)
|
||||||
|
date = "2000-01-01T00:00:00.+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_milliseconds(self):
|
||||||
|
"""
|
||||||
|
Test date with correct format of milliseconds
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.000+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date), date + " is incorrect")
|
||||||
|
|
||||||
|
date = "2000-01-01T00:00:00.999+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date), date + " is incorrect")
|
||||||
|
|
||||||
|
def test_wrong_hours(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong hours value
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T24:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_hours(self):
|
||||||
|
"""
|
||||||
|
Test date with correct hours values
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date), date + " is incorrect")
|
||||||
|
date = "2000-01-01T23:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date), date + " is incorrect")
|
||||||
|
|
||||||
|
def test_wrong_minutes(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong minutes value
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:60:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-01-01T00:000:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-01-01T00:1:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_minutes(self):
|
||||||
|
"""
|
||||||
|
Test date with correct minutes values
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:01:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-01-01T00:59:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_seconds(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong seconds value
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:60.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_seconds(self):
|
||||||
|
"""
|
||||||
|
Test date with good seconds values
|
||||||
|
"""
|
||||||
|
for second in range(60):
|
||||||
|
date = "2000-01-01T00:00:%0.2d.001+01:00" % second
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_days(self):
|
||||||
|
"""
|
||||||
|
Test date with incorrect days (january has always 31 days, no month
|
||||||
|
has lower number than 1)
|
||||||
|
"""
|
||||||
|
date = "2000-01-32T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-01-00T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_days(self):
|
||||||
|
"""
|
||||||
|
Test date with correct days (january has always 31 days)
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-01-31T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_month(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong month
|
||||||
|
"""
|
||||||
|
date = "2000-00-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-13-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-1-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-001-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_month(self):
|
||||||
|
"""
|
||||||
|
Test date with correct months
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "2000-12-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_wrong_year(self):
|
||||||
|
"""
|
||||||
|
Test date with wrong year
|
||||||
|
"""
|
||||||
|
date = "0000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "10000-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "900-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertFalse(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
def test_good_year(self):
|
||||||
|
"""
|
||||||
|
Test date with correct years
|
||||||
|
"""
|
||||||
|
date = "0001-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
date = "9999-01-01T00:00:00.001+01:00"
|
||||||
|
self.assertTrue(self.vimb._check_date(date))
|
||||||
|
|
||||||
|
|
||||||
|
class TestAuthorize(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger._authorize
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object (with good credentials, yes :>)
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
|
||||||
|
def test_happy_case(self):
|
||||||
|
"""
|
||||||
|
Try to login with good credentials
|
||||||
|
"""
|
||||||
|
self.assertTrue(self.vimob._authorize(shared.LOGIN,
|
||||||
|
shared.PASS) is None)
|
||||||
|
|
||||||
|
def test_wrong_login(self):
|
||||||
|
"""
|
||||||
|
Try to login with wrong login
|
||||||
|
"""
|
||||||
|
self.assertRaises(shared.BadAuthentication, self.vimob._authorize,
|
||||||
|
'joe', shared.PASS)
|
||||||
|
|
||||||
|
def test_wrong_pass(self):
|
||||||
|
"""
|
||||||
|
Try to login with wrong password
|
||||||
|
"""
|
||||||
|
self.assertRaises(shared.BadAuthentication, self.vimob._authorize,
|
||||||
|
'joe', shared.PASS)
|
||||||
|
|
||||||
|
|
||||||
|
class TestAddTag(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger._add_tag
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
self.post = shared.MockPost()
|
||||||
|
|
||||||
|
def test_add_tag(self):
|
||||||
|
"""
|
||||||
|
Add items to existing categories. List should be uniq.
|
||||||
|
"""
|
||||||
|
self.vimob._add_tag(self.post, 'item')
|
||||||
|
self.assertTrue(len(self.post.category) == 1)
|
||||||
|
|
||||||
|
# Item number should not change on the same label
|
||||||
|
self.vimob._add_tag(self.post, 'item')
|
||||||
|
self.assertTrue(len(self.post.category) == 1)
|
||||||
|
|
||||||
|
self.vimob._add_tag(self.post, 'item2')
|
||||||
|
self.assertTrue(len(self.post.category) == 2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestExtractDate(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger._extract_date
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
|
||||||
|
def test_extract_date(self):
|
||||||
|
"""
|
||||||
|
Date should be already verified by _check_date method, so only
|
||||||
|
extraction is tested
|
||||||
|
"""
|
||||||
|
date = "2000-01-01T00:00:00.001-10:00"
|
||||||
|
|
||||||
|
# wrong scenario
|
||||||
|
self.assertFalse(self.vimob._extract_date('wrong_date_string'))
|
||||||
|
|
||||||
|
# only date should be returned
|
||||||
|
self.assertEqual(self.vimob._extract_date(date), "2000-01-01")
|
||||||
|
|
||||||
|
# date and time should be returned
|
||||||
|
self.assertEqual(self.vimob._extract_date(date, True),
|
||||||
|
"2000-01-01 00:00:00")
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetPost(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger._get_post
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
self.vimob.blog = shared.Mock()
|
||||||
|
|
||||||
|
link = shared.Mock()
|
||||||
|
link.href = "mock.com"
|
||||||
|
link.feed = shared.Mock()
|
||||||
|
|
||||||
|
self.vimob.blog.get_post_link = lambda: link
|
||||||
|
|
||||||
|
def test_get_post(self):
|
||||||
|
"""
|
||||||
|
Nothing really to test here. Maybe in the future :)
|
||||||
|
"""
|
||||||
|
result = self.vimob._get_post('1234')
|
||||||
|
self.assertEqual(type(result), shared.MockPost)
|
||||||
|
|
||||||
|
|
||||||
|
class TestSetBlog(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger._set_blog
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
for bid, bname in {1: 'one', 3: 'test', 7: 'blog_name'}.items():
|
||||||
|
blog = shared.MockBlog(bname, bid)
|
||||||
|
self.vimob.feed.entry.append(blog)
|
||||||
|
|
||||||
|
def test_set_blog(self):
|
||||||
|
"""
|
||||||
|
Test setting a blog
|
||||||
|
"""
|
||||||
|
self.vimob._set_blog("no_valid_blog_name")
|
||||||
|
self.assertEqual(self.vimob.blog_id, None)
|
||||||
|
self.assertEqual(self.vimob.blog, None)
|
||||||
|
|
||||||
|
self.vimob._set_blog("blog_name")
|
||||||
|
self.assertEqual(self.vimob.blog_id, 7)
|
||||||
|
self.assertEqual(self.vimob.blog.get_blog_name(), 'blog_name')
|
||||||
|
|
||||||
|
self.vimob._set_blog("test")
|
||||||
|
self.assertEqual(self.vimob.blog_id, 3)
|
||||||
|
self.assertEqual(self.vimob.blog.get_blog_name(), 'test')
|
||||||
|
|
||||||
|
self.vimob._set_blog("one")
|
||||||
|
self.assertEqual(self.vimob.blog_id, 1)
|
||||||
|
self.assertEqual(self.vimob.blog.get_blog_name(), 'one')
|
||||||
|
|
||||||
|
|
||||||
|
class TestCreateArticle(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger.create_article
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
|
||||||
|
def test_create_simple_article(self):
|
||||||
|
"""
|
||||||
|
Test creation of article with minimum requirements
|
||||||
|
"""
|
||||||
|
html = "<p>article</p>"
|
||||||
|
post = self.vimob.create_article(html)
|
||||||
|
self.vimob.draft = True
|
||||||
|
|
||||||
|
self.assertEqual(post.id.text, '1234567890')
|
||||||
|
self.assertEqual(post.content.text, html)
|
||||||
|
self.assertEqual(post.published, None)
|
||||||
|
self.assertTrue(post.updated is not None)
|
||||||
|
self.assertEqual(post.title.text, "")
|
||||||
|
self.assertEqual(post.category, [])
|
||||||
|
self.assertEqual(post.control.draft.text, "yes")
|
||||||
|
|
||||||
|
def test_create_article(self):
|
||||||
|
"""
|
||||||
|
Test creation of article with full attrs
|
||||||
|
"""
|
||||||
|
html = u"<p>article \xe2\x80\x94 article</p>"
|
||||||
|
labels = "tag with spaces|vim|python|blogger".split("|")
|
||||||
|
attrs = {"title": u'Title \xe2\x80\x94 title',
|
||||||
|
"tags": ", ".join(labels),
|
||||||
|
"date": "2010-12-10T14:18:32+00:00"}
|
||||||
|
self.vimob.draft = False
|
||||||
|
|
||||||
|
post = self.vimob.create_article(html, attrs)
|
||||||
|
self.assertEqual(post.id.text, '1234567890')
|
||||||
|
self.assertEqual(post.content.text, html)
|
||||||
|
self.assertEqual(post.published.text, attrs['date'])
|
||||||
|
self.assertTrue(post.updated is not None)
|
||||||
|
self.assertEqual(post.title.text, attrs['title'])
|
||||||
|
self.assertEqual(len(post.category), 4)
|
||||||
|
|
||||||
|
for label in post.category:
|
||||||
|
self.assertTrue(label.term in labels)
|
||||||
|
del(labels[labels.index(label.term)])
|
||||||
|
|
||||||
|
self.assertEqual(post.control, None)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDeleteArticle(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger.create_article
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
for bid, bname in {1: 'one', 3: 'test', 7: 'blog_name'}.items():
|
||||||
|
blog = shared.MockBlog(bname, bid)
|
||||||
|
self.vimob.feed.entry.append(blog)
|
||||||
|
self.vimob._set_blog('test')
|
||||||
|
|
||||||
|
def test_delete_non_existing_article(self):
|
||||||
|
"""
|
||||||
|
Test removing article without id
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.vimob.delete_article(None),
|
||||||
|
"No article id provided")
|
||||||
|
|
||||||
|
def test_delete_article(self):
|
||||||
|
"""
|
||||||
|
Test removing article
|
||||||
|
"""
|
||||||
|
html = u"<p>article \xe2\x80\x94 article</p>"
|
||||||
|
labels = "tag with spaces|vim|python|blogger".split("|")
|
||||||
|
attrs = {"title": u'Title \xe2\x80\x94 title',
|
||||||
|
"tags": ", ".join(labels),
|
||||||
|
"date": "2010-12-10T14:18:32+00:00"}
|
||||||
|
self.vimob.draft = False
|
||||||
|
|
||||||
|
post = self.vimob.create_article(html, attrs)
|
||||||
|
self.assertEqual(self.vimob.delete_article(post.id.text), None)
|
||||||
|
|
||||||
|
|
||||||
|
class TestGetArticles(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger.get_articles
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
|
||||||
|
def test_get_articles(self):
|
||||||
|
"""
|
||||||
|
Test removing article without id
|
||||||
|
"""
|
||||||
|
articles = self.vimob.get_articles()
|
||||||
|
self.assertEqual(len(articles), 4)
|
||||||
|
|
||||||
|
articles = self.vimob.get_articles(maxarticles=2)
|
||||||
|
self.assertEqual(len(articles), 2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestUpdateArticle(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test method VimBlogger.update_article
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create VimBlogger object
|
||||||
|
"""
|
||||||
|
self.vimob = VimBlogger(None, shared.LOGIN, shared.PASS)
|
||||||
|
for bid, bname in {1: 'one', 3: 'test', 7: 'blog_name'}.items():
|
||||||
|
blog = shared.MockBlog(bname, bid)
|
||||||
|
self.vimob.feed.entry.append(blog)
|
||||||
|
self.vimob._set_blog('test')
|
||||||
|
|
||||||
|
def test_wrong_argument_types(self):
|
||||||
|
"""
|
||||||
|
Test update_article method with wrong argument types
|
||||||
|
"""
|
||||||
|
self.assertRaises(TypeError, self.vimob.update_article, None, None)
|
||||||
|
|
||||||
|
def test_no_id_in_attrs(self):
|
||||||
|
"""
|
||||||
|
Test update_article method with no id in attrs
|
||||||
|
"""
|
||||||
|
self.assertRaises(Exception, self.vimob.update_article,
|
||||||
|
'<p>update</p>', [])
|
||||||
|
|
||||||
|
def test_update(self):
|
||||||
|
"""
|
||||||
|
Test update_article method with no id in attrs
|
||||||
|
"""
|
||||||
|
attrs = {'id': 1234567890, 'title': 'update',
|
||||||
|
'date': '2001-01-01T00:02:19.001+01:00',
|
||||||
|
'tags': "tag1, tag2, tag3"}
|
||||||
|
post = self.vimob.update_article('<p>update</p>', attrs)
|
||||||
|
|
||||||
|
self.assertEqual(post.title.text, 'update')
|
||||||
|
self.assertEqual(post.id.text, '1234567890')
|
||||||
|
self.assertEqual(post.content.text, '<p>update</p>')
|
||||||
|
self.assertTrue(post.updated.text is not None)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
294
ftplugin/rst/rst2blogger/tests/test_main.py
Normal file
294
ftplugin/rst/rst2blogger/tests/test_main.py
Normal file
@@ -0,0 +1,294 @@
|
|||||||
|
# vim: set fileencoding=utf-8
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import webbrowser
|
||||||
|
|
||||||
|
webbrowser.open = lambda x: None
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
this_dir = os.path.abspath(os.path.join(this_dir, "../.."))
|
||||||
|
sys.path.insert(0, this_dir)
|
||||||
|
|
||||||
|
from rst2blogger.tests.shared import LOGIN, PASS, Eval, MockBuffer
|
||||||
|
from rst2blogger.main import Rst2Blogger
|
||||||
|
from gdata.client import BadAuthentication
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2Blogger(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Tests for vim - rest - blogger interface
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
|
||||||
|
def test_object_creation(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object and test it.
|
||||||
|
"""
|
||||||
|
self.assertTrue(self.obj is not None)
|
||||||
|
self.assertEqual(self.obj.docinfo_len, 3)
|
||||||
|
self.assertEqual(self.obj.login, "")
|
||||||
|
self.assertEqual(self.obj.password, "")
|
||||||
|
self.assertEqual(self.obj.blogname, "")
|
||||||
|
self.assertEqual(self.obj.buffer_encoding, "")
|
||||||
|
self.assertEqual(self.obj.vim_encoding, "")
|
||||||
|
self.assertEqual(self.obj.maxarticles, 0)
|
||||||
|
self.assertEqual(self.obj.draft, 0)
|
||||||
|
self.assertEqual(self.obj.confirm_del, 0)
|
||||||
|
self.assertEqual(self.obj.stylesheets, [])
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2BloggerSetDocinfoLen(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test _set_docinfo_len method on different docinfo configurations
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
|
||||||
|
def test_set_docinfo_len(self):
|
||||||
|
"""
|
||||||
|
Test with no defined docinfo
|
||||||
|
"""
|
||||||
|
self.obj.buff = self.obj.buff[4:]
|
||||||
|
self.obj._set_docinfo_len()
|
||||||
|
self.assertEqual(self.obj.docinfo_len, 0)
|
||||||
|
|
||||||
|
def test_set_docinfo_len2(self):
|
||||||
|
"""
|
||||||
|
Test with one docinfo entry
|
||||||
|
"""
|
||||||
|
self.obj.buff = self.obj.buff[:1] + [''] + self.obj.buff[4:]
|
||||||
|
self.obj._set_docinfo_len()
|
||||||
|
self.assertEqual(self.obj.docinfo_len, 1)
|
||||||
|
|
||||||
|
def test_set_docinfo_len3(self):
|
||||||
|
"""
|
||||||
|
Test with wrong docinfo definition
|
||||||
|
"""
|
||||||
|
self.obj.buff = self.obj.buff[:1] + self.obj.buff[4:]
|
||||||
|
self.obj._set_docinfo_len()
|
||||||
|
self.assertEqual(self.obj.docinfo_len, 0)
|
||||||
|
|
||||||
|
|
||||||
|
class TestCheckHtml(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Check HTML parser
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
|
||||||
|
def test_check_html1(self):
|
||||||
|
"""
|
||||||
|
Parse (generated) html string, should return empty string
|
||||||
|
"""
|
||||||
|
html = "<html><head><title>test</title></head><body></body></html>"
|
||||||
|
self.assertEqual(self.obj._check_html(html), "")
|
||||||
|
self.assertEqual(self.obj._check_html(html, True), "")
|
||||||
|
|
||||||
|
def test_check_html2(self):
|
||||||
|
"""
|
||||||
|
Parse html fragment string
|
||||||
|
"""
|
||||||
|
html = "<p>first paragraph</p><p>another paragraph</p>"
|
||||||
|
self.assertEqual(self.obj._check_html(html),
|
||||||
|
"junk after document element: line 1, column 22")
|
||||||
|
self.assertEqual(self.obj._check_html(html, True), "")
|
||||||
|
|
||||||
|
def test_check_html3(self):
|
||||||
|
"""
|
||||||
|
Parse wrong html string (crossed tags)
|
||||||
|
"""
|
||||||
|
html = "<p>first paragraph<b></p>another paragraph</b>"
|
||||||
|
self.assertEqual(self.obj._check_html(html),
|
||||||
|
"mismatched tag: line 1, column 23")
|
||||||
|
self.assertEqual(self.obj._check_html(html, True),
|
||||||
|
"mismatched tag: line 1, column 28")
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2BloggerDelete(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test delete method
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
self.obj.login = LOGIN
|
||||||
|
self.obj.password = PASS
|
||||||
|
self.obj.blogname = "test"
|
||||||
|
self.obj.vim_encoding = "utf-8"
|
||||||
|
|
||||||
|
def test_delete_without_password(self):
|
||||||
|
"""
|
||||||
|
Delete article, while password is incorrect/nonexistend
|
||||||
|
"""
|
||||||
|
self.obj.password = ""
|
||||||
|
self.assertRaises(BadAuthentication, self.obj.delete)
|
||||||
|
|
||||||
|
def test_delete(self):
|
||||||
|
"""
|
||||||
|
Delete article. Set confirmation attribute.
|
||||||
|
"""
|
||||||
|
self.obj.confirm_del = 1
|
||||||
|
Eval.value = 2 # set choice to answer "Y" for confirmation
|
||||||
|
Eval.blog = "test"
|
||||||
|
self.assertEqual(self.obj.delete(), "Article deleted")
|
||||||
|
|
||||||
|
def test_delete2(self):
|
||||||
|
"""
|
||||||
|
Delete article. Set confirmation attribute. Refuse to delete.
|
||||||
|
"""
|
||||||
|
self.obj.confirm_del = 1
|
||||||
|
Eval.value = 1 # set choice to answer "N" for confirmation
|
||||||
|
Eval.blog = "test"
|
||||||
|
self.assertEqual(self.obj.delete(), "No articles deleted")
|
||||||
|
|
||||||
|
def test_delete3(self):
|
||||||
|
"""
|
||||||
|
Delete article. Unset confirmation attribute. Delete returns something
|
||||||
|
else then None.
|
||||||
|
"""
|
||||||
|
Eval.value = 2
|
||||||
|
Eval.blog = "test"
|
||||||
|
Eval.gdata_delete = 1
|
||||||
|
self.assertEqual(self.obj.delete(), "Article deleted")
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2BloggerPost(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test post method
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
self.obj.login = LOGIN
|
||||||
|
self.obj.password = PASS
|
||||||
|
self.obj.blogname = "test"
|
||||||
|
self.obj.vim_encoding = "utf-8"
|
||||||
|
self.obj.buffer_encoding = "utf-8"
|
||||||
|
# create copy of the buffer list and assign copy to the buff attribute
|
||||||
|
self._rest = MockBuffer(self.obj.buff[:])
|
||||||
|
self.obj.buff = self._rest
|
||||||
|
|
||||||
|
def test_without_password(self):
|
||||||
|
"""
|
||||||
|
Post article, while password is incorrect/nonexistend
|
||||||
|
"""
|
||||||
|
self.obj.password = ""
|
||||||
|
self.assertRaises(BadAuthentication, self.obj.post)
|
||||||
|
|
||||||
|
def test_with_wrong_data(self):
|
||||||
|
"""
|
||||||
|
Try to post not well formed html
|
||||||
|
"""
|
||||||
|
self.obj.buff.append('')
|
||||||
|
self.obj.buff.append('.. raw:: html')
|
||||||
|
self.obj.buff.append('')
|
||||||
|
self.obj.buff.append(' <p>foo<b>bar</p>baz</b>')
|
||||||
|
self.obj.buff.append('')
|
||||||
|
self.obj.post()
|
||||||
|
self.assertEqual(self.obj.post(),
|
||||||
|
'There are errors in generated document')
|
||||||
|
|
||||||
|
def test_post_create(self):
|
||||||
|
"""
|
||||||
|
Try to post well formed html, as a new article
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.obj.post(),
|
||||||
|
'New article with id 1234567890 has been created')
|
||||||
|
|
||||||
|
def test_post_update(self):
|
||||||
|
"""
|
||||||
|
Try to post well formed html, as a new article
|
||||||
|
"""
|
||||||
|
self.obj.buff.append(':Id: 1234567890', 0)
|
||||||
|
self.assertEqual(self.obj.post(),
|
||||||
|
"Article 'Title \xe2\x80\x94 This is a test' "
|
||||||
|
"has been updated")
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2BloggerUpdateDocinfo(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test _update_docinfo
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
self.obj.login = LOGIN
|
||||||
|
self.obj.password = PASS
|
||||||
|
self.obj.blogname = "test"
|
||||||
|
self.obj.vim_encoding = "utf-8"
|
||||||
|
self.obj.buffer_encoding = "utf-8"
|
||||||
|
# create copy of the buffer list and assign copy to the buff attribute
|
||||||
|
self._rest = MockBuffer(self.obj.buff[:])
|
||||||
|
self.obj.buff = self._rest
|
||||||
|
|
||||||
|
def test_with_empty_docinfo(self):
|
||||||
|
"""
|
||||||
|
Try to post not well formed html
|
||||||
|
"""
|
||||||
|
self.obj.buff = MockBuffer(self.obj.buff[4:])
|
||||||
|
self.obj.docinfo_len = 0
|
||||||
|
self.obj._update_docinfo('title', 'title2')
|
||||||
|
|
||||||
|
|
||||||
|
class TestRst2BloggerPreview(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test preview
|
||||||
|
"""
|
||||||
|
def setUp(self):
|
||||||
|
"""
|
||||||
|
Create Rst2Blogger object
|
||||||
|
"""
|
||||||
|
self.obj = Rst2Blogger()
|
||||||
|
self.obj.login = LOGIN
|
||||||
|
self.obj.password = PASS
|
||||||
|
self.obj.blogname = "test"
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
"""
|
||||||
|
Remove leftovers in fs
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
os.unlink(self.obj.buff.name[:-4])
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
os.unlink(self.obj.buff.name[:-4] + ".html")
|
||||||
|
except OSError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_preview_open_in_browser(self):
|
||||||
|
"""
|
||||||
|
Try to post not well formed html
|
||||||
|
"""
|
||||||
|
Eval.value = 1
|
||||||
|
print self.obj.preview()
|
||||||
|
|
||||||
|
def test_preview_save_to_file(self):
|
||||||
|
"""
|
||||||
|
Try to post not well formed html
|
||||||
|
"""
|
||||||
|
Eval.value = 0
|
||||||
|
name = self.obj.buff.name[:-4] + ".html"
|
||||||
|
self.assertEqual(self.obj.preview(),
|
||||||
|
"Generated HTML has been written to %s" % name)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
79
ftplugin/rst/rst2blogger/tests/test_rest.py
Normal file
79
ftplugin/rst/rst2blogger/tests/test_rest.py
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
# vim: set fileencoding=utf-8
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import unittest
|
||||||
|
import re
|
||||||
|
|
||||||
|
this_dir = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
this_dir = os.path.abspath(os.path.join(this_dir, "../.."))
|
||||||
|
sys.path.insert(0, this_dir)
|
||||||
|
|
||||||
|
from rst2blogger.rest import blogArticleString, blogPreview
|
||||||
|
from rst2blogger.tests.shared import REST_ARTICLE
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlogPreview(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test generating HTML out of prepared reST text. It tests only for some
|
||||||
|
aspects of the entire thing, because it is not intendend to test all of
|
||||||
|
reST directives.
|
||||||
|
"""
|
||||||
|
def test_content(self):
|
||||||
|
"""
|
||||||
|
Simple case, check output
|
||||||
|
"""
|
||||||
|
html_out = blogPreview(REST_ARTICLE)
|
||||||
|
self.assertTrue(len(html_out) > 0)
|
||||||
|
self.assertTrue("<html" in html_out)
|
||||||
|
self.assertTrue("</html>" in html_out)
|
||||||
|
self.assertTrue("<?xml version=\"1.0\" encoding=\"utf-8\"" in
|
||||||
|
html_out)
|
||||||
|
self.assertTrue("\n\n<!-- more -->\n\n" in html_out)
|
||||||
|
self.assertTrue("<title>Title — This is a test</title>" in html_out)
|
||||||
|
self.assertTrue('type="text/css"' not in html_out)
|
||||||
|
self.assertTrue(re.search(r"<h1.*><a href=\"#\">Title — This is a"
|
||||||
|
" test</a></h1>", html_out))
|
||||||
|
self.assertTrue(re.search(r"<h2>Section 1</h2>", html_out))
|
||||||
|
self.assertTrue(re.search(r"<h3>Subsection 1.1</h3>", html_out))
|
||||||
|
self.assertTrue("description" not in html_out)
|
||||||
|
|
||||||
|
def test_stylesheets(self):
|
||||||
|
"""
|
||||||
|
Test output for stylesheets
|
||||||
|
"""
|
||||||
|
html_out = blogPreview(REST_ARTICLE, ["css/style1.css",
|
||||||
|
"css/blogger1.css"])
|
||||||
|
self.assertTrue('type="text/css"' in html_out)
|
||||||
|
match = re.search(r'<link rel="stylesheet" '
|
||||||
|
'href=".*" type="text/css" />', html_out)
|
||||||
|
self.assertTrue(match is not None)
|
||||||
|
self.assertEqual(len(match.span()), 2)
|
||||||
|
|
||||||
|
|
||||||
|
class TestBlogArticleString(unittest.TestCase):
|
||||||
|
"""
|
||||||
|
Test blogArticleString function, wich should return part of html and
|
||||||
|
dictionary with attributes.
|
||||||
|
"""
|
||||||
|
def test_blogArticleString(self):
|
||||||
|
html_out, attrs = blogArticleString(REST_ARTICLE)
|
||||||
|
self.assertEqual(len(attrs), 3)
|
||||||
|
self.assertTrue(len(html_out) > 0)
|
||||||
|
self.assertTrue("<html" not in html_out)
|
||||||
|
self.assertTrue("</html>" not in html_out)
|
||||||
|
self.assertTrue("<?xml version=\"1.0\" encoding=\"utf-8\"" not in
|
||||||
|
html_out)
|
||||||
|
self.assertTrue("\n\n<!-- more -->\n\n" in html_out)
|
||||||
|
self.assertTrue("<title>Title — This is a test</title>" not in
|
||||||
|
html_out)
|
||||||
|
self.assertTrue('type="text/css"' not in html_out)
|
||||||
|
self.assertTrue(re.search(r"<h4>Section 1</h4>", html_out))
|
||||||
|
self.assertTrue(re.search(r"<h5>Subsection 1.1</h5>", html_out))
|
||||||
|
self.assertTrue("description" not in html_out)
|
||||||
|
|
||||||
|
self.assertEqual(attrs['title'], u"Title — This is a test")
|
||||||
|
self.assertEqual(attrs['date'], "2010-12-12T12:36:36+01:00")
|
||||||
|
self.assertEqual(attrs['tags'], "this is a test, Blogger, rest")
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
||||||
@@ -25,7 +25,7 @@ if !exists("g:blogger_login")
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:blogger_pass")
|
if !exists("g:blogger_pass")
|
||||||
let g:blogger_pass = "Kurcz4czek"
|
let g:blogger_pass = ""
|
||||||
endif
|
endif
|
||||||
|
|
||||||
if !exists("g:blogger_draft")
|
if !exists("g:blogger_draft")
|
||||||
|
|||||||
Reference in New Issue
Block a user