mirror of
https://github.com/Hopiu/python-markdown-oembed.git
synced 2026-03-16 22:10:24 +00:00
use flit packaging tool, write simple test
This commit is contained in:
parent
79c7c2f060
commit
bb5eb5445e
15 changed files with 195 additions and 209 deletions
5
.gitignore
vendored
5
.gitignore
vendored
|
|
@ -2,7 +2,10 @@
|
|||
.idea
|
||||
/dist
|
||||
/.eggs
|
||||
/venv
|
||||
venv
|
||||
*.pyc
|
||||
*.egg
|
||||
*.egg-info
|
||||
*.coverage
|
||||
*.swp
|
||||
*.swo
|
||||
|
|
|
|||
13
README.md
Normal file
13
README.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Python Markdown Plugin for oEmbed
|
||||
|
||||
## Install flit
|
||||
|
||||
```
|
||||
pip install flit
|
||||
```
|
||||
|
||||
## Build needed packages for project
|
||||
|
||||
```
|
||||
flit install
|
||||
```
|
||||
27
flake.lock
Normal file
27
flake.lock
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1698611440,
|
||||
"narHash": "sha256-jPjHjrerhYDy3q9+s5EAsuhyhuknNfowY6yt6pjn9pc=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "0cbe9f69c234a7700596e943bfae7ef27a31b735",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
29
flake.nix
Normal file
29
flake.nix
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
description = "Oembed plugin flake";
|
||||
inputs = {
|
||||
nixpkgs.url = github:NixOS/nixpkgs/nixos-unstable;
|
||||
};
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
overlays = [];
|
||||
};
|
||||
pythonPackages = pkgs.python3Packages;
|
||||
system = "x86_64-linux";
|
||||
in rec {
|
||||
devShell.x86_64-linux = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.python3
|
||||
pkgs.python3Packages.pip
|
||||
];
|
||||
shellHook = ''
|
||||
export PS1='\u@md-oembed \$ '
|
||||
export PIP_PREFIX=$(pwd)/venv/pip_packages
|
||||
export PYTHONPATH="$PIP_PREFIX/${pkgs.python3.sitePackages}:$PYTHONPATH"
|
||||
export PATH="$PIP_PREFIX/bin:$PATH"
|
||||
unset SOURCE_DATE_EPOCH
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from mdx_oembed.extension import OEmbedExtension
|
||||
|
||||
|
||||
VERSION = '0.2.1'
|
||||
|
||||
|
||||
def makeExtension(**kwargs):
|
||||
return OEmbedExtension(**kwargs)
|
||||
46
pyproject.toml
Normal file
46
pyproject.toml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
[build-system]
|
||||
build-backend = "flit_core.buildapi"
|
||||
requires = ["flit_core >=3.8.0,<4"]
|
||||
|
||||
[project]
|
||||
name = "python_markdown-oembed_extension"
|
||||
version = "0.0.0"
|
||||
authors = [
|
||||
{name = "nmc", email = "contact-nmc@unibas.ch"},
|
||||
]
|
||||
description = "Detect inline pattern starting with '![', use the following data to request oembed data from the video hoster and create appropriate iframe html"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.7"
|
||||
keywords = ["markdown", "html", "oembed"]
|
||||
license = {text = "GPLv3"}
|
||||
classifiers = [
|
||||
"Programming Language :: Python :: 3",
|
||||
]
|
||||
dependencies = [
|
||||
"python-oembed",
|
||||
"markdown",
|
||||
"requests",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pylint ~=2.14.0",
|
||||
"toml ~=0.10.2",
|
||||
"yapf ~=0.32.0",
|
||||
]
|
||||
test = [
|
||||
"pytest-cov ~=3.0.0",
|
||||
"requests_mock",
|
||||
"pyyaml",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
my-script = "my_package.module:function"
|
||||
|
||||
[tool.coverage.run]
|
||||
source = ["src"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
addopts = "--cov --cov-report html --cov-report term-missing --cov-fail-under 15"
|
||||
# ... other project metadata fields as specified in:
|
||||
# https://packaging.python.org/en/latest/specifications/declaring-project-metadata/
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import oembed
|
||||
|
||||
YOUTUBE = oembed.OEmbedEndpoint('https://www.youtube.com/oembed', [
|
||||
|
|
@ -1,4 +1,3 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import logging
|
||||
from markdown.inlinepatterns import Pattern
|
||||
import oembed
|
||||
|
|
@ -10,7 +9,6 @@ LOG = logging.getLogger(__name__)
|
|||
OEMBED_LINK_RE = r'\!\[([^\]]*)\]\(((?:https?:)?//[^\)]*)' \
|
||||
r'(?<!png)(?<!jpg)(?<!jpeg)(?<!gif)(?<!avif)(?<!webp)\)'
|
||||
|
||||
|
||||
class OEmbedLinkPattern(Pattern):
|
||||
|
||||
def __init__(self, pattern, md=None, oembed_consumer=None):
|
||||
|
|
@ -1,8 +1,7 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from markdown import Extension
|
||||
import oembed
|
||||
from mdx_oembed.endpoints import DEFAULT_ENDPOINTS
|
||||
from mdx_oembed.inlinepatterns import OEmbedLinkPattern, OEMBED_LINK_RE
|
||||
from python_markdown_oembed_extension.endpoints import DEFAULT_ENDPOINTS
|
||||
from python_markdown_oembed_extension.inlinepatterns import OEmbedLinkPattern, OEMBED_LINK_RE
|
||||
|
||||
|
||||
class OEmbedExtension(Extension):
|
||||
|
|
@ -28,7 +27,8 @@ class OEmbedExtension(Extension):
|
|||
consumer = oembed.OEmbedConsumer()
|
||||
|
||||
if allowed_endpoints:
|
||||
for endpoint in allowed_endpoints:
|
||||
for endpoint in allowed_endpoints:
|
||||
consumer.addEndpoint(endpoint)
|
||||
|
||||
return consumer
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<p>In this video Jakob Zinsstag introduces the topic of the course. You will
|
||||
discover that the relationship between humans and animals is manifold.
|
||||
{.lead}</p>
|
||||
<p><figure class="oembed ratio ratio-16x9"><iframe src="https://player.vimeo.com/video/734276368?h=f29c542352&app_id=122963" width="426" height="240" frameborder="0" allow="autoplay; fullscreen; picture-in-picture" title="One-Health_Tales_EN_1-02"></iframe></figure> </p>
|
||||
<p>Have a look at the farm of Jakob Zinsstag’s cousin in the Canton of Jura,
|
||||
Switzerland. Different animals create different feelings: there are those we
|
||||
love, some provoke fears and others will be eaten. Jakob Zinsstag shares the
|
||||
personal experiences he has had with animals. </p>
|
||||
<p><strong>How do you categorise your own experience with animals?</strong></p>
|
||||
12
src/python_markdown_oembed_extension/tests/test_markdown.md
Normal file
12
src/python_markdown_oembed_extension/tests/test_markdown.md
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
In this video Jakob Zinsstag introduces the topic of the course. You will
|
||||
discover that the relationship between humans and animals is manifold.
|
||||
{.lead}
|
||||
|
||||

|
||||
|
||||
Have a look at the farm of Jakob Zinsstag’s cousin in the Canton of Jura,
|
||||
Switzerland. Different animals create different feelings: there are those we
|
||||
love, some provoke fears and others will be eaten. Jakob Zinsstag shares the
|
||||
personal experiences he has had with animals.
|
||||
|
||||
**How do you categorise your own experience with animals?**
|
||||
21
src/python_markdown_oembed_extension/tests/test_markdown.py
Normal file
21
src/python_markdown_oembed_extension/tests/test_markdown.py
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import markdown, yaml, requests_mock
|
||||
from python_markdown_oembed_extension.oembedextension import OEmbedExtension
|
||||
from python_markdown_oembed_extension.endpoints import VIMEO
|
||||
|
||||
|
||||
def test_full():
|
||||
with ( requests_mock.Mocker() as m
|
||||
, open('./src/python_markdown_oembed_extension/tests/vimeoMock.yaml', 'r') as vm
|
||||
, open('./src/python_markdown_oembed_extension/tests/test_markdown.md', 'r') as md
|
||||
, open('./src/python_markdown_oembed_extension/tests/test_expectedHtml.html', 'r') as expectedHtml
|
||||
):
|
||||
|
||||
yml = yaml.safe_load(vm)
|
||||
m.get(yml['request'], json=yml['response'])
|
||||
|
||||
mdString = md.read()
|
||||
htmlString = markdown.markdown(mdString, extensions=[OEmbedExtension()])
|
||||
print(htmlString)
|
||||
|
||||
assert htmlString == expectedHtml.read().rstrip()
|
||||
|
||||
30
src/python_markdown_oembed_extension/tests/vimeoMock.yaml
Normal file
30
src/python_markdown_oembed_extension/tests/vimeoMock.yaml
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
---
|
||||
request: 'https://vimeo.com/734276368/f29c542352'
|
||||
response:
|
||||
account_type: 'live_premium'
|
||||
author_name: 'NMC Universität Basel'
|
||||
author_url: 'https://vimeo.com/newmediacenterunibasel'
|
||||
description: ''
|
||||
duration: 282
|
||||
height: 240
|
||||
html: >-
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/734276368?h=f29c542352&app_id=122963"
|
||||
width="426" height="240" frameborder="0" allow="autoplay; fullscreen; picture-in-picture"
|
||||
title="One-Health_Tales_EN_1-02"
|
||||
>
|
||||
</iframe>
|
||||
is_plus: '0'
|
||||
provider_name: 'Vimeo'
|
||||
provider_url: 'https://vimeo.com/'
|
||||
thumbnail_height: 166
|
||||
thumbnail_url: 'https://i.vimeocdn.com/video/1480489232-5ca2d723cadc09ae077c8b437581e84bd0485049780c60e218986fda60881110-d_295x166'
|
||||
thumbnail_url_with_play_button: 'https://i.vimeocdn.com/filter/overlay?src0=https%3A%2F%2Fi.vimeocdn.com%2Fvideo%2F1480489232-5ca2d723cadc09ae077c8b437581e84bd0485049780c60e218986fda60881110-d_295x166&src1=http%3A%2F%2Ff.vimeocdn.com%2Fp%2Fimages%2Fcrawler_play.png'
|
||||
thumbnail_width: 295
|
||||
title: 'One-Health_Tales_EN_1-02'
|
||||
type: 'video'
|
||||
upload_date: '2022-07-28 04:16:03'
|
||||
uri: '/videos/734276368:f29c542352'
|
||||
version: '1.0'
|
||||
video_id: 734276368
|
||||
width: 426
|
||||
192
tests.py
192
tests.py
|
|
@ -1,192 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import re
|
||||
import unittest
|
||||
import markdown
|
||||
from mock import patch
|
||||
from nose.plugins.skip import SkipTest
|
||||
from mdx_oembed.extension import OEMBED_LINK_RE
|
||||
from mdx_oembed import endpoints
|
||||
|
||||
|
||||
class OEmbedPatternRegexTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.re = re.compile(OEMBED_LINK_RE)
|
||||
|
||||
def test_ignore_relative_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_absolute_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_png_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_jpg_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_ignore_gif_image_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNone(match)
|
||||
|
||||
def test_find_youtube_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
def test_find_youtube_short_link(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
def test_find_youtube_http(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
def test_find_youtube_https(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
def test_find_youtube_auto(self):
|
||||
text = ''
|
||||
match = self.re.match(text)
|
||||
self.assertIsNotNone(match)
|
||||
|
||||
|
||||
class OEmbedExtensionTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.markdown = markdown.Markdown(extensions=['oembed'])
|
||||
|
||||
def assert_convert(self, text, expected):
|
||||
with patch('oembed.OEmbedEndpoint') as MockOEmbedEndpoint:
|
||||
MockOEmbedEndpoint.get.return_value = expected
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
|
||||
class IgnoredTestCase(OEmbedExtensionTestCase):
|
||||
"""
|
||||
The OEmbedExtension should ignore these tags allowing markdown's image
|
||||
processor to find and handle them.
|
||||
"""
|
||||
|
||||
def test_relative(self):
|
||||
text = ''
|
||||
expected = '<p><img alt="alt" src="image.png" /></p>'
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_slash_relative(self):
|
||||
text = ''
|
||||
expected = '<p><img alt="alt" src="/image.png" /></p>'
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
def test_absolute(self):
|
||||
text = ''
|
||||
expected = '<p><img alt="Mumbo Jumbo" src="http://tannern.com/mumbo-jumbo.jpg" /></p>'
|
||||
output = self.markdown.convert(text)
|
||||
self.assertEqual(output, expected)
|
||||
|
||||
|
||||
class ProtocolVarietyTestCase(OEmbedExtensionTestCase):
|
||||
|
||||
def test_http(self):
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
def test_https(self):
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
def test_auto(self):
|
||||
raise SkipTest()
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
|
||||
class YoutubeTestCase(OEmbedExtensionTestCase):
|
||||
"""
|
||||
The OEmbedExtension should handle embedding for these cases.
|
||||
"""
|
||||
|
||||
def test_youtube_link(self):
|
||||
"""
|
||||
YouTube video link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
def test_youtube_short_link(self):
|
||||
"""
|
||||
Short format YouTube video link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
|
||||
class VimeoTestCase(OEmbedExtensionTestCase):
|
||||
|
||||
def test_vimeo_link(self):
|
||||
"""
|
||||
Vimeo video link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
class SlideshareTestCase(OEmbedExtensionTestCase):
|
||||
|
||||
def test_slideshare_link(self):
|
||||
"""
|
||||
Slideshare Presentation link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
|
||||
class LimitedOEmbedExtensionTestCase(OEmbedExtensionTestCase):
|
||||
def setUp(self):
|
||||
self.markdown = markdown.Markdown(
|
||||
extensions=['oembed'],
|
||||
extension_configs={
|
||||
'oembed': {
|
||||
'allowed_endpoints': [endpoints.YOUTUBE],
|
||||
}
|
||||
})
|
||||
|
||||
def test_youtube_link(self):
|
||||
"""
|
||||
YouTube video link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertIn('<iframe', output)
|
||||
|
||||
def test_vimeo_link(self):
|
||||
"""
|
||||
Vimeo video link.
|
||||
"""
|
||||
text = ''
|
||||
output = self.markdown.convert(text)
|
||||
self.assertNotIn('<iframe', output)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Reference in a new issue