pax_global_header00006660000000000000000000000064134636661770014535gustar00rootroot0000000000000052 comment=18ad9c73066676291e71c59115f62ae8252c4b33 flask-marshmallow-0.10.1/000077500000000000000000000000001346366617700152405ustar00rootroot00000000000000flask-marshmallow-0.10.1/.gitignore000066400000000000000000000006631346366617700172350ustar00rootroot00000000000000*.py[cod] # C extensions *.so # Packages *.egg *.egg-info dist build eggs parts bin var sdist develop-eggs .installed.cfg lib lib64 # Installer logs pip-log.txt # Unit test / coverage reports .cache .coverage .tox nosetests.xml # Translations *.mo # Mr Developer .mr.developer.cfg .project .pydevproject # Complexity output/*.html output/*/index.html # Sphinx docs/_build README.html .konchrc *.ai *.ipynb .ipynb_checkpoints flask-marshmallow-0.10.1/.pre-commit-config.yaml000066400000000000000000000007621346366617700215260ustar00rootroot00000000000000repos: - repo: https://github.com/asottile/pyupgrade rev: v1.16.3 hooks: - id: pyupgrade - repo: https://github.com/ambv/black rev: 19.3b0 hooks: - id: black language_version: python3.6 - repo: https://gitlab.com/pycqa/flake8 rev: 3.7.7 hooks: - id: flake8 additional_dependencies: ['flake8-bugbear==18.8.0; python_version >= "3.5"'] - repo: https://github.com/asottile/blacken-docs rev: v0.5.0 hooks: - id: blacken-docs additional_dependencies: [black==19.3b0] flask-marshmallow-0.10.1/.travis.yml000066400000000000000000000020011346366617700173420ustar00rootroot00000000000000language: python dist: xenial cache: pip install: travis_retry pip install -U tox script: tox jobs: fast_finish: true include: - { python: '3.6', env: TOXENV=lint } - { python: '2.7', env: TOXENV=py27-marshmallow2 } - { python: '3.5', env: TOXENV=py35-marshmallow2 } - { python: '3.5', env: TOXENV=py35-marshmallow3 } - { python: '3.6', env: TOXENV=py36-marshmallow2 } - { python: '3.6', env: TOXENV=py36-marshmallow3 } - { python: '3.7', env: TOXENV=py37-marshmallow2 } - { python: '3.7', env: TOXENV=py37-marshmallow3 } - { python: '3.6', env: TOXENV=docs } - stage: PyPI Release if: tag IS present python: "3.6" env: [] install: skip script: skip deploy: provider: pypi user: sloria on: tags: true distributions: sdist bdist_wheel password: secure: J05JjU6cY5RVHalwpCswhtGocSp3rcdVmUs1Z1FFRqBy18beTziRo1996OrqXqexXdFTQkW+RN2seirJDZhY2eB2WHp+2DN+cx2ynvu/VVGUq1L1WzylImOZptoUo+s5NEkM6R5AjEaJbOiLxMP3iYEiNPlRznw0V9NDOxX/xOg= flask-marshmallow-0.10.1/CHANGELOG.rst000066400000000000000000000077051346366617700172720ustar00rootroot00000000000000Changelog ========= 0.10.1 (2019-05-05) ******************* Bug fixes: * marshmallow 3.0.0rc6 compatibility (:pr:`134`). 0.10.0 (2019-03-09) ******************* Features: * Add `ma.TableSchema` (:pr:`124`). * SQLAlchemy requirements can be installed with ``pip install 'flask-marshmallow[sqlalchemy]'``. Bug fixes: * ``URLFor``, ``AbsoluteURLFor``, and ``HyperlinkRelated`` serialize to ``None`` if a passed attribute value is ``None`` (:issue:`18`, :issue:`68`, :pr:`72`). Thanks :user:`RobinRamuel`, :user:`ocervell`, and :user:`feigner` for reporting. Support: * Test against Python 3.7. * Drop support for Python 3.4. Only Python 2.7 and >=3.5 are supported. 0.9.0 (2018-04-29) ****************** * Add support for marshmallow 3 beta. Thanks :user:`SBillion` for the PR. * Drop support for Python 3.3. Only Python 2.7 and >=3.4 are supported. * Updated documentation to fix example ``ma.URLFor`` target. 0.8.0 (2017-05-28) ****************** * Fix compatibility with marshmallow>=3.0. Support: * *Backwards-incompatible*: Drop support for marshmallow<=2.0.0. * Test against Python 3.6. 0.7.0 (2016-06-28) ****************** * ``many`` argument to ``Schema.jsonify`` defaults to value of the ``Schema`` instance's ``many`` attribute (:issue:`42`). Thanks :user:`singingwolfboy`. * Attach `HyperlinkRelated` to `Marshmallow` instances. Thanks :user:`singingwolfboy` for reporting. Support: * Upgrade to invoke>=0.13.0. * Updated documentation to reference `HyperlinkRelated` instead of `HyperlinkModelSchema`. Thanks :user:`singingwolfboy`. * Updated documentation links to readthedocs.io subdomain. Thanks :user:`adamchainz`. 0.6.2 (2015-09-16) ****************** * Fix compatibility with marshmallow>=2.0.0rc2. Support: * Tested against Python 3.5. 0.6.1 (2015-09-06) ****************** * Fix compatibility with marshmallow-sqlalchemy>=0.4.0 (:issue:`25`). Thanks :user:`svenstaro` for reporting. Support: * Include docs in release tarballs. 0.6.0 (2015-05-02) ****************** Features: - Add Flask-SQLAlchemy/marshmallow-sqlalchemy support via the ``ModelSchema`` and ``HyperlinkModelSchema`` classes. - ``Schema.jsonify`` now takes the same arguments as ``marshmallow.Schema.dump``. Additional keyword arguments are passed to ``flask.jsonify``. - ``Hyperlinks`` field supports serializing a list of hyperlinks (:issue:`11`). Thanks :user:`royrusso` for the suggestion. Deprecation/Removal: - Remove support for ``MARSHMALLOW_DATEFORMAT`` and ``MARSHMALLOW_STRICT`` config options. Other changes: - Drop support for marshmallow<1.2.0. 0.5.1 (2015-04-27) ****************** * Fix compatibility with marshmallow>=2.0.0. 0.5.0 (2015-03-29) ****************** * *Backwards-incompatible*: Remove ``flask_marshmallow.SchemaOpts`` class and remove support for ``MARSHMALLOW_DATEFORMAT`` and ``MARSHMALLOW_STRICT`` (:issue:`8`). Prevents a ``RuntimeError`` when instantiating a ``Schema`` outside of a request context. 0.4.0 (2014-12-22) ****************** * *Backwards-incompatible*: Rename ``URL`` and ``AbsoluteURL`` to ``URLFor`` and ``AbsoluteURLFor``, respectively, to prevent overriding marshmallow's ``URL`` field (:issue:`6`). Thanks :user:`svenstaro` for the suggestion. * Fix bug that raised an error when deserializing ``Hyperlinks`` and ``URL`` fields (:issue:`9`). Thanks :user:`raj-kesavan` for reporting. Deprecation: * ``Schema.jsonify`` is deprecated. Use ``flask.jsonify`` on the result of ``Schema.dump`` instead. * The ``MARSHMALLOW_DATEFORMAT`` and ``MARSHMALLOW_STRICT`` config values are deprecated. Use a base ``Schema`` class instead (:issue:`8`). 0.3.0 (2014-10-19) ****************** * Supports marshmallow >= 1.0.0-a. 0.2.0 (2014-05-12) ****************** * Implementation as a proper class-based Flask extension. * Serializer and fields classes are available from the ``Marshmallow`` object. 0.1.0 (2014-04-25) ****************** * First release. * ``Hyperlinks``, ``URL``, and ``AbsoluteURL`` fields implemented. * ``Serializer#jsonify`` implemented. flask-marshmallow-0.10.1/CONTRIBUTING.rst000066400000000000000000000100101346366617700176710ustar00rootroot00000000000000Contributing Guidelines ======================= Questions, Feature Requests, Bug Reports, and Feedback… ------------------------------------------------------- …should all be reported on the `GitHub Issue Tracker`_ . .. _`GitHub Issue Tracker`: https://github.com/marshmallow-code/flask-marshmallow/issues?state=open Contributing Code ----------------- In General ++++++++++ - `PEP 8`_, when sensible. - Test ruthlessly. Write docs for new features. - Even more important than Test-Driven Development--*Human-Driven Development*. .. _`PEP 8`: http://www.python.org/dev/peps/pep-0008/ In Particular +++++++++++++ Setting Up for Local Development ******************************** 1. Fork flask-marshmallow_ on GitHub. :: $ git clone https://github.com/marshmallow-code/flask-marshmallow.git $ cd flask-marshmallow 2. Install development requirements. **It is highly recommended that you use a virtualenv.** Use the following command to install an editable version of flask-marshmallow along with its development requirements. :: # After activating your virtualenv $ pip install -e '.[dev]' 3. (Optional, but recommended) Install the pre-commit hooks, which will format and lint your git staged files. :: # The pre-commit CLI was installed above $ pre-commit install .. note:: flask-marshmallow uses `black `_ for code formatting, which is only compatible with Python>=3.6. Therefore, the ``pre-commit install`` command will only work if you have the ``python3.6`` interpreter installed. Git Branch Structure ******************** flask-marshmallow abides by the following branching model: ``dev`` Current development branch. **New features should branch off here**. ``X.Y-line`` Maintenance branch for release ``X.Y``. **Bug fixes should be sent to the most recent release branch.**. The maintainer will forward-port the fix to ``dev``. Note: exceptions may be made for bug fixes that introduce large code changes. **Always make a new branch for your work**, no matter how small. Also, **do not put unrelated changes in the same branch or pull request**. This makes it more difficult to merge your changes. Pull Requests ************** 1. Create a new local branch. :: # For a new feature $ git checkout -b name-of-feature dev # For a bugfix $ git checkout -b fix-something 1.2-line 2. Commit your changes. Write `good commit messages `_. :: $ git commit -m "Detailed commit message" $ git push origin name-of-feature 3. Before submitting a pull request, check the following: - If the pull request adds functionality, it is tested and the docs are updated. - You've added yourself to ``AUTHORS.rst``. 4. Submit a pull request to ``marshmallow-code:dev`` or the appropriate maintenance branch. The `Travis CI `_ build must be passing before your pull request is merged. Running Tests ************* To run all tests: :: $ pytest To run syntax checks: :: $ tox -e lint (Optional) To run tests on Python 2.7, 3.5, 3.6, and 3.7 virtual environments (must have each interpreter installed): :: $ tox Documentation ************* Contributions to the documentation are welcome. Documentation is written in `reStructured Text`_ (rST). A quick rST reference can be found `here `_. Builds are powered by Sphinx_. To build the docs in "watch" mode: :: $ tox -e watch-docs Changes in the `docs/` directory will automatically trigger a rebuild. Contributing Examples ********************* Have a usage example you'd like to share? Feel free to add it to the `examples `_ directory and send a pull request. .. _Sphinx: http://sphinx.pocoo.org/ .. _`reStructured Text`: http://docutils.sourceforge.net/rst.html .. _flask-marshmallow: https://github.com/marshmallow-code/flask-marshmallow flask-marshmallow-0.10.1/LICENSE000066400000000000000000000020621346366617700162450ustar00rootroot00000000000000Copyright 2014-2019 Steven Loria and contributors 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 the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. flask-marshmallow-0.10.1/MANIFEST.in000066400000000000000000000001731346366617700167770ustar00rootroot00000000000000include *.rst LICENSE recursive-include docs * recursive-exclude docs *.pyc recursive-exclude docs *.pyo prune docs/_build flask-marshmallow-0.10.1/README.rst000066400000000000000000000071541346366617700167360ustar00rootroot00000000000000***************** Flask-Marshmallow ***************** |pypi-package| |build-status| |docs| |marshmallow23| |black| Flask + marshmallow for beautiful APIs ====================================== Flask-Marshmallow is a thin integration layer for `Flask`_ (a Python web framework) and `marshmallow`_ (an object serialization/deserialization library) that adds additional features to marshmallow, including URL and Hyperlinks fields for HATEOAS-ready APIs. It also (optionally) integrates with `Flask-SQLAlchemy `_. Get it now ---------- :: pip install flask-marshmallow Create your app. .. code-block:: python from flask import Flask, jsonify from flask_marshmallow import Marshmallow app = Flask(__name__) ma = Marshmallow(app) Write your models. .. code-block:: python from your_orm import Model, Column, Integer, String, DateTime class User(Model): email = Column(String) password = Column(String) date_created = Column(DateTime, auto_now_add=True) Define your output format with marshmallow. .. code-block:: python class UserSchema(ma.Schema): class Meta: # Fields to expose fields = ("email", "date_created", "_links") # Smart hyperlinking _links = ma.Hyperlinks( {"self": ma.URLFor("user_detail", id=""), "collection": ma.URLFor("users")} ) user_schema = UserSchema() users_schema = UserSchema(many=True) Output the data in your views. .. code-block:: python @app.route("/api/users/") def users(): all_users = User.all() result = users_schema.dump(all_users) return jsonify(result.data) # OR # return user_schema.jsonify(all_users) @app.route("/api/users/") def user_detail(id): user = User.get(id) return user_schema.jsonify(user) # { # "email": "fred@queen.com", # "date_created": "Fri, 25 Apr 2014 06:02:56 -0000", # "_links": { # "self": "/api/users/42", # "collection": "/api/users/" # } # } http://flask-marshmallow.readthedocs.io/ ======================================== Learn More ========== To learn more about marshmallow, check out its `docs `_. Project Links ============= - Docs: https://flask-marshmallow.readthedocs.io/ - Changelog: http://flask-marshmallow.readthedocs.io/en/latest/changelog.html - PyPI: https://pypi.python.org/pypi/flask-marshmallow - Issues: https://github.com/marshmallow-code/flask-marshmallow/issues License ======= MIT licensed. See the bundled `LICENSE `_ file for more details. .. _Flask: http://flask.pocoo.org .. _marshmallow: http://marshmallow.readthedocs.io .. |pypi-package| image:: https://badgen.net/pypi/v/flask-marshmallow :target: https://pypi.org/project/flask-marshmallow/ :alt: Latest version .. |build-status| image:: https://badgen.net/travis/marshmallow-code/flask-marshmallow/dev :target: https://travis-ci.org/marshmallow-code/flask-marshmallow :alt: Travis-CI .. |docs| image:: https://readthedocs.org/projects/flask-marshmallow/badge/ :target: https://flask-marshmallow.readthedocs.io/ :alt: Documentation .. |marshmallow23| image:: https://badgen.net/badge/marshmallow/2,3?list=1 :target: https://marshmallow.readthedocs.io/en/latest/upgrading.html :alt: marshmallow 3 compatible .. |black| image:: https://badgen.net/badge/code%20style/black/000 :target: https://github.com/ambv/black :alt: code style: black flask-marshmallow-0.10.1/docs/000077500000000000000000000000001346366617700161705ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/Makefile000066400000000000000000000151711346366617700176350ustar00rootroot00000000000000# 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) . # the i18n builder cannot share the environment and doctrees with the others I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest 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 " 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)" 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/complexity.qhcp" @echo "To view the help file:" @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/complexity.qhc" devhelp: $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @echo "To view the help file:" @echo "# mkdir -p $$HOME/.local/share/devhelp/complexity" @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/complexity" @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." 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."flask-marshmallow-0.10.1/docs/_static/000077500000000000000000000000001346366617700176165ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_static/logo.png000066400000000000000000000150711346366617700212700ustar00rootroot00000000000000PNG  IHDRXX)tEXtSoftwareAdobe ImageReadyqe<IDATx읿r-6C?E֩b;&Txt#1[9 d96Ͳ^`)?.ZjH0 ` ߯jLK 0 ChnnnDJZ-eZݶ{:dN=Ӥb1}V_Xp] k!RbMb߽.^S0 $-KEHO3N&LB8iÌ Q$B}{_@pq%4,\JSSQ|)~x3XR%ἑ -ʈ#W,/Xp]ÄPYsދd0}d5@b>HtAOȂ|6` _c:jDlPdr +0(Լ+6O`v{E2 @8"GX*n` \N{SllwÄi{ 3d ?}!l.rHkw,][ o]"Ħz5<^4TנH;hC'HL5|M<.WiI{E4yx/WM Bs3<lV~Ild(!媔+U[}E/E??hb.{41܍DP`hCYh&3 L'< ^㥼/t^E$VsV~6<?E)cA;y +krqUIra <e\x](jW%?V>b^*IR.w:ߟ"0^kZa#yK<~K*K[JSyir)AF䍂YzkE{uÍ]U _Wi XEU9C%f=RKa l28'D@mE'+.p[s!$vCi;q ؒ%X0%%EdP㕳G͡':ߣiP;Fq8/?Sv )@Ħ~4Dof^W]X䱕X|m=IdRUx녅i τ}~ώgرT}u}.^E =Ws =m"XVlZOt{TnVC s/Wτߞ |i8gQ$:lHOc+N뿠z4Scp_]cX ]}5B;zY}D:xH4U KK(̣i?7+0hgTM׀;%jpϖ<\d؅ {2z8F89kkZO]}eNruߘs[ 2JU ,._N Â=Z˒V ͓n,Qmzv;\6)IF ߿ it9AHEsC[5 yLq%V-? Дt懜gx$(i=Rs& ATkb/xVO{WoP"mİ0ˀg9_h!봵Z1b{ J\x"2W% &3kJx.#yl)aIl^ю%^:RetR=߰1}yjyW>N~ckB3,-+6 8[Z7:][Y!-m+[4, <+új4q%' خ%\(m ]D@@Q Õ̃2ѽA~ȓ;˶MOd,*aB$d)xWg5!wHlJo^v^buU;B`^}!rS_޶V@`;E'2vuP1hx&nnnyպb='|@|=4Y,8Վ,qCzyJ} ,Z`ǥ v̵sUGÝ&oZly:9ۉڟ0hx^ThRL]˃;+ŞR'caRBel%"yV&6=oX{,2"GWhy[_ՊLդsc@=LMN5LuP)zҶ=G0&ߎ}Vt /fʬ@*$/\+ ZS4+aN;wZie.>Cd&mH^彆Mt#=6qf쩳& =y5tUwM#+Z7N1un0j,{70=̥^;pHKWyǖ :x st*G;$VUS>j 4ʨkCc2{>g.22XQXi =`*šP6[`m̆ļEͅ}M|#l"A5sMTnpk*|!,)quVO1S[+`>ɝͻ/Hb Ec-h2r`b@7Epzk)VX,,N.tѵ.C2[c[E玴gK4fm^"%el AIG"HO+E]S^?:tX@=Gࡻ JXaŋ^"~%6ֹfacbzK%؋ @EOH7j >lC~H^`e'گ-,%&n_~ZPIENDB`flask-marshmallow-0.10.1/docs/_templates/000077500000000000000000000000001346366617700203255ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_templates/side-primary.html000066400000000000000000000016321346366617700236220ustar00rootroot00000000000000

Flask-Marshmallow Home

Flask + marshmallow for beautiful APIs

Useful Links

Stay Informed

flask-marshmallow-0.10.1/docs/_templates/side-secondary.html000066400000000000000000000013221346366617700241220ustar00rootroot00000000000000

Flask-Marshmallow Home

Flask + marshmallow for beautiful APIs

Useful Links

flask-marshmallow-0.10.1/docs/_themes/000077500000000000000000000000001346366617700176145ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_themes/LICENSE000066400000000000000000000033751346366617700206310ustar00rootroot00000000000000Copyright (c) 2010 by Armin Ronacher. Some rights reserved. Redistribution and use in source and binary forms of the theme, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * The names of the contributors may not be used to endorse or promote products derived from this software without specific prior written permission. We kindly ask you to only use these themes in an unmodified manner just for Flask and Flask-related products, not for unrelated projects. If you like the visual style and want to use it for your own projects, please consider making some larger changes to the themes (such as changing font faces, sizes, colors or margins). THIS THEME IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS THEME, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. flask-marshmallow-0.10.1/docs/_themes/README000066400000000000000000000021051346366617700204720ustar00rootroot00000000000000Flask Sphinx Styles =================== This repository contains sphinx styles for Flask and Flask related projects. To use this style in your Sphinx documentation, follow this guide: 1. put this folder as _themes into your docs folder. Alternatively you can also use git submodules to check out the contents there. 2. add this to your conf.py: sys.path.append(os.path.abspath('_themes')) html_theme_path = ['_themes'] html_theme = 'flask' The following themes exist: - 'flask' - the standard flask documentation theme for large projects - 'flask_small' - small one-page theme. Intended to be used by very small addon libraries for flask. The following options exist for the flask_small theme: [options] index_logo = '' filename of a picture in _static to be used as replacement for the h1 in the index.rst file. index_logo_height = 120px height of the index logo github_fork = '' repository name on github for the "fork me" badge flask-marshmallow-0.10.1/docs/_themes/flask/000077500000000000000000000000001346366617700207145ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_themes/flask/layout.html000066400000000000000000000012651346366617700231230ustar00rootroot00000000000000{%- extends "basic/layout.html" %} {%- block extrahead %} {{ super() }} {% if theme_touch_icon %} {% endif %} {% endblock %} {%- block relbar2 %}{% endblock %} {% block header %} {{ super() }} {% if pagename == 'index' %}
{% endif %} {% endblock %} {%- block footer %} {% if pagename == 'index' %}
{% endif %} {%- endblock %} flask-marshmallow-0.10.1/docs/_themes/flask/relations.html000066400000000000000000000011161346366617700236010ustar00rootroot00000000000000

Related Topics

flask-marshmallow-0.10.1/docs/_themes/flask/static/000077500000000000000000000000001346366617700222035ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_themes/flask/static/flasky.css_t000066400000000000000000000215461346366617700245410ustar00rootroot00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * :copyright: Copyright 2010 by Armin Ronacher. * :license: Flask Design License, see LICENSE for details. */ {% set page_width = '940px' %} {% set sidebar_width = '220px' %} @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; background-color: white; color: #000; margin: 0; padding: 0; } div.document { width: {{ page_width }}; margin: 30px auto 0 auto; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 0 0 0 {{ sidebar_width }}; } div.sphinxsidebar { width: {{ sidebar_width }}; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 0 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { width: {{ page_width }}; margin: 20px auto 30px auto; font-size: 14px; color: #888; text-align: right; } div.footer a { color: #888; } div.related { display: none; } div.sphinxsidebar a { color: #444; text-decoration: none; border-bottom: 1px dotted #999; } div.sphinxsidebar a:hover { border-bottom: 1px solid #999; } div.sphinxsidebar { font-size: 14px; line-height: 1.5; } div.sphinxsidebarwrapper { padding: 18px 10px; } div.sphinxsidebarwrapper p.logo { padding: 0 0 20px 0; margin: 0; text-align: center; } div.sphinxsidebar h3, div.sphinxsidebar h4 { font-family: 'Garamond', 'Georgia', serif; color: #444; font-size: 24px; font-weight: normal; margin: 0 0 5px 0; padding: 0; } div.sphinxsidebar h4 { font-size: 20px; } div.sphinxsidebar h3 a { color: #444; } div.sphinxsidebar p.logo a, div.sphinxsidebar h3 a, div.sphinxsidebar p.logo a:hover, div.sphinxsidebar h3 a:hover { border: none; } div.sphinxsidebar p { color: #555; margin: 10px 0; } div.sphinxsidebar ul { margin: 10px 0; padding: 0; color: #000; } div.sphinxsidebar input { border: 1px solid #ccc; font-family: 'Georgia', serif; font-size: 1em; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } {% if theme_index_logo %} div.indexwrapper h1 { text-indent: -999999px; background: url({{ theme_index_logo }}) no-repeat center center; height: {{ theme_index_logo_height }}; } {% endif %} div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: #ddd; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition tt.xref, div.admonition a tt { border-bottom: 1px solid #fafafa; } dd div.admonition { margin-left: -60px; padding-left: 60px; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight { background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.9em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; background: #fdfdfd; font-size: 0.9em; } table.footnote + table.footnote { margin-top: -15px; border-top: none; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td.label { width: 0px; padding: 0.3em 0 0.3em 0.5em; } table.footnote td { padding: 0.3em 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } blockquote { margin: 0 0 0 30px; padding: 0; } ul, ol { margin: 10px 0 10px 30px; padding: 0; } pre { background: #eee; padding: 7px 30px; margin: 15px -30px; line-height: 1.3em; } dl pre, blockquote pre, li pre { margin-left: -60px; padding-left: 60px; } dl dl pre { margin-left: -90px; padding-left: 90px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; border-bottom: 1px solid white; } a.reference { text-decoration: none; border-bottom: 1px dotted #004B6B; } a.reference:hover { border-bottom: 1px solid #6D4100; } a.footnote-reference { text-decoration: none; font-size: 0.7em; vertical-align: top; border-bottom: 1px dotted #004B6B; } a.footnote-reference:hover { border-bottom: 1px solid #6D4100; } a:hover tt { background: #EEE; } @media screen and (max-width: 870px) { div.sphinxsidebar { display: none; } div.document { width: 100%; } div.documentwrapper { margin-left: 0; margin-top: 0; margin-right: 0; margin-bottom: 0; } div.bodywrapper { margin-top: 0; margin-right: 0; margin-bottom: 0; margin-left: 0; } ul { margin-left: 0; } .document { width: auto; } .footer { width: auto; } .bodywrapper { margin: 0; } .footer { width: auto; } .github { display: none; } } @media screen and (max-width: 875px) { body { margin: 0; padding: 20px 30px; } div.documentwrapper { float: none; background: white; } div.sphinxsidebar { display: block; float: none; width: 102.5%; margin: 50px -30px -20px -30px; padding: 10px 20px; background: #333; color: white; } div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, div.sphinxsidebar h3 a { color: white; } div.sphinxsidebar a { color: #aaa; } div.sphinxsidebar p.logo { display: none; } div.document { width: 100%; margin: 0; } div.related { display: block; margin: 0; padding: 10px 0 20px 0; } div.related ul, div.related ul li { margin: 0; padding: 0; } div.footer { display: none; } div.bodywrapper { margin: 0; } div.body { min-height: 0; padding: 0; } .rtd_doc_footer { display: none; } .document { width: auto; } .footer { width: auto; } .footer { width: auto; } .github { display: none; } } /* scrollbars */ ::-webkit-scrollbar { width: 6px; height: 6px; } ::-webkit-scrollbar-button:start:decrement, ::-webkit-scrollbar-button:end:increment { display: block; height: 10px; } ::-webkit-scrollbar-button:vertical:increment { background-color: #fff; } ::-webkit-scrollbar-track-piece { background-color: #eee; -webkit-border-radius: 3px; } ::-webkit-scrollbar-thumb:vertical { height: 50px; background-color: #ccc; -webkit-border-radius: 3px; } ::-webkit-scrollbar-thumb:horizontal { width: 50px; background-color: #ccc; -webkit-border-radius: 3px; } /* misc. */ .revsys-inline { display: none!important; }flask-marshmallow-0.10.1/docs/_themes/flask/theme.conf000066400000000000000000000002441346366617700226650ustar00rootroot00000000000000[theme] inherit = basic stylesheet = flasky.css pygments_style = flask_theme_support.FlaskyStyle [options] index_logo = '' index_logo_height = 120px touch_icon = flask-marshmallow-0.10.1/docs/_themes/flask_small/000077500000000000000000000000001346366617700221045ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_themes/flask_small/layout.html000066400000000000000000000012661346366617700243140ustar00rootroot00000000000000{% extends "basic/layout.html" %} {% block header %} {{ super() }} {% if pagename == 'index' %}
{% endif %} {% endblock %} {% block footer %} {% if pagename == 'index' %}
{% endif %} {% endblock %} {# do not display relbars #} {% block relbar1 %}{% endblock %} {% block relbar2 %} {% if theme_github_fork %} Fork me on GitHub {% endif %} {% endblock %} {% block sidebar1 %}{% endblock %} {% block sidebar2 %}{% endblock %} flask-marshmallow-0.10.1/docs/_themes/flask_small/static/000077500000000000000000000000001346366617700233735ustar00rootroot00000000000000flask-marshmallow-0.10.1/docs/_themes/flask_small/static/flasky.css_t000066400000000000000000000111761346366617700257270ustar00rootroot00000000000000/* * flasky.css_t * ~~~~~~~~~~~~ * * Sphinx stylesheet -- flasky theme based on nature theme. * * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ @import url("basic.css"); /* -- page layout ----------------------------------------------------------- */ body { font-family: 'Georgia', serif; font-size: 17px; color: #000; background: white; margin: 0; padding: 0; } div.documentwrapper { float: left; width: 100%; } div.bodywrapper { margin: 40px auto 0 auto; width: 700px; } hr { border: 1px solid #B1B4B6; } div.body { background-color: #ffffff; color: #3E4349; padding: 0 30px 30px 30px; } img.floatingflask { padding: 0 0 10px 10px; float: right; } div.footer { text-align: right; color: #888; padding: 10px; font-size: 14px; width: 650px; margin: 0 auto 40px auto; } div.footer a { color: #888; text-decoration: underline; } div.related { line-height: 32px; color: #888; } div.related ul { padding: 0 0 0 10px; } div.related a { color: #444; } /* -- body styles ----------------------------------------------------------- */ a { color: #004B6B; text-decoration: underline; } a:hover { color: #6D4100; text-decoration: underline; } div.body { padding-bottom: 40px; /* saved for footer */ } div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; margin: 30px 0px 10px 0px; padding: 0; } {% if theme_index_logo %} div.indexwrapper h1 { text-indent: -999999px; background: url({{ theme_index_logo }}) no-repeat center center; height: {{ theme_index_logo_height }}; } {% endif %} div.body h2 { font-size: 180%; } div.body h3 { font-size: 150%; } div.body h4 { font-size: 130%; } div.body h5 { font-size: 100%; } div.body h6 { font-size: 100%; } a.headerlink { color: white; padding: 0 4px; text-decoration: none; } a.headerlink:hover { color: #444; background: #eaeaea; } div.body p, div.body dd, div.body li { line-height: 1.4em; } div.admonition { background: #fafafa; margin: 20px -30px; padding: 10px 30px; border-top: 1px solid #ccc; border-bottom: 1px solid #ccc; } div.admonition p.admonition-title { font-family: 'Garamond', 'Georgia', serif; font-weight: normal; font-size: 24px; margin: 0 0 10px 0; padding: 0; line-height: 1; } div.admonition p.last { margin-bottom: 0; } div.highlight{ background-color: white; } dt:target, .highlight { background: #FAF3E8; } div.note { background-color: #eee; border: 1px solid #ccc; } div.seealso { background-color: #ffc; border: 1px solid #ff6; } div.topic { background-color: #eee; } div.warning { background-color: #ffe4e4; border: 1px solid #f66; } p.admonition-title { display: inline; } p.admonition-title:after { content: ":"; } pre, tt { font-family: 'Consolas', 'Menlo', 'Deja Vu Sans Mono', 'Bitstream Vera Sans Mono', monospace; font-size: 0.85em; } img.screenshot { } tt.descname, tt.descclassname { font-size: 0.95em; } tt.descname { padding-right: 0.08em; } img.screenshot { -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils { border: 1px solid #888; -moz-box-shadow: 2px 2px 4px #eee; -webkit-box-shadow: 2px 2px 4px #eee; box-shadow: 2px 2px 4px #eee; } table.docutils td, table.docutils th { border: 1px solid #888; padding: 0.25em 0.7em; } table.field-list, table.footnote { border: none; -moz-box-shadow: none; -webkit-box-shadow: none; box-shadow: none; } table.footnote { margin: 15px 0; width: 100%; border: 1px solid #eee; } table.field-list th { padding: 0 0.8em 0 0; } table.field-list td { padding: 0; } table.footnote td { padding: 0.5em; } dl { margin: 0; padding: 0; } dl dd { margin-left: 30px; } pre { padding: 0; margin: 15px -30px; padding: 8px; line-height: 1.3em; padding: 7px 30px; background: #eee; border-radius: 2px; -moz-border-radius: 2px; -webkit-border-radius: 2px; } dl pre { margin-left: -60px; padding-left: 60px; } tt { background-color: #ecf0f3; color: #222; /* padding: 1px 2px; */ } tt.xref, a tt { background-color: #FBFBFB; } a:hover tt { background: #EEE; } /* mods by sloria */ /* hack to make header links consistently styled */ .reference.internal em { font-style: normal; } flask-marshmallow-0.10.1/docs/_themes/flask_small/theme.conf000066400000000000000000000002571346366617700240610ustar00rootroot00000000000000[theme] inherit = basic stylesheet = flasky.css nosidebar = true pygments_style = flask_theme_support.FlaskyStyle [options] index_logo = 'logo.png' index_logo_height = 120px flask-marshmallow-0.10.1/docs/_themes/flask_theme_support.py000066400000000000000000000075011346366617700242470ustar00rootroot00000000000000# flasky extensions. flasky pygments style based on tango style from pygments.style import Style from pygments.token import ( Keyword, Name, Comment, String, Error, Number, Operator, Generic, Whitespace, Punctuation, Other, Literal, ) class FlaskyStyle(Style): background_color = "#f8f8f8" default_style = "" styles = { # No corresponding class for the following: # Text: "", # class: '' Whitespace: "underline #f8f8f8", # class: 'w' Error: "#a40000 border:#ef2929", # class: 'err' Other: "#000000", # class 'x' Comment: "italic #8f5902", # class: 'c' Comment.Preproc: "noitalic", # class: 'cp' Keyword: "bold #004461", # class: 'k' Keyword.Constant: "bold #004461", # class: 'kc' Keyword.Declaration: "bold #004461", # class: 'kd' Keyword.Namespace: "bold #004461", # class: 'kn' Keyword.Pseudo: "bold #004461", # class: 'kp' Keyword.Reserved: "bold #004461", # class: 'kr' Keyword.Type: "bold #004461", # class: 'kt' Operator: "#582800", # class: 'o' Operator.Word: "bold #004461", # class: 'ow' - like keywords Punctuation: "bold #000000", # class: 'p' # because special names such as Name.Class, Name.Function, etc. # are not recognized as such later in the parsing, we choose them # to look the same as ordinary variables. Name: "#000000", # class: 'n' Name.Attribute: "#c4a000", # class: 'na' - to be revised Name.Builtin: "#004461", # class: 'nb' Name.Builtin.Pseudo: "#3465a4", # class: 'bp' Name.Class: "#000000", # class: 'nc' - to be revised Name.Constant: "#000000", # class: 'no' - to be revised Name.Decorator: "#888", # class: 'nd' - to be revised Name.Entity: "#ce5c00", # class: 'ni' Name.Exception: "bold #cc0000", # class: 'ne' Name.Function: "#000000", # class: 'nf' Name.Property: "#000000", # class: 'py' Name.Label: "#f57900", # class: 'nl' Name.Namespace: "#000000", # class: 'nn' - to be revised Name.Other: "#000000", # class: 'nx' Name.Tag: "bold #004461", # class: 'nt' - like a keyword Name.Variable: "#000000", # class: 'nv' - to be revised Name.Variable.Class: "#000000", # class: 'vc' - to be revised Name.Variable.Global: "#000000", # class: 'vg' - to be revised Name.Variable.Instance: "#000000", # class: 'vi' - to be revised Number: "#990000", # class: 'm' Literal: "#000000", # class: 'l' Literal.Date: "#000000", # class: 'ld' String: "#4e9a06", # class: 's' String.Backtick: "#4e9a06", # class: 'sb' String.Char: "#4e9a06", # class: 'sc' String.Doc: "italic #8f5902", # class: 'sd' - like a comment String.Double: "#4e9a06", # class: 's2' String.Escape: "#4e9a06", # class: 'se' String.Heredoc: "#4e9a06", # class: 'sh' String.Interpol: "#4e9a06", # class: 'si' String.Other: "#4e9a06", # class: 'sx' String.Regex: "#4e9a06", # class: 'sr' String.Single: "#4e9a06", # class: 's1' String.Symbol: "#4e9a06", # class: 'ss' Generic: "#000000", # class: 'g' Generic.Deleted: "#a40000", # class: 'gd' Generic.Emph: "italic #000000", # class: 'ge' Generic.Error: "#ef2929", # class: 'gr' Generic.Heading: "bold #000080", # class: 'gh' Generic.Inserted: "#00A000", # class: 'gi' Generic.Output: "#888", # class: 'go' Generic.Prompt: "#745334", # class: 'gp' Generic.Strong: "bold #000000", # class: 'gs' Generic.Subheading: "bold #800080", # class: 'gu' Generic.Traceback: "bold #a40000", # class: 'gt' } flask-marshmallow-0.10.1/docs/changelog.rst000066400000000000000000000000561346366617700206520ustar00rootroot00000000000000.. _changelog: .. include:: ../CHANGELOG.rst flask-marshmallow-0.10.1/docs/conf.py000077500000000000000000000032561346366617700175000ustar00rootroot00000000000000# -*- coding: utf-8 -*- import datetime as dt import sys import os sys.path.insert(0, os.path.abspath(os.path.join("..", "src"))) import flask_marshmallow # noqa: E402 sys.path.append(os.path.abspath("_themes")) extensions = ["sphinx.ext.autodoc", "sphinx.ext.intersphinx", "sphinx_issues"] intersphinx_mapping = { "python": ("http://python.readthedocs.io/en/latest/", None), "flask": ("http://flask.pocoo.org/docs/latest/", None), "flask-sqlalchemy": ("http://flask-sqlalchemy.pocoo.org/latest/", None), "marshmallow": ("http://marshmallow.readthedocs.io/en/latest/", None), "marshmallow-sqlalchemy": ( "http://marshmallow-sqlalchemy.readthedocs.io/en/latest/", None, ), } primary_domain = "py" default_role = "py:obj" issues_github_path = "marshmallow-code/flask-marshmallow" # Add any paths that contain templates here, relative to this directory. templates_path = ["_templates"] # The suffix of source filenames. source_suffix = ".rst" # The master toctree document. master_doc = "index" # General information about the project. project = u"Flask-Marshmallow" copyright = u"2014-{:%Y}".format( dt.datetime.utcfromtimestamp(os.path.getmtime("../CHANGELOG.rst")) ) version = release = flask_marshmallow.__version__ exclude_patterns = ["_build"] # The name of the Pygments (syntax highlighting) style to use. pygments_style = "flask_theme_support.FlaskyStyle" html_theme = "flask_small" html_theme_path = ["_themes"] html_static_path = ["_static"] html_sidebars = { "index": ["side-primary.html", "searchbox.html"], "**": ["side-secondary.html", "localtoc.html", "relations.html", "searchbox.html"], } htmlhelp_basename = "flask-marshmallowdoc" flask-marshmallow-0.10.1/docs/index.rst000066400000000000000000000166421346366617700200420ustar00rootroot00000000000000********************************************************* Flask-Marshmallow: Flask + marshmallow for beautiful APIs ********************************************************* :ref:`changelog ` // `github `_ // `pypi `_ // `issues `_ Flask + marshmallow for beautiful APIs ====================================== Flask-Marshmallow is a thin integration layer for `Flask`_ (a Python web framework) and `marshmallow`_ (an object serialization/deserialization library) that adds additional features to marshmallow, including URL and Hyperlinks fields for HATEOAS-ready APIs. It also (optionally) integrates with `Flask-SQLAlchemy `_. Get it now ---------- :: pip install flask-marshmallow Create your app. .. code-block:: python from flask import Flask, jsonify from flask_marshmallow import Marshmallow app = Flask(__name__) ma = Marshmallow(app) Write your models. .. code-block:: python from your_orm import Model, Column, Integer, String, DateTime class User(Model): email = Column(String) password = Column(String) date_created = Column(DateTime, auto_now_add=True) Define your output format with marshmallow. .. code-block:: python class UserSchema(ma.Schema): class Meta: # Fields to expose fields = ("email", "date_created", "_links") # Smart hyperlinking _links = ma.Hyperlinks( {"self": ma.URLFor("user_detail", id=""), "collection": ma.URLFor("users")} ) user_schema = UserSchema() users_schema = UserSchema(many=True) Output the data in your views. .. code-block:: python @app.route("/api/users/") def users(): all_users = User.all() result = users_schema.dump(all_users) return jsonify(result.data) # OR # return users_schema.jsonify(all_users) @app.route("/api/users/") def user_detail(id): user = User.get(id) return user_schema.jsonify(user) # { # "email": "fred@queen.com", # "date_created": "Fri, 25 Apr 2014 06:02:56 -0000", # "_links": { # "self": "/api/users/42", # "collection": "/api/users/" # } # } Optional Flask-SQLAlchemy Integration ------------------------------------- Flask-Marshmallow includes useful extras for integrating with `Flask-SQLAlchemy `_ and `marshmallow-sqlalchemy `_. To enable SQLAlchemy integration, make sure that both Flask-SQLAlchemy and marshmallow-sqlalchemy are installed. :: pip install -U flask-sqlalchemy marshmallow-sqlalchemy Next, initialize the `~flask_sqlalchemy.SQLAlchemy` and `~flask_marshmallow.Marshmallow` extensions, in that order. .. code-block:: python from flask import Flask from flask_sqlalchemy import SQLAlchemy from flask_marshmallow import Marshmallow app = Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:////tmp/test.db" # Order matters: Initialize SQLAlchemy before Marshmallow db = SQLAlchemy(app) ma = Marshmallow(app) .. admonition:: Note on initialization order Flask-SQLAlchemy **must** be initialized before Flask-Marshmallow. Declare your models like normal. .. code-block:: python class Author(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) class Book(db.Model): id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(255)) author_id = db.Column(db.Integer, db.ForeignKey("author.id")) author = db.relationship("Author", backref="books") Generate marshmallow `Schemas ` from your models using `~flask_marshmallow.sqla.ModelSchema` or `~flask_marshmallow.sqla.TableSchema`. .. code-block:: python class AuthorSchema(ma.ModelSchema): class Meta: model = Author class BookSchema(ma.TableSchema): class Meta: table = Book.__table__ You can now use your schema to dump and load your ORM objects. .. code-block:: python db.create_all() author_schema = AuthorSchema() book_schema = BookSchema() author = Author(name="Chuck Paluhniuk") book = Book(title="Fight Club", author=author) db.session.add(author) db.session.add(book) db.session.commit() author_schema.dump(author).data # {'id': 1, 'name': 'Chuck Paluhniuk', 'books': [1]} `~flask_marshmallow.sqla.ModelSchema` is nearly identical in API to `marshmallow_sqlalchemy.ModelSchema` with the following exceptions: - By default, `~flask_marshmallow.sqla.ModelSchema` uses the scoped session created by Flask-SQLAlchemy. - `~flask_marshmallow.sqla.ModelSchema` subclasses `flask_marshmallow.Schema`, so it includes the `~flask_marshmallow.Schema.jsonify` method. Note: By default, Flask's `jsonify` method sorts the list of keys and returns consistent results to ensure that external HTTP caches aren't trashed. As a side effect, this will override `ordered=True `_ in the ModelSchema's `class Meta` (if you set it). To disable this, set `JSON_SORT_KEYS=False` in your Flask app config. In production it's recommended to let `jsonify` sort the keys and not set `ordered=True` in your `~flask_marshmallow.sqla.ModelSchema` in order to minimize generation time and maximize cachability of the results. You can also use `ma.HyperlinkRelated ` fields if you want relationships to be represented by hyperlinks rather than primary keys. .. code-block:: python class BookSchema(ma.ModelSchema): class Meta: model = Book author = ma.HyperlinkRelated("author_detail") .. code-block:: python with app.test_request_context(): print(book_schema.dump(book).data) # {'id': 1, 'title': 'Fight Club', 'author': '/authors/1'} The first argument to the `~flask_marshmallow.sqla.HyperlinkRelated` constructor is the name of the view used to generate the URL, just as you would pass it to the `~flask.url_for` function. If your models and views use the ``id`` attribute as a primary key, you're done; otherwise, you must specify the name of the attribute used as the primary key. To represent a one-to-many relationship, wrap the `~flask_marshmallow.sqla.HyperlinkRelated` instance in a `marshmallow.fields.List` field, like this: .. code-block:: python class AuthorSchema(ma.ModelSchema): class Meta: model = Author books = ma.List(ma.HyperlinkRelated("book_detail")) .. code-block:: python with app.test_request_context(): print(author_schema.dump(author).data) # {'id': 1, 'name': 'Chuck Paluhniuk', 'books': ['/books/1']} API === .. automodule:: flask_marshmallow :members: .. automodule:: flask_marshmallow.fields :members: .. automodule:: flask_marshmallow.sqla :members: Useful Links ============ - `Flask docs`_ - `marshmallow docs`_ .. _marshmallow docs: http://marshmallow.readthedocs.io .. _Flask docs: http://flask.pocoo.org/docs/ Project Info ============ .. toctree:: :maxdepth: 1 license changelog .. _marshmallow: http://marshmallow.readthedocs.io .. _Flask: http://flask.pocoo.org flask-marshmallow-0.10.1/docs/license.rst000066400000000000000000000000701346366617700203410ustar00rootroot00000000000000******* License ******* .. literalinclude:: ../LICENSE flask-marshmallow-0.10.1/docs/make.bat000066400000000000000000000145021346366617700175770ustar00rootroot00000000000000@ECHO OFF REM Command file for Sphinx documentation if "%SPHINXBUILD%" == "" ( set SPHINXBUILD=sphinx-build ) set BUILDDIR=_build set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . set I18NSPHINXOPTS=%SPHINXOPTS% . 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 goto end ) if "%1" == "clean" ( for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i del /q /s %BUILDDIR%\* goto end ) %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 ) 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\complexity.qhcp echo.To view the help file: echo.^> assistant -collectionFile %BUILDDIR%\qthelp\complexity.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 %BUILDDIR%/.. 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 %BUILDDIR%/.. 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" == "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 ) :endflask-marshmallow-0.10.1/docs/requirements.txt000066400000000000000000000000541346366617700214530ustar00rootroot00000000000000marshmallow_sqlalchemy sphinx sphinx-issues flask-marshmallow-0.10.1/setup.cfg000066400000000000000000000002111346366617700170530ustar00rootroot00000000000000[bdist_wheel] universal = 1 [flake8] ignore = E203, E266, E501, W503 max-line-length = 110 max-complexity = 18 select = B,C,E,F,W,T4,B9 flask-marshmallow-0.10.1/setup.py000066400000000000000000000046341346366617700167610ustar00rootroot00000000000000# -*- coding: utf-8 -*- import re from setuptools import setup, find_packages EXTRAS_REQUIRE = { "sqlalchemy": ["flask-sqlalchemy", "marshmallow-sqlalchemy>=0.13.0"], "lint": [ "flake8==3.7.7", 'flake8-bugbear==19.3.0; python_version >= "3.5"', "pre-commit==1.16.0", ], } EXTRAS_REQUIRE["tests"] = EXTRAS_REQUIRE["sqlalchemy"] + ["pytest", "mock"] EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["lint"] + ["tox"] REQUIRES = ["Flask", "marshmallow>=2.0.0", "six>=1.9.0"] def find_version(fname): """Attempts to find the version number in the file names fname. Raises RuntimeError if not found. """ version = "" with open(fname, "r") as fp: reg = re.compile(r'__version__ = [\'"]([^\'"]*)[\'"]') for line in fp: m = reg.match(line) if m: version = m.group(1) break if not version: raise RuntimeError("Cannot find version information") return version def read(fname): with open(fname) as fp: content = fp.read() return content setup( name="flask-marshmallow", version=find_version("src/flask_marshmallow/__init__.py"), description="Flask + marshmallow for beautiful APIs", long_description=read("README.rst"), author="Steven Loria", author_email="sloria1@gmail.com", url="https://github.com/marshmallow-code/flask-marshmallow", packages=find_packages("src"), package_dir={"": "src"}, include_package_data=True, install_requires=REQUIRES, extras_require=EXTRAS_REQUIRE, license="MIT", zip_safe=False, keywords="flask-marshmallow", classifiers=[ "Development Status :: 4 - Beta", "Environment :: Web Environment", "Intended Audience :: Developers", "License :: OSI Approved :: MIT License", "Natural Language :: English", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Topic :: Internet :: WWW/HTTP :: Dynamic Content", ], test_suite="tests", project_urls={ "Issues": "https://github.com/marshmallow-code/flask-marshmallow/issues", "Funding": "https://opencollective.com/marshmallow", }, ) flask-marshmallow-0.10.1/src/000077500000000000000000000000001346366617700160275ustar00rootroot00000000000000flask-marshmallow-0.10.1/src/flask_marshmallow/000077500000000000000000000000001346366617700215355ustar00rootroot00000000000000flask-marshmallow-0.10.1/src/flask_marshmallow/__init__.py000077500000000000000000000065501346366617700236570ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ flask_marshmallow ~~~~~~~~~~~~~~~~~ Integrates the marshmallow serialization/deserialization library with your Flask application. """ import warnings from distutils.version import LooseVersion from marshmallow import fields as base_fields, exceptions, pprint from . import fields from .schema import Schema has_sqla = False try: import flask_sqlalchemy # noqa: F401 except ImportError: has_sqla = False else: try: from . import sqla except ImportError: warnings.warn( "Flask-SQLAlchemy integration requires " "marshmallow-sqlalchemy to be installed." ) else: has_sqla = True __version__ = "0.10.1" __version_info__ = tuple(LooseVersion(__version__).version) __all__ = ["EXTENSION_NAME", "Marshmallow", "Schema", "fields", "exceptions", "pprint"] EXTENSION_NAME = "flask-marshmallow" def _attach_fields(obj): """Attach all the marshmallow fields classes to ``obj``, including Flask-Marshmallow's custom fields. """ for attr in base_fields.__all__: if not hasattr(obj, attr): setattr(obj, attr, getattr(base_fields, attr)) for attr in fields.__all__: setattr(obj, attr, getattr(fields, attr)) class Marshmallow(object): """Wrapper class that integrates Marshmallow with a Flask application. To use it, instantiate with an application:: from flask import Flask app = Flask(__name__) ma = Marshmallow(app) The object provides access to the :class:`Schema` class, all fields in :mod:`marshmallow.fields`, as well as the Flask-specific fields in :mod:`flask_marshmallow.fields`. You can declare schema like so:: class BookSchema(ma.Schema): class Meta: fields = ('id', 'title', 'author', 'links') author = ma.Nested(AuthorSchema) links = ma.Hyperlinks({ 'self': ma.URLFor('book_detail', id=''), 'collection': ma.URLFor('book_list') }) In order to integrate with Flask-SQLAlchemy, this extension must be initialized *after* `flask_sqlalchemy.SQLAlchemy`. :: db = SQLAlchemy(app) ma = Marshmallow(app) This gives you access to `ma.ModelSchema` and `ma.TableSchema`, which generate marshmallow `~marshmallow.Schema` classes based on the passed in model or table. :: class AuthorSchema(ma.ModelSchema): class Meta: model = Author :param Flask app: The Flask application object. """ def __init__(self, app=None): self.Schema = Schema if has_sqla: self.ModelSchema = sqla.ModelSchema self.TableSchema = sqla.TableSchema self.HyperlinkRelated = sqla.HyperlinkRelated _attach_fields(self) if app is not None: self.init_app(app) def init_app(self, app): """Initializes the application with the extension. :param Flask app: The Flask application object. """ app.extensions = getattr(app, "extensions", {}) # If using Flask-SQLAlchemy, attach db.session to ModelSchema if has_sqla and "sqlalchemy" in app.extensions: db = app.extensions["sqlalchemy"].db self.ModelSchema.OPTIONS_CLASS.session = db.session app.extensions[EXTENSION_NAME] = self flask-marshmallow-0.10.1/src/flask_marshmallow/compat.py000066400000000000000000000003261346366617700233730ustar00rootroot00000000000000"""Compatibility module. This module should be considered private API. """ import marshmallow _MARSHMALLOW_VERSION_INFO = tuple( [int(part) for part in marshmallow.__version__.split(".") if part.isdigit()] ) flask-marshmallow-0.10.1/src/flask_marshmallow/fields.py000077500000000000000000000121541346366617700233630ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ flask_marshmallow.fields ~~~~~~~~~~~~~~~~~~~~~~~~ Custom, Flask-specific fields. See the `marshmallow.fields` module for the list of all fields available from the marshmallow library. """ import re from flask import url_for from marshmallow import fields from marshmallow import missing __all__ = ["URLFor", "UrlFor", "AbsoluteURLFor", "AbsoluteUrlFor", "Hyperlinks"] _tpl_pattern = re.compile(r"\s*<\s*(\S*)\s*>\s*") def _tpl(val): """Return value within ``< >`` if possible, else return ``None``.""" match = _tpl_pattern.match(val) if match: return match.groups()[0] return None def _get_value(obj, key, default=missing): """Slightly-modified version of marshmallow.utils.get_value. If a dot-delimited ``key`` is passed and any attribute in the path is `None`, return `None`. """ if "." in key: return _get_value_for_keys(obj, key.split("."), default) else: return _get_value_for_key(obj, key, default) def _get_value_for_keys(obj, keys, default): if len(keys) == 1: return _get_value_for_key(obj, keys[0], default) else: value = _get_value_for_key(obj, keys[0], default) # XXX This differs from the marshmallow implementation if value is None: return None return _get_value_for_keys(value, keys[1:], default) def _get_value_for_key(obj, key, default): if not hasattr(obj, "__getitem__"): return getattr(obj, key, default) try: return obj[key] except (KeyError, IndexError, TypeError, AttributeError): return getattr(obj, key, default) class URLFor(fields.Field): """Field that outputs the URL for an endpoint. Acts identically to Flask's ``url_for`` function, except that arguments can be pulled from the object to be serialized. Usage: :: url = URLFor('author_get', id='') https_url = URLFor('author_get', id='', _scheme='https', _external=True) :param str endpoint: Flask endpoint name. :param kwargs: Same keyword arguments as Flask's url_for, except string arguments enclosed in `< >` will be interpreted as attributes to pull from the object. """ _CHECK_ATTRIBUTE = False def __init__(self, endpoint, **kwargs): self.endpoint = endpoint self.params = kwargs fields.Field.__init__(self, **kwargs) def _serialize(self, value, key, obj): """Output the URL for the endpoint, given the kwargs passed to ``__init__``. """ param_values = {} for name, attr_tpl in self.params.items(): attr_name = _tpl(str(attr_tpl)) if attr_name: attribute_value = _get_value(obj, attr_name, default=missing) if attribute_value is None: return None if attribute_value is not missing: param_values[name] = attribute_value else: raise AttributeError( "{attr_name!r} is not a valid " "attribute of {obj!r}".format(attr_name=attr_name, obj=obj) ) else: param_values[name] = attr_tpl return url_for(self.endpoint, **param_values) UrlFor = URLFor class AbsoluteURLFor(URLFor): """Field that outputs the absolute URL for an endpoint.""" def __init__(self, endpoint, **kwargs): kwargs["_external"] = True URLFor.__init__(self, endpoint=endpoint, **kwargs) AbsoluteUrlFor = AbsoluteURLFor def _rapply(d, func, *args, **kwargs): """Apply a function to all values in a dictionary or list of dictionaries, recursively.""" if isinstance(d, (tuple, list)): return [_rapply(each, func, *args, **kwargs) for each in d] if isinstance(d, dict): return {key: _rapply(value, func, *args, **kwargs) for key, value in d.items()} else: return func(d, *args, **kwargs) def _url_val(val, key, obj, **kwargs): """Function applied by `HyperlinksField` to get the correct value in the schema. """ if isinstance(val, URLFor): return val.serialize(key, obj, **kwargs) else: return val class Hyperlinks(fields.Field): """Field that outputs a dictionary of hyperlinks, given a dictionary schema with :class:`~flask_marshmallow.fields.URLFor` objects as values. Example: :: _links = Hyperlinks({ 'self': URLFor('author', id=''), 'collection': URLFor('author_list'), }) `URLFor` objects can be nested within the dictionary. :: _links = Hyperlinks({ 'self': { 'href': URLFor('book', id=''), 'title': 'book detail' } }) :param dict schema: A dict that maps names to :class:`~flask_marshmallow.fields.URLFor` fields. """ _CHECK_ATTRIBUTE = False def __init__(self, schema, **kwargs): self.schema = schema fields.Field.__init__(self, **kwargs) def _serialize(self, value, attr, obj): return _rapply(self.schema, _url_val, key=attr, obj=obj) flask-marshmallow-0.10.1/src/flask_marshmallow/schema.py000066400000000000000000000027321346366617700233530ustar00rootroot00000000000000# -*- coding: utf-8 -*- import flask import marshmallow as ma from flask_marshmallow.compat import _MARSHMALLOW_VERSION_INFO sentinel = object() class Schema(ma.Schema): """Base serializer with which to define custom serializers. See `marshmallow.Schema` for more details about the `Schema` API. """ def jsonify(self, obj, many=sentinel, *args, **kwargs): """Return a JSON response containing the serialized data. :param obj: Object to serialize. :param bool many: Whether `obj` should be serialized as an instance or as a collection. If unset, defaults to the value of the `many` attribute on this Schema. :param kwargs: Additional keyword arguments passed to `flask.jsonify`. .. versionchanged:: 0.6.0 Takes the same arguments as `marshmallow.Schema.dump`. Additional keyword arguments are passed to `flask.jsonify`. .. versionchanged:: 0.6.3 The `many` argument for this method defaults to the value of the `many` attribute on the Schema. Previously, the `many` argument of this method defaulted to False, regardless of the value of `Schema.many`. """ if many is sentinel: many = self.many if _MARSHMALLOW_VERSION_INFO[0] >= 3: data = self.dump(obj, many=many) else: data = self.dump(obj, many=many).data return flask.jsonify(data, *args, **kwargs) flask-marshmallow-0.10.1/src/flask_marshmallow/sqla.py000066400000000000000000000073241346366617700230550ustar00rootroot00000000000000# -*- coding: utf-8 -*- """ flask_marshmallow.sqla ~~~~~~~~~~~~~~~~~~~~~~ Integration with Flask-SQLAlchemy and marshmallow-sqlalchemy. Provides `ModelSchema ` classes that use the scoped session from Flask-SQLALchemy. """ from flask import url_for, current_app from six.moves.urllib import parse import marshmallow_sqlalchemy as msqla from marshmallow.exceptions import ValidationError from .schema import Schema class DummySession(object): """Placeholder session object.""" pass class SchemaOpts(msqla.ModelSchemaOpts): """Schema options for `~flask_marshmallow.sqla.ModelSchema`. Same as `marshmallow_sqlalchemy.SchemaOpts`, except that we add a placeholder `DummySession` if ``sqla_session`` is not defined on class Meta. The actual session from `flask_sqlalchemy` gets bound in `flask_marshmallow.Marshmallow.init_app`. """ session = DummySession() def __init__(self, meta, **kwargs): if not hasattr(meta, "sqla_session"): meta.sqla_session = self.session super(SchemaOpts, self).__init__(meta, **kwargs) class ModelSchema(msqla.ModelSchema, Schema): """ModelSchema that generates fields based on the `model` class Meta option, which should be a ``db.Model`` class from `flask_sqlalchemy`. Uses the scoped session from Flask-SQLAlchemy by default. See `marshmallow_sqlalchemy.ModelSchema` for more details on the `ModelSchema` API. """ OPTIONS_CLASS = SchemaOpts class TableSchema(msqla.TableSchema, Schema): """TableSchema that generates fields based on the `table` class Meta option, which should be a ``Table`` object from SQLAlchemy. Example: :: class UserSchema(ma.TableSchema): class Meta: table = models.User.__table__ See `marshmallow_sqlalchemy.TableSchema` for more details on the `TableSchema` API. """ class HyperlinkRelated(msqla.fields.Related): """Field that generates hyperlinks to indicate references between models, rather than primary keys. :param str endpoint: Flask endpoint name for generated hyperlink. :param str url_key: The attribute containing the reference's primary key. Defaults to "id". :param bool external: Set to `True` if absolute URLs should be used, instead of relative URLs. """ def __init__(self, endpoint, url_key="id", external=False, **kwargs): super(HyperlinkRelated, self).__init__(**kwargs) self.endpoint = endpoint self.url_key = url_key self.external = external def _serialize(self, value, attr, obj): if value is None: return None key = super(HyperlinkRelated, self)._serialize(value, attr, obj) kwargs = {self.url_key: key} return url_for(self.endpoint, _external=self.external, **kwargs) def _deserialize(self, value, *args, **kwargs): if self.external: parsed = parse.urlparse(value) value = parsed.path endpoint, kwargs = self.adapter.match(value) if endpoint != self.endpoint: raise ValidationError( ( 'Parsed endpoint "{endpoint}" from URL "{value}"; expected ' '"{self.endpoint}"' ).format(**locals()) ) if self.url_key not in kwargs: raise ValidationError( 'URL pattern "{self.url_key}" not found in {kwargs!r}'.format( **locals() ) ) return super(HyperlinkRelated, self)._deserialize( kwargs[self.url_key], *args, **kwargs ) @property def adapter(self): return current_app.url_map.bind("") flask-marshmallow-0.10.1/tests/000077500000000000000000000000001346366617700164025ustar00rootroot00000000000000flask-marshmallow-0.10.1/tests/__init__.py000066400000000000000000000000001346366617700205010ustar00rootroot00000000000000flask-marshmallow-0.10.1/tests/conftest.py000066400000000000000000000037761346366617700206160ustar00rootroot00000000000000"""Pytest fixtures for the test suite.""" from flask import Flask from flask_marshmallow import Marshmallow import pytest _app = Flask(__name__) _app.testing = True class Bunch(dict): def __init__(self, *args, **kwargs): super(Bunch, self).__init__(*args, **kwargs) self.__dict__ = self # Models class Author(Bunch): pass class Book(Bunch): pass @pytest.fixture def mockauthor(): author = Author(id=123, name="Fred Douglass") return author @pytest.fixture def mockauthorlist(): a1 = Author(id=1, name="Alice") a2 = Author(id=2, name="Bob") a3 = Author(id=3, name="Carol") return [a1, a2, a3] @pytest.fixture def mockbook(mockauthor): book = Book(id=42, author=mockauthor, title="Legend of Bagger Vance") return book @_app.route("/author/") def author(id): return "Steven Pressfield" @_app.route("/authors/") def authors(): return "Steven Pressfield, Chuck Paluhniuk" @_app.route("/books/") def books(): return "Legend of Bagger Vance, Fight Club" @_app.route("/books/") def book(id): return "Legend of Bagger Vance" @pytest.yield_fixture(scope="function") def app(): ctx = _app.test_request_context() ctx.push() yield _app ctx.pop() @pytest.fixture(scope="function") def ma(app): return Marshmallow(app) @pytest.fixture def schemas(ma): class AuthorSchema(ma.Schema): class Meta: fields = ("id", "name", "absolute_url", "links") absolute_url = ma.AbsoluteURLFor("author", id="") links = ma.Hyperlinks( {"self": ma.URLFor("author", id=""), "collection": ma.URLFor("authors")} ) class BookSchema(ma.Schema): class Meta: fields = ("id", "title", "author", "links") author = ma.Nested(AuthorSchema) links = ma.Hyperlinks( {"self": ma.URLFor("book", id=""), "collection": ma.URLFor("books")} ) # So we can access schemas.AuthorSchema, etc. return Bunch(**locals()) flask-marshmallow-0.10.1/tests/markers.py000066400000000000000000000003551346366617700204230ustar00rootroot00000000000000import pytest import flask from distutils.version import LooseVersion flask_version = LooseVersion(flask.__version__) flask_1_req = pytest.mark.skipif( flask_version < LooseVersion("0.11"), reason="flask 0.11 or higher required" ) flask-marshmallow-0.10.1/tests/test_core.py000077500000000000000000000041361346366617700207520ustar00rootroot00000000000000# -*- coding: utf-8 -*- import json from flask import Flask, url_for from werkzeug.wrappers import BaseResponse from flask_marshmallow import Marshmallow from tests.markers import flask_1_req from tests.utils import get_dump_data def test_deferred_initialization(): app = Flask(__name__) m = Marshmallow() m.init_app(app) assert "flask-marshmallow" in app.extensions def test_schema(app, schemas, mockauthor): s = schemas.AuthorSchema() result = get_dump_data(s, mockauthor) assert result["id"] == mockauthor.id assert result["name"] == mockauthor.name assert result["absolute_url"] == url_for("author", id=mockauthor.id, _external=True) links = result["links"] assert links["self"] == url_for("author", id=mockauthor.id) assert links["collection"] == url_for("authors") def test_jsonify_instance(app, schemas, mockauthor): s = schemas.AuthorSchema() resp = s.jsonify(mockauthor) assert isinstance(resp, BaseResponse) assert resp.content_type == "application/json" obj = json.loads(resp.get_data(as_text=True)) assert isinstance(obj, dict) @flask_1_req def test_jsonify_collection(app, schemas, mockauthorlist): s = schemas.AuthorSchema() resp = s.jsonify(mockauthorlist, many=True) assert isinstance(resp, BaseResponse) assert resp.content_type == "application/json" obj = json.loads(resp.get_data(as_text=True)) assert isinstance(obj, list) @flask_1_req def test_jsonify_collection_via_schema_attr(app, schemas, mockauthorlist): s = schemas.AuthorSchema(many=True) resp = s.jsonify(mockauthorlist) assert isinstance(resp, BaseResponse) assert resp.content_type == "application/json" obj = json.loads(resp.get_data(as_text=True)) assert isinstance(obj, list) def test_links_within_nested_object(app, schemas, mockbook): s = schemas.BookSchema() result = get_dump_data(s, mockbook) assert result["title"] == mockbook.title author = result["author"] assert author["links"]["self"] == url_for("author", id=mockbook.author.id) assert author["links"]["collection"] == url_for("authors") flask-marshmallow-0.10.1/tests/test_fields.py000066400000000000000000000077621346366617700212750ustar00rootroot00000000000000# -*- coding: utf-8 -*- from flask import url_for from werkzeug.routing import BuildError import pytest from flask_marshmallow.fields import _tpl @pytest.mark.parametrize( "template", ["", " ", " ", "< id>", "", "< id >"] ) def test_tpl(template): assert _tpl(template) == "id" assert _tpl(template) == "id" assert _tpl(template) == "id" def test_url_field(ma, mockauthor): field = ma.URLFor("author", id="") result = field.serialize("url", mockauthor) assert result == url_for("author", id=mockauthor.id) mockauthor.id = 0 result = field.serialize("url", mockauthor) assert result == url_for("author", id=0) def test_url_field_with_invalid_attribute(ma, mockauthor): field = ma.URLFor("author", id="") expected_msg = "{!r} is not a valid attribute of {!r}".format( "not-an-attr", mockauthor ) with pytest.raises(AttributeError, match=expected_msg): field.serialize("url", mockauthor) def test_url_field_handles_nested_attribute(ma, mockbook, mockauthor): field = ma.URLFor("author", id="") result = field.serialize("url", mockbook) assert result == url_for("author", id=mockauthor.id) def test_url_field_handles_none_attribute(ma, mockbook, mockauthor): mockbook.author = None field = ma.URLFor("author", id="") result = field.serialize("url", mockbook) assert result is None field = ma.URLFor("author", id="") result = field.serialize("url", mockbook) assert result is None def test_url_field_deserialization(ma): field = ma.URLFor("author", id="", allow_none=True) # noop assert field.deserialize("foo") == "foo" assert field.deserialize(None) is None def test_invalid_endpoint_raises_build_error(ma, mockauthor): field = ma.URLFor("badendpoint") with pytest.raises(BuildError): field.serialize("url", mockauthor) def test_hyperlinks_field(ma, mockauthor): field = ma.Hyperlinks( {"self": ma.URLFor("author", id=""), "collection": ma.URLFor("authors")} ) result = field.serialize("_links", mockauthor) assert result == { "self": url_for("author", id=mockauthor.id), "collection": url_for("authors"), } def test_hyperlinks_field_recurses(ma, mockauthor): field = ma.Hyperlinks( { "self": {"href": ma.URLFor("author", id=""), "title": "The author"}, "collection": {"href": ma.URLFor("authors"), "title": "Authors list"}, } ) result = field.serialize("_links", mockauthor) assert result == { "self": {"href": url_for("author", id=mockauthor.id), "title": "The author"}, "collection": {"href": url_for("authors"), "title": "Authors list"}, } def test_hyperlinks_field_recurses_into_list(ma, mockauthor): field = ma.Hyperlinks( [ {"rel": "self", "href": ma.URLFor("author", id="")}, {"rel": "collection", "href": ma.URLFor("authors")}, ] ) result = field.serialize("_links", mockauthor) assert result == [ {"rel": "self", "href": url_for("author", id=mockauthor.id)}, {"rel": "collection", "href": url_for("authors")}, ] def test_hyperlinks_field_deserialization(ma): field = ma.Hyperlinks({"href": ma.URLFor("author", id="")}, allow_none=True) # noop assert field.deserialize("/author") == "/author" assert field.deserialize(None) is None def test_absolute_url(ma, mockauthor): field = ma.AbsoluteURLFor("authors") result = field.serialize("abs_url", mockauthor) assert result == url_for("authors", _external=True) def test_absolute_url_deserialization(ma): field = ma.AbsoluteURLFor("authors", allow_none=True) assert field.deserialize("foo") == "foo" assert field.deserialize(None) is None def test_aliases(ma): from flask_marshmallow.fields import UrlFor, AbsoluteUrlFor, URLFor, AbsoluteURLFor assert UrlFor is URLFor assert AbsoluteUrlFor is AbsoluteURLFor flask-marshmallow-0.10.1/tests/test_io.py000066400000000000000000000000001346366617700204100ustar00rootroot00000000000000flask-marshmallow-0.10.1/tests/test_sqla.py000066400000000000000000000173771346366617700207720ustar00rootroot00000000000000# -*- coding: utf-8 -*- import pytest from flask import Flask, url_for from flask_sqlalchemy import SQLAlchemy from werkzeug.wrappers import BaseResponse from flask_marshmallow import Marshmallow from flask_marshmallow.sqla import HyperlinkRelated from tests.conftest import Bunch from tests.utils import get_dump_data, get_load_data class TestSQLAlchemy: @pytest.yield_fixture() def extapp(self): app_ = Flask("extapp") app_.testing = True app_.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///:memory:" app_.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False SQLAlchemy(app_) Marshmallow(app_) @app_.route("/author/") def author(id): return "...view for author {}...".format(id) @app_.route("/book/") def book(id): return "...view for book {}...".format(id) ctx = app_.test_request_context() ctx.push() yield app_ ctx.pop() @pytest.fixture() def db(self, extapp): return extapp.extensions["sqlalchemy"].db @pytest.fixture() def extma(self, extapp): return extapp.extensions["flask-marshmallow"] @pytest.yield_fixture() def models(self, db): class AuthorModel(db.Model): __tablename__ = "author" id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(255)) @property def url(self): return url_for("author", id=self.id) @property def absolute_url(self): return url_for("author", id=self.id, _external=True) class BookModel(db.Model): __tablename__ = "book" id = db.Column(db.Integer, primary_key=True) title = db.Column(db.String(255)) author_id = db.Column(db.Integer, db.ForeignKey("author.id")) author = db.relationship("AuthorModel", backref="books") @property def url(self): return url_for("book", id=self.id) @property def absolute_url(self): return url_for("book", id=self.id, _external=True) db.create_all() yield Bunch(Author=AuthorModel, Book=BookModel) db.drop_all() def test_can_declare_model_schemas(self, extma, models, db): class AuthorSchema(extma.ModelSchema): class Meta: model = models.Author class BookSchema(extma.ModelSchema): class Meta: model = models.Book author_schema = AuthorSchema() book_schema = BookSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) author_result = get_dump_data(author_schema, author) assert "id" in author_result assert "name" in author_result assert author_result["name"] == "Chuck Paluhniuk" assert author_result["books"][0] == book.id book_result = get_dump_data(book_schema, book) assert "id" in book_result assert book_result["author"] == author.id resp = author_schema.jsonify(author) assert isinstance(resp, BaseResponse) def test_can_declare_table_schemas(self, extma, models, db): class AuthorSchema(extma.TableSchema): class Meta: table = models.Author.__table__ class BookSchema(extma.TableSchema): class Meta: table = models.Book.__table__ author_schema = AuthorSchema() book_schema = BookSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) author_result = get_dump_data(author_schema, author) assert "id" in author_result assert "name" in author_result assert author_result["id"] == author.id assert author_result["name"] == "Chuck Paluhniuk" book_result = get_dump_data(book_schema, book) assert "id" in book_result assert "title" in book_result assert book_result["id"] == book.id assert book_result["title"] == book.title resp = author_schema.jsonify(author) assert isinstance(resp, BaseResponse) def test_hyperlink_related_field(self, extma, models, db, extapp): class BookSchema(extma.ModelSchema): class Meta: model = models.Book author = extma.HyperlinkRelated("author") book_schema = BookSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) db.session.add(author) db.session.add(book) db.session.flush() book_result = get_dump_data(book_schema, book) assert book_result["author"] == author.url deserialized, errors = get_load_data(book_schema, book_result) assert deserialized.author == author def test_hyperlink_related_field_serializes_none(self, extma, models): class BookSchema(extma.ModelSchema): class Meta: model = models.Book author = extma.HyperlinkRelated("author") book_schema = BookSchema() book = models.Book(title="Fight Club", author=None) book_result = get_dump_data(book_schema, book) assert book_result["author"] is None def test_hyperlink_related_field_errors(self, extma, models, db, extapp): class BookSchema(extma.ModelSchema): class Meta: model = models.Book author = HyperlinkRelated("author") book_schema = BookSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) db.session.add(author) db.session.add(book) db.session.flush() # Deserialization fails on bad endpoint book_result = get_dump_data(book_schema, book) book_result["author"] = book.url deserialized, errors = get_load_data(book_schema, book_result) assert 'expected "author"' in errors["author"][0] # Deserialization fails on bad URL key book_result = get_dump_data(book_schema, book) book_schema.fields["author"].url_key = "pk" deserialized, errors = get_load_data(book_schema, book_result) assert 'URL pattern "pk" not found' in errors["author"][0] def test_hyperlink_related_field_external(self, extma, models, db, extapp): class BookSchema(extma.ModelSchema): class Meta: model = models.Book author = HyperlinkRelated("author", external=True) book_schema = BookSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) db.session.add(author) db.session.add(book) db.session.flush() book_result = get_dump_data(book_schema, book) assert book_result["author"] == author.absolute_url deserialized, errors = get_load_data(book_schema, book_result) assert deserialized.author == author def test_hyperlink_related_field_list(self, extma, models, db, extapp): class AuthorSchema(extma.ModelSchema): class Meta: model = models.Author books = extma.List(HyperlinkRelated("book")) author_schema = AuthorSchema() author = models.Author(name="Chuck Paluhniuk") book = models.Book(title="Fight Club", author=author) db.session.add(author) db.session.add(book) db.session.flush() author_result = get_dump_data(author_schema, author) assert author_result["books"][0] == book.url deserialized, errors = get_load_data(author_schema, author_result) assert deserialized.books[0] == book flask-marshmallow-0.10.1/tests/utils.py000066400000000000000000000010161346366617700201120ustar00rootroot00000000000000from marshmallow import ValidationError from flask_marshmallow.compat import _MARSHMALLOW_VERSION_INFO def get_dump_data(schema, obj): if _MARSHMALLOW_VERSION_INFO[0] >= 3: return schema.dump(obj) return schema.dump(obj).data def get_load_data(schema, obj): if _MARSHMALLOW_VERSION_INFO[0] >= 3: try: return schema.load(obj), None except ValidationError as err: return None, err.normalized_messages() return schema.load(obj).data, schema.load(obj).errors flask-marshmallow-0.10.1/tox.ini000066400000000000000000000014141346366617700165530ustar00rootroot00000000000000[tox] envlist= lint py{27,35,36,37}-marshmallow2 py{35,36,37}-marshmallow3 docs [testenv] extras = tests deps = marshmallow2: marshmallow>=2.0.0,<3.0.0 marshmallow3: marshmallow>=3.0.0a1,<4.0.0 commands = pytest {posargs} [testenv:lint] deps = pre-commit~=1.16 skip_install = true commands = pre-commit run --all-files [testenv:docs] deps = -rdocs/requirements.txt extras = commands = sphinx-build docs/ docs/_build {posargs} ; Below tasks are for development only (not run in CI) [testenv:watch-docs] deps = -rdocs/requirements.txt sphinx-autobuild extras = commands = sphinx-autobuild --open-browser docs/ docs/_build {posargs} -z flask_marshmallow -s 2 [testenv:watch-readme] deps = restview skip_install = true commands = restview README.rst