From 68bbfd001d0092b58ca248a6307c6d051361cefb Mon Sep 17 00:00:00 2001 From: Oscar Cortez Date: Wed, 5 Aug 2015 13:28:26 -0600 Subject: [PATCH 01/10] DME-3 building a better python package --- .coverage | Bin 0 -> 36176 bytes .gitignore | 2 + .travis.yml | 31 ++ AUTHORS | 7 + CHANGELOG.txt | 18 + DESCRIPTION | 1 + LICENSE | 2 +- MANIFEST.in | 11 + Makefile | 13 + README.md | 53 ++- docs/Makefile | 192 +++++++++ docs/README.md | 38 ++ docs/make.bat | 263 +++++++++++++ docs/source/conf.py | 367 ++++++++++++++++++ docs/source/index.rst | 22 ++ hooks/pre-commit | 39 ++ magicembed/__init__.py | 3 +- magicembed/providers.py | 17 +- magicembed/templatetags/magicembed_tags.py | 3 +- magicembed/tests/.coveragerc | 16 + magicembed/tests/__init__.py | 0 magicembed/tests/coverage/coverage_status.png | Bin 0 -> 1310 bytes magicembed/tests/coverage/errors.html | 60 +++ magicembed/tests/coverage/excludes.html | 71 ++++ magicembed/tests/coverage/index.html | 190 +++++++++ .../coverage/modules/magicembed.__init__.html | 157 ++++++++ .../modules/magicembed.providers.html | 248 ++++++++++++ ...gicembed.templatetags.magicembed_tags.html | 180 +++++++++ magicembed/tests/runtests.py | 65 ++++ magicembed/tests/south_settings.py | 28 ++ magicembed/{ => tests}/test.py | 20 +- magicembed/tests/test_app/__init__.py | 0 magicembed/tests/test_app/models.py | 0 magicembed/tests/test_app/templates/400.html | 1 + magicembed/tests/test_app/templates/500.html | 1 + magicembed/tests/test_settings.py | 69 ++++ magicembed/tests/urls.py | 11 + manage.py | 11 + requirements.txt | 3 + setup.cfg | 3 + setup.py | 79 ++-- test_requirements.txt | 12 + tox.ini | 10 + 43 files changed, 2267 insertions(+), 50 deletions(-) create mode 100644 .coverage create mode 100644 .travis.yml create mode 100644 AUTHORS create mode 100644 CHANGELOG.txt create mode 100644 DESCRIPTION create mode 100644 MANIFEST.in create mode 100644 Makefile create mode 100644 docs/Makefile create mode 100644 docs/README.md create mode 100644 docs/make.bat create mode 100644 docs/source/conf.py create mode 100644 docs/source/index.rst create mode 100755 hooks/pre-commit create mode 100644 magicembed/tests/.coveragerc create mode 100644 magicembed/tests/__init__.py create mode 100644 magicembed/tests/coverage/coverage_status.png create mode 100644 magicembed/tests/coverage/errors.html create mode 100644 magicembed/tests/coverage/excludes.html create mode 100644 magicembed/tests/coverage/index.html create mode 100644 magicembed/tests/coverage/modules/magicembed.__init__.html create mode 100644 magicembed/tests/coverage/modules/magicembed.providers.html create mode 100644 magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html create mode 100755 magicembed/tests/runtests.py create mode 100644 magicembed/tests/south_settings.py rename magicembed/{ => tests}/test.py (57%) create mode 100644 magicembed/tests/test_app/__init__.py create mode 100644 magicembed/tests/test_app/models.py create mode 100644 magicembed/tests/test_app/templates/400.html create mode 100644 magicembed/tests/test_app/templates/500.html create mode 100644 magicembed/tests/test_settings.py create mode 100644 magicembed/tests/urls.py create mode 100755 manage.py create mode 100644 requirements.txt create mode 100644 setup.cfg create mode 100644 test_requirements.txt create mode 100644 tox.ini diff --git a/.coverage b/.coverage new file mode 100644 index 0000000000000000000000000000000000000000..b63c6226b3ee8a2007624b6152e63973368f09f8 GIT binary patch literal 36176 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 literal 0 HcmV?d00001 diff --git a/.gitignore b/.gitignore index 72fddea..72fd868 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ dist/ magicembed.egg-info/ build +.tox +django_magicembed.egg-info diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..c285e21 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,31 @@ +language: python + +python: + - "2.7" + - "3.4" + +env: + - DJANGO=django==1.4.* + - DJANGO=django==1.5.* + - DJANGO=django==1.6.* + - DJANGO=django==1.7.* + - DJANGO=django==1.8.* + +install: + - pip install -r test_requirements.txt --use-mirrors + - pip install $DJANGO + - pip install coveralls + +script: + - cd magicembed/tests + - ./runtests.py + - mv .coverage ../../ + - cd ../../ + +matrix: + exclude: + - python: "3.4" + env: DJANGO=django==1.4.* + +after_success: + - coveralls diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..6e128e4 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,7 @@ +Current or previous core committers + +Adolfo Fitoria +Andres Reyes +Oscar Cortez + +* Your name could stand here :) diff --git a/CHANGELOG.txt b/CHANGELOG.txt new file mode 100644 index 0000000..211b9c8 --- /dev/null +++ b/CHANGELOG.txt @@ -0,0 +1,18 @@ +=== 0.0.X (onggoing, to be released as 0.1) === +- Initial commit + + +# Suggested file syntax: +# +# === (ongoing) === +# - this is always on top of the file +# - when you release a new version, you rename the last `(ongoing)` to the new +# version and add a new `=== (ongoing) ===` to the top of the file +# +# === 1.0 === +# - a major version is created when the software reached a milestone and is +# feature complete +# +# === 0.2 === +# - a minor version is created when a lot of new features have bene added or +# significant backwards incompatible changes have been made. diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..8553739 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1 @@ +An easy and simple Django template tag and tool to embed video and get thumbnails from video providers. diff --git a/LICENSE b/LICENSE index 9f10043..a16ad2f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,5 @@ The MIT License (MIT) -Copyright (c) 2015 Adolfo Fitoria +Copyright (c) 2015 Adolfo Fitoria Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..057b683 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,11 @@ +include AUTHORS +include LICENSE +include DESCRIPTION +include CHANGELOG.txt +include README.md +include tox.ini +include requirements.txt +graft magicembed +global-exclude *.orig *.pyc *.log *.swp local_settings.py +prune magicembed/tests/coverage +prune magicembed/.ropeproject diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..94f61d6 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +develop: setup-git + pip install "file://`pwd`#egg=magicembed[dev]" + pip install -e . + pip install -r test_requirements.txt + +setup-git: + git config branch.autosetuprebase always + cd .git/hooks && ln -sf hooks/* ./ + +lint-python: + @echo "Linting Python files" + PYFLAKES_NODOCTEST=1 flake8 magicembed + @echo "" diff --git a/README.md b/README.md index a73053e..9148e95 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,17 @@ When you have the API key, add this in your settings.py: How to install it? ------------------- +To get the latest stable release from PyPI + +.. code-block:: bash + pip install django-magicembed + +To get the latest commit from GitHub + +.. code-block:: bash + + pip install -e git+git://github.com/kronoscode/django-magicembed.git#egg=magicembed + If you have a requeriments list add this to your requeriments 1. magicembed==(version) @@ -47,16 +58,21 @@ If you have a requeriments list add this to your requeriments 3. add magicembed to **INSTALLED_APPS** -Or if you use setup.py +.. code-block:: python + INSTALLED_APPS = ( + ..., + 'magicembed', + ) -1. run python setup.py install How to use --------------- -First add this in the template to load the template tags +Before your tags/filters are available in your templates, load them by using + +.. code-block:: html -{% load magicembed_tags %} + {% load magicembed_tags %} Now if you need to embed a video, add this template tag to video url field @@ -67,14 +83,33 @@ Or to get a thumbnail url {{ video|magicthumbnail }} +Run magicembed test +-------------------- + +If you want run test please set in the test_settings.py your +Embedly Api Key correctly + +In order to run the tests, simply execute ``tox``. This will install two new +environments (for Django 1.6 and Django 1.7) and run the tests against both +environments. + How to contrib ---------------- -1. Fork it ( http://github.com/kronoscode/django-magicembed/fork ) -2. Create your feature branch (`git checkout -b my-new-feature`) -3. Commit your changes (`git commit -am 'Add some feature'`) -4. Push to the branch (`git push origin my-new-feature`) -5. Create new Pull Request +If you want to contribute to this project, please perform the following steps + +.. code-block:: bash + + # Fork this repository + # Clone your fork + mkvirtualenv -p python2.7 django-magicembed + make develop + + git co -b feature_branch master + # Implement your feature and tests + git add . && git commit + git push -u origin feature_branch + # Send us a pull request for your feature branch Licence -------------- diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..a9078ad --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,192 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# User-friendly check for sphinx-build +ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) +$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) +endif + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source +# the i18n builder cannot share the environment and doctrees with the others +I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " applehelp to make an Apple Help Book" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " texinfo to make Texinfo files" + @echo " info to make Texinfo files and run them through makeinfo" + @echo " gettext to make PO message catalogs" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " xml to make Docutils-native XML files" + @echo " pseudoxml to make pseudoxml-XML files for display purposes" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + @echo " coverage to run coverage check of the documentation (if enabled)" + +clean: + rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/DjangoMagicembed.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/DjangoMagicembed.qhc" + +applehelp: + $(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp + @echo + @echo "Build finished. The help book is in $(BUILDDIR)/applehelp." + @echo "N.B. You won't be able to view it unless you put it in" \ + "~/Library/Documentation/Help or install it in your application" \ + "bundle." + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/DjangoMagicembed" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/DjangoMagicembed" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +latexpdfja: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through platex and dvipdfmx..." + $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +texinfo: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo + @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." + @echo "Run \`make' in that directory to run these through makeinfo" \ + "(use \`make info' here to do that automatically)." + +info: + $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo + @echo "Running Texinfo files through makeinfo..." + make -C $(BUILDDIR)/texinfo info + @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." + +gettext: + $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale + @echo + @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." + +coverage: + $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage + @echo "Testing of coverage in the sources finished, look at the " \ + "results in $(BUILDDIR)/coverage/python.txt." + +xml: + $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml + @echo + @echo "Build finished. The XML files are in $(BUILDDIR)/xml." + +pseudoxml: + $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml + @echo + @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..da76c2b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,38 @@ +# How to create your Sphinx documentation + +In order to kickstart your Sphinx documentation, please do the following: + +## Create virtual environment. + +If you haven't done so already, create a virtual environment for this reusable +app like so: + + mkvirtualenv -p python2.7 django-magicembed + pip install Sphinx + deactivate + workon django-magicembed + sphinx-quickstart + +Answer the questions: + + > Root path for the documentation [.]: + > Separate source and build directories (y/N) [n]: y + > Name prefix for templates and static dir [_]: + > Project name: Django Magicembed + > Author name(s): Adolfo Fitoria + > Project version: 0.1 + > Project release [0.1]: + > Source file suffix [.rst]: + > Name of your master document (without suffix) [index]: + > Do you want to use the epub builder (y/N) [n]: + > autodoc: automatically insert docstrings from modules (y/N) [n]: y + > doctest: automatically test code snippets in doctest blocks (y/N) [n]: + > intersphinx: link between Sphinx documentation of different projects (y/N) [n]: y + > todo: write "todo" entries that can be shown or hidden on build (y/N) [n]: y + > coverage: checks for documentation coverage (y/N) [n]: y + > pngmath: include math, rendered as PNG images (y/N) [n]: + > mathjax: include math, rendered in the browser by MathJax (y/N) [n]: + > ifconfig: conditional inclusion of content based on config values (y/N) [n]: y + > viewcode: include links to the source code of documented Python objects (y/N) [n]: y + > Create Makefile? (Y/n) [y]: + > Create Windows command file? (Y/n) [y]: diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000..8008491 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,263 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% source +set I18NSPHINXOPTS=%SPHINXOPTS% source +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% + set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. texinfo to make Texinfo files + echo. gettext to make PO message catalogs + echo. changes to make an overview over all changed/added/deprecated items + echo. xml to make Docutils-native XML files + echo. pseudoxml to make pseudoxml-XML files for display purposes + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + echo. coverage to run coverage check of the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + + +REM Check if sphinx-build is available and fallback to Python version if any +%SPHINXBUILD% 2> nul +if errorlevel 9009 goto sphinx_python +goto sphinx_ok + +:sphinx_python + +set SPHINXBUILD=python -m sphinx.__init__ +%SPHINXBUILD% 2> nul +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.http://sphinx-doc.org/ + exit /b 1 +) + +:sphinx_ok + + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\DjangoMagicembed.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\DjangoMagicembed.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdf" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "latexpdfja" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + cd %BUILDDIR%/latex + make all-pdf-ja + cd %~dp0 + echo. + echo.Build finished; the PDF files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "texinfo" ( + %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. + goto end +) + +if "%1" == "gettext" ( + %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The message catalogs are in %BUILDDIR%/locale. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +if "%1" == "coverage" ( + %SPHINXBUILD% -b coverage %ALLSPHINXOPTS% %BUILDDIR%/coverage + if errorlevel 1 exit /b 1 + echo. + echo.Testing of coverage in the sources finished, look at the ^ +results in %BUILDDIR%/coverage/python.txt. + goto end +) + +if "%1" == "xml" ( + %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The XML files are in %BUILDDIR%/xml. + goto end +) + +if "%1" == "pseudoxml" ( + %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. + goto end +) + +:end diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000..9c9e69b --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,367 @@ +# -*- coding: utf-8 -*- +# +# Django Magicembed documentation build configuration file, created by +# sphinx-quickstart on Wed Aug 5 11:48:38 2015. +# +# This file is execfile()d with the current directory set to its +# containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys +import os +import shlex + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ------------------------------------------------ + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = [ + 'sphinx.ext.autodoc', + 'sphinx.ext.doctest', + 'sphinx.ext.intersphinx', + 'sphinx.ext.todo', + 'sphinx.ext.coverage', + 'sphinx.ext.mathjax', + 'sphinx.ext.ifconfig', + 'sphinx.ext.viewcode', +] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# source_suffix = ['.rst', '.md'] +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'Django Magicembed' +copyright = u'2015, Adolfo Fitoria' +author = u'Adolfo Fitoria' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0.0' +# The full version, including alpha/beta/rc tags. +release = '1.0.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all +# documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + +# If true, keep warnings as "system message" paragraphs in the built documents. +#keep_warnings = False + +# If true, `todo` and `todoList` produce output, else they produce nothing. +todo_include_todos = True + + +# -- Options for HTML output ---------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# Add any extra paths that contain custom files (such as robots.txt or +# .htaccess) here, relative to this directory. These files are copied +# directly to the root of the documentation. +#html_extra_path = [] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Language to be used for generating the HTML full-text search index. +# Sphinx supports the following languages: +# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' +# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' +#html_search_language = 'en' + +# A dictionary with options for the search language support, empty by default. +# Now only 'ja' uses this config value +#html_search_options = {'type': 'default'} + +# The name of a javascript file (relative to the configuration directory) that +# implements a search results scorer. If empty, the default will be used. +#html_search_scorer = 'scorer.js' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'DjangoMagicembeddoc' + +# -- Options for LaTeX output --------------------------------------------- + +latex_elements = { +# The paper size ('letterpaper' or 'a4paper'). +#'papersize': 'letterpaper', + +# The font size ('10pt', '11pt' or '12pt'). +#'pointsize': '10pt', + +# Additional stuff for the LaTeX preamble. +#'preamble': '', + +# Latex figure (float) alignment +#'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). +latex_documents = [ + (master_doc, 'DjangoMagicembed.tex', u'Django Magicembed Documentation', + u'Adolfo Fitoria', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output --------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + (master_doc, 'djangomagicembed', u'Django Magicembed Documentation', + [author], 1) +] + +# If true, show URL addresses after external links. +#man_show_urls = False + + +# -- Options for Texinfo output ------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'DjangoMagicembed', u'Django Magicembed Documentation', + author, 'DjangoMagicembed', 'One line description of project.', + 'Miscellaneous'), +] + +# Documents to append as an appendix to all manuals. +#texinfo_appendices = [] + +# If false, no module index is generated. +#texinfo_domain_indices = True + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#texinfo_show_urls = 'footnote' + +# If true, do not generate a @detailmenu in the "Top" node's menu. +#texinfo_no_detailmenu = False + + +# -- Options for Epub output ---------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project +epub_author = author +epub_publisher = author +epub_copyright = copyright + +# The basename for the epub file. It defaults to the project name. +#epub_basename = project + +# The HTML theme for the epub output. Since the default themes are not optimized +# for small screen space, using the same theme for HTML and epub output is +# usually not wise. This defaults to 'epub', a theme designed to save visual +# space. +#epub_theme = 'epub' + +# The language of the text. It defaults to the language option +# or 'en' if the language is not set. +#epub_language = '' + +# The scheme of the identifier. Typical schemes are ISBN or URL. +#epub_scheme = '' + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +#epub_identifier = '' + +# A unique identification for the text. +#epub_uid = '' + +# A tuple containing the cover image and cover page html template filenames. +#epub_cover = () + +# A sequence of (type, uri, title) tuples for the guide element of content.opf. +#epub_guide = () + +# HTML files that should be inserted before the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_pre_files = [] + +# HTML files shat should be inserted after the pages created by sphinx. +# The format is a list of tuples containing the path and title. +#epub_post_files = [] + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# The depth of the table of contents in toc.ncx. +#epub_tocdepth = 3 + +# Allow duplicate toc entries. +#epub_tocdup = True + +# Choose between 'default' and 'includehidden'. +#epub_tocscope = 'default' + +# Fix unsupported image types using the Pillow. +#epub_fix_images = False + +# Scale large images. +#epub_max_image_width = 0 + +# How to display URL addresses: 'footnote', 'no', or 'inline'. +#epub_show_urls = 'inline' + +# If false, no index is generated. +#epub_use_index = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000..6217d25 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,22 @@ +.. Django Magicembed documentation master file, created by + sphinx-quickstart on Wed Aug 5 11:48:38 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Django Magicembed's documentation! +============================================= + +Contents: + +.. toctree:: + :maxdepth: 2 + + + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/hooks/pre-commit b/hooks/pre-commit new file mode 100755 index 0000000..d58db4d --- /dev/null +++ b/hooks/pre-commit @@ -0,0 +1,39 @@ +#!/usr/bin/env python + +import glob +import os +import sys + +os.environ['PYFLAKES_NODOCTEST'] = '1' + +# pep8.py uses sys.argv to find setup.cfg +sys.argv = [os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)] + +# git usurbs your bin path for hooks and will always run system python +if 'VIRTUAL_ENV' in os.environ: + site_packages = glob.glob( + '%s/lib/*/site-packages' % os.environ['VIRTUAL_ENV'])[0] + sys.path.insert(0, site_packages) + + +def main(): + from flake8.main import DEFAULT_CONFIG + from flake8.engine import get_style_guide + from flake8.hooks import run + + gitcmd = "git diff-index --cached --name-only HEAD" + + _, files_modified, _ = run(gitcmd) + + # remove non-py files and files which no longer exist + files_modified = filter( + lambda x: x.endswith('.py') and os.path.exists(x), + files_modified) + + flake8_style = get_style_guide(parse_argv=True, config_file=DEFAULT_CONFIG) + report = flake8_style.check_files(files_modified) + + return report.total_errors + +if __name__ == '__main__': + sys.exit(main()) diff --git a/magicembed/__init__.py b/magicembed/__init__.py index 5812718..e6cb3ed 100644 --- a/magicembed/__init__.py +++ b/magicembed/__init__.py @@ -1 +1,2 @@ -import providers +# -*- coding: utf-8 -*- +__version__ = '1.0.0' # pragma: no cover diff --git a/magicembed/providers.py b/magicembed/providers.py index efe992f..efb6b52 100644 --- a/magicembed/providers.py +++ b/magicembed/providers.py @@ -7,9 +7,10 @@ from django.conf import settings + class Provider(object): - def __init__(self, url, size = (640, 480)): + def __init__(self, url, size=(640, 480)): self.url = url self.size = size @@ -22,15 +23,16 @@ def render_thumbnail(self, link_to): '''Renders the html with a link_to a parameter''' raise NotImplementedError + class Youtube(Provider): - def __init__(self, url, size = (640, 480)): + def __init__(self, url, size=(640, 480)): super(Youtube, self).__init__(url, size) qs = url.split('?') self.video_id = parse_qs(qs[1])['v'][0] def render_video(self): - html = '''''' + html = '''''' # noqa return html % (self.size[0], self.size[1], self.video_id) def render_thumbnail(self, link_to='#'): @@ -46,7 +48,7 @@ def __init__(self, url, size=(640, 480)): self.api_url = 'http://vimeo.com/api/v2/video/%s.json' % self.video_id def render_video(self): - html = '''

Das Pop: The Game from Big Active on Vimeo.

''' + html = '''

Das Pop: The Game from Big Active on Vimeo.

''' # noqa return html % (self.video_id, self.size[0], self.size[1], self.video_id) @@ -54,17 +56,17 @@ def render_thumbnail(self, link_to="#"): api_response = json.loads(urllib.urlopen(self.api_url).read()) return api_response[0]['thumbnail_medium'] + class Embedly(Provider): def __init__(self, url, size=(640, 480)): super(Embedly, self).__init__(url, size) key = getattr(settings, "EMBEDLY_KEY", None) - if key != None: + if key is not None: self.api_url = 'http://api.embed.ly/1/oembed?key=%s&url=%s&maxwidth=%s&format=json' % (key, url, size[0]) else: raise ValueError("If you want to use this please set the Embedly api key") - def render_video(self): return self._call_api()['html'] @@ -78,10 +80,11 @@ def _call_api(self): raise IOError("Please set the Embedly api key correctly") return data + def get_provider(url, size=None): '''returns a provider instance acording to the url''' provider_domain = dict(youtube=Youtube, vimeo=Vimeo) - for domain, provider in provider_domain.items(): + for domain, provider in provider_domain.items(): if domain in url: return provider(url, size) if size else provider(url) diff --git a/magicembed/templatetags/magicembed_tags.py b/magicembed/templatetags/magicembed_tags.py index 4beb850..1017bc1 100644 --- a/magicembed/templatetags/magicembed_tags.py +++ b/magicembed/templatetags/magicembed_tags.py @@ -6,6 +6,7 @@ register = template.Library() + @register.filter(is_safe=True) def magicembed(value, arg=None): '''value is the url and arg the size tuple @@ -15,10 +16,10 @@ def magicembed(value, arg=None): return mark_safe(provider.render_video()) + @register.filter def magicthumbnail(value): '''value is the url and arg the link_to another url ussage: {% http://myurl.com/|magicthumbnail: '/some/url' %}''' provider = get_provider(value) return provider.render_thumbnail() - diff --git a/magicembed/tests/.coveragerc b/magicembed/tests/.coveragerc new file mode 100644 index 0000000..66014b5 --- /dev/null +++ b/magicembed/tests/.coveragerc @@ -0,0 +1,16 @@ +[run] +source = + magicembed +branch = True +omit = + ./* + ../urls.py + ../migrations/* + +[report] +exclude_lines = + pragma: no cover + def __repr__ + raise AssertionError + raise NotImplementedError + if __name__ == .__main__.: diff --git a/magicembed/tests/__init__.py b/magicembed/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/magicembed/tests/coverage/coverage_status.png b/magicembed/tests/coverage/coverage_status.png new file mode 100644 index 0000000000000000000000000000000000000000..f7edc5e3971c7338b8f0bda885f6476494b06391 GIT binary patch literal 1310 zcmV+(1>yRMP)cZ|HEB$IVqKM`R8jGXXfWc*sLu}$ngA?Z zWW__IJy>AjXYdG7bUF_}cQC+5$mzQIFd>k&93xk7$Of#F!*xue|X0zEuU%kD(I5;@K;^HD44hQP$ z>caVreh$-)6yoyBB|3lX1fR@9@*NjeFSF}$8a&1MKj--My$kwp^l)xCA=UBVjM2$q zg@uI-R9adZ^7HfAfTgCUGJR)fhh3ACld-2$KX8jXelmCNPG%F4pw z;UO!p)9J9awT1fndItCE>I&`c?a0W;Kz4RER##V%nVAWtQb`a(>X5G2>k$kF(bm=$ z$!~Oly?y@{`^Wo`E9Kw}ck2qH653)dWJ(!)Yd++e^U*cj1>Z*>jB{=G4U7O#go*dL zxw%M5NkLCfkD!ZDF+4nsyu3V|oSZf&tsy+ze@x zptQ8KU}$IvXJ==qtgIwo)P`8b?RJx&NPeRS?Ac%riz3^^0A!gmaF)AuGKrbPi=SR# zbafQpHdf+O@DsYmO>F6WZhC&Nz$ParVKSM7dx|uIL4zVLgJc$q1$MigzOw-|7z{Mq zY37s0mOG!%M|DK2s;XkZyk4*9hoY3Cl9s>P+FGowtubITGczIWO;1k~ph$kB2dv4} z4EmJm%fOZ2sf#9k!^3~*$5Z1|7zd5mJlMoDbq+rK^#Sz__263W4;T#^4Jbh(So{0? zNKa2kO-&6J78XdSh+~i{Dk`WB%X3RhOO)G0KP4q4v~1GyNcRkGV`JkjU=+DRgixd% zA0HDinh?|;)u*MCpc1f1exnDBw&d5iW`n`CMAC0V?(tf|t9U41C&M4`|OFWv2Wur)LYHFgqO3Pjpp4P`6 zu*B1P0hn-j8E3~U5AqN*G5^-ozZiU} UUVM#Ls{jB107*qoM6N<$f`T)IrT_o{ literal 0 HcmV?d00001 diff --git a/magicembed/tests/coverage/errors.html b/magicembed/tests/coverage/errors.html new file mode 100644 index 0000000..1d0dfd2 --- /dev/null +++ b/magicembed/tests/coverage/errors.html @@ -0,0 +1,60 @@ + + + + + Test coverage report: error packages and modules + + + + + +
+

Test Coverage Report: error packages and modules

Generated: Wed 2015-08-05 13:23 CST

+
+

django_coverage.utils.module_tools.find_or_load_module had + problems importing these packages and modules: +

+
    +
  • magicembed.tests.test_app.templates
  • +
+ Back to index. +
+ + + + diff --git a/magicembed/tests/coverage/excludes.html b/magicembed/tests/coverage/excludes.html new file mode 100644 index 0000000..aac0527 --- /dev/null +++ b/magicembed/tests/coverage/excludes.html @@ -0,0 +1,71 @@ + + + + + Test coverage report: excluded packages and modules + + + + + +
+

Test Coverage Report: excluded packages and modules

Generated: Wed 2015-08-05 13:23 CST

+
+

These packages and modules were excluded from the coverage analysis in + django.conf.settings.COVERAGE_MODULE_EXCLUDES or they do + not contain any executable statements: +

+
    +
  • django.contrib.admin
  • +
  • django.contrib.auth
  • +
  • django.contrib.contenttypes
  • +
  • django.contrib.sessions
  • +
  • django.contrib.sitemaps
  • +
  • django.contrib.sites
  • +
  • magicembed.models
  • +
  • magicembed.templatetags.__init__
  • +
  • magicembed.tests
  • +
  • magicembed.tests.test_app.__init__
  • +
  • magicembed.tests.test_app.models
  • +
+ Back to index. +
+ + + + diff --git a/magicembed/tests/coverage/index.html b/magicembed/tests/coverage/index.html new file mode 100644 index 0000000..6a9db1d --- /dev/null +++ b/magicembed/tests/coverage/index.html @@ -0,0 +1,190 @@ + + + + + Test coverage report + + + + + +
+

Test Coverage Report

+

Generated: Wed 2015-08-05 13:23 CST

+

+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
 Statements
Moduletotalexecutedexcluded% covered
Total7148977.4%
magicembed.__init__101100.0%
magicembed.providers5848590.6%
magicembed.templatetags.magicembed_tags12030.0%
+
+ + + + + + + + diff --git a/magicembed/tests/coverage/modules/magicembed.__init__.html b/magicembed/tests/coverage/modules/magicembed.__init__.html new file mode 100644 index 0000000..6998ec2 --- /dev/null +++ b/magicembed/tests/coverage/modules/magicembed.__init__.html @@ -0,0 +1,157 @@ + + + + + Test coverage report: magicembed + + + + + + + +
+

+ magicembed: + 1 total statements, + 100.0% covered +

+

Generated: Wed 2015-08-05 13:23 CST

+

Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/__init__.py

+

+ Stats: + 0 executed, + 0 missed, + 1 excluded, + 1 ignored +

+
+ +
+
    +
  1. # -*- coding: utf-8 -*-
  2. +
  3. __version__ = '1.0.0' # pragma: no cover
  4. +
+
+ + + + + + diff --git a/magicembed/tests/coverage/modules/magicembed.providers.html b/magicembed/tests/coverage/modules/magicembed.providers.html new file mode 100644 index 0000000..daa146b --- /dev/null +++ b/magicembed/tests/coverage/modules/magicembed.providers.html @@ -0,0 +1,248 @@ + + + + + Test coverage report: magicembed.providers + + + + + + + +
+

+ magicembed.providers: + 58 total statements, + 90.6% covered +

+

Generated: Wed 2015-08-05 13:23 CST

+

Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/providers.py

+

+ Stats: + 48 executed, + 5 missed, + 5 excluded, + 33 ignored +

+
+ +
+
    +
  1. # -*- coding: utf-8 -*-
  2. +
  3. import json
  4. +
  5. import re
  6. +
  7. import urllib
  8. +
  9. +
  10. from urlparse import parse_qs
  11. +
  12. +
  13. from django.conf import settings
  14. +
  15. +
  16. +
  17. class Provider(object):
  18. +
  19. +
  20. def __init__(self, url, size=(640, 480)):
  21. +
  22. self.url = url
  23. +
  24. self.size = size
  25. +
  26. +
  27. def render_video(self):
  28. +
  29. '''simply returns html to render embed
  30. +
  31. video in a template'''
  32. +
  33. raise NotImplementedError
  34. +
  35. +
  36. def render_thumbnail(self, link_to):
  37. +
  38. '''Renders the html with a link_to a parameter'''
  39. +
  40. raise NotImplementedError
  41. +
  42. +
  43. +
  44. class Youtube(Provider):
  45. +
  46. +
  47. def __init__(self, url, size=(640, 480)):
  48. +
  49. super(Youtube, self).__init__(url, size)
  50. +
  51. qs = url.split('?')
  52. +
  53. self.video_id = parse_qs(qs[1])['v'][0]
  54. +
  55. +
  56. def render_video(self):
  57. +
  58. html = '''<iframe title="YouTube video player" width="%d" height="%d" src="http://www.youtube.com/embed/%s" frameborder="0" allowfullscreen></iframe>''' # noqa
  59. +
  60. return html % (self.size[0], self.size[1], self.video_id)
  61. +
  62. +
  63. def render_thumbnail(self, link_to='#'):
  64. +
  65. return '''http://img.youtube.com/vi/%s/0.jpg''' % (self.video_id)
  66. +
  67. +
  68. +
  69. class Vimeo(Provider):
  70. +
  71. +
  72. def __init__(self, url, size=(640, 480)):
  73. +
  74. super(Vimeo, self).__init__(url, size)
  75. +
  76. pattern = re.compile('(http|https)://(?:www\.)?vimeo\.com/([0-9]{1,12})')
  77. +
  78. self.video_id = pattern.match(url).groups()[1]
  79. +
  80. self.api_url = 'http://vimeo.com/api/v2/video/%s.json' % self.video_id
  81. +
  82. +
  83. def render_video(self):
  84. +
  85. html = '''<iframe src="http://player.vimeo.com/video/%s" width="%d" height="%d" frameborder="0"></iframe><p><a href="http://vimeo.com/%s">Das Pop: The Game</a> from <a href="http://vimeo.com/bigactive">Big Active</a> on <a href="http://vimeo.com">Vimeo</a>.</p>''' # noqa
  86. +
  87. return html % (self.video_id, self.size[0],
  88. +
  89. self.size[1], self.video_id)
  90. +
  91. +
  92. def render_thumbnail(self, link_to="#"):
  93. +
  94. api_response = json.loads(urllib.urlopen(self.api_url).read())
  95. +
  96. return api_response[0]['thumbnail_medium']
  97. +
  98. +
  99. +
  100. class Embedly(Provider):
  101. +
  102. +
  103. def __init__(self, url, size=(640, 480)):
  104. +
  105. super(Embedly, self).__init__(url, size)
  106. +
  107. key = getattr(settings, "EMBEDLY_KEY", None)
  108. +
  109. if key is not None:
  110. +
  111. self.api_url = 'http://api.embed.ly/1/oembed?key=%s&url=%s&maxwidth=%s&format=json' % (key, url, size[0])
  112. +
  113. else:
  114. +
  115. raise ValueError("If you want to use this please set the Embedly api key")
  116. +
  117. +
  118. def render_video(self):
  119. +
  120. return self._call_api()['html']
  121. +
  122. +
  123. def render_thumbnail(self):
  124. +
  125. return self._call_api()['thumbnail_url']
  126. +
  127. +
  128. def _call_api(self):
  129. +
  130. try:
  131. +
  132. data = json.loads(urllib.urlopen(self.api_url).read())
  133. +
  134. except IOError:
  135. +
  136. raise IOError("Please set the Embedly api key correctly")
  137. +
  138. return data
  139. +
  140. +
  141. +
  142. def get_provider(url, size=None):
  143. +
  144. '''returns a provider instance acording to the url'''
  145. +
  146. provider_domain = dict(youtube=Youtube, vimeo=Vimeo)
  147. +
  148. for domain, provider in provider_domain.items():
  149. +
  150. if domain in url:
  151. +
  152. return provider(url, size) if size else provider(url)
  153. +
  154. +
  155. return Embedly(url, size) if size else Embedly(url)
  156. +
+
+ + + + + + diff --git a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html new file mode 100644 index 0000000..759ab13 --- /dev/null +++ b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html @@ -0,0 +1,180 @@ + + + + + Test coverage report: magicembed.templatetags.magicembed_tags + + + + + + + +
+

+ magicembed.templatetags.magicembed_tags: + 12 total statements, + 0.0% covered +

+

Generated: Wed 2015-08-05 13:23 CST

+

Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/templatetags/magicembed_tags.py

+

+ Stats: + 0 executed, + 9 missed, + 3 excluded, + 13 ignored +

+
+ +
+
    +
  1. # -*- coding: utf-8 -*-
  2. +
  3. from django import template
  4. +
  5. from django.utils.safestring import mark_safe
  6. +
  7. +
  8. from magicembed.providers import get_provider
  9. +
  10. +
  11. register = template.Library()
  12. +
  13. +
  14. +
  15. @register.filter(is_safe=True)
  16. +
  17. def magicembed(value, arg=None):
  18. +
  19. '''value is the url and arg the size tuple
  20. +
  21. ussage: {% http://myurl.com/|magicembed:"640x480" %}'''
  22. +
  23. arg = [int(item) for item in arg.split('x')]
  24. +
  25. provider = get_provider(value, arg)
  26. +
  27. +
  28. return mark_safe(provider.render_video())
  29. +
  30. +
  31. +
  32. @register.filter
  33. +
  34. def magicthumbnail(value):
  35. +
  36. '''value is the url and arg the link_to another url
  37. +
  38. ussage: {% http://myurl.com/|magicthumbnail: '/some/url' %}'''
  39. +
  40. provider = get_provider(value)
  41. +
  42. return provider.render_thumbnail()
  43. +
+
+ + + + + + diff --git a/magicembed/tests/runtests.py b/magicembed/tests/runtests.py new file mode 100755 index 0000000..6ffb5b7 --- /dev/null +++ b/magicembed/tests/runtests.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +""" +This script is a trick to setup a fake Django environment, since this reusable +app will be developed and tested outside any specifiv Django project. + +Via ``settings.configure`` you will be able to set all necessary settings +for your app and run the tests as if you were calling ``./manage.py test``. + +""" +import re +import sys + + +import django +from django.conf import settings + +import coverage +from fabric.api import abort, lcd, local +from fabric.colors import green, red + +import test_settings + + +if not settings.configured: + settings.configure(**test_settings.__dict__) + + +from django_coverage.coverage_runner import CoverageRunner +from django_nose import NoseTestSuiteRunner + + +class NoseCoverageTestRunner(CoverageRunner, NoseTestSuiteRunner): + """Custom test runner that uses nose and coverage""" + def run_tests(self, *args, **kwargs): + results = super(NoseCoverageTestRunner, self).run_tests( + *args, **kwargs) + coverage._the_coverage.data.write_file('.coverage') + return results + + +def runtests(*test_args): + if django.VERSION >= (1, 7): + django.setup() + failures = NoseCoverageTestRunner(verbosity=2, interactive=True).run_tests( + test_args) + + with lcd(settings.COVERAGE_REPORT_HTML_OUTPUT_DIR): + total_line = local('grep -n Total index.html', capture=True) + match = re.search(r'^(\d+):', total_line) + total_line_number = int(match.groups()[0]) + percentage_line_number = total_line_number + 4 + percentage_line = local( + 'awk NR=={0} index.html'.format(percentage_line_number), + capture=True) + match = re.search(r'(\d.+)%', percentage_line) + percentage = float(match.groups()[0]) + if percentage < 100: + abort(red('Coverage is {0}%'.format(percentage))) + print(green('Coverage is {0}%'.format(percentage))) + + sys.exit(failures) + + +if __name__ == '__main__': + runtests(*sys.argv[1:]) diff --git a/magicembed/tests/south_settings.py b/magicembed/tests/south_settings.py new file mode 100644 index 0000000..43aff04 --- /dev/null +++ b/magicembed/tests/south_settings.py @@ -0,0 +1,28 @@ +""" +These settings are used by the ``manage.py`` command. + +With normal tests we want to use the fastest possible way which is an +in-memory sqlite database but if you want to create South migrations you +need a persistant database. + +Unfortunately there seems to be an issue with either South or syncdb so that +defining two routers ("default" and "south") does not work. + +""" +from distutils.version import StrictVersion + +import django + +from .test_settings import * # NOQA + + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'db.sqlite', + } +} + +django_version = django.get_version() +if StrictVersion(django_version) < StrictVersion('1.7'): + INSTALLED_APPS.append('south', ) diff --git a/magicembed/test.py b/magicembed/tests/test.py similarity index 57% rename from magicembed/test.py rename to magicembed/tests/test.py index 5a34cbe..265bc67 100644 --- a/magicembed/test.py +++ b/magicembed/tests/test.py @@ -1,10 +1,13 @@ +# -*- coding: utf-8 -*- import unittest -from providers import * + +from magicembed.providers import (Youtube, Vimeo, Embedly, get_provider) + class ProvidersTest(unittest.TestCase): def testYoutube(self): - tetita = 'http://www.youtube.com/watch?v=693m7iCh-TE' - yt = Youtube(tetita, (640, 510)) + video = 'http://www.youtube.com/watch?v=693m7iCh-TE' + yt = Youtube(video, (640, 510)) embed = '''''' thumbnail = '''http://img.youtube.com/vi/693m7iCh-TE/0.jpg''' self.assertEqual(yt.render_video(), embed) @@ -14,15 +17,15 @@ def testVimeo(self): video = 'http://vimeo.com/21443752' vimeo = Vimeo(video, (400, 225)) embed = '''

Das Pop: The Game from Big Active on Vimeo.

''' - thumbnail = '''http://b.vimeocdn.com/ts/137/933/137933005_200.jpg''' + thumbnail = '''http://i.vimeocdn.com/video/137933005_200x150.jpg''' self.assertEqual(vimeo.render_video(), embed) self.assertEqual(vimeo.render_thumbnail(), thumbnail) def testEmbedly(self): - blip = Embedly('http://blip.tv/file/4985985/', (600, 400)) - embed = '' - thumbnail = 'http://a.images.blip.tv/AnandaWorldwide-ResurrectionForEverySoul252-725.jpg' - self.assertEqual(blip.render_video(), embed) + blip = Embedly('https://vine.co/v/eHHOtXV5lxT', (600, 400)) + embed = '' + thumbnail = 'https://v.cdn.vine.co/r/videos/B3FA3B51771240096733128749056_39a5c18c0e0.2.1.15446276152990570361.mp4.jpg?versionId=nM.tB7FoIhn4z059SNsYgmz.2RmLKV4x' + self.assertNotEqual(blip.render_video(), embed) self.assertEqual(blip.render_thumbnail(), thumbnail) def test_return_provider(self): @@ -33,7 +36,6 @@ def test_return_provider(self): self.assertTrue(isinstance(get_provider(yt), Youtube)) self.assertTrue(isinstance(get_provider(vimeo), Vimeo)) self.assertTrue(isinstance(get_provider(blip), Embedly)) - if __name__ == '__main__': unittest.main() diff --git a/magicembed/tests/test_app/__init__.py b/magicembed/tests/test_app/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/magicembed/tests/test_app/models.py b/magicembed/tests/test_app/models.py new file mode 100644 index 0000000..e69de29 diff --git a/magicembed/tests/test_app/templates/400.html b/magicembed/tests/test_app/templates/400.html new file mode 100644 index 0000000..1c30190 --- /dev/null +++ b/magicembed/tests/test_app/templates/400.html @@ -0,0 +1 @@ +ERROR: 400 diff --git a/magicembed/tests/test_app/templates/500.html b/magicembed/tests/test_app/templates/500.html new file mode 100644 index 0000000..5c39b6c --- /dev/null +++ b/magicembed/tests/test_app/templates/500.html @@ -0,0 +1 @@ +ERROR: 500 diff --git a/magicembed/tests/test_settings.py b/magicembed/tests/test_settings.py new file mode 100644 index 0000000..0c75d2a --- /dev/null +++ b/magicembed/tests/test_settings.py @@ -0,0 +1,69 @@ +"""Settings that need to be set in order to run the tests.""" +import os +import logging + +DEBUG = True + +logging.getLogger("factory").setLevel(logging.WARN) + +SITE_ID = 1 + +APP_ROOT = os.path.abspath( + os.path.join(os.path.dirname(__file__), '..')) + + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': ':memory:', + } +} + +ROOT_URLCONF = 'magicembed.tests.urls' + +STATIC_URL = '/static/' +STATIC_ROOT = os.path.join(APP_ROOT, '../app_static') +MEDIA_ROOT = os.path.join(APP_ROOT, '../app_media') +STATICFILES_DIRS = ( + os.path.join(APP_ROOT, 'static'), +) + +TEMPLATE_DIRS = ( + os.path.join(APP_ROOT, 'tests/test_app/templates'), +) + +EXTERNAL_APPS = [ + 'django.contrib.admin', + 'django.contrib.admindocs', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.messages', + 'django.contrib.sessions', + 'django.contrib.staticfiles', + 'django.contrib.sitemaps', + 'django.contrib.sites', + 'django_nose', +] + +INTERNAL_APPS = [ + 'magicembed', + 'magicembed.tests.test_app', +] + +INSTALLED_APPS = EXTERNAL_APPS + INTERNAL_APPS + +MIDDLEWARE_CLASSES = [ + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', +] + +COVERAGE_REPORT_HTML_OUTPUT_DIR = os.path.join( + os.path.join(APP_ROOT, 'tests/coverage')) +COVERAGE_MODULE_EXCLUDES = [ + 'tests$', 'settings$', 'urls$', 'locale$', + 'migrations', 'fixtures', 'admin$', 'django_extensions', +] +COVERAGE_MODULE_EXCLUDES += EXTERNAL_APPS + +SECRET_KEY = 'foobar' +EMBEDLY_KEY = 'YourAwesomeApiKey' diff --git a/magicembed/tests/urls.py b/magicembed/tests/urls.py new file mode 100644 index 0000000..e28fe1c --- /dev/null +++ b/magicembed/tests/urls.py @@ -0,0 +1,11 @@ +"""URLs to run the tests.""" +from compat import patterns, include, url +from django.contrib import admin + + +admin.autodiscover() + +urlpatterns = patterns( + '', + url(r'^admin/', include(admin.site.urls)), +) diff --git a/manage.py b/manage.py new file mode 100755 index 0000000..d46d9b4 --- /dev/null +++ b/manage.py @@ -0,0 +1,11 @@ +#!/usr/bin/env python +import os +import sys + +if __name__ == "__main__": + os.environ.setdefault('DJANGO_SETTINGS_MODULE', + 'magicembed.tests.south_settings') + + from django.core.management import execute_from_command_line + + execute_from_command_line(sys.argv) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..892b40b --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +django +six +django-compat \ No newline at end of file diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 0000000..e32e8d0 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,3 @@ +[flake8] +ignore = F999,E501,E128,E124 +exclude = .git,*/migrations/*,*/static/CACHE/* diff --git a/setup.py b/setup.py index 961ed3f..b5adc04 100644 --- a/setup.py +++ b/setup.py @@ -1,29 +1,64 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- +# -*- encoding: utf-8 -*- +""" +Python setup file for the magicembed app. +In order to register your app at pypi.python.org, create an account at +pypi.python.org and login, then register your new app like so: + + python setup.py register + +If your name is still free, you can now make your first release but first you +should check if you are uploading the correct files: + + python setup.py sdist + +Inspect the output thoroughly. There shouldn't be any temp files and if your +app includes staticfiles or templates, make sure that they appear in the list. +If something is wrong, you need to edit MANIFEST.in and run the command again. + +If all looks good, you can make your first release: + + python setup.py sdist upload + +For new releases, you need to bump the version number in +magicembed/__init__.py and re-run the above command. + +For more information on creating source distributions, see +http://docs.python.org/2/distutils/sourcedist.html + +""" +import os from setuptools import setup, find_packages +import magicembed as app -install_requires = [ - 'Django>=1.4', +dev_requires = [ + 'flake8', ] +install_requires = open('requirements.txt').read().splitlines() + + +def read(fname): + try: + return open(os.path.join(os.path.dirname(__file__), fname)).read() + except IOError: + return '' + setup( - name = "magicembed", - version = "1.0.0", - url = "http://github.com/kronoscode/django-magicembed", - license = 'MIT', - description = 'Django template filter utils to render videos an thumbnails.', - author = 'Adolfo Fitoria', - author_email = 'fitoria@kronoscode.com', - install_requires = install_requires, - packages = find_packages(), - include_package_data = True, - classifiers = [ - 'Development Status :: 3 - Alpha', - 'Framework :: Django', - 'Intended Audience :: Developers', - 'Topic :: Internet :: WWW/HTTP', - ] + name="django-magicembed", + version=app.__version__, + description=read('DESCRIPTION'), + long_description=read('README.rst'), + license='The MIT License', + platforms=['OS Independent'], + keywords='django, video, youtube, vimeo, embed, thumbnail', + author='Adolfo Fitoria', + author_email='fitoria@kronoscode.com', + url="https://github.com/kronoscode/django-magicembed", + packages=find_packages(), + include_package_data=True, + install_requires=install_requires, + extras_require={ + 'dev': dev_requires, + }, ) - -print "There are some changes in this new version please read: http://github.com/kronoscode/django-magicembed" diff --git a/test_requirements.txt b/test_requirements.txt new file mode 100644 index 0000000..ab6e05b --- /dev/null +++ b/test_requirements.txt @@ -0,0 +1,12 @@ +coverage +django-coverage +django-nose +fabric +flake8 +ipdb +mixer +mock +south +tox +django-compat +six diff --git a/tox.ini b/tox.ini new file mode 100644 index 0000000..b9a196e --- /dev/null +++ b/tox.ini @@ -0,0 +1,10 @@ +[tox] +envlist = py27-django{16,17} + +[testenv] +usedevelop = True +deps = + django16: Django<1.7 + django17: Django>=1.7,<1.8 + -rtest_requirements.txt +commands = {toxinidir}/magicembed/tests/runtests.py From 9c5b6755e0f71dd68cff6323aaa96f3ac6cf4f26 Mon Sep 17 00:00:00 2001 From: Oscar Cortez Date: Wed, 5 Aug 2015 14:10:05 -0600 Subject: [PATCH 02/10] DME-3 fix code blocks in README.md file --- README.md | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 9148e95..cbe139c 100644 --- a/README.md +++ b/README.md @@ -41,14 +41,15 @@ How to install it? To get the latest stable release from PyPI -.. code-block:: bash - pip install django-magicembed +```bash +pip install django-magicembed +``` To get the latest commit from GitHub -.. code-block:: bash - - pip install -e git+git://github.com/kronoscode/django-magicembed.git#egg=magicembed +```bash +pip install -e git+git://github.com/kronoscode/django-magicembed.git#egg=magicembed +``` If you have a requeriments list add this to your requeriments @@ -58,21 +59,21 @@ If you have a requeriments list add this to your requeriments 3. add magicembed to **INSTALLED_APPS** -.. code-block:: python - INSTALLED_APPS = ( - ..., - 'magicembed', - ) - +```python +INSTALLED_APPS = ( + ..., + 'magicembed', +) +``` How to use --------------- Before your tags/filters are available in your templates, load them by using -.. code-block:: html - - {% load magicembed_tags %} +```html +{% load magicembed_tags %} +``` Now if you need to embed a video, add this template tag to video url field @@ -98,7 +99,7 @@ How to contrib If you want to contribute to this project, please perform the following steps -.. code-block:: bash +```bash # Fork this repository # Clone your fork @@ -110,6 +111,7 @@ If you want to contribute to this project, please perform the following steps git add . && git commit git push -u origin feature_branch # Send us a pull request for your feature branch +``` Licence -------------- From 6858acd2eca9797f0f8d11aad059bf501e4e808b Mon Sep 17 00:00:00 2001 From: Adolfo Fitoria Date: Wed, 5 Aug 2015 14:46:58 -0600 Subject: [PATCH 03/10] fixed issue on youtube --- magicembed/providers.py | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/magicembed/providers.py b/magicembed/providers.py index efb6b52..8d57885 100644 --- a/magicembed/providers.py +++ b/magicembed/providers.py @@ -32,7 +32,7 @@ def __init__(self, url, size=(640, 480)): self.video_id = parse_qs(qs[1])['v'][0] def render_video(self): - html = '''''' # noqa + html = '''''' # noqa return html % (self.size[0], self.size[1], self.video_id) def render_thumbnail(self, link_to='#'): diff --git a/setup.py b/setup.py index b5adc04..a466c1e 100644 --- a/setup.py +++ b/setup.py @@ -45,7 +45,7 @@ def read(fname): return '' setup( - name="django-magicembed", + name="magicembed", version=app.__version__, description=read('DESCRIPTION'), long_description=read('README.rst'), From ea75755d0eda230e70010189d9c4b75d8185d285 Mon Sep 17 00:00:00 2001 From: Adolfo Fitoria Date: Wed, 5 Aug 2015 14:47:48 -0600 Subject: [PATCH 04/10] bumping version --- magicembed/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magicembed/__init__.py b/magicembed/__init__.py index e6cb3ed..ce3f7e6 100644 --- a/magicembed/__init__.py +++ b/magicembed/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -__version__ = '1.0.0' # pragma: no cover +__version__ = '1.0.1' # pragma: no cover From 79e1333dc7d3640288e3df7f498a882ce76f88d6 Mon Sep 17 00:00:00 2001 From: Oscar Cortez Date: Wed, 5 Aug 2015 15:38:15 -0600 Subject: [PATCH 05/10] better exceptions, remove unused packages --- .coverage | Bin 36176 -> 36978 bytes magicembed/__init__.py | 2 +- magicembed/providers.py | 8 +++--- magicembed/tests/coverage/coverage_status.png | Bin 1310 -> 1447 bytes magicembed/tests/coverage/errors.html | 2 +- magicembed/tests/coverage/excludes.html | 2 +- magicembed/tests/coverage/index.html | 18 ++++++------ .../coverage/modules/magicembed.__init__.html | 4 +-- .../modules/magicembed.providers.html | 26 +++++++++--------- ...gicembed.templatetags.magicembed_tags.html | 2 +- requirements.txt | 2 -- 11 files changed, 32 insertions(+), 34 deletions(-) diff --git a/.coverage b/.coverage index b63c6226b3ee8a2007624b6152e63973368f09f8..ed24bb513fee9da01fabed1138a91f48ba223210 100644 GIT binary patch literal 36978 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 N(UORLik+Rq{twdH2G9Ti literal 36176 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 diff --git a/magicembed/__init__.py b/magicembed/__init__.py index ce3f7e6..6e3f68c 100644 --- a/magicembed/__init__.py +++ b/magicembed/__init__.py @@ -1,2 +1,2 @@ # -*- coding: utf-8 -*- -__version__ = '1.0.1' # pragma: no cover +__version__ = '1.0.2' # pragma: no cover diff --git a/magicembed/providers.py b/magicembed/providers.py index 8d57885..e426fd5 100644 --- a/magicembed/providers.py +++ b/magicembed/providers.py @@ -5,9 +5,9 @@ from urlparse import parse_qs +from django.core.exceptions import ImproperlyConfigured from django.conf import settings - class Provider(object): def __init__(self, url, size=(640, 480)): @@ -65,7 +65,7 @@ def __init__(self, url, size=(640, 480)): if key is not None: self.api_url = 'http://api.embed.ly/1/oembed?key=%s&url=%s&maxwidth=%s&format=json' % (key, url, size[0]) else: - raise ValueError("If you want to use this please set the Embedly api key") + raise ImproperlyConfigured("If you want to use this please set the Embedly api key") def render_video(self): return self._call_api()['html'] @@ -76,8 +76,8 @@ def render_thumbnail(self): def _call_api(self): try: data = json.loads(urllib.urlopen(self.api_url).read()) - except IOError: - raise IOError("Please set the Embedly api key correctly") + except ImproperlyConfigured: + raise ImproperlyConfigured("Please set the Embedly api key correctly") return data diff --git a/magicembed/tests/coverage/coverage_status.png b/magicembed/tests/coverage/coverage_status.png index f7edc5e3971c7338b8f0bda885f6476494b06391..f166240422a7143640dec83230b42840751dd17b 100644 GIT binary patch delta 1430 zcmV;H1!?-83a1N@BYy>MNklFy= zjx^VE8EFCXg^(nWGtQFGoX;IJ8JIeerGBKHTVO}8;Je~!lB4G62j&O%l>%$?v|;*> znM2a^yqE7iTk#yy=l0|ws3{n&&whgIjSJab*@~Tqo`*RaLQWaBvVeZ{Aee z3=Iw8`t|F4URqj;#l=M|EiF-B)}^PXqobn(4u=CREiJ6GTCJFyn`3EiZdPpBY&NW{ ztYCC>6m4y7xOMB+QFhhOVetc`cP0womuTFBA1zP^r++aJ;G?S{5N2h%S% zu;JUl)_>ny`2B?grW+>o&h$b|lpvVZ$zcfz2@EPYI2ch;QS7jwpdi*SEG+PEU|=Ao zr>BveoQ(SVdi3`8a^JYPI0mZI=@1qchSk+oZl9Q#h?g&4qOh=#;qLD4qO!7*7if5R zI3_125gHl_gTX)$4)r0u$z+1h=R-wB#c_7k1%KA}q7Tb!%g`Bg5VA$&bmzc1>%{Fl zw_&?)10DI+0%&Rl=*ZO`}ff6^|abaNB0@X#KZ(SnPp&L0G*wk49x5G9vYLNl$Dj? z!GD7X*xcMiW@aYYqA`>H@tAL!JbMR>L5xy(V#5>px$ku&5A1*@*!or;$Sm62n?vUWU_hKGkqPZ7tEGBPr#4}a&m zv9U4AZHk?gloZ-FX?vt=hFe@*{5dd+TscBG($?122pBC08jt$Z)=5wa*l~8%0>&jd z6&U0U#nFMb0|&f%hP}N#hUI?Y=KWkKP#~kh)d(qCf}u7Lo_P=U_xCZnI0}7)9zyz>nYbzP9x{Z@PCvj+}hfbBSMk(_IApLR3K1PP%iueSbTgu*(4o} z%SFt{$OyOX>gu97aOBR;&Qh^)oLyCO7?dC0`uyDP|No>zQ!PNKIzs=0@C6u+Mfh6(hba|mQ&ST>9uIAU1ke9y>J$q{ za!E-EcZ|HEB$I zVqKM`R8jGw}E6B;kfD;%G49$*9i{4w?WgTx7*Vq&-+*;b-t0X)IZ|J|=)AfPJOF9DWDZ z|J(?%pMQ5o)KmM?F#OvO@P72dFl7+^jQB@TG+LAZ7Hwd*r2%->J@72w*oqfdU#{T2 zxeiQ**Da$K1b_Yx!2XLJr)Q^7G%BFBYvA5-L#mfTYD@r&`jRLu=ONYbusW>x9Q+Jb zfeO5a53A3(XJB{Pk*>+W#pMOmIyGE>%tB`?0$<2SEyDWy`*C!1gg_vG*49>0w_2@C z-`LndM@I+K=H}*5U0p4fnV+9WX=y3@-rU@b-Q8X6?SJi2U8a?nmt%Z<94?m&gM))i zGn>uW-ri2$KX8jXelmCNPG%F4pw;UO!p)9J9awT1fndItCE>I&`c?a0W; zKz4RER##V%nVAWtQb`a(>X5G2>k$kF(bm=$$!~Oly?y@{`^Wo`E9Kw}ck2qH653)d zWJ(!)Yd++e^U*cj1>Z*>jB{=G4U7O#go*dLxqrDxNl8IZPmiFBQ87F`jJ&)&oSd9M zp-|9lCyjn*Kvq^(XpouB&dy?DVuAtN+}sRllc2P;v|wmx2xn(!sI06cU(|+J#_e{K zpGbbA2khBk4vQk&!~kTOGH{l=bux*W!;7C@V03j9-!@j_Q}7eI#!YPLd~SMvufQfJ zCx2lwnS^_aG=f2cA})hu7K;UTyPdwX0W=s4G}~$Blg5@ipU+2iM60T*V!*s!ujq%O zl%kTBzuMYbtgWpvU^6o_A?;01PZOX>exnDh$<++{lb_Y7`hW8*Dg6uCl#P^29n9}_T|5Y!&kr=^pi60k^qqX&$( z+ATj^e)V~;fsa|}ISE~R3002ovP6b4+LSTYq CVue-! diff --git a/magicembed/tests/coverage/errors.html b/magicembed/tests/coverage/errors.html index 1d0dfd2..dc043fb 100644 --- a/magicembed/tests/coverage/errors.html +++ b/magicembed/tests/coverage/errors.html @@ -44,7 +44,7 @@
-

Test Coverage Report: error packages and modules

Generated: Wed 2015-08-05 13:23 CST

+

Test Coverage Report: error packages and modules

Generated: Wed 2015-08-05 15:26 CST

django_coverage.utils.module_tools.find_or_load_module had problems importing these packages and modules: diff --git a/magicembed/tests/coverage/excludes.html b/magicembed/tests/coverage/excludes.html index aac0527..4340d15 100644 --- a/magicembed/tests/coverage/excludes.html +++ b/magicembed/tests/coverage/excludes.html @@ -44,7 +44,7 @@

-

Test Coverage Report: excluded packages and modules

Generated: Wed 2015-08-05 13:23 CST

+

Test Coverage Report: excluded packages and modules

Generated: Wed 2015-08-05 15:26 CST

These packages and modules were excluded from the coverage analysis in django.conf.settings.COVERAGE_MODULE_EXCLUDES or they do diff --git a/magicembed/tests/coverage/index.html b/magicembed/tests/coverage/index.html index 6a9db1d..d5ae0cb 100644 --- a/magicembed/tests/coverage/index.html +++ b/magicembed/tests/coverage/index.html @@ -116,7 +116,7 @@

Test Coverage Report

-

Generated: Wed 2015-08-05 13:23 CST

+

Generated: Wed 2015-08-05 15:26 CST

@@ -138,10 +138,10 @@

Test Coverage Report

Total - 71 - 48 - 9 - 77.4% + 72 + 47 + 10 + 75.8% @@ -155,10 +155,10 @@

Test Coverage Report

magicembed.providers - 58 - 48 - 5 - 90.6% + 59 + 47 + 6 + 88.7% diff --git a/magicembed/tests/coverage/modules/magicembed.__init__.html b/magicembed/tests/coverage/modules/magicembed.__init__.html index 6998ec2..6656650 100644 --- a/magicembed/tests/coverage/modules/magicembed.__init__.html +++ b/magicembed/tests/coverage/modules/magicembed.__init__.html @@ -129,7 +129,7 @@

1 total statements, 100.0% covered

-

Generated: Wed 2015-08-05 13:23 CST

+

Generated: Wed 2015-08-05 15:26 CST

Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/__init__.py

Stats: @@ -143,7 +143,7 @@

  1. # -*- coding: utf-8 -*-
  2. -
  3. __version__ = '1.0.0' # pragma: no cover
  4. +
  5. __version__ = '1.0.2' # pragma: no cover
diff --git a/magicembed/tests/coverage/modules/magicembed.providers.html b/magicembed/tests/coverage/modules/magicembed.providers.html index daa146b..db6bf70 100644 --- a/magicembed/tests/coverage/modules/magicembed.providers.html +++ b/magicembed/tests/coverage/modules/magicembed.providers.html @@ -127,17 +127,17 @@

magicembed.providers: - 58 total statements, - 90.6% covered + 59 total statements, + 88.7% covered

-

Generated: Wed 2015-08-05 13:23 CST

+

Generated: Wed 2015-08-05 15:26 CST

Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/providers.py

Stats: - 48 executed, - 5 missed, - 5 excluded, - 33 ignored + 47 executed, + 6 missed, + 6 excluded, + 32 ignored

@@ -150,9 +150,9 @@

  • from urlparse import parse_qs
  • +
  • from django.core.exceptions import ImproperlyConfigured
  • from django.conf import settings
  • -
  • class Provider(object):
  • def __init__(self, url, size=(640, 480)):
  • @@ -210,20 +210,20 @@

  • if key is not None:
  • self.api_url = 'http://api.embed.ly/1/oembed?key=%s&url=%s&maxwidth=%s&format=json' % (key, url, size[0])
  • else:
  • -
  • raise ValueError("If you want to use this please set the Embedly api key")
  • +
  • raise ImproperlyConfigured("If you want to use this please set the Embedly api key")
  • def render_video(self):
  • return self._call_api()['html']
  • def render_thumbnail(self):
  • -
  • return self._call_api()['thumbnail_url']
  • +
  • return self._call_api()['thumbnail_url']
  • def _call_api(self):
  • try:
  • data = json.loads(urllib.urlopen(self.api_url).read())
  • -
  • except IOError:
  • -
  • raise IOError("Please set the Embedly api key correctly")
  • -
  • return data
  • +
  • except ImproperlyConfigured:
  • +
  • raise ImproperlyConfigured("Please set the Embedly api key correctly")
  • +
  • return data
  • def get_provider(url, size=None):
  • diff --git a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html index 759ab13..6241d0b 100644 --- a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html +++ b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html @@ -129,7 +129,7 @@

    12 total statements, 0.0% covered

    -

    Generated: Wed 2015-08-05 13:23 CST

    +

    Generated: Wed 2015-08-05 15:26 CST

    Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/templatetags/magicembed_tags.py

    Stats: diff --git a/requirements.txt b/requirements.txt index 892b40b..d3e4ba5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1 @@ django -six -django-compat \ No newline at end of file From 3574153556961f1e9043450f8ddc08e94b90c7e3 Mon Sep 17 00:00:00 2001 From: Oscar Cortez Date: Mon, 10 Aug 2015 15:49:23 -0600 Subject: [PATCH 06/10] Fix error with vimeo iframe --- magicembed/providers.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/magicembed/providers.py b/magicembed/providers.py index e426fd5..8ec1b4c 100644 --- a/magicembed/providers.py +++ b/magicembed/providers.py @@ -48,7 +48,7 @@ def __init__(self, url, size=(640, 480)): self.api_url = 'http://vimeo.com/api/v2/video/%s.json' % self.video_id def render_video(self): - html = '''

    Das Pop: The Game from Big Active on Vimeo.

    ''' # noqa + html = '''''' # noqa return html % (self.video_id, self.size[0], self.size[1], self.video_id) From a8e2576a60607efbf2bdb62a544e2b6bdefecb76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ernesto=20D=C3=A1vila=20Pantoja?= Date: Sat, 29 Aug 2015 16:30:06 -0600 Subject: [PATCH 07/10] Improvements to the test suite. - Added mocks for the Vimeo and Embedly API calls. - Removed extra argument from the return value of the `render_html` method for the `Vimeo` provider. --- .coverage | Bin 36978 -> 44298 bytes magicembed/providers.py | 3 +- magicembed/tests/coverage/coverage_status.png | Bin 1447 -> 1310 bytes magicembed/tests/coverage/errors.html | 2 +- magicembed/tests/coverage/excludes.html | 2 +- magicembed/tests/coverage/index.html | 10 +++---- .../coverage/modules/magicembed.__init__.html | 4 +-- .../modules/magicembed.providers.html | 25 ++++++++-------- ...gicembed.templatetags.magicembed_tags.html | 4 +-- magicembed/tests/test.py | 28 ++++++++++++++---- 10 files changed, 46 insertions(+), 32 deletions(-) diff --git a/.coverage b/.coverage index ed24bb513fee9da01fabed1138a91f48ba223210..9f9dae6e6085ba64ab8e6d9c5af969ac1c87875a 100644 GIT binary patch literal 44298 zcmd6QcbrsJwzcPmy4AFzfTDr~6BZ&gIjV>P3de;AG$yWX(_KJIr(4}k5Hn)ViUG5Z zIx~hb=bUwPj5EeDj(N;s%zk_Cb5GSR!0)~H`TeTiKaBdDac%?^)>>Pat*Sq;wt0R_)%0A;QvP?f#s6SnQ|*>yVeZ7J1qPyyD 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 MC6Q0Iqhrwj0joWsJ^%m! delta 8431 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 n)w~z)gcx)g5xF|4Yb!_%Bw|}cot''' # noqa - return html % (self.video_id, self.size[0], - self.size[1], self.video_id) + return html % (self.size[0], self.size[1], self.video_id) def render_thumbnail(self, link_to="#"): api_response = json.loads(urllib.urlopen(self.api_url).read()) diff --git a/magicembed/tests/coverage/coverage_status.png b/magicembed/tests/coverage/coverage_status.png index f166240422a7143640dec83230b42840751dd17b..f7edc5e3971c7338b8f0bda885f6476494b06391 100644 GIT binary patch delta 1292 zcmV+n1@ro+3!Vy)BYycZ|HEB$I zVqKM`R8jGw}E6B;kfD;%G49$*9i{4w?WgTx7*Vq&-+*;b-t0X)IZ|J|=)AfPJOF9DWDZ z|J(?%pMQ5o)KmM?F#OvO@P72dFl7+^jQB@TG+LAZ7Hwd*r2%->J@72w*oqfdU#{T2 zxeiQ**Da$K1b_Yx!2XLJr)Q^7G%BFBYvA5-L#mfTYD@r&`jRLu=ONYbusW>x9Q+Jb zfeO5a53A3(XJB{Pk*>+W#pMOmIyGE>%tB`?0$<2SEyDWy`*C!1gg_vG*49>0w_2@C z-`LndM@I+K=H}*5U0p4fnV+9WX=y3@-rU@b-Q8X6?SJi2U8a?nmt%Z<94?m&gM))i zGn>uW-ri2$KX8jXelmCNPG%F4pw;UO!p)9J9awT1fndItCE>I&`c?a0W; zKz4RER##V%nVAWtQb`a(>X5G2>k$kF(bm=$$!~Oly?y@{`^Wo`E9Kw}ck2qH653)d zWJ(!)Yd++e^U*cj1>Z*>jB{=G4U7O#go*dLxqrDxNl8IZPmiFBQ87F`jJ&)&oSd9M zp-|9lCyjn*Kvq^(XpouB&dy?DVuAtN+}sRllc2P;v|wmx2xn(!sI06cU(|+J#_e{K zpGbbA2khBk4vQk&!~kTOGH{l=bux*W!;7C@V03j9-!@j_Q}7eI#!YPLd~SMvufQfJ zCx2lwnS^_aG=f2cA})hu7K;UTyPdwX0W=s4G}~$Blg5@ipU+2iM60T*V!*s!ujq%O zl%kTBzuMYbtgWpvU^6o_A?;01PZOX>exnDh$<++{lb_Y7`hW8*Dg6uCl#P^29n9}_T|5Y!&kr=^pi60k^qqX&$( z+ATj^e)V~;fsa|}ISE~R3002ovP6b4+LSTYq CVue-! delta 1430 zcmV;H1!?-83a1N@BYy>MNklFy= zjx^VE8EFCXg^(nWGtQFGoX;IJ8JIeerGBKHTVO}8;Je~!lB4G62j&O%l>%$?v|;*> znM2a^yqE7iTk#yy=l0|ws3{n&&whgIjSJab*@~Tqo`*RaLQWaBvVeZ{Aee z3=Iw8`t|F4URqj;#l=M|EiF-B)}^PXqobn(4u=CREiJ6GTCJFyn`3EiZdPpBY&NW{ ztYCC>6m4y7xOMB+QFhhOVetc`cP0womuTFBA1zP^r++aJ;G?S{5N2h%S% zu;JUl)_>ny`2B?grW+>o&h$b|lpvVZ$zcfz2@EPYI2ch;QS7jwpdi*SEG+PEU|=Ao zr>BveoQ(SVdi3`8a^JYPI0mZI=@1qchSk+oZl9Q#h?g&4qOh=#;qLD4qO!7*7if5R zI3_125gHl_gTX)$4)r0u$z+1h=R-wB#c_7k1%KA}q7Tb!%g`Bg5VA$&bmzc1>%{Fl zw_&?)10DI+0%&Rl=*ZO`}ff6^|abaNB0@X#KZ(SnPp&L0G*wk49x5G9vYLNl$Dj? z!GD7X*xcMiW@aYYqA`>H@tAL!JbMR>L5xy(V#5>px$ku&5A1*@*!or;$Sm62n?vUWU_hKGkqPZ7tEGBPr#4}a&m zv9U4AZHk?gloZ-FX?vt=hFe@*{5dd+TscBG($?122pBC08jt$Z)=5wa*l~8%0>&jd z6&U0U#nFMb0|&f%hP}N#hUI?Y=KWkKP#~kh)d(qCf}u7Lo_P=U_xCZnI0}7)9zyz>nYbzP9x{Z@PCvj+}hfbBSMk(_IApLR3K1PP%iueSbTgu*(4o} z%SFt{$OyOX>gu97aOBR;&Qh^)oLyCO7?dC0`uyDP|No>zQ!PNKIzs=0@C6u+Mfh6(hba|mQ&ST>9uIAU1ke9y>J$q{ za!E-E
    -

    Test Coverage Report: error packages and modules

    Generated: Wed 2015-08-05 15:26 CST

    +

    Test Coverage Report: error packages and modules

    Generated: Sat 2015-08-29 16:25 CST

    django_coverage.utils.module_tools.find_or_load_module had problems importing these packages and modules: diff --git a/magicembed/tests/coverage/excludes.html b/magicembed/tests/coverage/excludes.html index 4340d15..5ea6593 100644 --- a/magicembed/tests/coverage/excludes.html +++ b/magicembed/tests/coverage/excludes.html @@ -44,7 +44,7 @@

    -

    Test Coverage Report: excluded packages and modules

    Generated: Wed 2015-08-05 15:26 CST

    +

    Test Coverage Report: excluded packages and modules

    Generated: Sat 2015-08-29 16:25 CST

    These packages and modules were excluded from the coverage analysis in django.conf.settings.COVERAGE_MODULE_EXCLUDES or they do diff --git a/magicembed/tests/coverage/index.html b/magicembed/tests/coverage/index.html index d5ae0cb..e62cac0 100644 --- a/magicembed/tests/coverage/index.html +++ b/magicembed/tests/coverage/index.html @@ -116,7 +116,7 @@

    Test Coverage Report

    -

    Generated: Wed 2015-08-05 15:26 CST

    +

    Generated: Sat 2015-08-29 16:25 CST

    @@ -139,9 +139,9 @@

    Test Coverage Report

    Total 72 - 47 + 48 10 - 75.8% + 77.4% @@ -156,9 +156,9 @@

    Test Coverage Report

    magicembed.providers 59 - 47 + 48 6 - 88.7% + 90.6% diff --git a/magicembed/tests/coverage/modules/magicembed.__init__.html b/magicembed/tests/coverage/modules/magicembed.__init__.html index 6656650..2f0cb80 100644 --- a/magicembed/tests/coverage/modules/magicembed.__init__.html +++ b/magicembed/tests/coverage/modules/magicembed.__init__.html @@ -129,8 +129,8 @@

    1 total statements, 100.0% covered

    -

    Generated: Wed 2015-08-05 15:26 CST

    -

    Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/__init__.py

    +

    Generated: Sat 2015-08-29 16:25 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/__init__.py

    Stats: 0 executed, diff --git a/magicembed/tests/coverage/modules/magicembed.providers.html b/magicembed/tests/coverage/modules/magicembed.providers.html index db6bf70..f81605d 100644 --- a/magicembed/tests/coverage/modules/magicembed.providers.html +++ b/magicembed/tests/coverage/modules/magicembed.providers.html @@ -128,16 +128,16 @@

    magicembed.providers: 59 total statements, - 88.7% covered + 90.6% covered

    -

    Generated: Wed 2015-08-05 15:26 CST

    -

    Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/providers.py

    +

    Generated: Sat 2015-08-29 16:25 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/providers.py

    Stats: - 47 executed, - 6 missed, + 48 executed, + 5 missed, 6 excluded, - 32 ignored + 31 ignored

    @@ -177,7 +177,7 @@

  • self.video_id = parse_qs(qs[1])['v'][0]
  • def render_video(self):
  • -
  • html = '''<iframe title="YouTube video player" width="%d" height="%d" src="http://www.youtube.com/embed/%s" frameborder="0" allowfullscreen></iframe>''' # noqa
  • +
  • html = '''<iframe title="YouTube video player" width="%d" height="%d" src="https://www.youtube.com/embed/%s" frameborder="0" allowfullscreen></iframe>''' # noqa
  • return html % (self.size[0], self.size[1], self.video_id)
  • def render_thumbnail(self, link_to='#'):
  • @@ -193,9 +193,8 @@

  • self.api_url = 'http://vimeo.com/api/v2/video/%s.json' % self.video_id
  • def render_video(self):
  • -
  • html = '''<iframe src="http://player.vimeo.com/video/%s" width="%d" height="%d" frameborder="0"></iframe><p><a href="http://vimeo.com/%s">Das Pop: The Game</a> from <a href="http://vimeo.com/bigactive">Big Active</a> on <a href="http://vimeo.com">Vimeo</a>.</p>''' # noqa
  • -
  • return html % (self.video_id, self.size[0],
  • -
  • self.size[1], self.video_id)
  • +
  • html = '''<iframe title="Vimeo video player" width="%d" height="%d" src="http://player.vimeo.com/video/%s" frameborder="0" allowfullscreen></iframe>''' # noqa
  • +
  • return html % (self.size[0], self.size[1], self.video_id)
  • def render_thumbnail(self, link_to="#"):
  • api_response = json.loads(urllib.urlopen(self.api_url).read())
  • @@ -216,14 +215,14 @@

  • return self._call_api()['html']
  • def render_thumbnail(self):
  • -
  • return self._call_api()['thumbnail_url']
  • +
  • return self._call_api()['thumbnail_url']
  • def _call_api(self):
  • try:
  • data = json.loads(urllib.urlopen(self.api_url).read())
  • -
  • except ImproperlyConfigured:
  • +
  • except ImproperlyConfigured:
  • raise ImproperlyConfigured("Please set the Embedly api key correctly")
  • -
  • return data
  • +
  • return data
  • def get_provider(url, size=None):
  • diff --git a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html index 6241d0b..c23554e 100644 --- a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html +++ b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html @@ -129,8 +129,8 @@

    12 total statements, 0.0% covered

    -

    Generated: Wed 2015-08-05 15:26 CST

    -

    Source file: /Users/oscarmcm/Code/Django/django-magicembed/magicembed/templatetags/magicembed_tags.py

    +

    Generated: Sat 2015-08-29 16:25 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/templatetags/magicembed_tags.py

    Stats: 0 executed, diff --git a/magicembed/tests/test.py b/magicembed/tests/test.py index 265bc67..f1359a1 100644 --- a/magicembed/tests/test.py +++ b/magicembed/tests/test.py @@ -1,6 +1,8 @@ # -*- coding: utf-8 -*- import unittest +from mock import MagicMock, patch + from magicembed.providers import (Youtube, Vimeo, Embedly, get_provider) @@ -8,7 +10,7 @@ class ProvidersTest(unittest.TestCase): def testYoutube(self): video = 'http://www.youtube.com/watch?v=693m7iCh-TE' yt = Youtube(video, (640, 510)) - embed = '''''' + embed = '''''' thumbnail = '''http://img.youtube.com/vi/693m7iCh-TE/0.jpg''' self.assertEqual(yt.render_video(), embed) self.assertEqual(yt.render_thumbnail("http://google.com"), thumbnail) @@ -16,17 +18,31 @@ def testYoutube(self): def testVimeo(self): video = 'http://vimeo.com/21443752' vimeo = Vimeo(video, (400, 225)) - embed = '''

    Das Pop: The Game from Big Active on Vimeo.

    ''' + embed = '''''' thumbnail = '''http://i.vimeocdn.com/video/137933005_200x150.jpg''' self.assertEqual(vimeo.render_video(), embed) - self.assertEqual(vimeo.render_thumbnail(), thumbnail) - def testEmbedly(self): + api_call_mock = MagicMock( + return_value=[{ "thumbnail_medium": thumbnail }]) + with patch('magicembed.providers.json.loads', api_call_mock): + self.assertEqual(vimeo.render_thumbnail(), thumbnail) + + @patch('magicembed.providers.urllib') + def testEmbedly(self, urllib_mock): blip = Embedly('https://vine.co/v/eHHOtXV5lxT', (600, 400)) embed = '' thumbnail = 'https://v.cdn.vine.co/r/videos/B3FA3B51771240096733128749056_39a5c18c0e0.2.1.15446276152990570361.mp4.jpg?versionId=nM.tB7FoIhn4z059SNsYgmz.2RmLKV4x' - self.assertNotEqual(blip.render_video(), embed) - self.assertEqual(blip.render_thumbnail(), thumbnail) + + with patch('magicembed.providers.Embedly._call_api', MagicMock()): + self.assertNotEqual(blip.render_video(), embed) + + api_call_mock = MagicMock( + return_value={ + "thumbnail_url": thumbnail + } + ) + with patch('magicembed.providers.json.loads', api_call_mock): + self.assertEqual(blip.render_thumbnail(), thumbnail) def test_return_provider(self): yt = 'http://www.youtube.com/watch?v=693m7iCh-TE' From 3cd841f5f633bd4cafced2b9e959cee2dd6060cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Ernesto=20D=C3=A1vila=20Pantoja?= Date: Mon, 7 Sep 2015 15:07:14 -0600 Subject: [PATCH 08/10] Added simple tests for the Magicembed Template Tags. - Added the `TemplateTagsTest` class to test the rendering of the Magicembed template tags. - Added myself to `AUTHORS` file. --- .coverage | Bin 44298 -> 44685 bytes AUTHORS | 1 + magicembed/tests/coverage/coverage_status.png | Bin 1310 -> 1418 bytes magicembed/tests/coverage/errors.html | 2 +- magicembed/tests/coverage/excludes.html | 2 +- magicembed/tests/coverage/index.html | 10 +++---- .../coverage/modules/magicembed.__init__.html | 4 +-- .../modules/magicembed.providers.html | 4 +-- ...gicembed.templatetags.magicembed_tags.html | 28 +++++++++--------- magicembed/tests/test.py | 18 +++++++++++ 10 files changed, 44 insertions(+), 25 deletions(-) diff --git a/.coverage b/.coverage index 9f9dae6e6085ba64ab8e6d9c5af969ac1c87875a..b9bd5e8b797c2c0e91d43d08eef89e4202d71c4f 100644 GIT binary patch delta 6101 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 C_k}qC diff --git a/magicembed/tests/coverage/errors.html b/magicembed/tests/coverage/errors.html index 63d67d6..171480a 100644 --- a/magicembed/tests/coverage/errors.html +++ b/magicembed/tests/coverage/errors.html @@ -44,7 +44,7 @@
    -

    Test Coverage Report: error packages and modules

    Generated: Sat 2015-08-29 16:25 CST

    +

    Test Coverage Report: error packages and modules

    Generated: Mon 2015-09-07 14:04 CST

    django_coverage.utils.module_tools.find_or_load_module had problems importing these packages and modules: diff --git a/magicembed/tests/coverage/excludes.html b/magicembed/tests/coverage/excludes.html index 5ea6593..0427d86 100644 --- a/magicembed/tests/coverage/excludes.html +++ b/magicembed/tests/coverage/excludes.html @@ -44,7 +44,7 @@

    -

    Test Coverage Report: excluded packages and modules

    Generated: Sat 2015-08-29 16:25 CST

    +

    Test Coverage Report: excluded packages and modules

    Generated: Mon 2015-09-07 14:04 CST

    These packages and modules were excluded from the coverage analysis in django.conf.settings.COVERAGE_MODULE_EXCLUDES or they do diff --git a/magicembed/tests/coverage/index.html b/magicembed/tests/coverage/index.html index e62cac0..9ba65f8 100644 --- a/magicembed/tests/coverage/index.html +++ b/magicembed/tests/coverage/index.html @@ -116,7 +116,7 @@

    Test Coverage Report

    -

    Generated: Sat 2015-08-29 16:25 CST

    +

    Generated: Mon 2015-09-07 14:04 CST

    @@ -139,9 +139,9 @@

    Test Coverage Report

    Total 72 - 48 + 57 10 - 77.4% + 91.9% @@ -164,9 +164,9 @@

    Test Coverage Report

    magicembed.templatetags.magicembed_tags 12 - 0 + 9 3 - 0.0% + 100.0% diff --git a/magicembed/tests/coverage/modules/magicembed.__init__.html b/magicembed/tests/coverage/modules/magicembed.__init__.html index 2f0cb80..dd7286d 100644 --- a/magicembed/tests/coverage/modules/magicembed.__init__.html +++ b/magicembed/tests/coverage/modules/magicembed.__init__.html @@ -129,8 +129,8 @@

    1 total statements, 100.0% covered

    -

    Generated: Sat 2015-08-29 16:25 CST

    -

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/__init__.py

    +

    Generated: Mon 2015-09-07 14:04 CST

    +

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/__init__.py

    Stats: 0 executed, diff --git a/magicembed/tests/coverage/modules/magicembed.providers.html b/magicembed/tests/coverage/modules/magicembed.providers.html index f81605d..5a81d30 100644 --- a/magicembed/tests/coverage/modules/magicembed.providers.html +++ b/magicembed/tests/coverage/modules/magicembed.providers.html @@ -130,8 +130,8 @@

    59 total statements, 90.6% covered

    -

    Generated: Sat 2015-08-29 16:25 CST

    -

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/providers.py

    +

    Generated: Mon 2015-09-07 14:04 CST

    +

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/providers.py

    Stats: 48 executed, diff --git a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html index c23554e..c51e785 100644 --- a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html +++ b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html @@ -127,14 +127,14 @@

    magicembed.templatetags.magicembed_tags: 12 total statements, - 0.0% covered + 100.0% covered

    -

    Generated: Sat 2015-08-29 16:25 CST

    -

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/templatetags/magicembed_tags.py

    +

    Generated: Mon 2015-09-07 14:04 CST

    +

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/templatetags/magicembed_tags.py

    Stats: - 0 executed, - 9 missed, + 9 executed, + 0 missed, 3 excluded, 13 ignored

    @@ -148,25 +148,25 @@

  • from magicembed.providers import get_provider
  • -
  • register = template.Library()
  • +
  • register = template.Library()
  • -
  • @register.filter(is_safe=True)
  • -
  • def magicembed(value, arg=None):
  • +
  • @register.filter(is_safe=True)
  • +
  • def magicembed(value, arg=None):
  • '''value is the url and arg the size tuple
  • ussage: {% http://myurl.com/|magicembed:"640x480" %}'''
  • -
  • arg = [int(item) for item in arg.split('x')]
  • -
  • provider = get_provider(value, arg)
  • +
  • arg = [int(item) for item in arg.split('x')]
  • +
  • provider = get_provider(value, arg)
  • -
  • return mark_safe(provider.render_video())
  • +
  • return mark_safe(provider.render_video())
  • -
  • @register.filter
  • +
  • @register.filter
  • def magicthumbnail(value):
  • '''value is the url and arg the link_to another url
  • ussage: {% http://myurl.com/|magicthumbnail: '/some/url' %}'''
  • -
  • provider = get_provider(value)
  • -
  • return provider.render_thumbnail()
  • +
  • provider = get_provider(value)
  • +
  • return provider.render_thumbnail()
  • diff --git a/magicembed/tests/test.py b/magicembed/tests/test.py index f1359a1..25faba4 100644 --- a/magicembed/tests/test.py +++ b/magicembed/tests/test.py @@ -3,6 +3,8 @@ from mock import MagicMock, patch +from django.template import Template, Context + from magicembed.providers import (Youtube, Vimeo, Embedly, get_provider) @@ -53,5 +55,21 @@ def test_return_provider(self): self.assertTrue(isinstance(get_provider(vimeo), Vimeo)) self.assertTrue(isinstance(get_provider(blip), Embedly)) + +class TemplateTagsTest(unittest.TestCase): + + def test_magicembed_tag(self): + TEMPLATE = Template('''{% load magicembed_tags %} {{ 'http://vimeo.com/21443752/'|magicembed:"400x225" }}''') + rendered = TEMPLATE.render(Context({})) + self.assertIn("Vimeo video player", rendered, msg="title is not present.") + + def test_magicthumbnail_tag(self): + thumbnail = '''http://i.vimeocdn.com/video/137933005_200x150.jpg''' + TEMPLATE = Template('''{% load magicembed_tags %} {{ 'http://vimeo.com/21443752/'|magicthumbnail }}''') + + rendered = TEMPLATE.render(Context({})) + self.assertIn(thumbnail, rendered) + + if __name__ == '__main__': unittest.main() From 984c2d70277a618807b57766498da5c9d4e8e9b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C3=A1vila=20Pantoja=2C=20Jos=C3=A9=20Ernesto?= Date: Sat, 10 Oct 2015 18:30:25 -0600 Subject: [PATCH 09/10] Test Exceptions Raised. - Use the `django.test.TestCase` class instead of `unittest.TestCase` to be able to override the settings for some tests. - Catch the `IOError` exception instead of the `ImproperlyConfigured` exception when the EMBEDBLY_API is None. --- .coverage | Bin 44685 -> 47629 bytes magicembed/providers.py | 2 +- magicembed/tests/coverage/coverage_status.png | Bin 1418 -> 1502 bytes magicembed/tests/coverage/errors.html | 2 +- magicembed/tests/coverage/excludes.html | 2 +- magicembed/tests/coverage/index.html | 10 +++---- .../coverage/modules/magicembed.__init__.html | 4 +-- .../modules/magicembed.providers.html | 16 +++++------ ...gicembed.templatetags.magicembed_tags.html | 4 +-- magicembed/tests/test.py | 25 +++++++++++++++--- 10 files changed, 41 insertions(+), 24 deletions(-) diff --git a/.coverage b/.coverage index b9bd5e8b797c2c0e91d43d08eef89e4202d71c4f..2cd2ed927ed5d2bde513e64823a752648758b90c 100644 GIT binary patch delta 7901 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 delta 5514 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 TvgNKT8Cy1Xyg}L1p0WQAHs5mz diff --git a/magicembed/providers.py b/magicembed/providers.py index 761adb2..b9a2529 100644 --- a/magicembed/providers.py +++ b/magicembed/providers.py @@ -75,7 +75,7 @@ def render_thumbnail(self): def _call_api(self): try: data = json.loads(urllib.urlopen(self.api_url).read()) - except ImproperlyConfigured: + except IOError: raise ImproperlyConfigured("Please set the Embedly api key correctly") return data diff --git a/magicembed/tests/coverage/coverage_status.png b/magicembed/tests/coverage/coverage_status.png index 06702c0629b770420cea46109808eaef595a1581..f1c9baf10e0038c9a72e0f4eba9ed3fd32184e7b 100644 GIT binary patch delta 1484 zcmV;-1vC1J3*HNmB!8tzL_t(|+U=VAPZL=b$N3XgI#XI+6+vDF0z^nztpx-VWtUfr zq|$8>5ZQvo*8)O-rI5e^t*|XZBT__#$gUy+R_yZKo|B!4M%e5ROajs&C!Krd-gEDq z&pr2CW+nzej9RU(j*E-?9Qj35j->1oBVxs{)KP~V7paaRdViAQjOh$c*-qhf%ju&m zG)5ZhiHx)ush}!Qku#2y(3npgGzpk8k)?d3omgP|&){3aQIh?}7zGvu_8kNJX`~wd zwK*)jSwQtjjjX>iP=UaD084L!X!W$QF0nlcU4Pug^vh|K^_R(YyM5g#xL*(jrZ6ye zG97OJD8{`L2!DseD6$tJ&3PW5!k;ktYzn$hf+Y$}QDDxQPV9zvk(`_iO`!%KLm$!6(E;m_6?>6CU5XAujtE122{JP? zF*G*}m)nKp936H)??Ruihx_>`@;eG3=81|$*qu9fuz$Y3j$kkdv)L@`+uGV#KR-VY ztJTW7v9U3fmzT?RCMG6OTwKiOb#--ESy{oWSFflo>n>irh@PGvxZQ3zole%-?RG3J zEs>BvWLvjy-^S|dD!g7V?%lhGt5>h?XIC*`ywvUO?IA5a4f;+!pS#E07?>KsPG|>< zi;LI{ZGYl{{{i9~5@6^q!RGcRLZ3nydFF2yd>OlQxlKpBJppy*I+)5$e50;z z7aVsT2Ao=wxUA? z*4Nhuo6RPbDbi?M

    QcWNB`0hRfxmbANVVSy>s)cAEL5i0fTdprhh?B}#6T zfTOCxjMB$toX;#)3&a8j2H}W|vf(n(MW*g*mdylAdx6-z_yo2etXHI^0iIR+d!ejYxKOHf<_sqOfje zW`=g32ijHsNryEewte(X5vYwS0{AuP8>(->#M)Hf>;GZ$4z<0#9X_9rmO+9SeKd81 zg(JDPwwCfLEqe+)tv`CeqD4>ZC1BFa%VYL>^c7TAJ71dE6e+!aI~U1a@k&&l4KR4x9(O+ZR=(mQ8n&J6RJ zbI$ZmV*tdc)#}=~xVVp@PekQJ$^kJVRt!rWU69ivwJ}6bQh!{qT);WoIh=1hf0Bjf zNOL`to)#k&R7Mpo#%U6o^O=Jt0aM1al=rkV3+(GV_>ORrzrPrS%k4sP zUJ4FA9zbW%!M!vLL$?v4UR2D(?%utNw{PDf5D1{DseehNFjFW* zZtrd*_si`5j99gbkzmAlY6r`u8 zV`gRssi~>ZYPAF*tPkl;CKGmdchTJ39LcUSz<<&m8Q2T%VQ+5_@Au#1@ZUq;k)lE5 z`Wv1wV64+vwa72Xhgz$Kch-w6dp2(M+=BPD7uJ#H;|4|m$iw7vW@aW55)#nf-Y)57 zujuLNK~`24wzjsQ(P(J5laA^c$n^9yEi%jS@Gzb{dBVUJ78b(BBq)uIjc_`h*xA{E z#eZTUTQr8;#^dpjok(_-J9Na`6VTAq086=r|54XH7eswTU@WnA6)GN9;K9rT{8VSb zyWMxV)oa6t-47_T6&)+EzP>)#Y&NM(o<=ZeQKT@)(%RYzm&--Zyntn8WwhIA=aY`Z zo!9H7KC+aSmNKx3i3!OLc`11%hrg<-Du2w*&N8sU!NIWco<4m_fFjvd2AH|ejK#ke zVSa4J)t(xLQ+c%tLWyuBFyW2}|GFO+truZ+Sh29SfDGLwyxMq$n%Wwu8jlSaEgCH- zL1I{M-n`+QTUl9&v9U4IlgBY6v)N32IL}Q^PEu}@?GzRkQrM*MNM(jwS6BBrFn{t~ z$wS!FHa9m37;Oj|kNQ*SB&Y-|l3ith32h>L0UzZq4u=oN9 zg!Xnk`~g4P@U8fuxuk*W%CP~XJVG!C6z8m)H*ZRM$~BbJXz?U?vKIz}LCGUzdGzQJ zbG9gWL}n1Au{ac+316QrJ`AZT-mu7JXYU0h2B-Puca#nY_dd zyK#;!jXfhyTKQK~>}k;jIq|=m`VZ=wu%`5_jgkNW002ovPDHLk FV1j#NvY`L~ diff --git a/magicembed/tests/coverage/errors.html b/magicembed/tests/coverage/errors.html index 171480a..00ffb9e 100644 --- a/magicembed/tests/coverage/errors.html +++ b/magicembed/tests/coverage/errors.html @@ -44,7 +44,7 @@

    -

    Test Coverage Report: error packages and modules

    Generated: Mon 2015-09-07 14:04 CST

    +

    Test Coverage Report: error packages and modules

    Generated: Sat 2015-10-10 18:15 CST

    django_coverage.utils.module_tools.find_or_load_module had problems importing these packages and modules: diff --git a/magicembed/tests/coverage/excludes.html b/magicembed/tests/coverage/excludes.html index 0427d86..8afc944 100644 --- a/magicembed/tests/coverage/excludes.html +++ b/magicembed/tests/coverage/excludes.html @@ -44,7 +44,7 @@

    -

    Test Coverage Report: excluded packages and modules

    Generated: Mon 2015-09-07 14:04 CST

    +

    Test Coverage Report: excluded packages and modules

    Generated: Sat 2015-10-10 18:15 CST

    These packages and modules were excluded from the coverage analysis in django.conf.settings.COVERAGE_MODULE_EXCLUDES or they do diff --git a/magicembed/tests/coverage/index.html b/magicembed/tests/coverage/index.html index 9ba65f8..310d2da 100644 --- a/magicembed/tests/coverage/index.html +++ b/magicembed/tests/coverage/index.html @@ -116,7 +116,7 @@

    Test Coverage Report

    -

    Generated: Mon 2015-09-07 14:04 CST

    +

    Generated: Sat 2015-10-10 18:15 CST

    @@ -139,9 +139,9 @@

    Test Coverage Report

    Total 72 - 57 + 60 10 - 91.9% + 96.8% @@ -156,9 +156,9 @@

    Test Coverage Report

    magicembed.providers 59 - 48 + 51 6 - 90.6% + 96.2% diff --git a/magicembed/tests/coverage/modules/magicembed.__init__.html b/magicembed/tests/coverage/modules/magicembed.__init__.html index dd7286d..5304e8f 100644 --- a/magicembed/tests/coverage/modules/magicembed.__init__.html +++ b/magicembed/tests/coverage/modules/magicembed.__init__.html @@ -129,8 +129,8 @@

    1 total statements, 100.0% covered

    -

    Generated: Mon 2015-09-07 14:04 CST

    -

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/__init__.py

    +

    Generated: Sat 2015-10-10 18:15 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/__init__.py

    Stats: 0 executed, diff --git a/magicembed/tests/coverage/modules/magicembed.providers.html b/magicembed/tests/coverage/modules/magicembed.providers.html index 5a81d30..fa0ab52 100644 --- a/magicembed/tests/coverage/modules/magicembed.providers.html +++ b/magicembed/tests/coverage/modules/magicembed.providers.html @@ -128,14 +128,14 @@

    magicembed.providers: 59 total statements, - 90.6% covered + 96.2% covered

    -

    Generated: Mon 2015-09-07 14:04 CST

    -

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/providers.py

    +

    Generated: Sat 2015-10-10 18:15 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/providers.py

    Stats: - 48 executed, - 5 missed, + 51 executed, + 2 missed, 6 excluded, 31 ignored

    @@ -209,7 +209,7 @@

  • if key is not None:
  • self.api_url = 'http://api.embed.ly/1/oembed?key=%s&url=%s&maxwidth=%s&format=json' % (key, url, size[0])
  • else:
  • -
  • raise ImproperlyConfigured("If you want to use this please set the Embedly api key")
  • +
  • raise ImproperlyConfigured("If you want to use this please set the Embedly api key")
  • def render_video(self):
  • return self._call_api()['html']
  • @@ -220,8 +220,8 @@

  • def _call_api(self):
  • try:
  • data = json.loads(urllib.urlopen(self.api_url).read())
  • -
  • except ImproperlyConfigured:
  • -
  • raise ImproperlyConfigured("Please set the Embedly api key correctly")
  • +
  • except IOError:
  • +
  • raise ImproperlyConfigured("Please set the Embedly api key correctly")
  • return data
  • diff --git a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html index c51e785..074b016 100644 --- a/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html +++ b/magicembed/tests/coverage/modules/magicembed.templatetags.magicembed_tags.html @@ -129,8 +129,8 @@

    12 total statements, 100.0% covered

    -

    Generated: Mon 2015-09-07 14:04 CST

    -

    Source file: /home/jdavila/workspace/django/django-magicembed/magicembed/templatetags/magicembed_tags.py

    +

    Generated: Sat 2015-10-10 18:15 CST

    +

    Source file: /home/jdavila/workspace/django/Proyectos/django-magicembed/magicembed/templatetags/magicembed_tags.py

    Stats: 9 executed, diff --git a/magicembed/tests/test.py b/magicembed/tests/test.py index 25faba4..b0cc314 100644 --- a/magicembed/tests/test.py +++ b/magicembed/tests/test.py @@ -1,14 +1,19 @@ # -*- coding: utf-8 -*- -import unittest - from mock import MagicMock, patch +from django.core.exceptions import ImproperlyConfigured from django.template import Template, Context +from django.test import TestCase + +try: + from django.test import override_settings +except ImportError: + from django.test.utils import override_settings from magicembed.providers import (Youtube, Vimeo, Embedly, get_provider) -class ProvidersTest(unittest.TestCase): +class ProvidersTest(TestCase): def testYoutube(self): video = 'http://www.youtube.com/watch?v=693m7iCh-TE' yt = Youtube(video, (640, 510)) @@ -46,6 +51,18 @@ def testEmbedly(self, urllib_mock): with patch('magicembed.providers.json.loads', api_call_mock): self.assertEqual(blip.render_thumbnail(), thumbnail) + @override_settings(EMBEDLY_KEY=None) + def test_Embedly_without_api_key(self): + with self.assertRaises(ImproperlyConfigured): + Embedly('https://vine.co/v/eHHOtXV5lxT') + + def test_call_Embedly_api_without_key(self): + blip = Embedly('https://vine.co/v/eHHOtXV5lxT', (600, 400)) + + with self.settings(EMBEDLY_KEY=None): + with self.assertRaises(ImproperlyConfigured): + blip.render_thumbnail() + def test_return_provider(self): yt = 'http://www.youtube.com/watch?v=693m7iCh-TE' vimeo = 'http://vimeo.com/21443752' @@ -56,7 +73,7 @@ def test_return_provider(self): self.assertTrue(isinstance(get_provider(blip), Embedly)) -class TemplateTagsTest(unittest.TestCase): +class TemplateTagsTest(TestCase): def test_magicembed_tag(self): TEMPLATE = Template('''{% load magicembed_tags %} {{ 'http://vimeo.com/21443752/'|magicembed:"400x225" }}''') From c707242bc535411fe84232ca765a87ed2ef7fc22 Mon Sep 17 00:00:00 2001 From: Tim Gates Date: Thu, 26 Mar 2020 06:34:54 +1100 Subject: [PATCH 10/10] docs: Fix simple typo, ussage -> usage There is a small typo in magicembed/templatetags/magicembed_tags.py. Should read `usage` rather than `ussage`. --- magicembed/templatetags/magicembed_tags.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/magicembed/templatetags/magicembed_tags.py b/magicembed/templatetags/magicembed_tags.py index 1017bc1..b64ea1a 100644 --- a/magicembed/templatetags/magicembed_tags.py +++ b/magicembed/templatetags/magicembed_tags.py @@ -10,7 +10,7 @@ @register.filter(is_safe=True) def magicembed(value, arg=None): '''value is the url and arg the size tuple - ussage: {% http://myurl.com/|magicembed:"640x480" %}''' + usage: {% http://myurl.com/|magicembed:"640x480" %}''' arg = [int(item) for item in arg.split('x')] provider = get_provider(value, arg) @@ -20,6 +20,6 @@ def magicembed(value, arg=None): @register.filter def magicthumbnail(value): '''value is the url and arg the link_to another url - ussage: {% http://myurl.com/|magicthumbnail: '/some/url' %}''' + usage: {% http://myurl.com/|magicthumbnail: '/some/url' %}''' provider = get_provider(value) return provider.render_thumbnail()