diff --git a/markdone-python/.gitignore b/markdone-python/.gitignore new file mode 100644 index 0000000..bf3817f --- /dev/null +++ b/markdone-python/.gitignore @@ -0,0 +1,10 @@ +*.pyc +.cache/ +.coverage +.eggs/ +.idea/ +.pytest_cache/ +.tox/ +env/ +*.egg-info/ +tags diff --git a/markdone-python/Makefile b/markdone-python/Makefile new file mode 100644 index 0000000..a171301 --- /dev/null +++ b/markdone-python/Makefile @@ -0,0 +1,84 @@ +DOCKER_TAG := markdone-dev +OPEN_CMD := $(shell type xdg-open &> /dev/null && echo 'xdg-open' || echo 'open') + +.PHONY: default +default: test + +# Builds the python3 venv with all dev requirements +env: + python3 -m venv env + ./env/bin/pip install -r requirements-dev.txt + + +# Generates a smaller env for running tox, which builds it's own env +.PHONY: test-env +test-env: + python3 -m venv env + ./env/bin/pip install tox + +# Runs tests with tox +.PHONY: test +test: env + ./env/bin/tox + +# Generates a small build env for building and uploading dists +.PHONY: build-env +build-env: + python3 -m venv env + ./env/bin/pip install twine wheel + +# Builds wheel for package to upload +.PHONY: build +build: env + ./env/bin/python setup.py sdist + ./env/bin/python setup.py bdist_wheel + +# Verify that the python version matches the git tag so we don't push bad shas +.PHONY: verify-tag-version +verify-tag-version: + $(eval TAG_NAME = $(shell [ -n "$(DRONE_TAG)" ] && echo $(DRONE_TAG) || git describe --tags --exact-match)) + test "v$(shell python setup.py -V)" = "$(TAG_NAME)" + +# Uses twine to upload to pypi +.PHONY: upload +upload: verify-tag-version build + ./env/bin/twine upload dist/* + +# Uses twine to upload to test pypi +.PHONY: upload-test +upload-test: verify-tag-version build + ./env/bin/twine upload --repository-url https://test.pypi.org/legacy/ dist/* + +# Cleans all build, runtime, and test artifacts +.PHONY: clean +clean: + rm -fr ./build ./markdone_python.egg-info ./htmlcov ./.coverage ./.pytest_cache ./.tox + find . -name '*.pyc' -delete + find . -name '__pycache__' -delete + +# Cleans dist and env +.PHONY: dist-clean +dist-clean: clean + rm -fr ./dist ./env + +# Install pre-commit hooks +.PHONY: install-hooks +install-hooks: env + ./env/bin/tox -e pre-commit -- install -f --install-hooks + +# Generates test coverage +.coverage: + ./env/bin/tox + +# Builds coverage html +htmlcov/index.html: .coverage + ./env/bin/coverage html + +# Opens coverage html in browser (on macOS and some Linux systems) +.PHONY: open-coverage +open-coverage: htmlcov/index.html + $(OPEN_CMD) htmlcov/index.html + +.PHONY: docker-build +docker-build: + docker build . -t $(DOCKER_TAG) diff --git a/markdone-python/markdone_python/__init__.py b/markdone-python/markdone_python/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/markdone-python/markdone_python/common.py b/markdone-python/markdone_python/common.py new file mode 100644 index 0000000..5337ce9 --- /dev/null +++ b/markdone-python/markdone_python/common.py @@ -0,0 +1,13 @@ +import re + + +section_pattern = re.compile(r'^#') +tag_pattern = re.compile(r'(\![\w]+\b)') +task_pattern = re.compile(r'^[\s]*[*]?[\s]*\[[ xX]?\]') + + +if __name__ == '__main__': + print(tag_pattern.findall('Got some !tags !here')) + for m in tag_pattern.finditer('Got some !tags !here'): + import ipdb; ipdb.set_trace() # XXX BREAKPOINT + print(m) diff --git a/markdone-python/markdone_python/note.py b/markdone-python/markdone_python/note.py new file mode 100644 index 0000000..cac0bc5 --- /dev/null +++ b/markdone-python/markdone_python/note.py @@ -0,0 +1,54 @@ +import markdown + +from markdone_python.common import section_pattern +from markdone_python.common import tag_pattern +from markdone_python.common import task_pattern +from markdone_python.rendering_extensions import MarkdoneExtension + + +class Note(object): + def __init__(self, text: str): + self.text = text + self.tasks = [] + self.sections = [] + self.tags = set() + self.parse(text) + + def parse(self, text: str): + for line in text.splitlines(): + if section_pattern.match(line): + self.sections.append(line) + elif task_pattern.match(line): + self.tasks.append(line) + + tags = tag_pattern.findall(line) + if tags: + print('tags: ', tags) + self.tags.update(tags) + + print('All tags: ', self.tags) + + def render(self): + + print(markdown.markdown( + self.text, + extensions=[MarkdoneExtension()] + )) + + +if __name__ == '__main__': + Note(""" +# My header + +## Subheader +Got some !tags !here + +* [] task1 !tag +* [ ] task2 +* [x] task3 +* [X] task4 + * [X] task4 +* [ ] task5 + * [ ] task6 +* [ ] task7 +""").render() diff --git a/markdone-python/markdone_python/rendering_extensions.py b/markdone-python/markdone_python/rendering_extensions.py new file mode 100644 index 0000000..16afb31 --- /dev/null +++ b/markdone-python/markdone_python/rendering_extensions.py @@ -0,0 +1,32 @@ +from markdown.extensions import Extension +from markdown.inlinepatterns import SimpleTagPattern +from markdown.inlinepatterns import SimpleTextPattern +from markdown.util import etree + +from markdone_python.common import tag_pattern + + +class SimpleTagPattern(Pattern): # pragma: no cover + """ + Return element of type `tag` with a text attribute of group(3) + of a Pattern. + + """ + def __init__(self, pattern, tag): + Pattern.__init__(self, pattern) + self.tag = tag + + def handleMatch(self, m): + el = util.etree.Element(self.tag) + el.text = m.group(3) + return el + + +class MarkdoneExtension(Extension): + def extendMarkdown(self, md, md_globals): + md.inlinePatterns.add( + 'markdone_tag', + SimpleTagPattern(tag_pattern.pattern, 'em'), + '_begin', + ) + diff --git a/markdone-python/markdone_python/task.py b/markdone-python/markdone_python/task.py new file mode 100644 index 0000000..e69de29 diff --git a/markdone-python/requirements-dev.txt b/markdone-python/requirements-dev.txt new file mode 100644 index 0000000..bd7e1b9 --- /dev/null +++ b/markdone-python/requirements-dev.txt @@ -0,0 +1,6 @@ +-r requirements.txt +ipython +pytest +tox +twine +wheel diff --git a/markdone-python/requirements.txt b/markdone-python/requirements.txt new file mode 100644 index 0000000..d6e1198 --- /dev/null +++ b/markdone-python/requirements.txt @@ -0,0 +1 @@ +-e . diff --git a/markdone-python/setup.py b/markdone-python/setup.py new file mode 100644 index 0000000..c02aa38 --- /dev/null +++ b/markdone-python/setup.py @@ -0,0 +1,45 @@ +from codecs import open +from os import path + +from setuptools import find_packages +from setuptools import setup + +here = path.abspath(path.dirname(__file__)) + +# Get the long description from the README file +# with open(path.join(here, 'README.md'), encoding='utf-8') as f: +# long_description = f.read() +long_description="A module for parsing and rendering Markdone files" + +setup( + name='markdone', + version='0.0.0', + description='A module for handling Markdone files', + long_description=long_description, + url='https://git.iamthefij.com/iamthefij/markdone', + author='Ian Fijolek', + author_email='ian@iamthefij.com', + classifiers=[ + # How mature is this project? Common values are + # 4 - Beta + # 5 - Production/Stable + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Intended Audience :: System Administrators', + 'License :: OSI Approved :: Apache Software License', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + ], + keywords='minitor monitoring alerting', + packages=find_packages(exclude=['contrib', 'docs', 'tests']), + install_requires=[ + 'markdown', + ], + # entry_points={ + # 'console_scripts': [ + # 'minitor=minitor.main:main', + # ], + # }, +) diff --git a/markdone-python/tox.ini b/markdone-python/tox.ini new file mode 100644 index 0000000..c18bb96 --- /dev/null +++ b/markdone-python/tox.ini @@ -0,0 +1,26 @@ +[tox] +envlist = py3 + +[testenv] +deps = + -rrequirements-dev.txt +commands = + coverage erase + coverage run --source=markdone_python/ -m pytest --capture=no -vv {posargs:tests} + coverage report -m --fail-under 70 + pre-commit run --all-files + +[testenv:pre-commit] +deps = + pre-commit +commands = + pre-commit {posargs} + +[flake8] +exclude = .svn,CVS,.bzr,.hg,.git,__pycache__,.ropeproject,.tox,docs,virtualenv_run +filename = *.py,*.wsgi +max-line-length = 80 +ignore = F403 + +[pytest] +norecursedirs = .* _darcs CVS docs virtualenv_run