# -*- coding: utf-8 -*-
from setuptools import setup

packages = \
['qai']

package_data = \
{'': ['*']}

install_requires = \
['requests>=2.26.0,<3.0.0', 'sanic>=21.3.4,<22.0.0']

setup_kwargs = {
    'name': 'qai',
    'version': '6.0.0rc4',
    'description': 'Helper functions and classes for interacting with the rest of the Writer platform',
    'long_description': '# library.qai.utilities\n\nHelper functions and classes for interacting with the rest of the Writer platform. The main components are:\n\n- `qai.issues.make_issue`: makes a dictionary that conforms to Writer platform standards\n- `qai.spacy_factor.SpacyFactor`: a helper class which turns a spaCy Span into an issue\n- `qai.server.QRest`: a helper class which builds a Sanic REST server for you\n- `qai.validation.Validator`: a simple validator class that can be used to skip segments without processing them, e.g. for being empty or having HTML. You would only want to import this yourself if you aren\'t using `QRest`\n\nIf you are building a Sanic app without using `QRest`, you still may be interested in the following middleware:\n\n- `qai.server.set_valid_segments`: stores valid segments to `request.ctx.segments` and also sets `request.ctx.info`\n- `qai.server.postprocess_issues`: changes the string indexing to be utf-16 based, and filters no ops\n\n(See GitHub history for older docs - QAI used to do a lot more!)\n\n## Testing QAI services\n\nWith QAI >=6.0.0, it is easy to test a QAI-based service running in k8s, first start the k8s proxy with `$kubectl proxy` and then `$ python` (or, if you are fancy, `$ python -m IPython`)\n\n```python\nfrom qai.testing import *\n\nname_test_qai("testing string", "service name")\n```\n\nThat\'s all! The meta is inferred from the service name.\n\nYou can also test a service running on localhost port 5000 by:\n\n```python\nfrom qai.testing import *\n\ntest_qai("testing string", url=5000)\n# or to imply meta by name\ntest_qai("testing string", "service name", url=5000)\n# or to explicitly specify meta\ntest_qai("testing string", meta={"some key": val}, url=5000)\n```\n\n## Upgrading to v5\n\n- `Analyzer` class must now be callable. It will be passed `(segment: str, meta: dict, all_info: dict)` - `segment` is the string to analyze, `meta` is the `meta` object that was sent, or `{}` if none was sent, and `all_info` is the entire payload the server received - in case you need access to clientID or something. Feel free to define `def __call__(self, segment: str, meta: dict, _)` if you don\'t expect to need the request.\n- `QRest` can be passed a Sanic app, or be passed a dictionary which maps issue types to categories (in addition to the default behavior). This is useful for services that handle multiple categories, for which the default behavior doesn\'t work.\n- QAI has a simpler structure, so all imports look different\n- Configs, Strings, Storage, and Document are gone. The later 2 because they aren\'t needed anymore, the former 2 because you should manage that yourself. Whitelisting is also gone - just don\'t make the issues if you don\'t want them.\n- All issues are created in the v2 format (meaning, the format we switched to after new segmentation - defined [here](https://writerai.atlassian.net/wiki/spaces/HOME/pages/2115928140/NLP+Services+API+Contract+Meta))\n- By default, issue `from` and `until` keys are now based on UTF-16 indexing, to make things easier for JS. We add `_from_p` and `_until_p` keys for debugging, which are the Python string indexes. This happens as response middleware in QRest.\n\n## Usage\n\nYou can explicitly create a REST connection like this:\n\n```python\nfrom app import Analyzer\n\nfrom qai.server import QRest\n\n\n# setting the category / service name does nothing\n# we use the category passed on the request\ncategory = \'service_name\'\nhost = \'0.0.0.0\'\nport = 5000\n\n\nif __name__ == \'__main__\':\n    analyzer = Analyzer()\n    rest_connection = QRest(\n      analyzer,\n      category=category,\n      host=host,\n      port=port\n    )\n    # create a blocking connection:\n    rest_connection.connect()\n```\n\nThe above will create *as many workers as you have cores.* This is great, sometimes. For example, there is a known bug where AutoML crashes if you are using more than one worker. So pass `workers=1` if this happens\n\nThere is also a helper class for turning spaCy `Span`s into issues the rest of the platform can process:\n\n```python\nfrom spacy.tokens import Span\nfrom qai.spacy_factor import SpacyFactor\n\n\nMyFactor = SpacyFactor(\n    "subject_object_verb_spacing",\n    "Keep the subject, verb, and object of a sentence close together to help the reader understand the sentence."\n)\n\nSpan.set_extension("score", default=0)\nSpan.set_extension("suggestions", default=[])\n\ndoc = nlp("Holders of the Class A and Class B-1 certificates will be entitled to receive on each Payment Date, to the extent monies are available therefor (but not more than the Class A Certificate Balance or Class B-1 Certificate Balance then outstanding), a distribution.")\nscore = analyze(doc)\nif score is not None:\n    span = Span(doc, 0, len(doc))  # or whichever tokens/spans are the issue (don\'t have to worry about character indexes)\n    span._.score = score\n    span._.suggestions = get_suggestions(doc)\n    issue = MyFactor(span)\n```\n\n## Installation\n\n`pip install qai` or `poetry add qai`\n\n## Testing\n\nSee Confluence for docs on input format expectations.\n\n`scripts/test_qai.sh` has some helpful testing functions.\n\n### CI/CD\n\nGitHub Actions will push to PyPi when you merge into the `main` branch.\n\n### License\n\nThis software is not licensed. If you do not work at Writer, you are not legally allowed to use it. Also, it\'s just helper functions that really won\'t help you. If something in it does look interesting, and you would like access or our help, open an issue.\n',
    'author': 'Sam Havens',
    'author_email': 'sam.havens@writer.com',
    'maintainer': None,
    'maintainer_email': None,
    'url': None,
    'packages': packages,
    'package_data': package_data,
    'install_requires': install_requires,
    'python_requires': '>=3.8,<4.0',
}


setup(**setup_kwargs)
