{ "info": { "author": "Maarten van Gompel", "author_email": "proycon@anaproy.nl", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "Intended Audience :: Science/Research", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", "Operating System :: POSIX", "Programming Language :: Python :: 3.2", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5", "Topic :: Text Processing :: Linguistic" ], "description": ".. image:: http://applejack.science.ru.nl/lamabadge.php/foliadocserve\n :target: http://applejack.science.ru.nl/languagemachines/\n\n*****************************************\nFoLiA Document Server\n*****************************************\n\nThe FoLiA Document Server is a backend HTTP service to interact with documents\nin the FoLiA format, a rich XML-based format for linguistic annotation\n(http://proycon.github.io/folia). It provides an interface to efficiently edit\nFoLiA documents through the FoLiA Query Language (FQL). However, it is not\ndesigned as a multi-document search tool.\n\nThe FoLiA Document server is used by FLAT (https://github.com/proycon/flat)\n\nThe FoLiA Document Server is written in Python 3, using the FoLiA library in\npynlpl and cherrypy.\n\n\n============================================\nArchitecture\n============================================\n\nThe FoLiA Document Server consists of a document store that groups documents\ninto namespaces, a namespace can correspond for instance to a user ID or a\nproject.\n\nDocuments are automatically loaded and unloaded as they are requested and\nexpire. Loaded documents are kept in memory fully to facilitate rapid access\nand are serialised back to XML files on disk when unloaded.\n\nThe document server is a webservice that receives requests over HTTP. Requests\ninteracting with a FoLiA document consist of statements in FoLiA Query Language\n(FQL). For some uses the Corpus Query Language (CQL) is also supported.\nResponses are FoLiA XML or parsed into JSON (may contain HTML excerpts too), as\nrequested in the FQL queries themselves.\n\nFeatures:\n\n* webservice\n* queries using FQL, or alternatively CQL (limited)\n* multiple return formats (FoLiA XML, JSON, FLAT)\n* versioning control support using git\n* full support for corrections, alternatives!\n* support for concurrency\n\nNote that this webservice is *NOT* intended to be publicly exposed, but rather\nto be used as a back-end by another system. The document server does support\nconstraining namespaces to certain session ids, constraining FQL queries to not\nviolate their namespace, and constraining uploads by session id or namespace.\nThis is secure for public exposure only when explicitly enabled and used over\nHTTPS.\n\nIf you are looking for a command line tool that interprets FQL/CQL and queries\nFoLiA documents, use the ``foliaquery`` tool from the FoLiA-tools package\nrather than this document server, see https://github.com/proycon/folia\n\n=======================\nInstallation & Usage\n=======================\n\nYou can directly fetch the document server from the Python Package Index::\n\n $ pip install foliadocserve\n\nAlternatively, install manually from the git repository or downloaded tarball::\n\n $ python setup.py install\n\nYou may need to use ``sudo`` for global installation.\n\nCreate a writable directory to hold documents, this is the document root path. Then\nstart the document server as follows::\n\n $ foliadocserve -d /path/to/document/root\n\nSee ``-h`` for further options.\n\nWhen started, a simple web-interface will be available on the specified host and port.\n\n=========================================\nWebservice Specification\n=========================================\n\nCommon variables in request URLs:\n\n* **namespace** - A group identifier\n* **docid** - The FoLiA document ID\n* **sessionid** - A session ID, can be set to ``NOSID`` if no sessioning is\n desired. Usage of session IDs enable functionality such as caching and\n concurrency.\n\n---------------------------\nQuerying & Annotating\n---------------------------\n\n* ``/query/`` (POST) - Content body consists of FQL queries, one per line (text/plain). The request header may contain ``X-sessionid`` and must contain ``Content-Length``.\n* ``/query/?query=`` (GET) -- HTTP GET alias for the above, limited to a single query\n\nThese URLs will return HTTP 200 OK, with data in the format as requested in the FQL\nquery if the query is succesful. If the query contains an error, an HTTP 404 response\nwill be returned.\n\n-------------\nVersioning\n-------------\n\n* ``/getdochistory//`` (GET) - Obtain the git history for the specified document. Returns a JSON response: ``{'history':[ {'commit': commithash, 'msg': commitmessage, 'date': commitdata } ] }``\n* ``/revert///`` (GET) - Revert the document's state to the specified commit hash\n\n---------------------------\nDocument Management\n---------------------------\n\n* ``/namespaces/`` (GET) -- List of all the namespaces\n* ``/documents//`` (GET) -- Document Index for the given namespace (JSON list)\n* ``/upload//`` (POST) -- Uploads a FoLiA XML document to a namespace, request body contains FoLiA XML.\n* ``/create//`` (POST) -- Create a new namespace\n\n\n\n\n========================================\nFoLiA Query Language (FQL)\n========================================\n\nFQL statements are separated by newlines and encoded in UTF-8. The expressions\nare case sensitive, all keywords are in upper case, all element names and\nattributes in lower case.\n\nFQL is also strict about parentheses, they are generally either required or forbidden\nfor an expression. Parentheses usually indicate a sub-expression, and it is also used in\nboolean logic.\n\nAs a general rule, it is more efficient to do a single big query than multiple\nstandalone queries.\n\nNote that for readability, queries may have been split on multiple lines\nin the presentation here, whereas in reality they should be on one.\n\n\n-------------------\nGlobal variables\n-------------------\n\n* ``SET =`` - Sets global variables that apply to all statements that follow. String values need to be in double quotes. Available variables are:\n* **annotator** - The name of the annotator\n* **annotatortype** - The type of the annotator, can be *auto* or *manual*\n\nUsually your queries on a particular annotation type are limited to one\nspecific set. To prevent having to enter the set explicitly in your queries,\nyou can set defaults. The annotation type corresponds to a FoLiA element::\n\n DEFAULTSET entity https://raw.githubusercontent.com/proycon/folia/master/setdefinitions/namedentitycorrection.foliaset.xml\n\nIf the FoLiA document only has one set of that type anyway, then this is not even\nnecessary and the default will be automatically set.\n\n-------------------\nDocument Selection\n-------------------\n\nFQL statements for the document server start with a document selector, represented by the\nkeyword **USE**::\n\n USE /\n\nThis selects what document to apply the query to, the document will be\nautomatically loaded and unloaded by the server as it sees fit. It can be\nprepended to any action query or used standalone, in which case it will apply o\nall subsequent queries.\n\nAlternatively, the **LOAD** statement loads an arbitrary file from disk, but its use\nis restricted to the command line ``foliaquery`` tool rather than this document server::\n\n LOAD \n\nIf you're interested in retrieving the full document rather than doing specific querying, use\n``GET`` statement immediately after a ``USE`` or ``LOAD`` expression.\n\n-----------------\nDeclarations\n-----------------\n\nAll annotation types in FoLiA need to be declared. FQL does this for you\nautomatically. If you make an edit of a previously undeclared set, it will be\ndeclared for you. These default declarations will never assign default\nannotators or annotator types.\n\nExplicit declarations are possible using the ``DECLARE`` keyword followed by\nthe annotation type you want to declare, this represented the tag of the\nrespective FoLiA annotation element::\n\n DECLARE entity OF \"https://github.com/proycon/folia/blob/master/setdefinitions/namedentities.foliaset.xml\"\n WITH annotator = \"me\" annotatortype = \"manual\"\n\nNote that the statement must be on one single line, it is split here only for ease of\npresentation.\n\nThe **WITH** clause is optional, the set following the **OF** keyword is mandatory.\n\nDeclarations may be chained, i.e. multiple **DECLARE** statements may be issued\non one line, as well as prepended to action statements (see next section).\n\n---------\nActions\n---------\n\nThe core part of an FQL statement consists of an action verb, the following are\navailable\n\n* ``SELECT []`` - Selects an annotation\n* ``DELETE []`` - Deletes an annotation\n* ``EDIT [] []`` - Edits an existing annotation\n* ``ADD `` - Adds an annotation (to the target expression)\n* ``APPEND `` - Inserts an annotation after the target expression\n* ``PREPEND `` - Inserts an annotation before the target expression\n\nFollowing the action verb is the focus expression, this starts with an\nannotation type, which is equal to the FoLiA XML element tag. The set is\nspecified using ``OF `` and/or the ID with ``ID ``. An example:\n\n pos OF \"http://some.domain/some.folia.set.xml\"\n\nIf an annotation type is already declared and there is only one in document, or\nif the **DEFAULTSET** statement was used earlier, then the **OF** statement can\nbe omitted and will be implied and detected automatically. If it is ambiguous,\nan error will be raised (rather than applying the query regardless of set).\n\nTo further filter a the focus, the expression may consist of a **WHERE** clause\nthat filters on one or more FoLiA attributes:\n\n* **class**\n* **annotator**\n* **annotatortype**\n* **n**\n* **confidence**\n\nThe following attribute is also available on when the elements contains text:\n\n* **text**\n\nThe **WHERE** statement requires an operator (=,!=,>,<,<=,>=,CONTAINS,MATCHES), the **AND**,\n**OR** and **NOT** operators are available (along with parentheses) for\ngrouping and boolean logic. The operators must never be glued to the attribute\nname or the value, but have spaces left and right.\n\nWe can now show some examples of full queries with some operators:\n\n* ``SELECT pos OF \"http://some.domain/some.folia.set.xml\"``\n* ``SELECT pos WHERE class = \"n\" AND annotator = \"johndoe\"``\n* ``DELETE pos WHERE class = \"n\" AND annotator != \"johndoe\"``\n* ``DELETE pos WHERE class = \"n\" AND annotator CONTAINS \"john\"``\n* ``DELETE pos WHERE class = \"n\" AND annotator MATCHES \"^john$\"``\n\nThe **ADD** and **EDIT** change actual attributes, this is done in the\n*assignment expression* that starts with the **WITH** keyword. It applies to\nall the common FoLiA attributes like the **WHERE** keyword, but has no operator or\nboolean logic, as it is a pure assignment function.\n\nSELECT and DELETE only support WHERE, EDIT supports both WHERE and WITH, if\nboth are use they than WHERE is always before WITH. the ADD action supports only WITH. If\nan EDIT is done on an annotation that can not be found, and there is no WHERE\nclause, then it will fall back to ADD.\n\nHere is an **EDIT** query that changes all nouns in the document to verbs::\n\n EDIT pos WHERE class = \"n\" WITH class \"v\" AND annotator = \"johndoe\"\n\nThe query is fairly crude as it still lacks a *target expression*: A *target\nexpression* determines what elements the focus is applied to, rather than to\nthe document as a whole, it starts with the keyword **FOR** and is followed by\neither an annotation type (i.e. a FoLiA XML element tag) *or* the ID of an\nelement. The target expression also determines what elements will be returned.\nMore on this in a later section.\n\nThe following FQL query shows how to get the part of speech tag for a\nword::\n\n SELECT pos FOR ID mydocument.word.3\n\nOr for all words::\n\n SELECT pos FOR w\n\nThe **ADD** action almost always requires a target expression::\n\n ADD pos WITH class \"n\" FOR ID mydocument.word.3\n\nMultiple targets may be specified, comma delimited::\n\n ADD pos WITH class \"n\" FOR ID mydocument.word.3 , ID myword.document.word.25\n\nThe target expression can again contain a **WHERE** filter::\n\n SELECT pos FOR w WHERE class != \"PUNCT\"\n\nTarget expressions, starting with the **FOR** keyword, can be nested::\n\n SELECT pos FOR w WHERE class != \"PUNCT\" FOR event WHERE class = \"tweet\"\n\nYou may also use the SELECT keyword without focus expression, but only with a target expression. This is particularly useful when you want to return multiple distinct elements, for instance by ID::\n\n SELECT FOR ID mydocument.word.3 , ID myword.document.word.25\n\nThe **SELECT** keyword can also be used with the special **ALL** selector that selects all elemens in the scope, the following two statement are identical and will return all elements in the document::\n\n SELECT ALL\n SELECT FOR ALL\n\nIt can be used at deeper levels too, the following will return everything under all words::\n\n SELECT ALL FOR w\n\nTarget expressions are vital for span annotation, the keyword **SPAN** indicates\nthat the target is a span (to do multiple spans at once, repeat the SPAN\nkeyword again), the operator ``&`` is used for consecutive spans, whereas ``,``\nis used for disjoint spans::\n\n ADD entity WITH class \"person\" FOR SPAN ID mydocument.word.3 & ID myword.document.word.25\n\nThis works with filters too, the ``&`` operator enforced a single consecutive span::\n\n ADD entity WITH class \"person\" FOR SPAN w WHERE text = \"John\" & w WHERE text = \"Doe\"\n\nRemember we can do multiple at once::\n\n ADD entity WITH class \"person\" FOR SPAN w WHERE text = \"John\" & w WHERE text = \"Doe\"\n SPAN w WHERE text = \"Jane\" & w WHERE text = \"Doe\"\n\nThe **HAS** keyword enables you to descend down in the document tree to\nsiblings. Consider the following example that changes the part of speech tag\nto \"verb\", for all occurrences of words that have lemma \"fly\". The parentheses\nare mandatory for a **HAS** statement::\n\n EDIT pos OF \"someposset\" WITH class = \"v\" FOR w WHERE (lemma OF \"somelemmaset\" HAS class \"fly\")\n\nTarget expressions can be former with either **FOR** or with **IN**, the\ndifference is that **IN** is much stricter, the element has to be a direct\nchild of the element in the **IN** statement, whereas **FOR** may skip\nintermediate elements. In analogy with XPath, **FOR** corresponds to ``//`` and\n**IN** corresponds to ``/``. **FOR** and **IN** may be nested and mixed at\nwill. The following query would most likely not yield any results because there are\nlikely to be paragraphs and/or sentences between the wod and event structures::\n\n SELECT pos FOR w WHERE class != \"PUNCT\" IN event WHERE class = \"tweet\"\n\n\nMultiple actions can be combined, all share the same target expressions::\n\n ADD pos WITH class \"n\" ADD lemma WITH class \"house\" FOR w WHERE text = \"house\" OR text = \"houses\"\n\nIt is also possible to nest actions, use parentheses for this, the nesting\noccurs after any WHERE and WITH statements::\n\n ADD w ID mydoc.sentence.1.word.1 (ADD t WITH text \"house\" ADD pos WITH class \"n\") FOR ID mydoc.sentence.1\n\nThough explicitly specified here, IDs will be automatically generated when necessary and not specified.\n\nThe **ADD** action has two cousins: **APPEND** and **PREPEND**.\nInstead of adding something in the scope of the target expression, they either append\nor prepend an element, so the inserted element will be a sibling::\n\n APPEND w (ADD t WITH text \"house\") FOR w WHERE text = \"the\"\n\nThis above query appends/inserts the word \"house\" after every definite article.\n\n---------\nText\n---------\n\nOur previous examples mostly focussed on part of speech annotation. In this\nsection we look at text content, which in FoLiA is an annotation element too\n(t).\n\nHere we change the text of a word::\n\n EDIT t WITH text = \"house\" FOR ID mydoc.word.45\n\nHere we edit or add (recall that EDIT falls back to ADD when not found and\nthere is no further selector) a lemma and check on text content::\n\n EDIT lemma WITH class \"house\" FOR w WHERE text = \"house\" OR text = \"houses\"\n\n\nYou can use WHERE text on all elements, it will cover both explicit text\ncontent as well as implicit text content, i.e. inferred from child elements. If\nyou want to be really explicit you can do::\n\n EDIT lemma WITH class \"house\" FOR w WHERE (t HAS text = \"house\")\n\n\n**Advanced**:\n\nSuch syntax is required when covering texts with custom classes, such as\nOCRed or otherwise pre-normalised text. Consider the following OCR correction::\n\n ADD t WITH text = \"spell\" FOR w WHERE (t HAS text = \"5pe11\" AND class = \"OCR\" )\n\n\n---------------\nQuery Response\n---------------\n\nWe have shown how to do queries but not yet said anything on how the response is\nreturned. This is regulated using the **RETURN** keyword:\n\n* **RETURN focus** (default)\n* **RETURN parent** - Returns the parent of the focus\n* **RETURN target** or **RETURN inner-target**\n* **RETURN outer-target**\n* **RETURN ancestor-target**\n\nThe default focus mode just returns the focus. Sometimes, however, you may want\nmore context and may want to return the target expression instead. In the\nfollowing example returning only the pos-tag would not be so interesting, you\nare most likely interested in the word to which it applies::\n\n SELECT pos WHERE class = \"n\" FOR w RETURN target\n\nWhen there are nested FOR/IN loops, you can specify whether you want to return\nthe inner one (highest granularity, default) or the outer one (widest scope).\nYou can also decide to return the first common structural ancestor of the\n(outer) targets, which may be specially useful in combination with the **SPAN**\nkeyword.\n\nThe return type can be set using the **FORMAT** statement:\n\n* **FORMAT xml** - Returns FoLiA XML, the response is contained in a simple\n ```` structure.\n* **FORMAT single-xml** - Like above, but returns pure unwrapped FoLiA XML and\n therefore only works if the response only contains one element. An error\n will be raised otherwise.\n* **FORMAT json** - Returns JSON list\n* **FORMAT single-json** - Like above, but returns a single element rather than\n a list. An error will be raised if the response contains multiple.\n* **FORMAT python** - Returns a Python object, can only be used when\n directly querying the FQL library without the document server\n* **FORMAT flat** - Returns a parsed format optimised for FLAT. This is a JSON reply\n containing an HTML skeleton of structure elements (key html), parsed annotations\n (key annotations). If the query returns a full FoLiA document, then the JSON object will include parsed set definitions, (key\n setdefinitions), and declarations.\n\nThe **RETURN** statement may be used standalone or appended to a query, in\nwhich case it applies to all subsequent queries. The same applies to the\n**FORMAT** statement, though an error will be raised if distinct formats are\nrequested in the same HTTP request.\n\nWhen context is returned in *target* mode, this can get quite big, you may\nconstrain the type of elements returned by using the **REQUEST** keyword, it\ntakes the names of FoLiA XML elements. It can be used standalone so it applies\nto all subsequent queries::\n\n REQUEST w,t,pos,lemma\n\n..or after a query::\n\n SELECT pos FOR w WHERE class!=\"PUNCT\" FOR event WHERE class=\"tweet\" REQUEST w,pos,lemma\n\nTwo special uses of request are ``REQUEST ALL`` (default) and ``REQUEST\nNOTHING``, the latter may be useful in combination with **ADD**, **EDIT** and\n**DELETE**, by default it will return the updated state of the document.\n\nNote that if you set REQUEST wrong you may quickly end up with empty results.\n\n---------------------\nSpan Annotation\n---------------------\n\nSelecting span annotations is identical to token annotation. You may be aware\nthat in FoLiA span annotation elements are technically stored in a separate\nstand-off layers, but you can forget this fact when composing FQL queries and can\naccess them right from the elements they apply to.\n\nThe following query selects all named entities (of an actual rather than a\nfictitious set for a change) of people that have the name John::\n\n SELECT entity OF \"https://github.com/proycon/folia/blob/master/setdefinitions/namedentities.foliaset.xml\"\n WHERE class = \"person\" FOR w WHERE text = \"John\"\n\nOr consider the selection of noun-phrase syntactic units (su) that contain the\nword house::\n\n SELECT su WHERE class = \"np\" FOR w WHERE text CONTAINS \"house\"\n\nNote that if the **SPAN** keyword were used here, the selection would be\nexclusively constrained to single words \"John\"::\n\n SELECT entity WHERE class = \"person\" FOR SPAN w WHERE text = \"John\"\n\nWe can use that construct to select all people named John Doe for instance::\n\n SELECT entity WHERE class = \"person\" FOR SPAN w WHERE text = \"John\" & w WHERE text = \"Doe\"\n\n\n\nSpan annotations like syntactic units are typically nested trees, a tree query\nsuch as \"//pp/np/adj\" can be represented as follows. Recall that the **IN**\nstatement starts a target expression like **FOR**, but is stricter on the\nhierarchy, which is what we would want here::\n\n SELECT su WHERE class = \"adj\" IN su WHERE class = \"np\" IN su WHERE class = \"pp\"\n\nIn such instances we may be most interested in obtaining the full PP::\n\n SELECT su WHERE class = \"adj\" IN su WHERE class = \"np\" IN su WHERE class = \"pp\" RETURN outer-target\n\n\nThe **EDIT** action is not limited to editing attributes, sometimes you\nwant to alter the element of a span. A separate **RESPAN** keyword (without\nFOR/IN/WITH) accomplishes this. It takes the keyword **RESPAN** which behaves the\nsame as a **FOR SPAN** target expression and represents the new scope of the\nspan, the normal target expression represents the old scope::\n\n EDIT entity WHERE class= \"person\" RESPAN ID word.1 & ID word.2 FOR SPAN ID word.1 & ID word.2 & ID word.3\n\n**WITH** statements can be used still too, they always preceed **RESPAN**::\n\n EDIT entity WHERE class= \"person\" WITH class=\"location\" RESPAN ID word.1 & ID word.2 FOR SPAN ID word.1 & ID word.2 & ID word.3\n\n\n\n------------------------------\nCorrections and Alternatives\n------------------------------\n\nBoth FoLiA and FQL have explicit support for corrections and alternatives on\nannotations. A correction is not a blunt substitute of an annotation of any\ntype, but the original is preserved as well. Similarly, an alternative\nannotation is one that exists alongside the actual annotation of the same type\nand set, and is not authoritative.\n\nThe following example is a correction but not in the FoLiA sense, it bluntly changes part-of-speech\nannotation of all occurrences of the word \"fly\" from \"n\" to \"v\", for example to\ncorrect erroneous tagger output::\n\n EDIT pos WITH class \"v\" WHERE class = \"n\" FOR w WHERE text = \"fly\"\n\nNow we do the same but as an explicit correction::\n\n EDIT pos WITH class \"v\" WHERE class = \"n\" (AS CORRECTION OF \"some/correctionset\" WITH class \"wrongpos\")\n FOR w WHERE text = \"fly\"\n\nAnother example in a spelling correction context, we correct the misspelling\n*concous* to *conscious**::\n\n EDIT t WITH text \"conscious\" (AS CORRECTION OF \"some/correctionset\" WITH class \"spellingerror\")\n FOR w WHERE text = \"concous\"\n\nThe **AS CORRECTION** keyword (always in a separate block within parentheses) is used to\ninitiate a correction. The correction is itself part of a set with a class that\nindicates the type of correction.\n\nAlternatives are simpler, but follow the same principle::\n\n EDIT pos WITH class \"v\" WHERE class = \"n\" (AS ALTERNATIVE) FOR w WHERE text = \"fly\"\n\nConfidence scores are often associationed with alternatives::\n\n EDIT pos WITH class \"v\" WHERE class = \"n\" (AS ALTERNATIVE WITH confidence 0.6)\n FOR w WHERE text = \"fly\"\n\nThe **AS** clause is also used to select alternatives rather than the\nauthoritative form, this will get all alternative pos tags for words with the\ntext \"fly\"::\n\n SELECT pos (AS ALTERNATIVE) FOR w WHERE text = \"fly\"\n\nIf you want the authoritative tag as well, you can chain the actions. The\nsame target expression (FOR..) always applies to all chained actions, but the AS clause\napplies only to the action in the scope of which it appears::\n\n SELECT pos SELECT pos (AS ALTERNATIVE) FOR w WHERE text = \"fly\"\n\nFilters on the alternative themselves may be applied as expected using the WHERE clause::\n\n SELECT pos (AS ALTERNATIVE WHERE confidence > 0.6) FOR w WHERE text = \"fly\"\n\nNote that filtering on the attributes of the annotation itself is outside of the scope of\nthe AS clause::\n\n SELECT pos WHERE class = \"n\" (AS ALTERNATIVE WHERE confidence > 0.6) FOR w WHERE text = \"fly\"\n\nCorrections by definition are authoritative, so no special syntax is needed to\nobtain them. Assuming the part of speech tag is corrected, this will\ncorrectly obtain it, no AS clause is necessary::\n\n SELECT pos FOR w WHERE text = \"fly\"\n\nAdding **AS CORRECTION** will only enforce to return those that were actually\ncorrected::\n\n SELECT pos (AS CORRECTION) FOR w WHERE text = \"fly\"\n\nHowever, if you want to obtain the original prior to correction, you can do so\nusing **AS CORRECTION ORIGINAL**::\n\n SELECT pos (AS CORRECTION ORIGINAL) FOR w WHERE text = \"fly\"\n\nFoLiA does not just distinguish corrections, but also supports suggestions for\ncorrection. Envision a spelling checker suggesting output for misspelled\nwords, but leaving it up to the user which of the suggestions to accept.\nSuggestions are not authoritative and can be obtained in a similar fashion\nby using the **SUGGESTION** keyword::\n\n SELECT pos (AS CORRECTION SUGGESTION) FOR w WHERE text = \"fly\"\n\nNote that **AS CORRECTION** may take the **OF** keyword to\nspecify the correction set, they may also take a **WHERE** clause to filter::\n\n SELECT t (AS CORRECTION OF \"some/correctionset\" WHERE class = \"confusible\") FOR w\n\nThe **SUGGESTION** keyword can take a WHERE filter too::\n\n SELECT t (AS CORRECTION OF \"some/correctionset\" WHERE class = \"confusible\" SUGGESTION WHERE confidence > 0.5) FOR w\n\nTo add a suggestion for correction rather than an actual authoritative\ncorrection, you can do::\n\n EDIT pos (AS CORRECTION OF \"some/correctionset\" WITH class \"poscorrection\" SUGGESTION class \"n\") FOR w ID some.word.1\n\nThe absence of a WITH statement in the action clause indicates that this is purely a suggestion. The actual suggestion follows the **SUGGESTION** keyword.\n\nAny attributes associated with the suggestion can be set with a **WITH** statement after the suggestion::\n\n EDIT pos (AS CORRECTION OF \"some/correctionset\" WITH class \"poscorrection\" SUGGESTION class \"n\" WITH confidence 0.8) FOR w ID some.word.1\n\nEven if a **WITH** statement is present for the action, making it an actual\ncorrection, you can still add suggestions::\n\n EDIT pos WITH class \"v\" (AS CORRECTION OF \"some/correctionset\" WITH class \"poscorrection\" SUGGESTION class \"n\" WITH confidence 0.8) FOR w ID some.word.1\n\nThe **SUGGESTION** keyword can be chaineed to add multiple suggestions at once::\n\n EDIT pos (AS CORRECTION OF \"some/correctionset\" WITH class \"poscorrection\"\n SUGGESTION class \"n\" WITH confidence 0.8\n SUGGESTION class \"v\" wITH confidence 0.2) FOR w ID some.word.1\n\nAnother example in a spelling correction context::\n\n EDIT t (AS CORRECTION OF \"some/correctionset\" WITH class \"spellingerror\"\n SUGGESTION text \"conscious\" WITH confidence 0.8 SUGGESTION text \"couscous\" WITH confidence 0.2)\n FOR w WHERE text = \"concous\"\n\nA similar construction is available for alternatives as well. First we\nestablish that the following two statements are identical::\n\n EDIT pos WHERE class = \"n\" WITH class \"v\" (AS ALTERNATIVE WITH confidence 0.6) FOR w WHERE text = \"fly\"\n EDIT pos WHERE class = \"n\" (AS ALTERNATIVE class \"v\" WITH confidence 0.6) FOR w WHERE text = \"fly\"\n\nSpecifying multiple alternatives is then done by simply adding enother\n**ALTERNATIVE** clause::\n\n EDIT pos (AS ALTERNATIVE class \"v\" WITH confidence 0.6 ALTERNATIVE class \"n\" WITH confidence 0.4 ) FOR w WHERE text = \"fly\"\n\nWhen a correction is made on an element, all annotations below it (recursively) are left\nintact, i.e. they are copied from the original element to the new correct element. The\nsame applies to suggestions. Moreover, all references to the original element,\nfrom for instance span annotation elements, will be made into references to the\nnew corrected elements.\n\nThis is not always what you want, if you want the correction not to have any\nannotations inherited from the original, simply use **AS BARE CORRECTION** instead of **AS\nCORRECTION**.\n\nYou can also use **AS CORRECTION** with **ADD** and **DELETE**.\n\n\nThe most complex kind of corrections are splits and merges. A split separates a\nstructure element such as a word into multiple, a merge unifies multiple\nstructure elements into one.\n\nIn FQL, this is achieved through substitution, using the action **SUBSTITUTE**::\n\n SUBSTITUTE w WITH text \"together\" FOR SPAN w WHERE text=\"to\" & w WHERE text=\"gether\"\n\nSubactions are common with SUBSTITUTE, the following is equivalent to the above::\n\n SUBSTITUTE w (ADD t WITH text \"together\") FOR SPAN w WHERE text=\"to\" & w WHERE text=\"gether\"\n\nTo perform a split into multiple substitutes, simply chain the SUBSTITUTE\nclause::\n\n SUBSTITUTE w WITH text \"each\" SUBSTITUTE w WITH TEXT \"other\" FOR w WHERE text=\"eachother\"\n\nLike **ADD**, both **SUBSTITUTE** may take assignments (**WITH**), but no filters (**WHERE**).\n\nYou may have noticed that the merge and split examples were not corrections in\nthe FoLiA-sense; the originals are removed and not preserved. Let's make it\ninto proper corrections::\n\n SUBSTITUTE w WITH text \"together\"\n (AS CORRECTION OF \"some/correctionset\" WITH class \"spliterror\")\n FOR SPAN w WHERE text=\"to\" & w WHERE text=\"gether\"\n\nAnd a split::\n\n SUBSTITUTE w WITH text \"each\" SUBSTITUTE w WITH text \"other\"\n (AS CORRECTION OF \"some/correctionset\" WITH class \"runonerror\")\n FOR w WHERE text=\"eachother\"\n\nTo make this into a suggestion for correction instead, use the **SUGGESTION**\nkeyword followed by **SUBSTITUTE**, inside the **AS** clause, where the chain\nof substitute statements has to be enclosed in parentheses::\n\n SUBSTITUTE (AS CORRECTION OF \"some/correctionset\" WITH class \"runonerror\" SUGGESTION (SUBTITUTE w WITH text \"each\" SUBSTITUTE w WITH text \"other\") )\n FOR w WHERE text=\"eachother\"\n\n(Alternatively, you can use **ADD** instead of **SUBSTITUTE** after the **SUGGESTION** clause, which behaves identically)\n\nIn FoLiA, suggestions for deletion are simply empty suggestions, and they are made using the **DELETION** keyword::\n\n SUBSTITUTE (AS CORRECTION OF \"some/correctionset\" WITH class \"redundantword\" SUGGESTION DELETION )\n FOR w WHERE text=\"something\"\n\nSuggestions may indicate they modify the parent structure when applied. For\ninstance, a suggestion for removal of a redundant period is often also a\nsuggestion that the sentence should be merged. This is explicitly indicated in\nFoLiA with a ``merge`` attribute on the suggestion, and in FQL with the\n**MERGE** keyword immediately following **SUGGESTION**. An example::\n\n SUBSTITUTE (AS CORRECTION OF \"some/correctionset\" WITH class \"redundantpunctuation\" SUGGESTION MERGE DELETION )\n FOR w WHERE text=\".\"\n\nThe reverse situation would be insertion of a missing period, which is\ngenerally also a suggestion to split the parent sentence. For this we use the\n**SPLIT** keyword. Insertions are typically done using the **APPEND** or\n**PREPEND** actions, as there is nothing to substitute::\n\n APPEND (AS CORRECTION OF \"some/correctionset\" WITH class \"missingpunctuation\" SUGGESTION SPLIT (ADD w WITH text \".\") )\n FOR w WHERE text=\"end\"\n\nlast, but not least, when deleting corrections explicitly, you may use the **RESTORE** keyword to restore the original.\nExample::\n\n DELETE correction ID \"some.correction\" RESTORE ORIGINAL\n\n-------------------------------\nI can haz context plz?\n-------------------------------\n\nWe've seen that with the **FOR** keyword we can move to bigger elements in the FoLiA\ndocument, and with the **HAS** keyword we can move to siblings. There are\nseveral *context keywords* that give us all the tools we need to peek at the\ncontext. Like **HAS** expressions, these need always be enclosed in\nparentheses.\n\nFor instance, consider part-of-speech tagging scenario. If we have a word where\nthe left neighbour is a determiner, and the right neighbour a noun, we can be\npretty sure the word under our consideration (our target expression) is an\nadjective. Let's add the pos tag::\n\n EDIT pos WITH class = \"adj\" FOR w WHERE (PREVIOUS w WHERE (pos HAS class == \"det\")) AND (NEXT w WHERE (pos HAS class == \"n\"))\n\nYou may append a number directly to the **PREVIOUS**/**NEXT** modifier if\nyou're interested in further context, or you may use\n**LEFTCONTEXT**/**RIGHTCONTEXT**/**CONTEXT** if you don't care at what position\nsomething occurs::\n\n EDIT pos WITH class = \"adj\" FOR w WHERE (PREVIOUS2 w WHERE (pos HAS class == \"det\")) AND (PREVIOUS w WHERE (pos HAS class == \"adj\")) AND (RIGHTCONTEXT w WHERE (pos HAS class == \"n\"))\n\nInstead of the **NEXT** and **PREVIOUS** keywords, a target expression can be used with the **SPAN** keyword and the **&** operator::\n\n SELECT FOR SPAN w WHERE text = \"the\" & w WHERE (pos HAS class == \"adj\") & w WHERE text = \"house\"\n\nWithin a **SPAN** keyword, an **expansion expression** can be used to select\nany number, or a certain number, of elements. You can do this by appending\ncurly braces after the element name (but not attached to it) and specifying the\nminimum and maximum number of elements. The following expression selects from\nzero up to three adjectives between the words \"the\" and \"house\"::\n\n SELECT FOR SPAN w WHERE text = \"the\" & w {0,3} WHERE (pos HAS class == \"adj\") & w WHERE text = \"house\"\n\nIf you specify only a single number in the curly braces, it will require that\nexact number of elements. To match at least one word up to an unlimited number,\nuse an expansion expression such as ``{1,}``.\n\nIf you are now perhaps tempted to use the FoLiA document server and FQL for searching through\nlarge corpora in real-time, then be advised that this is not a good idea. It will be prohibitively\nslow on large datasets as this requires smart indexing, which this document\nserver does not provide. You can therefore not do this real-time, but perhaps\nonly as a first step to build an actual search index.\n\nOther modifiers are PARENT and and ANCESTOR. PARENT will at most go one element\nup, whereas ANCESTOR will go on to the largest element::\n\n SELECT lemma FOR w WHERE (PARENT s WHERE text CONTAINS \"wine\")\n\nInstead of **PARENT**, the use of a nested **FOR** is preferred and more efficient::\n\n SELECT lemma FOR w FOR s WHERE text CONTAINS \"wine\"\n\nLet's revisit syntax trees for a bit now we know how to obtain context. Imagine\nwe want an NP to the left of a PP::\n\n SELECT su WHERE class = \"np\" AND (NEXT su WHERE class = \"pp\")\n\n... and where the whole thing is part of a VP::\n\n SELECT su WHERE class = \"np\" AND (NEXT su WHERE class = \"pp\") IN su WHERE class = \"vp\"\n\n... and return that whole tree rather than just the NP we were looking for::\n\n SELECT su WHERE class = \"np\" AND (NEXT su WHERE class = \"pp\") IN su WHERE class = \"vp\" RETURN target\n\n-------------------------------\nSlicing\n-------------------------------\n\nFQL target expressions may be sliced using the **START** and **END** or\n**ENDBEFORE** keywords (the former is inclusive, the latter is not). They take\na selection expression. You can for instance slice between two specific IDs::\n\n SELECT FOR w START ID \"first.element.id\" END ID \"last.element.id\"\n\nOr to select all words from the first occurrence of *the* to the next::\n\n SELECT FOR w START w WHERE text = \"the\" ENDBEFORE w WHERE text = \"the\"\n\nThe query will usually end after the **END**/**ENDBEFORE** statement. You may however\nwant to continue until the start expression is encountered again, in that case,\nadd the keyword **REPEAT**::\n\n SELECT FOR w START w WHERE text = \"the\" ENDBEFORE w WHERE text = \"the\" REPEAT\n\nNote that slicing only works on target expressions, therefore the **FOR** is\nmandatory. If multiple target expressions are chained, then each may set their\nown slice.\n\n-------------------------------\nShortcuts\n-------------------------------\n\nClasses are prevalent all throughout FoLiA, it is very common to want to select\non classes. To select words with pos tag \"n\" for example you can do::\n\n SELECT w WHERE (pos HAS class = \"n\")\n\nBecause this is so common, there is a shortcut. Specify the annotation type\ndirectly preceeded by a colon, and a HAS statement that matches on class will\nautomatically be constructed::\n\n SELECT w WHERE :pos = \"n\"\n\nThe two statements are completely equivalent.\n\nAnother third alternative to obtain the same result set is to use a target\nexpression::\n\n SELECT pos WHERE class = \"n\" FOR w RETURN target\n\nThis illustrates that there are often multiple ways of obtaining the same\nresult set. Due to lazy evaluation in the FQL library, there is not much\ndifference performance-wise.\n\nAnother kind of shortcut exists for setting text on structural elements. You\ncan add a word with text like this::\n\n ADD w (ADD t WITH text \"hello\") IN ID some.sentence\n\nOr using the shortcut::\n\n ADD w WITH text \"hello\" IN ID some.sentence\n\n\n\n\n========================================\nCorpus Query Language (CQL)\n========================================\n\nThe FoLiA Document Server also supports a basic subset of CQL. CQL focusses on\nquerying only, and has no data manipulation functions like FQL. CQL, however,\nis considerably more concise than FQL, already well-spread, and its syntax is\neasier.\n\nTo use CQL instead of FQL, just start your query as usual with an FQL **USE**\nor , then use the **CQL** keyword and everything thereafter will be interpreted\nas CQL. Example::\n\n USE mynamespace/proycon CQL \"the\" [ tag=\"JJ.*\" ]? [ lemma=\"house\" & tag=\"N\" ]\n\nThe ``tag`` attribute maps to the FoLiA ``pos`` type. ``word`` maps to\nFoLiA/FQL ``text``, any other attributes are unmapped so you can simply use the\nFoLiA names from CQL, including any span annotation.\n\nIf multiple sets are available for a type, make sure to use the ``DEFAULTSET``\nFQL keyword to set a default, otherwise the query will fail as CQL does not know\nthe FoLiA set paradigm.\n\nThe CQL language is documented here:\nhttp://www.sketchengine.co.uk/documentation/wiki/SkE/CorpusQuerying , the\nadvanced operators mentioned there are not supported yet.", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/proycon/foliadocserve", "keywords": "nlp computational_linguistics rest database document server", "license": "GPL", "maintainer": "", "maintainer_email": "", "name": "foliadocserve", "package_url": "https://pypi.org/project/foliadocserve/", "platform": "", "project_url": "https://pypi.org/project/foliadocserve/", "project_urls": { "Homepage": "https://github.com/proycon/foliadocserve" }, "release_url": "https://pypi.org/project/foliadocserve/0.7.2/", "requires_dist": null, "requires_python": "", "summary": "The FoLiA Document Server is a backend HTTP service to interact with documents in the FoLiA format, a rich XML-based format for linguistic annotation (http://proycon.github.io/folia). It provides an interface to efficiently edit FoLiA documents through the FoLiA Query Language (FQL).", "version": "0.7.2" }, "last_serial": 5759445, "releases": { "0.2.1": [ { "comment_text": "", "digests": { "md5": "0fcebe7e51c60eeddfba80a28c96a86f", "sha256": "7d36e1117716ecd84536578ce7fb22d86977a40c023ba044f6fd7bdb77f3618a" }, "downloads": -1, "filename": "foliadocserve-0.2.1.tar.gz", "has_sig": false, "md5_digest": "0fcebe7e51c60eeddfba80a28c96a86f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 59841, "upload_time": "2015-03-20T18:53:41", "url": "https://files.pythonhosted.org/packages/e6/50/84a50514ee866aed27baa43889e40fa8e1678118f3fd1644cb06a1e727fe/foliadocserve-0.2.1.tar.gz" } ], "0.3.0": [ { "comment_text": "", "digests": { "md5": "77ea6e56faa73adc4629ca84bebd720f", "sha256": "7ab7edbcaf3e330f5b3b88b4ae3d67c005c8cab5567185a55c199f9f85edbb35" }, "downloads": -1, "filename": "foliadocserve-0.3.0.tar.gz", "has_sig": false, "md5_digest": "77ea6e56faa73adc4629ca84bebd720f", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 63945, "upload_time": "2015-04-01T17:20:38", "url": "https://files.pythonhosted.org/packages/cf/ff/67dba4c21d2a27f937e401046f75c3909c1ce8ab81e5e7a8cdc4d71eaf97/foliadocserve-0.3.0.tar.gz" } ], "0.3.1": [ { "comment_text": "", "digests": { "md5": "7fe98e9ac6cf2dbdf9d3341af9b2a862", "sha256": "daf4e32dc5ece8a0a0e9ff57d045befe64a0b6f8b712f873544d424ff67197a1" }, "downloads": -1, "filename": "foliadocserve-0.3.1.tar.gz", "has_sig": false, "md5_digest": "7fe98e9ac6cf2dbdf9d3341af9b2a862", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 64748, "upload_time": "2015-05-20T10:23:13", "url": "https://files.pythonhosted.org/packages/16/13/c64223208e633e3a1755981d62f908619e349f5f664f7d7a5190c04a5718/foliadocserve-0.3.1.tar.gz" } ], "0.3.4": [ { "comment_text": "", "digests": { "md5": "7f4d8bd2c222a79804e906b1af7d8544", "sha256": "c13aac26c874090c76ac801ca65b9ac8ce5e484f34d21fa83ac7ceed9ab40711" }, "downloads": -1, "filename": "foliadocserve-0.3.4.tar.gz", "has_sig": false, "md5_digest": "7f4d8bd2c222a79804e906b1af7d8544", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 66298, "upload_time": "2016-04-02T09:00:33", "url": "https://files.pythonhosted.org/packages/43/3f/e837f99374746b82aac9fe828f4c99fd21f4340ce25c3ea4ed0852db6db6/foliadocserve-0.3.4.tar.gz" } ], "0.3.5": [ { "comment_text": "", "digests": { "md5": "65fe3165e65e0960e71166dbfeaee64b", "sha256": "7c389ac460b088f072b221b9aa3a448b4a95fbeed55a7e3df280c69a7a59fb6c" }, "downloads": -1, "filename": "foliadocserve-0.3.5.tar.gz", "has_sig": false, "md5_digest": "65fe3165e65e0960e71166dbfeaee64b", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67169, "upload_time": "2016-05-10T16:26:38", "url": "https://files.pythonhosted.org/packages/08/ba/ed77acdbad7df70b0255fd8674dbff581e4ae9f8c81963af811e7b0e008a/foliadocserve-0.3.5.tar.gz" } ], "0.3.6": [ { "comment_text": "", "digests": { "md5": "8921d77d99e320a46df7ae3d04a7cd32", "sha256": "d6bed8d31c03b06840fc3d9b5e0a6030c918a70342de6d626f573ebb36cfa0f9" }, "downloads": -1, "filename": "foliadocserve-0.3.6.tar.gz", "has_sig": false, "md5_digest": "8921d77d99e320a46df7ae3d04a7cd32", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67179, "upload_time": "2016-05-25T13:29:43", "url": "https://files.pythonhosted.org/packages/2d/17/0171e33c649cf842118728d821307893a56475744f35ab51a4493a45ccf5/foliadocserve-0.3.6.tar.gz" } ], "0.4": [ { "comment_text": "", "digests": { "md5": "7fef56b35e9bf05ac719d83ed1fd6071", "sha256": "106f0ed0735bd4e1977e14db92f3325c208f9e911be0671ce5ee2e9b41dadabb" }, "downloads": -1, "filename": "foliadocserve-0.4.tar.gz", "has_sig": false, "md5_digest": "7fef56b35e9bf05ac719d83ed1fd6071", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 67872, "upload_time": "2016-09-01T16:26:00", "url": "https://files.pythonhosted.org/packages/e8/30/991b46e15980178fe62970dea8716282fc641292d386b288d16c1aab3465/foliadocserve-0.4.tar.gz" } ], "0.4.1": [ { "comment_text": "", "digests": { "md5": "9b889bf3618b18654805229fcaf0ffd6", "sha256": "6969e616a0f8941b64b89f0f5f492df40ee7ca18965f20e8664512e536c0c604" }, "downloads": -1, "filename": "foliadocserve-0.4.1.tar.gz", "has_sig": false, "md5_digest": "9b889bf3618b18654805229fcaf0ffd6", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 68387, "upload_time": "2016-10-01T12:15:18", "url": "https://files.pythonhosted.org/packages/e4/13/a0641caf8341879bfdd0bc36488db01796d06d2d1c05b75530e36bd1c304/foliadocserve-0.4.1.tar.gz" } ], "0.4.2": [ { "comment_text": "", "digests": { "md5": "8ebe8ce94b7c263a3e9a8076c5275a34", "sha256": "365d2008ef7a1c9feec1ae752b0d77cf10dccf9483c9c9a0310b9622622bba12" }, "downloads": -1, "filename": "foliadocserve-0.4.2.tar.gz", "has_sig": false, "md5_digest": "8ebe8ce94b7c263a3e9a8076c5275a34", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 68392, "upload_time": "2016-10-25T12:47:32", "url": "https://files.pythonhosted.org/packages/ca/ed/4c316c64be41583ac7fe964e21d33554d9fe3d0898d363dcad0a3827b87c/foliadocserve-0.4.2.tar.gz" } ], "0.5": [ { "comment_text": "", "digests": { "md5": "3be4607f77e2c4c6f91ae344bb13225a", "sha256": "2f0b04d1cec7e9468e9fc4439bdf85662388349e78e423709c075a71c89862f3" }, "downloads": -1, "filename": "foliadocserve-0.5.tar.gz", "has_sig": false, "md5_digest": "3be4607f77e2c4c6f91ae344bb13225a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71395, "upload_time": "2016-12-29T20:05:53", "url": "https://files.pythonhosted.org/packages/6f/90/6328ec665639ae5b84de8169665ecdd7b796ebf6c1f39160b2a75bf69083/foliadocserve-0.5.tar.gz" } ], "0.5.1": [ { "comment_text": "", "digests": { "md5": "cacfaca291c36bd64a7a27955a43c014", "sha256": "e4d1850f64f2b5bf438aa3fd99fa3bd4ce7c9d44f2fb9cf20e7df635936b36a8" }, "downloads": -1, "filename": "foliadocserve-0.5.1.tar.gz", "has_sig": false, "md5_digest": "cacfaca291c36bd64a7a27955a43c014", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71552, "upload_time": "2017-01-03T13:53:24", "url": "https://files.pythonhosted.org/packages/b0/78/fb06e83e1672645db0c5f2f8341fdc6bba6ca39c08da84cd9454e75b4cf1/foliadocserve-0.5.1.tar.gz" } ], "0.6.0": [ { "comment_text": "", "digests": { "md5": "dab032e8eaf61c13294be27960a09c4c", "sha256": "bb6ee670d3d906a572c00b009d9d683bf239730e0d48981ecd2ec2f2d5c8f7cc" }, "downloads": -1, "filename": "foliadocserve-0.6.0.tar.gz", "has_sig": false, "md5_digest": "dab032e8eaf61c13294be27960a09c4c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71923, "upload_time": "2017-03-02T12:14:46", "url": "https://files.pythonhosted.org/packages/14/ad/07dfe1202e7f0c70c5bacbc3a2ed92ae24183521f7c6cb7c53f11d22ac88/foliadocserve-0.6.0.tar.gz" } ], "0.6.1": [ { "comment_text": "", "digests": { "md5": "480c5d92fc2757066a1ac7d6233cf91e", "sha256": "11c508a046e9144292572b91beb696e8cfc02a83c2efaceac398e95157016415" }, "downloads": -1, "filename": "foliadocserve-0.6.1.tar.gz", "has_sig": false, "md5_digest": "480c5d92fc2757066a1ac7d6233cf91e", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 71991, "upload_time": "2017-03-20T12:49:17", "url": "https://files.pythonhosted.org/packages/4b/f8/434a588931235efa17142db9014f32dece7cacb8059dd862a584ec69b171/foliadocserve-0.6.1.tar.gz" } ], "0.6.2": [ { "comment_text": "", "digests": { "md5": "6511f93b18bc687199ad1aadbfbc9668", "sha256": "dc4144728ffebe086b4a81f8297ef9c08b9ed8591e98e112747935a08fcc607f" }, "downloads": -1, "filename": "foliadocserve-0.6.2.tar.gz", "has_sig": false, "md5_digest": "6511f93b18bc687199ad1aadbfbc9668", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 72005, "upload_time": "2017-05-05T13:35:54", "url": "https://files.pythonhosted.org/packages/8f/1d/db87321e3dc964ea785895fc33e5aa7a46f032f97beb9c3b42201102d89f/foliadocserve-0.6.2.tar.gz" } ], "0.6.3": [ { "comment_text": "", "digests": { "md5": "de9a583b151757c4f306b4109b2530a8", "sha256": "4361502b95a1a8e512e9c5cc742c7c02694bcb9df67b63d26f6a7c99f305ce6f" }, "downloads": -1, "filename": "foliadocserve-0.6.3.tar.gz", "has_sig": false, "md5_digest": "de9a583b151757c4f306b4109b2530a8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 72221, "upload_time": "2017-10-09T09:27:02", "url": "https://files.pythonhosted.org/packages/1a/bb/53407d986aa1c4e015c7db2f618c9f805dc8eb671ae9ddd2a985ec983132/foliadocserve-0.6.3.tar.gz" } ], "0.6.4": [ { "comment_text": "", "digests": { "md5": "12b4ff5414db301c0c680a45bce7200a", "sha256": "3e87a6f61235b4b3029dd3e0d7e71a07e8fcd13f910d684c03e0cbc2248437a8" }, "downloads": -1, "filename": "foliadocserve-0.6.4.tar.gz", "has_sig": false, "md5_digest": "12b4ff5414db301c0c680a45bce7200a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 72753, "upload_time": "2017-10-23T10:20:03", "url": "https://files.pythonhosted.org/packages/c6/db/72f9931c625c68057ac012f907ef1088ec1ee43116ca0054ca76fa608c05/foliadocserve-0.6.4.tar.gz" } ], "0.6.5": [ { "comment_text": "", "digests": { "md5": "87e53da43091c5633447a126e73813f8", "sha256": "a865d7be05aecb128a73448bd8949366bd93cbe2acb349cef26df14988db6119" }, "downloads": -1, "filename": "foliadocserve-0.6.5.tar.gz", "has_sig": false, "md5_digest": "87e53da43091c5633447a126e73813f8", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 73271, "upload_time": "2018-02-04T22:09:37", "url": "https://files.pythonhosted.org/packages/f1/5c/f3bd3059bfca903bb42d1b4ccccb8086c7ab3f5b8caeaa9b8fe780d1f789/foliadocserve-0.6.5.tar.gz" } ], "0.6.6": [ { "comment_text": "", "digests": { "md5": "b6cf610605f65366aaefb46cadef09ff", "sha256": "a80b727adb1d03cba4c2dc06604394ebb922cec4f6d9bc804985185ff0c7fb13" }, "downloads": -1, "filename": "foliadocserve-0.6.6.tar.gz", "has_sig": false, "md5_digest": "b6cf610605f65366aaefb46cadef09ff", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 73297, "upload_time": "2018-02-05T22:19:04", "url": "https://files.pythonhosted.org/packages/2b/40/c9db75f1441abc102710ad1243e42212e2416eda94bedf20a72b36cc6a77/foliadocserve-0.6.6.tar.gz" } ], "0.6.7": [ { "comment_text": "", "digests": { "md5": "9d7b40c0bcea3747c849d49c31fbc858", "sha256": "dde4c1701474eb94461b3b2bd1af0ad69833dc3f60ff86e49da0582e76bded67" }, "downloads": -1, "filename": "foliadocserve-0.6.7.tar.gz", "has_sig": false, "md5_digest": "9d7b40c0bcea3747c849d49c31fbc858", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 73287, "upload_time": "2018-04-23T09:51:17", "url": "https://files.pythonhosted.org/packages/3f/30/ad890f014e9cb37d471255c2fa9644919967fb6dd21d2a91ad0e7fa4d474/foliadocserve-0.6.7.tar.gz" } ], "0.7.0": [ { "comment_text": "", "digests": { "md5": "832de8da594774e0755dc4058d685bc5", "sha256": "a6e180f52ea3d0592ac532d5580e5de609476bd1da3f23a3b55bac37f9ff96d4" }, "downloads": -1, "filename": "foliadocserve-0.7.0-py3.7.egg", "has_sig": false, "md5_digest": "832de8da594774e0755dc4058d685bc5", "packagetype": "bdist_egg", "python_version": "3.7", "requires_python": null, "size": 81842, "upload_time": "2019-04-30T10:54:13", "url": "https://files.pythonhosted.org/packages/30/60/fed7066b90a4164d0f089469e3d1d29490da7f54339e4407fd42d6475385/foliadocserve-0.7.0-py3.7.egg" }, { "comment_text": "", "digests": { "md5": "34892ef2a8df10f59bddad28366dc244", "sha256": "42fcd450a292279acb283343915a954367a7e39b0b81292d5d55d1dc11f14609" }, "downloads": -1, "filename": "foliadocserve-0.7.0.tar.gz", "has_sig": false, "md5_digest": "34892ef2a8df10f59bddad28366dc244", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 73814, "upload_time": "2019-04-30T10:54:20", "url": "https://files.pythonhosted.org/packages/34/a3/9e79a01a8b5498787ae93596fa583f617d8fed9befa898f34a05c076d047/foliadocserve-0.7.0.tar.gz" } ], "0.7.1": [ { "comment_text": "", "digests": { "md5": "911de6349079cf23a29ff70e2a80bd7c", "sha256": "f7e6c7075f31fb53d2136b3b9ece4c318eff695c6d4e45846f7604707d736ed1" }, "downloads": -1, "filename": "foliadocserve-0.7.1.tar.gz", "has_sig": false, "md5_digest": "911de6349079cf23a29ff70e2a80bd7c", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 73975, "upload_time": "2019-08-15T15:21:23", "url": "https://files.pythonhosted.org/packages/62/81/69891b3382174e128620298ed9e966a0587517cd64b2e9afd51e9edb5ff1/foliadocserve-0.7.1.tar.gz" } ], "0.7.2": [ { "comment_text": "", "digests": { "md5": "7a45edffa785865aeb19e59edd0b930a", "sha256": "53bd831885a5cdbd73dcf276b833129f712eccbdc477ed2dc03ad8995bfe56db" }, "downloads": -1, "filename": "foliadocserve-0.7.2.tar.gz", "has_sig": false, "md5_digest": "7a45edffa785865aeb19e59edd0b930a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 74352, "upload_time": "2019-08-30T09:54:47", "url": "https://files.pythonhosted.org/packages/06/02/ccc66bfc7ec6da20a80db81d918adc18af820698d95cb214c1bdc99df1b2/foliadocserve-0.7.2.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "7a45edffa785865aeb19e59edd0b930a", "sha256": "53bd831885a5cdbd73dcf276b833129f712eccbdc477ed2dc03ad8995bfe56db" }, "downloads": -1, "filename": "foliadocserve-0.7.2.tar.gz", "has_sig": false, "md5_digest": "7a45edffa785865aeb19e59edd0b930a", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 74352, "upload_time": "2019-08-30T09:54:47", "url": "https://files.pythonhosted.org/packages/06/02/ccc66bfc7ec6da20a80db81d918adc18af820698d95cb214c1bdc99df1b2/foliadocserve-0.7.2.tar.gz" } ] }