diff --git a/.travis.yml b/.travis.yml index afb3cc2..24720c8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: python python: - "3.4.5" - "3.5" + - "3.6" # command to install dependencies install: - pip install -r requirements.txt diff --git a/CHANGES.mD b/CHANGES.mD new file mode 100644 index 0000000..b51398e --- /dev/null +++ b/CHANGES.mD @@ -0,0 +1,13 @@ +Change logs +=== + +## 1.0.2 - 26/01/2017 + +By @ponteineptique + +- Moved to Mozilla Public License Version 2 +- Fixed a bug tests would fail in mockup ( Issue #112 ) +- Added a warning when base_url is not correct ( Issue #109 ) +- Harmonized chunkers parameter names ( Issue #113 ) +- Created a new tutorial on https://github.com/capitains/tutorial-nemo ( Issues #14, #78 and #97 ) +- Added a CHANGES.md diff --git a/LICENSE b/LICENSE index 562b45f..2f8ed18 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,374 @@ -MIT License - -Copyright (c) 2018 Perseus, Tufts; Humboldt Chair of Digital Humanities, Leipzig; Thibault Clérice - -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. +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at http://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. + diff --git a/README.rst b/README.rst index 5bf5fc1..ded51d5 100644 --- a/README.rst +++ b/README.rst @@ -14,13 +14,31 @@ .. image:: https://badge.fury.io/py/flask_nemo.svg :target: https://badge.fury.io/py/flask_nemo -Capitains Nemo is an User Interface built around the need to make CTS a easy to use, human readable standard for texts. -Capitains Nemo counts multiple language implementation, including this one in Python for Flask. Presentend as a classic Flask -Extension, `flask.ext.nemo` intends to be a simple, customizable interface between your enduser and your CTS5 API. + +.. image:: https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg + :alt: License: MPL 2.0 + :target: https://opensource.org/licenses/MPL-2.0 + + +.. image:: https://raw.githubusercontent.com/Capitains/tutorial-nemo/master/header.png + :alt: Nemo Banner + :target: http://capitains.org + +Capitains Nemo is an User Interface built around the need to make CapiTainS an easy-to-use, human-readable standard for texts. +Capitains Nemo counts multiple language implementations, including this one in Python for Flask. Built as a classic Flask +Extension, `flask.ext.nemo` intends to be a simple, customizable interface between your end-user and your Text APIs. + +If you are new to the Capitains world, feel free to get some reading time on the `generic website `_ The Flask's extension Nemo can be customized from its stylesheets to its functions. Adding routes or removing them is as easy as adding a XSL Stylesheet to transform the very own result of a CTS GetPassage results to your own expected output. +Tutorial and example +#################### + +You can find a tutorial on `Github Capitains/tutorial-nemo `_ repository and +an example server (based on this tutorial) on `Heroku `_ + Install ####### diff --git a/docs/Nemo.api.rst b/docs/Nemo.api.rst index 205aeb3..4c16f22 100644 --- a/docs/Nemo.api.rst +++ b/docs/Nemo.api.rst @@ -95,11 +95,6 @@ Chunkers .. automethod:: flask_nemo.chunker.level_grouper .. automethod:: flask_nemo.chunker.level_chunker -PrevNexter -********** - -.. automethod:: flask_nemo.Nemo.default_prevnext - Plugin ###### diff --git a/docs/Nemo.examples.rst b/docs/Nemo.examples.rst index 9bdc6e7..96131f4 100644 --- a/docs/Nemo.examples.rst +++ b/docs/Nemo.examples.rst @@ -1,188 +1,7 @@ Examples ======== +Examples have been removed from this repository. It has been replace by a tutorial. - -Simple Configuration -#################### - -.. topic:: User story [1] - - A **researcher** , an **engineer** or both is interested in **CTS** but has **no time** to develop their own application and their own theme : *flask.ext.nemo* will provide a simple, easy to use interface that you can deploy on any server. Even with a really limited knowledge of python. - -.. topic:: User story [2] - - A **researcher**, an **engineer** or both has already a CTS endpoint and wants to check the output and the browsing system visually. - - -The simplest configuration of Nemo, or close to it, is to simply give an endpoint url to your Nemo extension, the app you are using -and the name of a CTS inventory (if required). This will run a browsing interface with support for collections, textgroups, texts and passages browsing. - -- The application will itself do the GetCapabilities request to retrieve the available texts and organize them through collection, textgroups and works. -- Once an edition or a translation is clicked, a page showing available references is shown. -- Once a passage is clicked, the passage is shown with available metadata. - -.. _example1.code: - -.. code-block:: python - - # We import Flask - from flask import Flask - # We import Nemo - from flask.ext.nemo import Nemo - # We import enough resources from MyCapytain to retrieve data - from MyCapytain.resolvers.cts.api import HttpCtsResolver - from MyCapytain.retrievers.cts5 import HttpCtsRetriever - - # We set up a resolver which communicates with an API available in Leipzig - resolver = HttpCtsResolver(HttpCtsRetriever("http://cts.dh.uni-leipzig.de/api/cts/")) - # We create an application. You can simply use your own - app = Flask( - "My Application" - ) - # We register a Nemo object with the minimal settings - nemo = Nemo( - # We give a resolver - resolver=resolver, - # We set up the base url to be empty. If you want nemo to be on a - # subpath called "cts", you would have - # base_url="cts", - base_url="", - # We give thee ap object - app=app - ) - # We run the application - app.run() - -.. note:: You can run this example using `python example.py default` - -XSLT, CSS and Javascript addons -############################### - -.. topic:: User Story - - A developer, with no or only limited understanding of python, wants to expose their CTS works but have some modifications to do regarding the design. - - -Because Python is not a natural language and because not everybody knows it in academia, you might find yourself in a situation where you don't know it. On the other hand, XML TEI, HTML, CSS - and thus xsl and sometimes Javascript - are quite common languages known to both researchers and engineers. Capitains Nemo for Flask accepts custom templates, CSS, Javascript, XSL and statics. And in a simple, nice way : - -.. code-block:: python - - # ... - nemo = Nemo( - # We give a resolver - resolver=resolver, - base_url="", - inventory="ciham", - # For transform parameters, we provide a path to an xsl which will be used for every - transform={"default" : "examples/ciham.xslt"}, - # CSS value should be a list of path to CSS own files - css=["examples/ciham.css"], - # JS follows the same scheme - js=[ - # use own js file to load a script to go from normalized edition to diplomatic one. - "examples/ciham.js" - ], - templates={ - "main": "examples/ciham" - }, - additional_static=[ - "path/to/picture.png" - ] - ) - -.. topic:: Additional CSS, JS or Statics in Templates - - To call or make a link to a static in your own template, you should always use the helper `url_for` and the route name `secondary_assets`. Additional statics can be linked to using the filename (be sure they do not collide !) and the type : css, js or static. Example : `{{url_for('nemo.secondary_assets', type='static', asset='picture.png')}}`. - -.. note:: Templates are written with `Jinja2 `_. See also :ref:`Templates.documentation`. For XSL, we have some unfortunate restrictions, see :ref:`lxml.strip-spaces` - -.. note:: You can run an example using css, js, templates and transform with `python example.py ciham` - -Own Chunker -########### - -.. warning:: Starting from this example, the configuration and changes implied require the capacity to develop in Python. - -.. topic:: User Story - - A developer wants to add a custom scheme for browsing text passages by groups that are not part of the citation scheme of the text. The custom scheme should be triggered by text identifier or using available CTS metadata about the text, such as the Citation Scheme. - - CTS is good, but getValidReff can really be a hassle. The default generation of browsing level will always retrieve the deepest level of citations available. For the Iliad of Homer, which is composed of two levels, books and lines, this would translate to a GetValidReff level 2. This would mean that the generic chunker would return on the text page a link to each line of each book (it's a total of 15337 lines, if you did not know). - - Chunker provides a simple, easy to develop interface to deal with such a situation : for example, returning only 50 lines groups of links (1.1-1.50, 1.51-1.100, etc.). The Nemo class accepts a chunker dictionary where **keys** are **urns** and where the key "**default**" is the default chunker to be applied. Given a chunker named *homer_chunker* and one named *default_chunker*, if the urn of Homer is **urn:cts:greekLit:tlg0012.tlg001.opp-grc1** (See :ref:`function skeleton ` for ): - -.. code-block:: python - - # ... - nemo = Nemo( - # ... - chunker= { - "urn:cts:greekLit:tlg0012.tlg001.opp-grc1" : homer_chunker, - "default": default_chunker - } - ) - -.. note:: You can run an example using chunker with `python example.py chunker` - -.. note:: Parameters XSLT and prevnext work the same way. See relevant documentation : :ref:`Nemo.chunker` for more information about and examples of chunkers - -Adding routes -############# - -.. topic:: User story - - The user has needs in terms of new routes that would cover specific needs, like vis-a-vis edition. - -There is multiple way to deal with this kind of situation. The best way is to create a subclass of Nemo. The idea behind that is that you rely on specific functionalities of Nemo and its context object. To deal with that and make as much as possible a good use of Nemo extension, you just need to add a new route to url using a tuple : first value would be the route, according to Flask standards, *ie* `/read//////` , the name of the function or method (naming convention makes them start by r\_), *ie* `r_double`, and a list of methods, by default ["GET"]. - -As you will most likely use a new template, don't forget to register it with the templates parameter ! - -.. code-block:: python - - # #We create a class based on Nemo - class NemoDouble(Nemo): - def r_double(self, collection, collection2, work, version, passage_identifier, visavis): - """ Optional route to add a visavis version - - :param collection: Collection identifier - :type collection: str - :param textgroup: Textgroup Identifier - :type textgroup: str - :param work: Work identifier - :type work: str - :param version: Version identifier - :type version: str - :param passage_identifier: Reference identifier - :type passage_identifier: str - :param version: Visavis version identifier - :type version: str - :return: Template, version inventory object and Markup object representing the text - :rtype: {str: Any} - - .. todo:: Change text_passage to keep being lxml and make so self.render turn etree element to Markup. - """ - - # Simply call the url of the - args = self.r_passage(collection, textgroup, work, version, passage_identifier) - # Call with other identifiers and add "visavis_" front of the argument - args.update({ "visavis_{0}".format(key):value for key, value in self.r_passage(collection, textgroup, work, visavis, passage_identifier).items()}) - args["template"] = "double::r_double.html" - return args - - nemo = NemoDouble( - api_url="http://cts.perseids.org/api/cts/", - base_url="", - inventory="nemo", - # We reuse Nemo.Routes and add a new one - urls= Nemo.ROUTES + [("/read//////", "r_double", ["GET"])], - css=[ - "examples/translations.css" - ], - # We think about registering the new route - templates={ - "double": "./examples/translations" - } - ) - -.. note:: You can run an example using chunker with `python example.py translations` +You can find the tutorial on `Github Capitains/tutorial-nemo `_ repository and +an example server (based on this tutorial) on `Heroku `_ diff --git a/docs/_static/images/header.png b/docs/_static/images/header.png new file mode 100644 index 0000000..6874bce Binary files /dev/null and b/docs/_static/images/header.png differ diff --git a/docs/index.rst b/docs/index.rst index d07455d..5c4450f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -12,6 +12,7 @@ Welcome to the flask extension Nemo documentation! :maxdepth: 2 Nemo.examples + Nemo.api Nemo.workflow Nemo.query Nemo.developer_guide @@ -19,5 +20,4 @@ Welcome to the flask extension Nemo documentation! Nemo.chunker Nemo.plugin Nemo.plugins - LXML - Nemo.api + LXML \ No newline at end of file diff --git a/example.py b/example.py deleted file mode 100644 index af53ada..0000000 --- a/example.py +++ /dev/null @@ -1,80 +0,0 @@ -# Import Flask and Nemo -# This script can take a first argument giving a configuration from examples.py -from flask import Flask -from flask_nemo import Nemo -from flask_caching import Cache -from flask_nemo.chunker import level_grouper -from MyCapytain.resolvers.cts.local import CTSCapitainsLocalResolver -from MyCapytain.resources.collections.cts import TextInventory -from MyCapytain.resources.prototypes.cts.inventory import TextInventoryCollection -from MyCapytain.resolvers.utils import CollectionDispatcher -import logging - -# We create a Flask app -app = Flask( - __name__ -) - -tic = TextInventoryCollection() -latin = TextInventory("urn:perseus:latinLit", parent=tic) -latin.set_label("Classical Latin", "eng") -farsi = TextInventory("urn:perseus:farsiLit", parent=tic) -farsi.set_label("Farsi", "eng") -gc = TextInventory("urn:perseus:greekLit", parent=tic) -gc.set_label("Ancient Greek", "eng") -gc.set_label("Grec Ancien", "fre") - -dispatcher = CollectionDispatcher(tic) - - -@dispatcher.inventory("urn:perseus:latinLit") -def dispatchLatinLit(collection, path=None, **kwargs): - if collection.id.startswith("urn:cts:latinLit:"): - return True - return False - - -@dispatcher.inventory("urn:perseus:farsiLit") -def dispatchfFarsiLit(collection, path=None, **kwargs): - if collection.id.startswith("urn:cts:farsiLit:"): - return True - return False - - -@dispatcher.inventory("urn:perseus:greekLit") -def dispatchGreekLit(collection, path=None, **kwargs): - if collection.id.startswith("urn:cts:greekLit:"): - return True - return False - -cache = Cache() - -NautilusDummy = CTSCapitainsLocalResolver( - resource=[ - #"../../canonicals/First1KGreek", - "repositories/canonical-latinLit", - "repositories/canonical-greekLit", - "repositories/canonical-farsiLit", - #"./tests/test_data/nautilus/farsiLit", - #"./tests/test_data/nautilus/latinLit" - ], - dispatcher=dispatcher -) -NautilusDummy.logger.setLevel(logging.ERROR) - -nemo = Nemo( - app=app, - base_url="", - resolver=NautilusDummy, - chunker={"default": lambda x, y: level_grouper(x, y, groupby=20)}, - plugins=None, - cache=cache, - transform={ - "default": "/home/thibault/dev/perseus_nemo_ui/aperire_ui/data/assets/static/xslt/epidocShort.xsl" - } -) - -cache.init_app(app) - -if __name__ == "__main__": - app.run() diff --git a/examples/__init__.py b/examples/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/examples/ciham.css b/examples/ciham.css deleted file mode 100644 index 932682f..0000000 --- a/examples/ciham.css +++ /dev/null @@ -1,59 +0,0 @@ -/* mise en forme des span pour un affichage normalisé*/ -span.reg { - display: none; -} -span.expan { - display: none; -} - -/* mise en forme position du texte et effets de caractères */ -span.above { - vertical-align: 15px; - font-size: 90%; - color: #000000; -} -span.below { - vertical-align: -15px; - font-size: 90%; - color: #000000; -} -span.decorated-initial { - color: red; - font-size: 150%; -} -span.first-letter-capital { - text-transform: capitalize; -} -span.capital { - text-transform: uppercase; -} -span.underline { - text-decoration: underline; -} -span.rubricated { - color: red; -} -span.smaller { - font-size: 80%; -} -span.bigger { - font-size: 120%; -} -span.widder { - word-spacing: 20px; -} -span.overstrike { - text-decoration: line-through; -} -span.exponct { - border-bottom: thick dotted; -} -span.norm { - text-decoration: none; - word-spacing: none; - font-size: 100%; - color: black; - vertical-align: 0; - text-transform: none; - border: 0; -} diff --git a/examples/ciham.js b/examples/ciham.js deleted file mode 100644 index 03d3ab0..0000000 --- a/examples/ciham.js +++ /dev/null @@ -1,57 +0,0 @@ -(function ($) { - $.each(['show', 'hide'], function (i, ev) { - var el = $.fn[ev]; - $.fn[ev] = function () { - this.trigger(ev); - return el.apply(this, arguments); - }; - }); - })(jQuery); - - -$(document).ready(function() { - - $("ol, span").removeClass("norm"); - - $("#fac").on("click", function() { - that = $(this); - $("ol, span").removeClass("norm"); - $(".orig , .abbr" ).show(); - $(".reg , .expan").hide(); - $("br").show(); - $(".btn-success").addClass("btn-default").removeClass("btn-success"); - that.addClass("btn-success").removeClass("btn-default"); - - }); - - - $("#reg").on("click", function() { - that = $(this); - $("ol, span, div").addClass("norm"); - $(".orig , .abbr").hide(); - $(".reg , .expan").show(); - $("br").hide(); - //$(".metamark").removeClass("information-hr"); - //that.removeClass("information-hr"); - $(".btn-success").addClass("btn-default").removeClass("btn-success"); - that.addClass("btn-success").removeClass("btn-default"); - }); - - $("#seeWitness").on("click", function() { - that = $(this); - $("#seeWitness li").toggleClass("wit"); - }); - - - - - $("sup a, .information-hr").tooltip(); - - $(".orig , .abbr , .reg , .expan").on("show", function(e) { - if($(this).is("span")) { - //$(this).css("display", "inline-block");// - } - }); -}); - - diff --git a/examples/ciham.xslt b/examples/ciham.xslt deleted file mode 100644 index 9295030..0000000 --- a/examples/ciham.xslt +++ /dev/null @@ -1,282 +0,0 @@ - - - - - - - - - - - - - - -
- - -
-
-
-
    - -
-
-
-
-
- - - - - - - - -   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - [ col. - - ] - -
- - -
- - [ fol. - - ] - -
- - - - - - orig - - - - - - abbr - - - - - - orig - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - lacuna - -              - - - - - - - corr - - - - - - - - - del - - - - - - - - - - - - - - - - - - - - reg - - - - - - expan - - - - - - - margin-left: 0; - background-color:#c5e88f; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  • - - - - - -
  • -
    - - - - - - - - - - - - - - - - - - -
    \ No newline at end of file diff --git a/examples/ciham/menu.html b/examples/ciham/menu.html deleted file mode 100644 index 82e9eac..0000000 --- a/examples/ciham/menu.html +++ /dev/null @@ -1,29 +0,0 @@ -
    - -
    -Text provided by CIHAM, propulsed by Capitains -
    - Collection -
    - -{% if textgroups %} -
    - Authors -
    - - -
    -
    - -
    - -{% endif %} \ No newline at end of file diff --git a/examples/configs.py b/examples/configs.py deleted file mode 100644 index bc61b63..0000000 --- a/examples/configs.py +++ /dev/null @@ -1,117 +0,0 @@ -import lxml.etree as etree -from flask import Markup -from flask_nemo.chunker import scheme_chunker, level_grouper -from flask.ext.nemo import Nemo - - -configs = { - # The CIHAM project is made of critical editions. We load for it a specific xslt to render the result of GetPassage - # And specifics assets - "ciham": { - "api_url": "http://cts.perseids.org/api/cts/", - "base_url": "", - "inventory": "nemo", - "transform": {"default" : "examples/ciham.xslt"}, # Use own xsl - "css": [ - # USE Own CSS - "examples/ciham.css" - ], - "js": [ - # use own js file to load a script to go from normalized edition to diplomatic one. - "examples/ciham.js" - ], - "templates":{ - "menu": "examples/ciham" - }, - "chunker": { - # The default chunker takes care of book, poem, lines - # but it would be cool to have 30 lines group for Nemo - "urn:cts:froLit:jns915.jns1856.ciham-fro1": lambda text, cb: [(reff.split(":")[-1], reff.split(":")[-1]) for reff in cb(1)], - "default": scheme_chunker # lambda text, cb: Nemo.line_grouper(text, cb, 50) - } - }, - "translations": { - "api_url": "http://cts.perseids.org/api/cts/", - "base_url": "", - "inventory": "nemo", - "urls" : Nemo.ROUTES + [("/read//////", "r_double", ["GET"])], - "css": [ - "examples/translations.css" - ], - "chunker": { - # The default chunker takes care of book, poem, lines - # but it would be cool to have 30 lines group for Nemo - "urn:cts:froLit:jns915.jns1856.ciham-fro1": lambda text, cb: [(reff.split(":")[-1], reff.split(":")[-1]) for reff in cb(1)], - "default": scheme_chunker # lambda text, cb: Nemo.line_grouper(text, cb, 50) - }, - "templates": { - "double": "./examples/translations" - } - }, - "chunker": { - "api_url": "http://localhost:5000", - "base_url": "", - "inventory": "nemo", - "chunker": { - # The default chunker takes care of book, poem, lines - # but it would be cool to have 30 lines group for Nemo - "urn:cts:latinLit:phi1294.phi002.perseus-lat2": lambda text, cb: [(reff.split(":")[-1], reff.split(":")[-1]) for reff in cb(2)], - "default": level_grouper # lambda text, cb: Nemo.line_grouper(text, cb, 50) - }, - "css" : [ - # Use teibp from default nemo configuration - "examples/tei.pb.min.css" - ] - }, - "default": { - "api_url": "http://cts.perseids.org/api/cts/", - "base_url": "", - "inventory": "nemo", - "css" : [ - # Use teibp from default nemo configuration - "examples/tei.pb.min.css", - "static/nemo.min.css" - ] - } -} - - -class NemoDouble(Nemo): - """ Implementation of Nemo with a new route accepting a second version for comparison. - - """ - def r_double(self, collection, textgroup, work, version, passage_identifier, visavis): - """ Optional route to add a visavis version - - :param collection: Collection identifier - :type collection: str - :param textgroup: Textgroup Identifier - :type textgroup: str - :param work: Work identifier - :type work: str - :param version: Version identifier - :type version: str - :param passage_identifier: Reference identifier - :type passage_identifier: str - :param version: Visavis version identifier - :type version: str - :return: Template, version inventory object and Markup object representing the text - :rtype: {str: Any} - - .. todo:: Change text_passage to keep being lxml and make so self.render turn etree element to Markup. - """ - - # Simply call the url of the - args = self.r_passage(collection, textgroup, work, version, passage_identifier) - # Call with other identifiers and add "visavis_" front of the argument - args.update({"visavis_{0}".format(key): value for key, value in self.r_passage(collection, textgroup, work, visavis, passage_identifier).items()}) - args["template"] = "double::r_double.html" - return args - - -classes = { - "default": Nemo, - "ciham": Nemo, - "chunker": Nemo, - "translations": NemoDouble -} diff --git a/examples/tei.pb.min.css b/examples/tei.pb.min.css deleted file mode 100644 index 4679628..0000000 --- a/examples/tei.pb.min.css +++ /dev/null @@ -1,1859 +0,0 @@ -@import url('http://fonts.googleapis.com/css?family=Arvo:400,700,400italic,700italic|Gentium+Book+Basic:400,400italic,700,700italic'); -/* imports */ -/* @import url("shell.css"); */ -/* namespaces */ -/* @namespace "http://www.tei-c.org/ns/1.0"; */ -/* @namespace with prefix, as below, throws and error in less. */ -/* @namespace html "http://www.w3.org/1999/xhtml"; */ -/* Less variables */ -.note-like { - display: block; - margin: 1.5em auto 1.5em auto; - padding: .5em 1.5em 1.5em 1.5em; - border: 1px solid black; - border-radius: 15px; - width: 325px; - position: relative; - border: 1px solid #aaaaaa; - background: #fafafa; - /* reset text-indent for note with ancestors. */ - - text-indent: 0; - font-size: 85%; - text-align: justify; - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); -} -/* US Style Quotes */ -.quotesUS { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -/* UK-Style Quotes */ -.quotesUK { - quotes: "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019"; -} -.quotes { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -.block-margins { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -/* teibp classes */ -.-teibp-thumbnail { - max-height: 60px; -} -.-teibp-pb { - display: block; - width: 100%; - text-align: right; - color: gray; - margin: 2em 0 2em 0; - font-size: 11pt; -} -.box-shadow { - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); -} -.hide { - display: none; -} -.mono { - font-family: Courier,monospace; -} -.page-setup { - margin-left: 2em; - margin-right: 4em; - padding: 2.5em; - font-family: "Gentium Book Basic", Cochin, Georgia, Serif; - font-size: 14pt; - background-color: #ebebeb; - color: #292929; - width: 33em; -} -.table-border { - /* -border-left: 2px solid @border-color; -border-top:2px solid @border-color; -*/ - - border: 1px dotted #aaaaaa; -} -/* Choice elements */ -choice abbr + expan:before, -choice expan + abbr:before, -choice sic + corr:before, -choice corr + sic:before, -choice orig + reg:before, -choice reg + orig:before { - content: " ("; -} -choice abbr + expan:after, -choice expan + abbr:after, -choice sic + corr:after, -choice corr + sic:after, -choice orig + reg:after, -choice reg + orig:after { - content: ")"; -} -/* A */ -ab { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -accMat { - display: block; -} -accMat:before { - content: "accompanying materials: "; -} -acquisition { - display: block; - margin-top: 0; - margin-bottom: 0; -} -acquisition:before { - font-weight: bold; - content: "acquisition"; -} -activity { - display: block; -} -activity:before { - content: "activity: "; -} -actor { - /* Empty Rule Set */ -} -/* add */ -/* Could add other [place=] variations */ -add { - vertical-align: super; - font-size: 90%; -} -add[place=below] { - vertical-align: sub; - font-size: 90%; -} -addName { - /* Empty Rule Set */ -} -addSpan { - /* Empty Rule Set */ -} -additional { - display: block; -} -additions { - display: block; -} -additions:before { - content: "Significant additions within the document: "; -} -addrLine { - display: block; -} -address { - /* Empty Rule Set */ -} -address[rend~="block"], -addresss[rendition~="#block"] { - display: block; -} -adminInfo { - display: block; -} -affiliation { - /* Empty Rule Set */ -} -age { - /* Empty Rule Set */ -} -alt { - /* Empty Rule Set */ -} -altGrp { - /* Empty Rule Set */ -} -altIdent { - /* Empty Rule Set */ -} -altIdentifier { - display: block; -} -altIdentifier:before { - content: "Alternate ID: "; -} -am { - /* Empty Rule Set */ -} -analytic { - /* Empty Rule Set */ -} -anchor { - /* Empty Rule Set */ -} -app { - display: block; -} -appInfo { - display: block; -} -appInfo:before { - content: "Application information: "; -} -application { - display: block; -} -application:after { - content: " " attr(version); -} -arc { - /* Empty Rule Set */ -} -argument { - display: block; -} -att { - font-family: Courier,monospace; -} -att:before { - content: "@"; -} -attDef { - /* Empty Rule Set */ -} -attList { - /* Empty Rule Set */ -} -attRef { - /* Empty Rule Set */ -} -author { - /* Empty Rule Set */ -} -titleStmt > author { - display: block; - font-family: Arvo, sans-serif; - font-weight: normal; - margin-bottom: 1em; -} -authority { - /* Empty Rule Set */ -} -publicationStmt > availability { - font-size: 80%; -} -publicationStmt > availability:before { - font-weight: bold; - content: "Availability: "; -} -publicationStmt > availability[status]:before { - font-weight: bold; - content: "Availability (" attr(status) "): "; -} -/* B */ -back { - display: block; -} -bibl { - /* Empty Rule Set */ -} -bibl[rend~="block"], -bibl[rendition~="#block"] { - display: block; - padding-left: 2em; - text-indent: -2em; -} -biblFull { - display: block; -} -biblScope { - /* Empty Rule Set */ -} -biblStruct { - /* Empty Rule Set */ -} -bicond { - /* Empty Rule Set */ -} -binary { - /* Empty Rule Set */ -} -binaryObject { - /* Empty Rule Set */ -} -binding { - display: block; -} -binding:before { - content: "Binding: \a"; - white-space: pre-wrap; -} -binding[contemporary]:before { - content: "Binding: \A" "Contemporary: " attr(contemporary) "\A"; - white-space: pre-wrap; -} -bindingDesc { - display: block; -} -bindngDesc:before { - content: "Binding Description: \A"; -} -birth { - display: block; -} -birth:before { - content: "Birth: "; -} -bloc { - /* Empty Rule Set */ -} -broadcast { - /* Empty Rule Set */ -} -byline { - /* Empty Rule Set */ -} -/* c */ -c { - /* Empty Rule Set */ -} -cRefPattern { - display: none; -} -caesura { - /* Empty Rule Set */ -} -camera { - /* Empty Rule Set */ -} -caption { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -case[value]:before { - font-weight: bold; - content: attr(value) " "; -} -castGroup { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -castItem { - display: list-item; - list-style-type: none; -} -castList { - display: block; - margin-top: 1em; - margin-bottom: 1em; - margin-left: 2em; -} -catDesc { - /* Empty Rule Set */ -} -catRef { - /* Empty Rule Set */ -} -category { - /* Empty Rule Set */ -} -cb { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -cb:before { - content: "[column break]"; -} -cell { - display: table-cell; - padding: 1em 1.5em 1em 1em; - /* -border-left: 2px solid @border-color; -border-top:2px solid @border-color; -*/ - - border: 1px dotted #aaaaaa; - width: 100%; -} -/* for cell or row with @role = label */ -[role=label] { - font-weight: bold; -} -certainty { - /* Empty Rule Set */ -} -change { - /* Empty Rule Set */ -} -channel { - /* Empty Rule Set */ -} -charDecl { - display: none; -} -charName { - /* Empty Rule Set */ -} -charProp { - /* Empty Rule Set */ -} -choice { - /* Empty Rule Set */ -} -cit { - /* Empty Rule Set */ -} -cl { - /* Empty Rule Set */ -} -classCode { - /* Empty Rule Set */ -} -classDecl { - /* Empty Rule Set */ -} -classRef { - /* Empty Rule Set */ -} -classSpec { - /* Empty Rule Set */ -} -classes { - /* Empty Rule Set */ -} -climate { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -climate:before { - font-weight: bold; - content: "Climate: "; -} -closer { - /* Empty Rule Set */ -} -code { - font-family: Courier,monospace; -} -/* jawalsh: -For things like collation, condition, etc. that can have text or paragraphs as -children, we should use margins, when the content is text, and no margins when there -are child paragraphs (or other block elements). Otherwise we end up with double -margins. */ -collation { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -collection { - /* Empty Rule Set */ -} -colloc { - /* Empty Rule Set */ -} -colophon { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -cond { - /* Empty Rule Set */ -} -condition { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -constitution { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -constitution:before { - font-weight: bold; - content: "Constitution: "; -} -constitution[type] { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -constitution[type]:before { - font-weight: bold; - content: "Constitution (" attr(type) "): "; -} -constitution[type=frags] { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -constitution[type=frags]:before { - font-weight: bold; - content: "Constitution (fragments): "; -} -constraint { - /* Empty Rule Set */ -} -constraintSpec { - /* Empty Rule Set */ -} -content { - /* Empty Rule Set */ -} -/* jawalsh: -Need to discuss and coordinate handling of sic/corr, abbr/expan, and orig/reg */ -corr { - /* Empty Rule Set */ -} -correction { - /* Empty Rule Set */ -} -country { - /* Empty Rule Set */ -} -creation { - /* Empty Rule Set */ -} -/*jawalsh: -Need to handle attributes for custEvent. All the att.datable* attributes will be tricky. -custodialHist and custEvent may normally be hidden along with other header metadata, but -we'll have other datable elements that may be tricky. */ -custEvent { - display: list-item; -} -custodialHist { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -/* d */ -date[when]:empty:before { - content: attr(when); -} -/* e */ -egXML { - display: block; - font-size: 80%; - margin-left: 1em; - padding-left: 1em; - border-left: 1px solid #aaaaaa; - margin-top: .75em; - margin-bottom: .75em; - padding-top: .75em; - padding-bottom: .75em; - font-family: monospace; - white-space: pre; -} -encodingDesc { - display: none; -} -epigraph { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -fileDesc > extent { - display: none; -} -/* f */ -figure { - display: block; - text-align: center; - margin-left: auto; - margin-right: auto; -} -/* g */ -g { - /* Empty Rule Set */ -} -gap { - /* GLS: Depending upon how we handle gap and lacuna, we may want to enclose in [] */ - -} -gb { - /* Empty Rule Set */ -} -gen { - /* Empty Rule Set */ -} -genName { - /* Empty Rule Set */ -} -geo { - /* Empty Rule Set */ -} -geoDecl { - /* Empty Rule Set */ -} -geogFeat { - /* Empty Rule Set */ -} -geogName { - /* Empty Rule Set */ -} -gi { - font-family: Courier,monospace; -} -gi:before { - content: "<"; -} -gi:after { - content: ">"; -} -gloss { - /* Empty Rule Set */ -} -glyph { - /* Empty Rule Set */ -} -glyphName { - /* Empty Rule Set */ -} -gram { - /* Empty Rule Set */ -} -gramGrp { - /* Empty Rule Set */ -} -graph { - /* Empty for now */ - -} -graphic { - display: none; -} -group { - /* Empty Rule Set */ -} -/* h */ -handDesc { - /* Empty Rule Set */ -} -handNote { - /* Empty Rule Set */ -} -handNotes { - /* Empty Rule Set */ -} -handShift { - /* Empty Rule Set */ -} -/* Need head with TEI parent to distinguish from HTML head */ -TEI head { - display: block; - font-family: Arvo, sans-serif; - font-weight: normal; -} -body > head { - font-size: 180%; - text-indent: -0.5em; -} -div > head { - font-size: 170%; - text-indent: -0.5em; -} -div > div > head { - font-size: 155%; -} -div > div > div > head { - font-size: 140%; -} -div > div > div > div > head, -list > head { - font-size: 130%; -} -div > div > div > div > div > head { - font-size: 120%; -} -div > div > div > div > div > div head { - font-size: 110%; -} -figure > head { - display: block; - margin: 1.5em auto 1.5em auto; - padding: .5em 1.5em 1.5em 1.5em; - border: 1px solid black; - border-radius: 15px; - width: 325px; - position: relative; - border: 1px solid #aaaaaa; - background: #fafafa; - /* reset text-indent for note with ancestors. */ - - text-indent: 0; - font-size: 85%; - text-align: justify; - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - width: 85%; - font-family: "Gentium Book Basic", Cochin, Georgia, Serif; - font-size: 14pt; -} -headItem { - /* Empty Rule Set */ -} -headLabel { - /* Empty Rule Set */ -} -height { - /* Empty Rule Set */ -} -heraldry { - /* Empty Rule Set */ -} -hi { - /* GLS: do we want to bold this or change the background color? */ - -} -history { - /* Empty Rule Set */ -} -hom { - /* Empty Rule Set */ -} -hyph { - /* Empty Rule Set */ -} -hyphenation { - /* Empty Rule Set */ -} -/* i */ -iNode { - /* Empty Rule Set */ -} -iType { - /* Empty Rule Set */ -} -ident { - font-family: Courier,monospace; -} -idno { - /* Empty Rule Set */ -} -if { - /* Empty Rule Set */ -} -iff { - /* Empty Rule Set */ -} -imprimatur { - /* Empty Rule Set */ -} -imprint { - /* Empty Rule Set */ -} -incident { - /* Empty Rule Set */ -} -incipit { - /* Empty Rule Set */ -} -index { - /* Empty Rule Set */ -} -institution { - /* Empty Rule Set */ -} -interaction { - /* Empty Rule Set */ -} -interpGrp { - /* Empty Rule Set */ -} -interpretation { - /* Empty Rule Set */ -} -item { - display: list-item; - margin-left: 1em; -} -cell item { - margin-left: 1em; -} -list[type="gloss"] > item { - margin-left: 2em; -} -/* j */ -join { - /* Empty Rule Set */ -} -joinGrp { - /* Empty Rule Set */ -} -/* k */ -keywords { - /* Empty Rule Set */ -} -kinesic { - /* Empty Rule Set */ -} -/* l */ -l { - display: block; - padding-left: 2em; - text-indent: -2em; -} -list[type="gloss"] > label { - display: block; - margin-top: 0.25em; - margin-bottom: 0.25em; - font-weight: bold; -} -l:nth-of-type(5n):before { - content: attr(n); - width: 2em; - display: block; - float: left; - margin-left: -2em; -} -lacunaEnd { - /* Empty Rule Set */ -} -lacunaStart { - /* Empty Rule Set */ -} -lang { - /* Empty Rule Set */ -} -langKnowledge { - /* Empty Rule Set */ -} -langKnown { - /* Empty Rule Set */ -} -langUsage { - /* Empty Rule Set */ -} -language { - /* Empty Rule Set */ -} -layout { - /* Empty Rule Set */ -} -layoutDesc { - /* Empty Rule Set */ -} -lb { - /* Empty Rule Set */ -} -lb:after { - content: '\a'; - white-space: pre; -} -lbl { - /* Empty Rule Set */ -} -leaf { - /* Empty Rule Set */ -} -lem { - /* Empty Rule Set */ -} -lg { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -link { - /* Empty Rule Set */ -} -linkGrp { - /* Empty Rule Set */ -} -list { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -item > list { - margin-top: 0; -} -/* Match only lists that are descendants of -text. Otherwise they show up in the header. */ -text list[type=simple] { - list-style-type: none; -} -text list[type=bulleted] { - list-style-type: disc; -} -text list[type=ordered] { - list-style-type: none; - counter-reset: items 0; -} -text list[type=ordered] > item { - display: list-item; - margin-left: 0; - list-style-type: none; - counter-increment: items; -} -item > list[type=ordered] { - margin-left: 1em; -} -text list[type=ordered] > item:before { - content: counter(items, decimal) ". "; -} -text list[type=gloss] { - list-style-type: none; -} -item > list[type=ordered] { - margin-left: 1em; -} -localName { - /* Empty Rule Set */ -} -locale { - /* Empty Rule Set */ -} -location { - /* Empty Rule Set */ -} -locus { - /* Empty Rule Set */ -} -locusGrp { - /* Empty Rule Set */ -} -/* m */ -m { - /* Empty Rule Set */ -} -macroRef { - /* Empty Rule Set NOT SURE WHAT EXACTLY*/ -} -macroSpec { - /* dunno */ -} -mapping { - /* not sure, maybe create rends for a few standard types, maybe hide */ -} -material { - /* Empty Rule Set */ -} -measure { - /* Empty Rule Set */ -} -measureGrp { - /* probably want to display attributes, at least units and type */ -} -meeting { - /*Block */ -} -memberOf { - /* Empty Rule Set */ -} -mentioned { - /* think do nothing, not real clear on function, maybe hide? */ -} -metDecl { - /* Empty Rule Set */ -} -metSym { - /* Empty Rule Set */ -} -milestone { - display: block; - margin-left: auto; - margin-right: auto; - text-align: center; -} -milestone:before { - content: "* * * * *"; -} -moduleRef { - /* probably hide, not sure how we want to deal */ -} -moduleSpec { - /* probably hide, not sure how we want to deal */ -} -monogr { - /* block with space above, below */ -} -mood { - /* Empty Rule Set */ -} -move { - /* not sure, block, maybe just ital, maybe in parenths*/ -} -msContents .block-margins { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -msDesc { - /* block with space above, below */ -} -msIdentifier { - /* block */ -} -msItem { - /* block */ -} -msItemStruct { - /* block */ -} -msName { - /* Empty Rule Set */ -} -msPart { - /* not sure, think block */ -} -musicNotation { - font-weight: bold; -} -musicNotation:before { - font-weight: bold; - content: "Musical Notation: "; -} -/* n */ -name { - /* Empty Rule Set */ -} -nameLink { - /* Empty Rule Set */ -} -namespace { - /* not sure, hide? */ -} -nationality { - /* Empty Rule Set */ -} -node { - display: none; -} -normalization { - /* Empty Rule Set */ -} -note { - display: block; - margin: 1.5em auto 1.5em auto; - padding: .5em 1.5em 1.5em 1.5em; - border: 1px solid black; - border-radius: 15px; - width: 325px; - position: relative; - border: 1px solid #aaaaaa; - background: #fafafa; - /* reset text-indent for note with ancestors. */ - - text-indent: 0; - font-size: 85%; - text-align: justify; - -webkit-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - -moz-box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); - box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25); -} -notesStmt { - /* do we want to box each individual if they're in a ? */ - - display: none; -} -num { - /* Empty Rule Set */ -} -number { - /* Empty Rule Set */ -} -numeric { - /* not sure, depends how we're dealing with 's */ -} -nym { - /* not really sure here */ -} -/* o */ -oRef { - /* not sure, think do nothing */ -} -oVar { - font-style: italic; -} -objectDesc { - /* Empty Rule Set */ -} -objectType { - /* Empty Rule Set */ -} -occupation { - /* Empty Rule Set */ -} -offset { - /* Empty Rule Set */ -} -opener { - /* Empty Rule Set */ -} -org { - /* Empty Rule Set */ -} -orgName { - /* Empty Rule Set */ -} -origDate { - /* Empty Rule Set */ -} -origPlace { - font-weight: bold; -} -origPlace:before { - font-weight: bold; - content: "Place of Origin: "; -} -origin { - /* Empty Rule Set */ -} -/* p */ -p { - display: block; - margin-top: 1em; - margin-bottom: 1em; - text-align: justify; -} -*[rendition~="#center"] p { - text-align: center; -} -availability > p:first-child { - margin-top: 0em; -} -pRef { - /* rend attribute target */ -} -pVar { - /* rend attribute target */ -} -particDesc { - /* Empty Rule Set */ -} -pause { - /* Empty Rule Set*/ -} -.pb { - display: block; - width: 100%; - text-align: right; - color: gray; - margin: 2em 0 2em 0; - font-size: 11pt; -} -pc { - /* Empty Rule Set */ -} -per { - /* don't know, check back */ -} -performance { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -persName { - /* Empty Rule Set */ -} -person { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -personGrp { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -phr { - /* Empty Rule Set */ -} -physDesc { - /* Empty Rule Set */ -} -place { - /* Empty Rule Set */ -} -placeName { - /* Empty Rule Set */ -} -population { - /* dunno with this one */ -} -pos { - /* Empty Rule Set */ -} -postBox { - /* Empty Rule Set */ -} -postCode { - /* Empty Rule Set */ -} -postscript { - display: block; - margin-top: 2em; -} -precision { - /* Empty Rule Set */ -} -preparedness { - /* Empty Rule Set */ -} -principal { - font-weight: bold; -} -principal:before { - font-weight: bold; - content: "Principal: "; -} -profileDesc { - display: none; -} -projectDesc { - /* Empty Rule Set */ -} -prologue { - /* Empty Rule Set */ -} -pron { - /* Empty Rule Set */ -} -provenance { - display: block; - margin-top: 0; - margin-bottom: 0; -} -ptr { - /* dunno */ -} -pubPlace { - /* Empty Rule Set */ -} -publicationStmt > * { - display: none; -} -publicationStmt { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -publicationStmt > date { - display: none; -} -publicationStmt > publisher { - display: none; -} -purpose { - /* Empty Rule Set */ -} -/* q */ -q { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -q:before { - content: open-quote; -} -q:after { - content: close-quote; -} -q[next]:after { - content: "" !important; -} -q[prev]:before { - content: "" !important; -} -quotation { - /* Empty Rule Set */ -} -quote { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -quote:before { - content: open-quote; -} -quote:after { - content: close-quote; -} -quote[next]:after { - content: "" !important; -} -quote[prev]:before { - content: "" !important; -} -/* r */ -rdg { - /*perhaps choice */ -} -rdgGrp { - /* Empty Rule Set */ -} -re { - display: block; - margin-top: 0; - margin-bottom: 0; -} -recordHist { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -recording { - /* not sure here, only in header? */ -} -recordingStmt { - /* Empty Rule Set */ -} -ref { - /*include link if target */ -} -region { - /* Empty Rule Set */ -} -relatedItem { - /* Empty Rule Set */ -} -relation { - /* Don't Know*/ -} -relationGrp { - /* Empty Rule Set */ -} -remarks { - font-weight: bold; -} -remarks:before { - font-weight: bold; - content: "remarks: "; -} -rendition { - /*Don't remember what we decided to do with this*/ -} -repository { - /* Empty Rule Set */ -} -residence { - /* Empty Rule Set */ -} -resp { - /* Empty Rule Set */ -} -respStmt { - display: block; - margin-top: 0; - margin-bottom: 0; -} -/* hide */ -restore { - /* footnote or sidenote perhaps*/ -} -revisionDesc { - display: none; -} -rhyme { - /* Empty Rule Set */ -} -role { - /* put on same line as roledesc? */ -} -roleDesc { - /* put on same line as role */ -} -roleName { - /* Empty Rule Set */ -} -root { - /* don't know */ -} -row { - display: table-row; -} -rs { - /* Empty Rule Set */ -} -/*label*/ -/* s */ -/* When TEI document is embedded in HTML page, - TEI's element can be interpreted by - browser as HTML , which results in - a strike-through from the "user agent" - styles. */ -s { - text-decoration: none; -} -said { - /* Empty Rule Set */ -} -salute { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -samplingDecl { - display: block; - margin-top: 0; - margin-bottom: 0; -} -schemaSpec { - /*NOT SURE, talk over with group */ -} -scriptDesc { - /*NOT SURE, talk over with group */ -} -scriptNote { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -scriptStmt { - /* not sure */ -} -seal { - display: block; - margin-top: 0; - margin-bottom: 0; -} -seal:before { - font-weight: bold; - content: "Seal: "; -} -sealDesc { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -secFol:before { - font-weight: bold; - content: "Second Folio: "; -} -seg { - /* Empty Set Rule */ -} -segmentation { - /* Empty Rule Set */ -} -sense { - display: block; - margin-top: 0; - margin-bottom: 0; -} -series { - /* treat same as seriesstmt? */ -} -seriesStmt { - display: none; -} -set { - /* Empty Set Rule */ -} -setting { - display: block; - margin-top: 0; - margin-bottom: 0; -} -settingDesc { - /* Empty Set Rule */ -} -settlement { - /* Empty Set Rule */ -} -sex { - /* Empty Rule Set */ -} -shift { - /* seems a bit to complex to do anything with */ -} -sic { - /* rend as choice when contained within a choice tag, perhaps as label with parenthesis after when alone */ -} -signatures { - /* DON't KNOW, look again later */ -} -signed { - display: block; - margin-top: 2em; - /*should make name a block when contained within */ - -} -soCalled { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -soCalled:before { - content: open-quote; -} -soCalled:after { - content: close-quote; -} -soCalled[next]:after { - content: "" !important; -} -soCalled[prev]:before { - content: "" !important; -} -socecStatus { - /* Empty Set Rule */ -} -sound { - font-style: italic; -} -source { - display: block; - margin-top: 0; - margin-bottom: 0; -} -sourceDesc { - display: none; -} -sp { - /*empty rule set*/ -} -space:before { - font-weight: bold; - content: ""; -} -TEI span { - /* jawalsh: why were we hiding this? */ - - /* .hide; */ - -} -TEI egXML span { - display: inline; -} -spanGrp { - /* NOT SURE, look back on */ -} -speaker { - font-weight: bold; - margin-right: 0; -} -specDesc { - /* NOT SURE, look back on */ -} -specGrp { - /* NOT SURE, look back on */ -} -specGrpRef { - /* NOT SURE, look back on */ -} -specList { - /* Empty Set Rule */ -} -sponsor { - display: block; - margin-top: 0; - margin-bottom: 0; - /* Block element, maybe labeled */ - -} -sponsor:before { - font-weight: bold; - content: "Sponsor:"; -} -stage { - display: block; - margin-top: 1em; - margin-bottom: 1em; - font-style: italic; -} -stamp { - display: block; - margin-top: 1em; - margin-bottom: 1em; -} -stamp:before { - font-weight: bold; - content: "Stamped: "; -} -state { - /* Empty Set Rule */ -} -stdVals { - /* Empty Set Rule */ -} -street { - /* Empty Set Rule */ -} -stress { - /* Empty Set Rule */ -} -string { - /* Empty Set Rule */ -} -stringVal { - /* doesn't seem to be part of tei 5 */ -} -subc { - /* Empty Set Rule */ -} -subst { - /* Empty Set Rule */ -} -summary { - /* Empty Set Rule */ -} -superEntry { - /* Block with space above and below, maybe have no block and space for when contained by this element */ -} -supplied { - /* not sure on this one, seems like we should indicate somehow. Is there a standard way to do this? */ -} -support { - /* Empty Set Rule */ -} -supportDesc { - /* do nothing with or maybe block */ -} -surface { - /* choice */ -} -surname { - /* Empty Set Rule */ -} -surplus { - display: none; -} -surrogates { - /*Empty Rule Set */ -} -syll { - /* Empty Set Rule */ -} -symbol { - /* Empty Set Rule */ -} -/* t */ -TEI { - display: block; -} -table { - border-collapse: separate; - border-spacing: 2px; -} -/* Why is this selector "TEI table" instead of just "table"? */ -TEI table { - display: block; - margin-top: 2em; - margin-bottom: 2em; - font-size: 12pt; -} -table > head { - text-align: center; -} -teiHeader { - display: block; - /* -border-radius: 15px; -border: 1px solid black; -background:white; -*/ - - margin-top: 2em; - margin-bottom: 2em; - border-bottom: 1px solid #999; -} -TEI > text { - display: block; - /* -border-radius: 15px; -border: 1px solid black; -background:white; -*/ - - line-height: 1.5; -} -textClass { - display: none; -} -textDesc { - display: none; -} -/* title */ -/* Need TEI ancestor to distinguish TEI title from HTML title */ -TEI title { - display: inline; -} -TEI title[level=a] { - quotes: "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d" "\2018" "\2019" "\201c" "\201d"; -} -TEI title[level=a]:before { - content: open-quote; -} -TEI title[level=a]:after { - content: close-quote; -} -TEI title[level=a][next]:after { - content: "" !important; -} -TEI title[level=a][prev]:before { - content: "" !important; -} -title[level=m] { - font-style: italic; -} -/* We transformed teiHeader//title to tei.title */ -/* as a hack to solve a JavaScript/jQuery issue. */ -titleStmt > tei-title { - display: block; - font-family: Arvo, sans-serif; - font-weight: normal; - font-weight: bold !important; - font-size: 150%; -} -titleStmt > editor:before { - content: "Edited by "; -} -typeDesc { - display: none; -} -/* u */ -u:before { - content: "-"; -} -unicodeName { - /* Empty Rule Set */ -} -usg { - /* Empty Rule Set */ -} -/* v */ -vAlt { - /* Empty Rule Set */ -} -vColl { - /* Empty Rule Set */ -} -vDefault { - /* Empty Rule Set */ -} -vLabel { - /* Empty Rule Set */ -} -vMerge { - /* Empty Rule Set */ -} -vNot { - /* Empty Rule Set */ -} -vRange { - /* Empty Rule Set */ -} -val { - /* Empty Rule Set */ -} -valDesc { - /* Empty Rule Set */ -} -valItem { - /* Empty Rule Set */ -} -valList { - /* Empty Rule Set */ -} -value { - /* Empty Rule Set */ -} -variantEncoding { - /* Empty Rule Set */ -} -view { - font-style: italic; -} -vocal { - /* Empty Rule Set */ -} -/* w */ -w { - /* Empty Rule Set */ -} -watermark { - /* Empty Rule Set */ -} -when { - /* Empty Rule Set */ -} -width { - /* Empty Rule Set */ -} -wit { - /* Empty Rule Set */ -} -witDetail { - /* Empty Rule Set */ -} -witEnd { - /* Empty Rule Set */ -} -witStart { - /* Empty Rule Set */ -} -witness { - /* Empty Rule Set */ -} -writing { - /* Empty Rule Set */ -} -/* x */ -xr { - /* Empty Rule Set */ -} -/* z */ -zone { - /* Empty Rule Set */ -} -/* styles for html shell and html elements in TEI (e.g., and ) */ -/* xml-serialization */ -.eg-element { - color: #0165c8; -} -.eg-comment { - color: gray; -} -.eg-att, -.eg-nsdecl { - color: #f58650; -} -.eg-attvalue, -.eg-ns { - color: #993300; -} -.eg-text { - color: #292929; -} -/* loading animation */ -#loading { - display: none; - position: fixed; - left: 0; - top: 0; - width: 100%; - height: 100%; -} -/* facsViewer */ -#resizable { - background-color: #ebebeb; - width: 550px; - height: 700px; - overflow: hidden; - padding: 0 1em .25em 0; -} -div.facsImage { - width: 100%; - height: 98%; - overflow-y: scroll; - border: 1px solid black; -} -div.facsImage img { - max-width: 98% !important; - margin-top: .5em; -} -div.facsImage img:first-child { - margin-top: 0; -} -.head-font { - font-family: Arvo, sans-serif; - font-weight: normal; -} - diff --git a/examples/translations.css b/examples/translations.css deleted file mode 100644 index 4fd33f4..0000000 --- a/examples/translations.css +++ /dev/null @@ -1,12 +0,0 @@ -#reading-container article { - padding:0.404em 2.617em 1.2em; - margin:0 auto 3em; - font-family: 'Palatino', 'Palatino Linotype', 'Georgia', 'Serif'; - max-width: 90%; - background-color: #FFF; - - -moz-box-shadow: 1px 2px 0px 0px #656565; - -webkit-box-shadow: 1px 2px 0px 0px #656565; - -o-box-shadow: 1px 2px 0px 0px #656565; - box-shadow: 1px 2px 0px 0px #656565; -} \ No newline at end of file diff --git a/examples/translations/r_double.html b/examples/translations/r_double.html deleted file mode 100644 index 4f71045..0000000 --- a/examples/translations/r_double.html +++ /dev/null @@ -1,36 +0,0 @@ -{% extends "main::container.html" %} - -{% block article %} -
    - -
    -
    -

    {{visavis_version.metadata["description"][lang]}}

    -
    -
    - {{ visavis_text_passage }} -
    -
    -
    -{% endblock %} \ No newline at end of file diff --git a/flask_nemo/__init__.py b/flask_nemo/__init__.py index 078a8f6..c594744 100644 --- a/flask_nemo/__init__.py +++ b/flask_nemo/__init__.py @@ -7,22 +7,27 @@ """ from urllib.parse import quote -import os.path as op from operator import itemgetter -import jinja2 -from flask import render_template, Blueprint, abort, Markup, send_from_directory, Flask, url_for, redirect, request -from lxml import etree +from warnings import warn +from collections import Callable, OrderedDict from copy import deepcopy as copy from pkg_resources import resource_filename -from collections import Callable, OrderedDict + +from lxml import etree +from flask import render_template, Blueprint, abort, Markup, send_from_directory, Flask, url_for, redirect, request + +import jinja2 +import inspect +import os.path as op + from MyCapytain.common.constants import Mimetypes from MyCapytain.resources.prototypes.metadata import ResourceCollection from MyCapytain.resources.prototypes.cts.inventory import CtsWorkMetadata, CtsEditionMetadata from MyCapytain.errors import UnknownCollection -import inspect import flask_nemo._data import flask_nemo.filters +from flask_nemo.errors import ValueWarning from flask_nemo.chunker import level_grouper as __level_grouper__ from flask_nemo.plugins.default import Breadcrumb from flask_nemo.common import resource_qualifier, ASSETS_STRUCTURE @@ -122,7 +127,7 @@ def __init__(self, cache=None, resolver=None, plugins=None, template_folder=None, static_folder=None, static_url_path=None, - urls=None, transform=None, chunker=None, prevnext=None, + urls=None, transform=None, chunker=None, css=None, js=None, templates=None, statics=None, prevent_plugin_clearing_assets=False, original_breadcrumb=True, default_lang="eng"): @@ -130,6 +135,11 @@ def __init__(self, self.name = __name__ if name: self.name = name + + if base_url == "/": + warn("Nemo(base_url) cannot be '/'. If you wish to use the root URL, you need to use an empty value ''. " + "This was automatically set to ''", ValueWarning) + base_url = "" self.prefix = base_url self.resolver = resolver diff --git a/flask_nemo/chunker.py b/flask_nemo/chunker.py index b46974d..dfb1337 100644 --- a/flask_nemo/chunker.py +++ b/flask_nemo/chunker.py @@ -61,7 +61,7 @@ def line_chunker(text, getreffs, lines=30): return reffs -def level_chunker(text, getValidReff, level=1): +def level_chunker(text, getreffs, level=1): """ Chunk a text at the passage level :param text: Text object @@ -71,15 +71,15 @@ def level_chunker(text, getValidReff, level=1): :return: List of urn references with their human readable version :rtype: [(str, str)] """ - references = getValidReff(level=level) + references = getreffs(level=level) return [(ref.split(":")[-1], ref.split(":")[-1]) for ref in references] -def level_grouper(text, getValidReff, level=None, groupby=20): +def level_grouper(text, getreffs, level=None, groupby=20): """ Alternative to level_chunker: groups levels together at the latest level :param text: Text object - :param getValidReff: GetValidReff query callback + :param getreffs: GetValidReff query callback :param level: Level of citation to retrieve :param groupby: Number of level to groupby :return: Automatically curated references @@ -87,7 +87,7 @@ def level_grouper(text, getValidReff, level=None, groupby=20): if level is None or level > len(text.citation): level = len(text.citation) - references = [ref.split(":")[-1] for ref in getValidReff(level=level)] + references = [ref.split(":")[-1] for ref in getreffs(level=level)] _refs = OrderedDict() for key in references: diff --git a/flask_nemo/errors.py b/flask_nemo/errors.py new file mode 100644 index 0000000..1be7c69 --- /dev/null +++ b/flask_nemo/errors.py @@ -0,0 +1,3 @@ +class ValueWarning(Warning): + """ This warning is issued when a value was incorrect and automatically corrected """ + pass \ No newline at end of file diff --git a/setup.py b/setup.py index 6e9e335..1538eab 100644 --- a/setup.py +++ b/setup.py @@ -1,13 +1,13 @@ from setuptools import setup, find_packages -version = "1.0.1" +version = "1.0.2" setup( name='flask_nemo', version=version, packages=find_packages(exclude=["examples", "tests"]), url='https://github.com/capitains/flask-capitains-nemo', - license='GNU GPL', + license='Mozilla Public License Version 2.0', author='Thibault Clerice', author_email='leponteineptique@gmail.com', description='Flask Extension to browse CTS Repository', diff --git a/tests/test_init.py b/tests/test_init.py index 1297d87..319b7cf 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -56,3 +56,9 @@ def test_other_endpoint(self): """ Test when an endpoint is set """ nemo = Nemo(resolver=NautilusDummy) self.assertEqual(nemo.resolver, NautilusDummy, "Endpoint should be set through endpoint parameter") + + def test_warn_on_empty_value(self): + """ Test when an endpoint is set """ + from flask_nemo.errors import ValueWarning + with self.assertWarns(ValueWarning): + nemo = Nemo(base_url="/") diff --git a/tests/test_resources.py b/tests/test_resources.py index c03a612..acbff07 100644 --- a/tests/test_resources.py +++ b/tests/test_resources.py @@ -22,15 +22,21 @@ def create_test_app(debug=False, config=None): class RequestPatch(object): """ Request patch object to deal with patching reply in flask.ext.nemo """ + encoding = "utf-8" + def __init__(self, f): self.__text = f.read() + @staticmethod + def raise_for_status(): + return None + @property def text(self): return self.__text -class RequestPatchChained(object): +class RequestPatchChained(RequestPatch): """ Request patch object to deal with patching reply in flask.ext.nemo """ def __init__(self, requests):