Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 107 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
.static_storage/
.media/
local_settings.py

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# Jupyter Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/

# IDE
.idea
20 changes: 20 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
language: python
python:
- '3.5'
sudo: true
dist: trusty
install:
- wget https://github.com/jgm/pandoc/releases/download/2.1.1/pandoc-2.1.1-1-amd64.deb
- sudo dpkg -i pandoc-2.1.1-1-amd64.deb
- pip install -r bin/requirements.txt
script:
- python bin/dw_deploy.py tutorials
branches:
only:
- master
env:
global:
- DW_URL: https://edux.fit.cvut.cz/courses/MI-AFP
- DW_NAMESPACE: tutorials:master
- DW_USERNAME: suchama4
- secure: kfeUcNiJ/wCzae4fSgi6m4dze44izWh3g9Yx/jpkwOeoAvEd1K7wf20dUs1dLclBCDechD2x5zjyomSJhg8zkpqDn0/6y/0Q2qtuLHcIihUybnaBg1y0OzvynPfhb9tm6ZxifvwfHPt3KmJ8QZP7EgWzXWoUpu2grrOEDVHza/K5PIyCq+TiK2NGfko/FQmpUKHYeLtcFt/gkX1KfZAJYWbcjWVkt1hhQmFH4w4eh5I4NQk+yvI8LoDzYm/b0XHtd5CCQZ+VOGoM8eKmNfDgmlIKQn6bPQHZUh57iJ7P2HEO5xfXn64fNPshEkqLgXdjRbYIo8kljRBHBkjsu0jfy3w9jCDpJR9FFAJS5ZmMfIiMrrFvbPPjmwXOAMt+ExF/lkJpp1idJoET/JLlz/GSgKdvFQGX3tDG9cNKbvNbUOd03g+FdL9Nh03HhYyFpxat94vZDK8tvm9ctTcF7dg2cW49qSa4OKp+YdBkhFvNPx3M7S5fQ+ODRFoeFhlJt2YMgW1iw8o5o77mPWTN2cGkeXeM6W4+PkN3R10nTOe2H7ZN6N+5u1NBXWCqtzit2Cq9lDSuDjRZwMhwA1znuoBtM4n1Qtz9qFov+48sZIPTk/pqHLVTF6wGpHpT5Hi65XHWqKQsjVM1+2W9dWIB+jhidKi0TlSkwBKQhQlygh7E7sQ=
1 change: 1 addition & 0 deletions bin/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
set_env.sh
151 changes: 151 additions & 0 deletions bin/dw_deploy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
# Markdown to DW deployment script
# inspired by https://github.com/cvut/MI-PYT
import os
import re

import click
import pypandoc
import requests

from lxml import etree


def prefilter_haskellcode(input_md):
"""Make use of pascal to enable haskell code highlighting (in md)"""
return input_md.replace('```haskell', '```pascal')


def postfilter_haskellcode(output_dw):
"""Make use of pascal to enable haskell code highlighting (in dw)"""
return output_dw.replace('<code pascal>', '<code haskell>')


def prefilter_interlinking(input_md):
"""Removed md from local interlinked documents in the same directory"""
return re.sub(r'\[([^\]]*)]\(([^\)\/]*)\.md\)', r'[\1](\2)', input_md)


class DW:
PREFILTERS = [
prefilter_haskellcode,
prefilter_interlinking
]
POSTFILTERS = [
postfilter_haskellcode
]

def __init__(self, url, username, password):
self.url = url + '/doku.php'
self.session = self._init_session(username, password)

@staticmethod
def _find_elem(content, type, attr, value):
tree = etree.HTML(content)
for elem in tree.findall('.//' + type):
if elem.attrib.get(attr) == value:
return elem
return None

def _init_session(self, username, password):
session = requests.Session()

params = {'id': 'start', 'do': 'login'}
r = session.get(self.url, params=params)
sectok_input = self._find_elem(r.text, 'input', 'name', 'sectok')
if sectok_input is None:
raise ValueError('Could not find sectok on login page')

sectok = sectok_input.attrib.get('value', '')
login_data = {
'sectok': sectok,
'id': 'start',
'do': 'login',
'authnProvider': '2',
'u': username,
'p': password,
'r': '1',
}
params['sectok'] = sectok
r = session.post(self.url, params=params, data=login_data)
if 'logout' not in r.text:
raise ValueError('Could not login')

return session

def put_page(self, dw_page, content):
params = {'id': dw_page, 'do': 'edit'}
r = self.session.get(self.url, params=params)

edit_form = self._find_elem(r.text, 'form', 'id', 'dw__editform')
if edit_form is None:
raise ValueError('Could not find edit form on parsed page')

data = {}
for inp in edit_form.findall('.//input'):
name = inp.attrib.get('name')
if not name.startswith('do['):
data[name] = inp.attrib.get('value', '')

data['wikitext'] = content
data['do[save]'] = 'Yes, please!'

self.session.post(r.url, data=data)

def put_md(self, dw_page, file):
self.put_page(dw_page, self._transform_md2dw(file))

@classmethod
def _transform_md2dw(cls, file):
with open(file, mode='r') as f:
content = f.read()
content = cls._apply_filters(cls.PREFILTERS, content)
content = pypandoc.convert_text(content, 'dokuwiki', format='md')
content = cls._apply_filters(cls.POSTFILTERS, content)
return content

@staticmethod
def _apply_filters(filters, text):
for flt in filters:
text = flt(text)
return text

@staticmethod
def join(*args):
return ':'.join(args)


def get_files(root, extension):
files = dict()
ext_mlen = -len(extension)
for file in os.listdir(root):
path = os.path.join(root, file)
if os.path.isfile(path) and file.endswith(extension):
files[file[0:ext_mlen]] = path
return files


@click.command()
@click.argument('root', type=click.Path(exists=True))
@click.option('-d', '--dw-url', help='DokuWiki URL',
envvar='DW_URL', required=True)
@click.option('-u', '--dw-username', help='DokuWiki username',
envvar='DW_USERNAME', required=True)
@click.option('-p', '--dw-password', help='DokuWiki password',
envvar='DW_PASSWORD', required=True)
@click.option('-n', '--dw-namespace', help='Target DokuWiki namespace',
envvar='DW_NAMESPACE', required=True)
def cli(root, dw_url, dw_username, dw_password, dw_namespace):
dw = DW(dw_url, dw_username, dw_password)
markdowns = get_files(root, '.md')
print('Deploying {} markdown file(s) to {}'.format(
len(markdowns), dw_url
))
for name, file in markdowns.items():
qname = dw.join(dw_namespace, name)
print('| ', file, '-->', qname)
dw.put_md(qname, file)
print('Done!')


if __name__ == '__main__':
cli()
4 changes: 4 additions & 0 deletions bin/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
click
lxml
pypandoc
requests
Loading