├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── example ├── Client.py ├── mc_rapidminer.py └── mc_showcase.py ├── meaningcloud ├── ClassRequest.py ├── ClassResponse.py ├── ClusteringRequest.py ├── ClusteringResponse.py ├── DeepCategorizationRequest.py ├── DeepCategorizationResponse.py ├── LanguageRequest.py ├── LanguageResponse.py ├── ParserRequest.py ├── ParserResponse.py ├── Request.py ├── Response.py ├── SentimentRequest.py ├── SentimentResponse.py ├── SummarizationRequest.py ├── SummarizationResponse.py ├── TopicsRequest.py ├── TopicsResponse.py └── __init__.py ├── setup.cfg ├── setup.py └── tests ├── ClassRequestTest.py ├── ClassResponseTest.py ├── ClusteringRequestTest.py ├── ClusteringResponseTest.py ├── DeepCategorizationRequestTest.py ├── DeepCategorizationResponseTest.py ├── LanguageRequestTest.py ├── LanguageResponseTest.py ├── ParserRequestTest.py ├── ParserResponseTest.py ├── RequestTest.py ├── ResponseTest.py ├── SentimentRequestTest.py ├── SentimentResponseTest.py ├── SummarizationRequestTest.py ├── SummarizationResponseTest.py ├── TopicsRequestTest.py ├── TopicsResponseTest.py └── resources └── file.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # PyCharm 107 | .idea/ 108 | 109 | # README for PyPI 110 | README.rst -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 MeaningCloud LLC 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include README.rst -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # MeaningCloud for Python 2 | 3 | This is MeaningCloud's official Python client, designed to enable you to use MeaningCloud's services easily from your own applications. 4 | 5 | ## MeaningCloud 6 | 7 | MeaningCloud is a cloud-based text analytics service that through APIs allows you extract meaning from all kind of unstructured content: social conversation, articles, documents... You can check our demos here: https://www.meaningcloud.com/demos 8 | 9 | The different APIs provide easy access to many NLP tasks such as automatic classification, sentiment analysis, topic extraction, etc. To be able to use the service you just have to log into MeaningCloud (by registering or using other services to log in: https://www.meaningcloud.com/developer/login), and you will receive a license key associated to a basic Free plan. 10 | 11 | You can read more about the plans and the features available here: https://www.meaningcloud.com/products/pricing 12 | 13 | ## SDK versions 14 | 15 | With version 1.2 retired the classification API `class-1.1` is no longer available. Please refer to the 16 | [class-1.1 to class-2.0 Model Migration Guide](https://www.meaningcloud.com/blog/text-classification-20-migration-guide) 17 | to upgrade your classification models. 18 | 19 | | | v2.0 | 20 | |---------------------|------------------------| 21 | | Class | class-2.0 | 22 | | Deep Categorization | deepcategorization-1.0 | 23 | | Language Detection | lang-2.0 | 24 | | Parser | parser-2.0 | 25 | | Sentiment Analysis | sentiment-2.1 | 26 | | Topics Extraction | topics-2.0 | 27 | 28 | 29 | ## Getting started 30 | 31 | ### Installation 32 | 33 | You can load meaningcloud-python into your project by using: 34 | ``` 35 | pip install MeaningCloud-python 36 | ``` 37 | 38 | You can also clone the code and type the following on your shell: 39 | 40 | ``` 41 | python setup.py install 42 | ``` 43 | 44 | ### Configuration 45 | 46 | The only thing you need to start using MeaningCloud's APIs is to log into MeaningCloud (by registering or using other services to log in). Once you've done that, you will be given a license key (https://www.meaningcloud.com/developer/account/subscription). Copy it and paste it in the corresponding place in the code, select the API you want to use and the parameters you want to use, and that's it. 47 | 48 | You can find all the technical documentation about the APIs in the API section of the website: https://www.meaningcloud.com/developer/apis 49 | 50 | And we are always available at support@meaningcloud.com 51 | 52 | ### Functionality 53 | 54 | This SDK currently contains the following: 55 | 56 | - **Request**: manages requests to any of MeaningCloud's APIS. It can also be used to directly generate requests without using specific classes . 57 | - **ClassRequest**: models a request to MeaningCloud Text Classification API. 58 | - **ClusteringRequest**: models a request to MeaningCloud Text Clustering API. 59 | - **DeepCategorizationRequest**: models a request to MeaningCloud Deep Categorization API. 60 | - **LanguageRequest**: models a request to MeaningCloud Language Identification API. 61 | - **ParserRequest**: models a request to Meaningcloud Lemmatization, PoS and Parsing API. 62 | - **SentimentRequest**: models a request to MeaningCloud Sentiment Analysis API. 63 | - **SummarizationRequest**: models a request to Meaningcloud Summarization API. 64 | - **TopicsRequest**: models a request to MeaningCloud TopicsExtraction API. 65 | - **Response**: models a generic response from the MeaningCloud API. 66 | - **ClassResponse**: models a response from the Text Classification API, providing auxiliary functions to work with the response and extract the different fields in each category. 67 | - **ClusteringResponse**: models a response from the Text Clustering API, providing auxiliary functions to work with the response and extract the different fields in each cluster. 68 | - **DeepCategorizationResponse**: models a response from the Deep Categorization API, providing auxiliary functions to work with the response and extract the different fields in each category. 69 | - **LanguageResponse**: models a response from the Language Identification API, providing auxiliary functions to work with the response and extract the sentiment detected at different levels and for different elements. 70 | - **ParserResponse**: models a response from the Lemmatization, PoS and Parsing API, providing auxiliary functions to work with the response and extract the lemmatization and PoS tagging of the text provided. 71 | - **SentimentResponse**: models a response from the Sentiment Analysis API, providing auxiliary functions to work with the response and extract the sentiment detected at different levels and for different elements. 72 | - **SummarizationResponse**: models a response from the Summarization API, providing auxiliary functions to work with the response and obtain the summary extracted. 73 | - **TopicsResponse**: models a response from the Topic Extraction API, providing auxiliary functions to work with the response, extracting the different types of topics and some of the most used fields in them. 74 | 75 | ### Usage 76 | 77 | In the _example_ folder, there are two examples: 78 | - **Client.py**, which contains a simple example on how to use the SDK. 79 | - **mc_rapidminer.py**, which contains a script you can run from RapidMiner using the [Python scripting extension](https://docs.rapidminer.com/latest/studio/operators/utility/scripting/execute_python.html) 80 | - **mc_showcase.py**, which implements a pipeline where plain text files are read from a folder, and two CSV files result as output: one with several types of analyses done over each text, and the results from running [Text Clustering](https://www.meaningcloud.com/developer/text-clustering) over the complete collection. 81 | The analyses done are: 82 | 83 | * [Language Identification](https://www.meaningcloud.com/developer/language-identification): detects the language and returns code or name 84 | * [Sentiment Analysis](https://www.meaningcloud.com/developer/sentiment-analysis): detects the global polarity detected in the text 85 | * [Topics Extraction](https://www.meaningcloud.com/developer/topics-extraction): detects the most relevant entities and concepts in the text. If the _get_fibo_ variable is enabled, FIBO concepts will be output (requires access to the [Financial Industry pack](https://www.meaningcloud.com/developer/documentation/vertical-packs#financial_industry)) 86 | * [Deep Categorization](https://www.meaningcloud.com/developer/deep-categorization): categorizes the text according to the *IAB 2.0* taxonomy 87 | * [Text Classification](https://www.meaningcloud.com/developer/text-classification): classifies the text according the *IPTC* taxonomy 88 | * [Summarization](https://www.meaningcloud.com/developer/summarization): extracts a summary from the text 89 | 90 | 91 | This is what **Client.py** looks like: 92 | 93 | ```python 94 | #! /usr/bin/env python 95 | 96 | # Created by MeaningCloud Support Team 97 | # Date: 26/02/18 98 | 99 | import sys 100 | import meaningcloud 101 | 102 | # @param model str - Name of the model to use. Example: "IAB_en" by default = "IPTC_en" 103 | model = 'IAB_en' 104 | 105 | # @param license_key - Your license key (found in the subscription section in https://www.meaningcloud.com/developer/) 106 | license_key = '<<<<< your license key >>>>>' 107 | 108 | # @param text - Text to use for different API calls 109 | text = 'London is a very nice city but I also love Madrid.' 110 | 111 | 112 | try: 113 | # We are going to make a request to the Topics Extraction API 114 | topics_response = meaningcloud.TopicsResponse(meaningcloud.TopicsRequest(license_key, txt=text, lang='en', 115 | topicType='e').sendReq()) 116 | 117 | # If there are no errors in the request, we print the output 118 | if topics_response.isSuccessful(): 119 | print("\nThe request to 'Topics Extraction' finished successfully!\n") 120 | 121 | entities = topics_response.getEntities() 122 | if entities: 123 | print("\tEntities detected (" + str(len(entities)) + "):\n") 124 | for entity in entities: 125 | print("\t\t" + topics_response.getTopicForm(entity) + ' --> ' + 126 | topics_response.getTypeLastNode(topics_response.getOntoType(entity)) + "\n") 127 | 128 | else: 129 | print("\tNo entities detected!\n") 130 | else: 131 | if topics_response.getResponse() is None: 132 | print("\nOh no! The request sent did not return a Json\n") 133 | else: 134 | print("\nOh no! There was the following error: " + topics_response.getStatusMsg() + "\n") 135 | 136 | # CLASS API CALL 137 | # class_response = meaningcloud.ClassResponse( 138 | # meaningcloud.ClassRequest(license_key, txt=text, model=model).sendReq()) 139 | 140 | # SENTIMENT API CALL 141 | # sentiment_response = meaningcloud.SentimentResponse( 142 | # meaningcloud.SentimentRequest(license_key, lang='en', txt=text, txtf='plain').sendReq()) 143 | 144 | # GENERIC API CALL 145 | # generic = meaningcloud.Request(url="url_of_specific_API",key=key) 146 | # generic.addParam('parameter','value') 147 | # generic_result = generic.sendRequest() 148 | # generic_response = meaningcloud.Response(generic_result) 149 | 150 | # We are going to make a request to the Language Identification API 151 | lang_response = meaningcloud.LanguageResponse(meaningcloud.LanguageRequest(license_key, txt=text).sendReq()) 152 | 153 | # If there are no errors in the request, we will use the language detected to make a request to Sentiment and Topics 154 | if lang_response.isSuccessful(): 155 | print("\nThe request to 'Language Identification' finished successfully!\n") 156 | first_lang = lang_response.getFirstLanguage() 157 | if first_lang: 158 | language = lang_response.getLanguageCode(first_lang) 159 | print("\tLanguage detected: " + lang_response.getLanguageName(first_lang) + ' (' + language + ")\n") 160 | else: 161 | print("\tNo language detected!\n") 162 | 163 | # We are going to make a request to the Lemmatization, PoS and Parsing API 164 | parser_response = meaningcloud.ParserResponse( 165 | meaningcloud.ParserRequest(license_key, txt=text, lang='en').sendReq()) 166 | 167 | # If there are no errors in the request, print tokenization and lemmatization 168 | if parser_response.isSuccessful(): 169 | print("\nThe request to 'Lemmatization, PoS and Parsing' finished successfully!\n") 170 | lemmatization = parser_response.getLemmatization(True) 171 | print("\tLemmatization and PoS Tagging:\n") 172 | for token, analyses in lemmatization.items(): 173 | print("\t\tToken -->", token) 174 | for analysis in analyses: 175 | print("\t\t\tLemma -->", analysis['lemma']) 176 | print("\t\t\tPoS Tag -->", analysis['pos'], "\n") 177 | 178 | 179 | except ValueError: 180 | e = sys.exc_info()[0] 181 | print("\nException: " + str(e)) 182 | ``` 183 | -------------------------------------------------------------------------------- /example/Client.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # Created by MeaningCloud Support Team 4 | # Date: 26/02/18 5 | 6 | import sys 7 | import meaningcloud 8 | 9 | # @param model str - Name of the model to use. Example: "IAB_en" by default = "IPTC_en" 10 | model = 'IAB_en' 11 | 12 | # @param license_key - Your license key (found in the subscription section in https://www.meaningcloud.com/developer/) 13 | license_key = '<<<<< your license key >>>>>' 14 | 15 | # @param text - Text to use for different API calls 16 | text = 'London is a very nice city but I also love Madrid.' 17 | 18 | 19 | try: 20 | # We are going to make a request to the Topics Extraction API 21 | topics_response = meaningcloud.TopicsResponse(meaningcloud.TopicsRequest(license_key, txt=text, lang='en', 22 | topicType='e').sendReq()) 23 | 24 | # If there are no errors in the request, we print the output 25 | if topics_response.isSuccessful(): 26 | print("\nThe request to 'Topics Extraction' finished successfully!\n") 27 | 28 | entities = topics_response.getEntities() 29 | if entities: 30 | print("\tEntities detected (" + str(len(entities)) + "):\n") 31 | for entity in entities: 32 | print("\t\t" + topics_response.getTopicForm(entity) + ' --> ' + 33 | topics_response.getTypeLastNode(topics_response.getOntoType(entity)) + "\n") 34 | 35 | else: 36 | print("\tNo entities detected!\n") 37 | else: 38 | if topics_response.getResponse() is None: 39 | print("\nOh no! The request sent did not return a Json\n") 40 | else: 41 | print("\nOh no! There was the following error: " + topics_response.getStatusMsg() + "\n") 42 | 43 | # CLASS API CALL 44 | # class_response = meaningcloud.ClassResponse( 45 | # meaningcloud.ClassRequest(license_key, txt=text, model=model).sendReq()) 46 | 47 | # SENTIMENT API CALL 48 | # sentiment_response = meaningcloud.SentimentResponse( 49 | # meaningcloud.SentimentRequest(license_key, lang='en', txt=text, txtf='plain').sendReq()) 50 | 51 | # GENERIC API CALL 52 | # generic = meaningcloud.Request(url="url_of_specific_API",key=key) 53 | # generic.addParam('parameter','value') 54 | # generic_result = generic.sendRequest() 55 | # generic_response = meaningcloud.Response(generic_result) 56 | 57 | # We are going to make a request to the Language Identification API 58 | lang_response = meaningcloud.LanguageResponse(meaningcloud.LanguageRequest(license_key, txt=text).sendReq()) 59 | 60 | # If there are no errors in the request, we will use the language detected to make a request to Sentiment and Topics 61 | if lang_response.isSuccessful(): 62 | print("\nThe request to 'Language Identification' finished successfully!\n") 63 | first_lang = lang_response.getFirstLanguage() 64 | if first_lang: 65 | language = lang_response.getLanguageCode(first_lang) 66 | print("\tLanguage detected: " + lang_response.getLanguageName(first_lang) + ' (' + language + ")\n") 67 | else: 68 | print("\tNo language detected!\n") 69 | 70 | # We are going to make a request to the Lemmatization, PoS and Parsing API 71 | parser_response = meaningcloud.ParserResponse( 72 | meaningcloud.ParserRequest(license_key, txt=text, lang='en').sendReq()) 73 | 74 | # If there are no errors in the request, print tokenization and lemmatization 75 | if parser_response.isSuccessful(): 76 | print("\nThe request to 'Lemmatization, PoS and Parsing' finished successfully!\n") 77 | lemmatization = parser_response.getLemmatization(True) 78 | print("\tLemmatization and PoS Tagging:\n") 79 | for token, analyses in lemmatization.items(): 80 | print("\t\tToken -->", token) 81 | for analysis in analyses: 82 | print("\t\t\tLemma -->", analysis['lemma']) 83 | print("\t\t\tPoS Tag -->", analysis['pos'], "\n") 84 | 85 | 86 | except ValueError: 87 | e = sys.exc_info()[0] 88 | print("\nException: " + str(e)) 89 | -------------------------------------------------------------------------------- /example/mc_rapidminer.py: -------------------------------------------------------------------------------- 1 | # Created by MeaningCloud Support Team 2 | # Copyright 2020 MeaningCloud LLC 3 | # Date: 23/02/2020 4 | 5 | import sys 6 | import os 7 | import meaningcloud 8 | import pandas as pd 9 | 10 | # @param license_key - Your license key (found in the subscription section in https://www.meaningcloud.com/developer/) 11 | license_key = '<<>>' 12 | 13 | # @param text_column - Name of the column where the texts will be 14 | text_column = 'Review' 15 | 16 | 17 | # auxiliary variables to follow progress of the process 18 | index_count = 1 19 | 20 | 21 | # Analyzes the text passed as a parameter 22 | def analyzeText(text): 23 | global index_count 24 | print("Analyzing text " + str(index_count)) 25 | 26 | 27 | # this is where we are going to store our results 28 | polarity = '' 29 | entities = '' 30 | concepts = '' 31 | iab2 = '' 32 | 33 | try: 34 | # We are going to make a request to the Sentiment Analysis API 35 | print("\tGetting sentiment analysis...") 36 | sentiment_response = meaningcloud.SentimentResponse(meaningcloud.SentimentRequest(license_key, lang='en', txt=text, txtf='markup').sendReq()) 37 | if sentiment_response.isSuccessful(): 38 | polarity = sentiment_response.getGlobalScoreTag() 39 | else: 40 | print('Request to sentiment was not succesful: ' + sentiment_response.getStatusMsg()) 41 | 42 | 43 | # We are going to make a request to the Topics Extraction API 44 | print("\tGetting entities and concepts...") 45 | topics_req = meaningcloud.TopicsRequest(license_key, txt=text, lang='en', topicType='ec', otherparams={'txtf':'markup'}) 46 | topics_response = meaningcloud.TopicsResponse(topics_req.sendReq()) 47 | 48 | # If there are no errors in the request, we extract the entities and concepts 49 | if topics_response.isSuccessful(): 50 | entities_list = topics_response.getEntities() 51 | formatted_entities = [] 52 | if entities_list: 53 | for entity in entities_list: 54 | if int(topics_response.getTopicRelevance(entity)) >= 100: #we limit the entities to those with relevance higher than 100 55 | formatted_entities.append(topics_response.getTopicForm(entity) + ' (' + topics_response.getTypeLastNode(topics_response.getOntoType(entity)) + ')') 56 | entities = ', '.join(formatted_entities) 57 | 58 | concepts_list = topics_response.getConcepts() 59 | formatted_concepts = [] 60 | if concepts_list: 61 | for concept in concepts_list: 62 | if int(topics_response.getTopicRelevance(concept)) >= 100: #we limit the entities to those with relevance higher than 100 63 | formatted_concepts.append(topics_response.getTopicForm(concept)) 64 | 65 | concepts = ', '.join(list(dict.fromkeys(formatted_concepts))) 66 | else: 67 | print('Request to topics was not succesful: ' + topics_response.getStatusMsg()) 68 | 69 | 70 | # We are going to make a request to the Deep Categorization API 71 | print("\tGetting IAB 2.0 classification...") 72 | deepcat_response = meaningcloud.DeepCategorizationResponse(meaningcloud.DeepCategorizationRequest(license_key, model='IAB_2.0_en', txt=text, otherparams={'txtf':'markup'}).sendReq()) 73 | if deepcat_response.isSuccessful(): 74 | categories = deepcat_response.getCategories() 75 | iab2 = (', '.join(deepcat_response.getCategoryCode(cat) for cat in categories[:1])) if categories else '' 76 | else: 77 | print('Request to Deep Categorization was not succesful: ' + deepcat_response.getStatusMsg()) 78 | 79 | except ValueError: 80 | e = sys.exc_info()[0] 81 | print("\nException: " + str(e)) 82 | 83 | index_count += 1 84 | 85 | return pd.Series([polarity, entities, concepts, iab2]) 86 | 87 | 88 | 89 | ############# Main flow ###################### 90 | 91 | 92 | # Flow when it's run from RapidMiner 93 | def rm_main(data): 94 | print('Number ot texts to analyze: ' + str(len(data))) 95 | index = 0 96 | results = data 97 | 98 | #create pandas data frame from the given dictionary 99 | df = pd.DataFrame(data) 100 | 101 | # check if data frame creation worked 102 | if not isinstance(df, pd.DataFrame): 103 | print("ERROR: Conversion to data frame failed.") 104 | return; 105 | 106 | if not text_column in df: 107 | print('ERROR: The column configured does not exist in the data input!') 108 | return; 109 | 110 | # main analysis 111 | label_list = ['Polarity', 'Entities', 'Concepts', 'IAB2'] 112 | df[label_list] = df[text_column].apply(analyzeText) 113 | 114 | 115 | # connect output ports to see the results 116 | return df -------------------------------------------------------------------------------- /example/mc_showcase.py: -------------------------------------------------------------------------------- 1 | # Created by MeaningCloud Support Team 2 | # Copyright 2019 MeaningCloud LLC 3 | # Date: 12/11/2019 4 | 5 | import sys 6 | import meaningcloud 7 | import os 8 | import pandas as pd 9 | 10 | 11 | # This script illustrates how the different functionalities provided by MeaningCloud can be used and combined to extract 12 | # information from a collection of files. The script receives as input a folder that contains files with plain text (UTF-8) 13 | # and results in two CSV files, one with analyses for each one of the texts and another one with the result of clustering 14 | # the files in the folder. Progress of the process will be shown through the console (stout) 15 | 16 | 17 | ############ CONFIGURATION ############ 18 | # @param license_key - Your license key (found in the subscription section in https://www.meaningcloud.com/developer/) 19 | license_key = '<<<<< your license key >>>>>' 20 | # @param get_fibo - Determines if the analysis will get FIBO concepts. Access to the pack is needed: https://www.meaningcloud.com/developer/documentation/vertical-packs#financial_industry 21 | get_fibo = True 22 | # @param number_categories - Number of categories to show in the results in Deep Categorization and Text Classification analysis 23 | number_categories = 3 24 | # @param topics_relevance - Relevance used for filtering entities and concepts 25 | topics_relevance = 80 26 | 27 | # @param cluster_score_threshold - Relative score used for filtering clusters 28 | cluster_score_threshold = 50 29 | 30 | # auxiliary variables to follow progress of the process 31 | index_count = 1 32 | total_files = None 33 | 34 | 35 | ############## FUNCTIONS ############## 36 | 37 | # Calls Sentiment Analysis and returns the global polarity for the text 38 | def getSentimentAnalysis(text): 39 | polarity = '' 40 | # We are going to make a request to the Sentiment Analysis API 41 | print("\tGetting sentiment analysis...") 42 | sentiment_response = meaningcloud.SentimentResponse(meaningcloud.SentimentRequest(license_key, lang='en', txt=text, txtf='markup').sendReq()) 43 | if sentiment_response.isSuccessful(): 44 | polarity = sentiment_response.getGlobalScoreTag() 45 | else: 46 | print("\tOops! Request to sentiment was not succesful: (" + sentiment_response.getStatusCode() + ') ' + sentiment_response.getStatusMsg()) 47 | return polarity 48 | 49 | 50 | # Calls Language Detection and returns the code or name for the text 51 | def detectLanguage(text, get_name=False): 52 | language = '' 53 | # We are going to make a request to the Language Identification API 54 | print("\tDetecting language...") 55 | lang_response = meaningcloud.LanguageResponse(meaningcloud.LanguageRequest(license_key, txt=text).sendReq()) 56 | if lang_response.isSuccessful(): 57 | langs = lang_response.getLanguages() 58 | if langs: 59 | language = lang_response.getLanguageCode(langs[0]) if not get_name else lang_response.getLanguageName(langs[0]) 60 | else: 61 | print("\tOops! Request to detect language was not succesful: (" + lang_response.getStatusCode() + ') ' + lang_response.getStatusMsg()) 62 | return language 63 | 64 | 65 | # Calls Topics Extraction and returns the entities, concepts and fibo concepts if cofigured 66 | def extractTopics(text, fibo, relevance): 67 | 68 | entities = '' 69 | concepts = '' 70 | if fibo: 71 | fibo_concepts = '' 72 | 73 | print("\tGetting entities and concepts...") 74 | topics_req = meaningcloud.TopicsRequest(license_key, txt=text, lang='en', topicType='ec', otherparams={'txtf':'markup'}) 75 | if fibo: 76 | topics_req.addParam('ud', 'FIBO_en') 77 | 78 | topics_response = meaningcloud.TopicsResponse(topics_req.sendReq()) 79 | 80 | # If there are no errors in the request, we extract the entities and concepts 81 | if topics_response.isSuccessful(): 82 | entities_list = topics_response.getEntities() 83 | formatted_entities = [] 84 | if entities_list: 85 | for entity in entities_list: 86 | if int(topics_response.getTopicRelevance(entity)) >= relevance: #we limit the entities to those with relevance higher than 80 87 | formatted_entities.append(topics_response.getTopicForm(entity) + ' (' + topics_response.getTypeLastNode(topics_response.getOntoType(entity)) + ')') 88 | entities = ', '.join(formatted_entities) 89 | else: 90 | entities = '(none)' 91 | 92 | concepts_list = topics_response.getConcepts() 93 | formatted_concepts = [] 94 | formatted_fibo_concepts = [] 95 | if concepts_list: 96 | for concept in concepts_list: 97 | if fibo and 'dictionary' in concept.keys() and concept['dictionary'] == 'FIBO_en': 98 | formatted_fibo_concepts.append(topics_response.getTopicForm(concept) + ' (' + topics_response.getTypeLastNode(topics_response.getOntoType(concept)) + ')') 99 | #we limit the concepts to those with relevance higher than 80 or multiwords, or user defined concepts 100 | elif int(topics_response.getTopicRelevance(concept)) >= relevance or (' ' in topics_response.getTopicForm(concept) and int(topics_response.getTopicRelevance(concept)) >= (relevance/2)) or topics_response.isUserDefined(concept): 101 | formatted_concepts.append(topics_response.getTopicForm(concept) + ' (' + topics_response.getTypeLastNode(topics_response.getOntoType(concept)) + ')') 102 | 103 | concepts = ', '.join(formatted_concepts) if formatted_concepts else '(none)' 104 | fibo_concepts = ', '.join(formatted_fibo_concepts) if formatted_fibo_concepts else '(none)' 105 | else: 106 | concepts = "(none)" 107 | fibo_concepts = "(none)" 108 | else: 109 | print("\tOops! Request to topics was not succesful: (" + topics_response.getStatusCode() + ') ' + topics_response.getStatusMsg()) 110 | 111 | 112 | return entities, concepts, fibo_concepts if fibo else entities, concepts 113 | 114 | 115 | # Calls Deep Categorization for a given model and returns the label and relevance of the categories 116 | def getDeepCategorization(text, model, num_cats): 117 | # We are going to make a request to the Deep Categorization API 118 | formatted_categories = '' 119 | print("\tGetting " + model[0:len(model) - 3].replace('_', ' ') + " analysis...") 120 | deepcat_response = meaningcloud.DeepCategorizationResponse(meaningcloud.DeepCategorizationRequest(license_key, model=model, txt=text).sendReq()) 121 | if deepcat_response.isSuccessful(): 122 | categories = deepcat_response.getCategories() 123 | formatted_categories = (', '.join(deepcat_response.getCategoryLabel(cat) + ' (' + deepcat_response.getCategoryRelevance(cat) +')' for cat in categories[:num_cats])) if categories else '(none)' 124 | else: 125 | print("\tOops! Request to Deep Categorization was not succesful: (" + deepcat_response.getStatusCode() + ') ' + deepcat_response.getStatusMsg()) 126 | 127 | return formatted_categories 128 | 129 | 130 | # Calls Text Classification for a specific model and returns the label and relevance of the categories 131 | def getTextClassification(text, model, num_cats): 132 | formatted_categories = '' 133 | print("\tGetting " + model[0:len(model) - 3].replace('_', ' ')+ " analysis...") 134 | class_response = meaningcloud.ClassResponse(meaningcloud.ClassRequest(license_key, txt=text, model=model, otherparams={'txtf': 'markup'}).sendReq()) 135 | if class_response.isSuccessful(): 136 | categories = class_response.getCategories() 137 | formatted_categories = (', '.join(class_response.getCategoryLabel(cat) + ' (' + class_response.getCategoryRelevance(cat) +')' for cat in categories[:num_cats])) if categories else '(none)' 138 | else: 139 | print("\tOops! The request to Text Classification was not succesful: (" + class_response.getStatusCode() + ') ' + class_response.getStatusMsg()) 140 | 141 | return formatted_categories 142 | 143 | 144 | # Calls Summarization and obtains an extractive summary with the number of sentences especified 145 | def getSummarization(text, sentences): 146 | # We are going to make a request to the Summarization API 147 | summary = '' 148 | print("\tGetting automatic summarization...") 149 | summarization_response = meaningcloud.SummarizationResponse(meaningcloud.SummarizationRequest(license_key, sentences=sentences, txt=text).sendReq()) 150 | if summarization_response.isSuccessful(): 151 | summary = summarization_response.getSummary() 152 | else: 153 | print("\tOops! Request to Summarization was not succesful: (" + summarization_response.getStatusCode() + ') ' + summarization_response.getStatusMsg()) 154 | 155 | return summary 156 | 157 | 158 | # This function obtains the text clustering of the text collection passed as a parameter 159 | def getClustering(text_collection, cluster_score_threshold): 160 | 161 | # We are going to make a request to the Clustering API 162 | print("Getting clustering analysis...") 163 | clustering_response = meaningcloud.ClusteringResponse(meaningcloud.ClusteringRequest(license_key, lang='en', texts=text_collection).sendReq()) 164 | if clustering_response.isSuccessful(): 165 | clusters = clustering_response.getClusters() 166 | maximum_score = float(clustering_response.getClusterScore(clusters[0])) #first one has higher score 167 | titles = [] 168 | sizes = [] 169 | scores = [] 170 | docs = [] 171 | for cl in clusters: 172 | if (maximum_score == 0 or (float(clustering_response.getClusterScore(cl))/maximum_score)*100 >= cluster_score_threshold): 173 | titles.append(clustering_response.getClusterTitle(cl)) 174 | sizes.append(clustering_response.getClusterSize(cl)) 175 | scores.append(clustering_response.getClusterScore(cl)) 176 | docs.append(', '.join(cl['document_list'].keys())) 177 | return titles, sizes, scores, docs 178 | else: 179 | print('Request to clustering was not succesful: (' + clustering_response.getStatusCode() + ') ' + clustering_response.getStatusMsg()) 180 | return [], [], [], [] 181 | 182 | 183 | # Analyzes the text passed as a parameter 184 | def analyzeText(text, fibo=False): 185 | # this is where we are going to store our results 186 | global index_count 187 | 188 | print("Analyzing file " + str(index_count) + " of "+ str(total_files)) 189 | index_count += 1 190 | 191 | try: 192 | # We are going to make a request to the Language Identification API 193 | language = detectLanguage(text, get_name=True) 194 | 195 | # We are going to make a request to the Sentiment Analysis API 196 | polarity = getSentimentAnalysis(text) 197 | 198 | # We are going to make a request to the Topics Extraction API 199 | topics = extractTopics(text, fibo, topics_relevance) 200 | entities = topics[0] 201 | concepts = topics[1] 202 | if fibo: 203 | fibo_concepts = topics[2] 204 | 205 | # We are going to make a request to the Deep Categorization API 206 | iab2 = getDeepCategorization(text, 'IAB_2.0_en', number_categories) 207 | 208 | # We are going to make a request to the Text Classification API 209 | iptc = getTextClassification(text, 'IPTC_en', number_categories) 210 | 211 | # We are going to make a request to the Summarization API 212 | summary = getSummarization(text, 3) 213 | 214 | except ValueError: 215 | e = sys.exc_info()[0] 216 | print("\nException: " + str(e)) 217 | 218 | if fibo: 219 | return pd.Series([polarity, language, entities, concepts, fibo_concepts, iab2, iptc, summary]) 220 | else: 221 | return pd.Series([polarity, language, entities, concepts, iab2, iptc, summary]) 222 | 223 | 224 | 225 | ###################### Main flow ###################### 226 | # Flow when the script is run from the command line 227 | if __name__ == "__main__": 228 | 229 | # checks the args needed 230 | if len(sys.argv)<=2: 231 | print("\nusage: mc_showcase.py \n") 232 | exit() 233 | 234 | input_folder = sys.argv[1] 235 | output_file = sys.argv[2] 236 | 237 | # read files 238 | input_files = {} 239 | for file_name in os.listdir('./' + input_folder): 240 | f = open(input_folder + '/' + file_name, 'r', encoding='utf-8', errors='ignore') 241 | if f.mode == 'r': 242 | input_files[file_name] = f.read() 243 | 244 | total_files = len(input_files) 245 | 246 | 247 | print(str(total_files) + " files read from '" + input_folder + "'") 248 | 249 | # Process texts 250 | df = pd.DataFrame({'Text': input_files}) 251 | label_list = ['Polarity', 'Language', 'Entities', 'Concepts', 'FIBO_concepts', 'IAB2', 'IPTC', 'Summary'] if get_fibo else ['Polarity', 'Language', 'Entities', 'Concepts', 'IAB2', 'IPTC', 'Summary'] 252 | df[label_list] = df['Text'].apply(analyzeText, fibo=get_fibo) 253 | df.to_csv('./' + output_file + '.csv', index_label='File_name') 254 | print("Results printed to '"+ output_file + ".csv'!") 255 | # print(df) 256 | 257 | 258 | # Cluster all files 259 | resulting_clusters = getClustering(input_files, cluster_score_threshold) 260 | df_clusters = pd.DataFrame( {'Cluster_Name': resulting_clusters[0], 'Size': resulting_clusters[1], 'Score': resulting_clusters[2], 'Documents': resulting_clusters[3]}) 261 | df_clusters.to_csv('./' + output_file + '_clusters.csv', index_label='Cluster_ID') 262 | print("Clustering results printed to '"+ output_file + "_clusters.csv'!") 263 | # print(df_clusters) 264 | -------------------------------------------------------------------------------- /meaningcloud/ClassRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class ClassRequest(meaningcloud.Request): 5 | 6 | endpoint = 'class-2.0' 7 | otherparams = None 8 | extraheaders = None 9 | type_ = "" 10 | 11 | def __init__(self, key, model='IPTC_en', txt=None, url=None, doc=None, 12 | otherparams=None, extraheaders=None, 13 | server='https://api.meaningcloud.com/'): 14 | """ 15 | ClassRequest constructor 16 | 17 | :param key: 18 | license key 19 | :param txt: 20 | Text to use in the API calls 21 | :param url: 22 | Url to use in the API calls 23 | :param doc: 24 | File to use in the API calls 25 | :param model: 26 | Name of the model to use in the classification 27 | :param otherparams: 28 | Array where other params can be added to be used in the API call 29 | :param server: 30 | String with the server the requests will be sent to 31 | """ 32 | 33 | if server[len(server)-1] != '/': 34 | server += '/' 35 | 36 | self._params = {} 37 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 38 | self.otherparams = otherparams 39 | self.extraheaders = extraheaders 40 | self._url = server + self.endpoint 41 | 42 | self.addParam('key', key) 43 | self.addParam('model', model) 44 | 45 | if txt: 46 | type_ = 'txt' 47 | elif doc: 48 | type_ = 'doc' 49 | elif url: 50 | type_ = 'url' 51 | else: 52 | type_ = 'default' 53 | 54 | options = {'doc': lambda: self.setContentFile(doc), 55 | 'url': lambda: self.setContentUrl(url), 56 | 'txt': lambda: self.setContentTxt(txt), 57 | 'default': lambda: self.setContentTxt(txt) 58 | } 59 | options[type_]() 60 | if (otherparams): 61 | for key in otherparams: 62 | self.addParam(key, otherparams[key]) 63 | 64 | def sendReq(self): 65 | return self.sendRequest(self.extraheaders) 66 | -------------------------------------------------------------------------------- /meaningcloud/ClassResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class ClassResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | ClassResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | def getCategories(self): 19 | """ 20 | Get categories from the analyzed text 21 | 22 | :return: 23 | Array with the categories detected 24 | """ 25 | 26 | return (self._response['category_list'] 27 | if (('category_list' in self._response.keys()) and (self._response['category_list'] is not None)) 28 | else {}) 29 | 30 | # Generic auxiliary functions 31 | 32 | def getCategoryCode(self, category): 33 | """ 34 | Get the code of a category 35 | 36 | :param category: 37 | Category you want the code from 38 | :return: 39 | Category code 40 | """ 41 | 42 | return (category['code'] 43 | if ((len(category) > 0) and ('code' in category.keys()) and (category['code'] is not None)) 44 | else "") 45 | 46 | def getCategoryLabel(self, category): 47 | """ 48 | Get the label of a category 49 | 50 | :param category: 51 | Category you want the label from 52 | :return: 53 | Category label 54 | """ 55 | 56 | return (category['label'] 57 | if ((len(category) > 0) and ('label' in category.keys()) and (category['label'] is not None)) 58 | else "") 59 | 60 | def getCategoryAbsRelevance(self, category): 61 | """ 62 | Get the absolute relevance of a category 63 | 64 | :param category: 65 | Category you want the abs_relevance from 66 | :return: 67 | Category abs_relevance 68 | """ 69 | 70 | return (category['abs_relevance'] 71 | if ((len(category) > 0) and ('abs_relevance' in category.keys()) and 72 | (category['abs_relevance'] is not None)) 73 | else "") 74 | 75 | def getCategoryRelevance(self, category): 76 | """ 77 | Get the relevance of a category 78 | 79 | :param category: 80 | Category you want the relevance from 81 | :return: 82 | Category relevance 83 | """ 84 | 85 | return (category['relevance'] 86 | if ((len(category) > 0) and ('relevance' in category.keys()) and (category['relevance'] is not None)) 87 | else "") 88 | -------------------------------------------------------------------------------- /meaningcloud/ClusteringRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class ClusteringRequest(meaningcloud.Request): 5 | 6 | endpoint = 'clustering-1.1' 7 | otherparams = None 8 | extraheaders = None 9 | type_ = "" 10 | 11 | def __init__(self, key, lang, texts, mode='tm', otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 12 | """ 13 | ClusteringRequest constructor 14 | 15 | :param key: 16 | license key 17 | :param lang: 18 | language of the text 19 | :param txt: 20 | Collection of texts to cluster. Dictionary expected where the keys are the IDs of the text/doc 21 | :param mode: 22 | Clustering algorithm 23 | :param otherparams: 24 | Array where other params can be added to be used in the API call 25 | :param extraheaders: 26 | Array where other headers can be added to be used in the request 27 | :param server: 28 | String with the server the requests will be sent to 29 | """ 30 | if server[len(server)-1] != '/': 31 | server += '/' 32 | self._params = {} 33 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 34 | self.otherarams = otherparams 35 | self.extraheaders = extraheaders 36 | self._url = server + self.endpoint 37 | 38 | self.addParam('key', key) 39 | self.addParam('lang', lang) 40 | self.addParam('mode', mode) 41 | self.addParam('txt', "\r\n".join(val.replace("\r", ' ').replace("\n", " ").replace("\f", " ").replace("\x00", " ").replace("\x01", " ").replace("\x02", " ") for val in texts.values())) 42 | self.addParam('id', "\r\n".join(texts.keys())) 43 | 44 | if (otherparams): 45 | for key in otherparams: 46 | self.addParam(key, otherparams[key]) 47 | 48 | def sendReq(self): 49 | return self.sendRequest(self.extraheaders) 50 | -------------------------------------------------------------------------------- /meaningcloud/ClusteringResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class ClusteringResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | ClusteringResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | def getClusters(self): 19 | """ 20 | Get clusters found for the texts sent 21 | 22 | :return: 23 | Array with the categories detected 24 | """ 25 | 26 | return (self._response['cluster_list'] 27 | if (('cluster_list' in self._response.keys()) and (self._response['cluster_list'] is not None)) 28 | else {}) 29 | 30 | # Generic auxiliary functions 31 | 32 | def getClusterTitle(self, cluster): 33 | """ 34 | Get the title of a cluster 35 | 36 | :param cluster: 37 | Cluster you want the title from 38 | :return: 39 | Cluster title 40 | """ 41 | 42 | return (cluster['title'] 43 | if ((len(cluster) > 0) and ('title' in cluster.keys()) and (cluster['title'] is not None)) 44 | else "") 45 | 46 | def getClusterSize(self, cluster): 47 | """ 48 | Get the size of a cluster 49 | 50 | :param cluster: 51 | Cluster you want the size from 52 | :return: 53 | Cluster size 54 | """ 55 | 56 | return (cluster['size'] 57 | if ((len(cluster) > 0) and ('size' in cluster.keys()) and (cluster['size'] is not None)) 58 | else "") 59 | 60 | def getClusterScore(self, cluster): 61 | """ 62 | Get the score of a cluster 63 | 64 | :param cluster: 65 | Cluster you want the score from 66 | :return: 67 | Cluster score 68 | """ 69 | 70 | return (cluster['score'] 71 | if ((len(cluster) > 0) and ('score' in cluster.keys()) and (cluster['score'] is not None)) 72 | else "") 73 | 74 | def getClusterDocuments(self, cluster): 75 | """ 76 | Get the list of documents in a cluster 77 | 78 | :param cluster: 79 | Cluster you want the relevance from 80 | :return: 81 | Cluster relevance 82 | """ 83 | 84 | return (self._response['document_list'] 85 | if (('document_list' in self._response.keys()) and (self._response['document_list'] is not None)) 86 | else {}) -------------------------------------------------------------------------------- /meaningcloud/DeepCategorizationRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class DeepCategorizationRequest(meaningcloud.Request): 5 | 6 | endpoint = 'deepcategorization-1.0' 7 | otherparams = None 8 | extraheaders = None 9 | type_ = "" 10 | 11 | def __init__(self, key, model, txt=None, url=None, doc=None, polarity='n', otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 12 | """ 13 | DeepCategorizationRequest constructor 14 | 15 | :param key: 16 | license key 17 | :param txt: 18 | Text to use in the API calls 19 | :param url: 20 | Url to use in the API calls 21 | :param doc: 22 | File to use in the API calls 23 | :param model: 24 | Name of the model to use in the classification 25 | :param polarity: 26 | Determines if categories will contain an associated polarity value. 27 | :param otherparams: 28 | Array where other params can be added to be used in the API call 29 | :param extraheaders: 30 | Array where other headers can be added to be used in the request 31 | :param server: 32 | String with the server the requests will be sent to 33 | """ 34 | 35 | if server[len(server)-1] != '/': 36 | server += '/' 37 | self._params = {} 38 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 39 | self.otherarams = otherparams 40 | self.extraheaders = extraheaders 41 | self._url = server + self.endpoint 42 | 43 | self.addParam('key', key) 44 | self.addParam('model', model) 45 | self.addParam('polarity', polarity) 46 | 47 | if txt: 48 | type_ = 'txt' 49 | elif doc: 50 | type_ = 'doc' 51 | elif url: 52 | type_ = 'url' 53 | else: 54 | type_ = 'default' 55 | 56 | options = {'doc': lambda: self.setContentFile(doc), 57 | 'url': lambda: self.setContentUrl(url), 58 | 'txt': lambda: self.setContentTxt(txt), 59 | 'default': lambda: self.setContentTxt(txt) 60 | } 61 | options[type_]() 62 | if (otherparams): 63 | for key in otherparams: 64 | self.addParam(key, otherparams[key]) 65 | 66 | def sendReq(self): 67 | return self.sendRequest(self.extraheaders) 68 | -------------------------------------------------------------------------------- /meaningcloud/DeepCategorizationResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class DeepCategorizationResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | DeepCategorizationResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | def getCategories(self): 19 | """ 20 | Get categories from the analyzed text 21 | 22 | :return: 23 | Array with the categories detected 24 | """ 25 | 26 | return (self._response['category_list'] 27 | if (('category_list' in self._response.keys()) and (self._response['category_list'] is not None)) 28 | else {}) 29 | 30 | # Generic auxiliary functions 31 | 32 | def getCategoryCode(self, category): 33 | """ 34 | Get the code of a category 35 | 36 | :param category: 37 | Category you want the code from 38 | :return: 39 | Category code 40 | """ 41 | 42 | return (category['code'] 43 | if ((len(category) > 0) and ('code' in category.keys()) and (category['code'] is not None)) 44 | else "") 45 | 46 | def getCategoryLabel(self, category): 47 | """ 48 | Get the label of a category 49 | 50 | :param category: 51 | Category you want the label from 52 | :return: 53 | Category label 54 | """ 55 | 56 | return (category['label'] 57 | if ((len(category) > 0) and ('label' in category.keys()) and (category['label'] is not None)) 58 | else "") 59 | 60 | def getCategoryAbsRelevance(self, category): 61 | """ 62 | Get the absolute relevance of a category 63 | 64 | :param category: 65 | Category you want the abs_relevance from 66 | :return: 67 | Category abs_relevance 68 | """ 69 | 70 | return (category['abs_relevance'] 71 | if ((len(category) > 0) and ('abs_relevance' in category.keys()) and 72 | (category['abs_relevance'] is not None)) 73 | else "") 74 | 75 | def getCategoryRelevance(self, category): 76 | """ 77 | Get the relevance of a category 78 | 79 | :param category: 80 | Category you want the relevance from 81 | :return: 82 | Category relevance 83 | """ 84 | 85 | return (category['relevance'] 86 | if ((len(category) > 0) and ('relevance' in category.keys()) and (category['relevance'] is not None)) 87 | else "") 88 | 89 | def getCategoryPolarity(self, category): 90 | """ 91 | Get the polarity of a category 92 | 93 | :param category: 94 | Category you want the polarity from 95 | :return: 96 | Category relevance 97 | """ 98 | 99 | return (category['polarity'] 100 | if ((len(category) > 0) and ('polarity' in category.keys()) and (category['polarity'] is not None)) 101 | else "") -------------------------------------------------------------------------------- /meaningcloud/LanguageRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class LanguageRequest(meaningcloud.Request): 5 | endpoint = 'lang-2.0' 6 | otherparams = None 7 | extraheaders = None 8 | type_ = "" 9 | 10 | def __init__(self, key, txt=None, url=None, doc=None, otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 11 | """ 12 | LanguageRequest constructor 13 | 14 | :param key: 15 | License key 16 | :param txt: 17 | Text to use in the API calls 18 | :param url: 19 | Url to use in the API calls 20 | :param doc: 21 | File to use in the API calls 22 | :param otherparams: 23 | Array where other params can be added to be used in the API call 24 | :param extraheaders: 25 | Array where other headers can be added to be used in the request 26 | :param server: 27 | String with the server the requests will be sent to 28 | """ 29 | 30 | if server[len(server)-1] != '/': 31 | server += '/' 32 | self._params = {} 33 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 34 | self.otherarams = otherparams 35 | self.extraheaders = extraheaders 36 | self._url = server + self.endpoint 37 | 38 | self.addParam('key', key) 39 | 40 | if txt: 41 | type_ = 'txt' 42 | 43 | elif doc: 44 | type_ = 'doc' 45 | 46 | elif url: 47 | type_ = 'url' 48 | 49 | else: 50 | type_ = 'default' 51 | 52 | options = {'doc': lambda: self.setContentFile(doc), 53 | 'url': lambda: self.setContentUrl(url), 54 | 'txt': lambda: self.setContentTxt(txt), 55 | 'default': lambda: self.setContentTxt(txt) 56 | } 57 | options[type_]() 58 | if otherparams: 59 | for key in otherparams: 60 | self.addParam(key, otherparams[key]) 61 | 62 | def sendReq(self): 63 | return self.sendRequest(self.extraheaders) 64 | -------------------------------------------------------------------------------- /meaningcloud/LanguageResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class LanguageResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | LanguageResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | # Getters for the different objects returned 19 | def getLanguages(self): 20 | """ 21 | Get languages from the analyzed text 22 | 23 | :return: 24 | Array with the languages detected 25 | """ 26 | 27 | return (self._response['language_list'] 28 | if (('language_list' in self._response.keys()) and (self._response['language_list'] is not None)) 29 | else {}) 30 | 31 | def getFirstLanguage(self): 32 | """ 33 | Get first language returned for the analyzed text 34 | 35 | :return: 36 | Array with the field of the language detected 37 | """ 38 | 39 | languages = (self._response['language_list'] 40 | if (('language_list' in self._response.keys()) and (self._response['language_list'] is not None)) 41 | else {}) 42 | return languages[0] if((len(languages) > 0) and (languages[0] is not None)) else [] 43 | 44 | def getLanguageCode(self, language): 45 | """ 46 | Get the code of a language 47 | 48 | :param language: 49 | Language you want the code from 50 | :return: 51 | Language code 52 | """ 53 | 54 | return (language['language'] 55 | if ((len(language) > 0) and ('language' in language.keys()) and (language['language'] is not None)) 56 | else "") 57 | 58 | def getLanguageName(self, language): 59 | """ 60 | Get the name of a language 61 | 62 | :param language: 63 | Language you want the name from 64 | :return: 65 | Language name 66 | """ 67 | 68 | return (language['name'] 69 | if ((len(language) > 0) and ('name' in language.keys()) and (language['name'] is not None)) 70 | else "") 71 | -------------------------------------------------------------------------------- /meaningcloud/ParserRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class ParserRequest(meaningcloud.Request): 5 | endpoint = 'parser-2.0' 6 | otherparams = None 7 | extraheaders = None 8 | type_ = "" 9 | 10 | def __init__(self, key, txt=None, doc=None, url=None, lang=None, otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 11 | """ 12 | ParserRequest constructor 13 | 14 | :param key: 15 | License key 16 | :param txt: 17 | Text to use in the API calls 18 | :param doc: 19 | File to use in the API calls 20 | :param url: 21 | Url to use in the API calls 22 | :param lang: 23 | Language used in the request 24 | :param otherparams: 25 | Array where other params can be added to be used in the API call 26 | :param extraheaders: 27 | Array where other headers can be added to be used in the request 28 | :param server: 29 | String with the server the requests will be sent to 30 | """ 31 | 32 | if server[len(server)-1] != '/': 33 | server += '/' 34 | 35 | self._params = {} 36 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 37 | self.otherparams = otherparams 38 | self.extraheaders = extraheaders 39 | self._url = server + self.endpoint 40 | 41 | self.addParam('key', key) 42 | self.addParam('lang', lang) 43 | 44 | if txt: 45 | type_ = 'txt' 46 | elif doc: 47 | type_ = 'doc' 48 | elif url: 49 | type_ = 'url' 50 | else: 51 | type_ = 'default' 52 | 53 | options = {'doc': lambda: self.setContentFile(doc), 54 | 'url': lambda: self.setContentUrl(url), 55 | 'txt': lambda: self.setContentTxt(txt), 56 | 'default': lambda: self.setContentTxt(txt) 57 | } 58 | options[type_]() 59 | if otherparams: 60 | for key in otherparams: 61 | self.addParam(key, otherparams[key]) 62 | 63 | def sendReq(self): 64 | return self.sendRequest(self.extraheaders) 65 | -------------------------------------------------------------------------------- /meaningcloud/ParserResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class ParserResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | ParserResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | 17 | meaningcloud.Response.__init__(self, response) 18 | 19 | # This function obtains the lemmas and PoS for the text sent 20 | # @param boolean fullPOSTag set to true to obtain the complete PoS tag 21 | # @return array of tokens from the syntactic tree with their lemmas and PoS 22 | def getLemmatization(self, fullPOSTag=False): 23 | """ 24 | This function obtains the lemmas and PoS for the text sent 25 | 26 | :param fullPOSTag: 27 | Set to true to obtain the complete PoS tag 28 | :return: 29 | Dictionary of tokens from the syntactic tree with their lemmas and PoS 30 | """ 31 | 32 | leaves = self._getTreeLeaves() 33 | lemmas = {} 34 | for leaf in leaves: 35 | analyses = [] 36 | if 'analysis_list' in leaf.keys(): 37 | for analysis in leaf['analysis_list']: 38 | analyses.append({ 39 | 'lemma': analysis['lemma'], 40 | 'pos': analysis['tag'] if fullPOSTag else analysis['tag'][:2] 41 | }) 42 | lemmas[leaf['form']] = analyses 43 | 44 | return lemmas 45 | 46 | def _getTreeLeaves(self): 47 | if 'token_list' in self._response.keys(): 48 | leaves = [] 49 | for sentence in self._response['token_list']: 50 | self._traverseTree(sentence, leaves) 51 | 52 | return leaves 53 | 54 | def _traverseTree(self, token, leaves): 55 | if 'token_list' in token.keys(): 56 | for t in token['token_list']: 57 | if 'token_list' in t.keys(): 58 | self._traverseTree(t, leaves) 59 | else: 60 | leaves.append(t) 61 | -------------------------------------------------------------------------------- /meaningcloud/Request.py: -------------------------------------------------------------------------------- 1 | import requests 2 | import sys 3 | if sys.version_info.major < 3: 4 | from urllib import urlencode 5 | elif sys.version_info.major == 3: 6 | from urllib.parse import urlencode 7 | 8 | 9 | class Request: 10 | _timeout = 60 11 | _url = "" 12 | _key = "" 13 | _params = {} 14 | 15 | _file = {} 16 | 17 | CONTENT_TYPE_TXT = 'txt' 18 | CONTENT_TYPE_URL = 'url' 19 | CONTENT_TYPE_FILE = 'doc' 20 | 21 | def __init__(self, url, key): 22 | """ 23 | Request constructor 24 | 25 | :param url: 26 | URL of the API against which the request will be made 27 | :param key: 28 | License key 29 | """ 30 | 31 | if not url or not key: 32 | raise ValueError("URL and key cannot be empty") 33 | self._url = url 34 | self._key = key 35 | self.addParam('key', key) 36 | 37 | def addParam(self, paramName, paramValue): 38 | """ 39 | Add a parameter to the request 40 | 41 | :param paramName: 42 | Name of the parameter 43 | :param paramValue: 44 | Value of the parameter 45 | """ 46 | 47 | if not paramName: 48 | raise ValueError('paramName cannot be empty') 49 | self._params[paramName] = paramValue 50 | 51 | def setContent(self, type_, value): 52 | """ 53 | Sets the content that's going to be sent to analyze according to its type 54 | 55 | :param type_: 56 | Type of the content (text, file or url) 57 | :param value: 58 | Value of the content 59 | """ 60 | 61 | if type_ in [self.CONTENT_TYPE_TXT, self.CONTENT_TYPE_URL, 62 | self.CONTENT_TYPE_FILE]: 63 | if type_ == self.CONTENT_TYPE_FILE: 64 | self._file = {} 65 | self._file = {'doc': open(value, 'rb')} 66 | else: 67 | self.addParam(type_, value) 68 | 69 | def setContentTxt(self, txt): 70 | """ 71 | Sets a text content to send to the API 72 | 73 | :param txt: 74 | Text to be sent to the API 75 | """ 76 | 77 | self.setContent(self.CONTENT_TYPE_TXT, txt) 78 | 79 | def setContentUrl(self, url): 80 | """ 81 | Sets a URL content to send to the API 82 | 83 | :param url: 84 | URL to be analyzed by the API 85 | """ 86 | 87 | self.setContent(self.CONTENT_TYPE_URL, url) 88 | 89 | def setContentFile(self, file): 90 | """ 91 | Sets a File content to send to the API. 92 | 93 | :param file: 94 | File to be sent to the API 95 | """ 96 | 97 | self.setContent(self.CONTENT_TYPE_FILE, file) 98 | 99 | def sendRequest(self, extraHeaders=""): 100 | """ 101 | Sends a request to the URL specified and returns a response only if the HTTP code returned is OK 102 | 103 | :param extraHeaders: 104 | Allows to configure additional headers in the request 105 | :return: 106 | Response object set to None if there is an error 107 | """ 108 | if not 'src' in self._params.keys(): 109 | self.addParam('src', 'mc-python') 110 | 111 | params = urlencode(self._params) 112 | 113 | url = self._url 114 | 115 | if 'doc' in self._file.keys(): 116 | headers = {} 117 | 118 | if (extraHeaders is not None) and (extraHeaders is dict): 119 | headers = headers.update(extraHeaders) 120 | 121 | result = requests.post(url=url, data=self._params, files=self._file, headers=headers) 122 | result.encoding = 'utf-8' 123 | return result 124 | else: 125 | headers = {'Content-Type': 'application/x-www-form-urlencoded'} 126 | if (extraHeaders is not None) and (extraHeaders is dict): 127 | headers = headers.update(extraHeaders) 128 | result = requests.request("POST", url=url, data=params, headers=headers, timeout=self._timeout) 129 | result.encoding = 'utf-8' 130 | return result 131 | 132 | # Getters and Setters 133 | 134 | def getUrl(self): 135 | """ 136 | Get the url of the request 137 | 138 | :return: 139 | String with the url 140 | """ 141 | 142 | return self._url 143 | 144 | def setUrl(self, url): 145 | """ 146 | Set a new URL 147 | 148 | :param url: 149 | New URL 150 | """ 151 | 152 | self._url = url 153 | 154 | def getParams(self): 155 | """ 156 | Get the params attribute 157 | 158 | :return: 159 | params attribute 160 | """ 161 | 162 | return self._params 163 | 164 | def getTimeout(self): 165 | """ 166 | Get the timeout value 167 | 168 | :return: 169 | timeout value 170 | """ 171 | 172 | return self._timeout 173 | 174 | def setTimeout(self, timeout): 175 | """ 176 | Set a new timeout value 177 | 178 | :param timeout: 179 | New timeout 180 | """ 181 | 182 | self._timeout = timeout 183 | 184 | def getFile(self): 185 | """ 186 | Get the file attribute 187 | 188 | :return: 189 | file attribute 190 | """ 191 | 192 | return self._file 193 | -------------------------------------------------------------------------------- /meaningcloud/Response.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | class Response: 5 | _response = {} 6 | __strResponse = {} 7 | __aux = {} 8 | 9 | def __init__(self, response): 10 | """ 11 | Response constructor 12 | 13 | :param response: 14 | Array returned by the request 15 | """ 16 | 17 | if not response: 18 | raise Exception("The request sent did not return a response") 19 | self.__strResponse = response 20 | if response.__class__ == 'str'.__class__: 21 | self._response = json.loads(response) 22 | else: 23 | self._response = json.loads(response.text) 24 | 25 | def isSuccessful(self): 26 | """ 27 | Checks if the response has been successful at application level (code returned by the API) 28 | 29 | :return: 30 | Boolean indicating if the request has finished successfully (application level) 31 | """ 32 | 33 | return(self.getStatusCode() == '0') 34 | 35 | # Getters and Setters 36 | 37 | def getStatusCode(self): 38 | """ 39 | Returns the code of the status or None if it does not exist 40 | 41 | :return: 42 | Status code of the response 43 | """ 44 | 45 | if 'status' in self._response.keys(): 46 | if (self._response['status'] is not None) and ('code' in self._response['status'].keys()) and (self._response['status']['code'] is not None): 47 | return self._response['status']['code'] 48 | 49 | else: 50 | return None 51 | else: 52 | return None 53 | 54 | def getStatusMsg(self): 55 | """ 56 | Returns the message of the status or an empty string if it does not exist 57 | 58 | :return: 59 | Status message of the response 60 | """ 61 | 62 | if 'status' in self._response.keys(): 63 | if (self._response['status'] is not None) and ('msg' in self._response['status'].keys()) and (self._response['status']['msg'] is not None): 64 | return self._response['status']['msg'] 65 | else: 66 | return '' 67 | 68 | def getConsumedCredits(self): 69 | """ 70 | Returns the credit consumed by the request made 71 | 72 | :return: 73 | String with the number of credits consumed 74 | """ 75 | 76 | if 'status' in self._response.keys(): 77 | if (self._response['status'] is not None) and ('credits' in self._response['status'].keys()): 78 | if self._response['status']['credits'] is not None: 79 | return self._response['status']['credits'] 80 | else: 81 | return '0' 82 | else: 83 | print("Not credits field\n") 84 | else: 85 | return None 86 | 87 | def getRemainingCredits(self): 88 | """ 89 | Returns the remaining credits for the license key used after the request was made 90 | 91 | :return: 92 | String with remaining credits 93 | """ 94 | 95 | if 'status' in self._response.keys(): 96 | if (self._response['status'] is not None) and ('remaining_credits' in self._response['status'].keys()): 97 | if self._response['status']['remaining_credits'] is not None: 98 | return self._response['status']['remaining_credits'] 99 | else: 100 | return '' 101 | else: 102 | print("Not remaining credits field\n") 103 | else: 104 | return None 105 | 106 | def getResults(self): 107 | """ 108 | Returns the results from the API without the status of the request 109 | 110 | :return: 111 | Dictionary with the results 112 | """ 113 | 114 | results = self._response.copy() 115 | if 'status' in self._response.keys(): 116 | if results['status'] is not None: 117 | del results['status'] 118 | return results 119 | else: 120 | return None 121 | 122 | def getResponse(self): 123 | """ 124 | Returns the complete response from the API 125 | 126 | :return: 127 | Dictionary with the response 128 | """ 129 | 130 | return self._response 131 | 132 | def getStrResponse(self): 133 | """ 134 | Returns the response from the API as a string 135 | 136 | :return: 137 | String with the response 138 | """ 139 | 140 | return self.__strResponse 141 | -------------------------------------------------------------------------------- /meaningcloud/SentimentRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class SentimentRequest(meaningcloud.Request): 5 | endpoint = 'sentiment-2.1' 6 | otherparams = None 7 | extraheaders = None 8 | type_ = "" 9 | 10 | def __init__(self, key, lang=None, txt=None, txtf='plain', url=None, doc=None, otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 11 | """ 12 | SentimentRequest constructor 13 | 14 | :param key: 15 | License key 16 | :param lang: 17 | Language used in the request 18 | :param txt: 19 | Text to use in the API calls 20 | :param txtf: 21 | Format of the text 22 | :param url: 23 | Url to use in the API calls 24 | :param doc: 25 | File to use in the API calls 26 | :param otherparams: 27 | Array where other params can be added to be used in the API call 28 | :param extraheaders: 29 | Array where other headers can be added to be used in the request 30 | :param server: 31 | String with the server the requests will be sent to 32 | """ 33 | 34 | if server[len(server)-1] != '/': 35 | server += '/' 36 | 37 | self._params = {} 38 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 39 | 40 | self.otherarams = otherparams 41 | self.extraheaders = extraheaders 42 | self._url = server + self.endpoint 43 | 44 | self.addParam('key', key) 45 | self.addParam('lang', lang) 46 | self.addParam('txtf', txtf) 47 | 48 | if txt: 49 | type_ = 'txt' 50 | elif doc: 51 | type_ = 'doc' 52 | elif url: 53 | type_ = 'url' 54 | else: 55 | type_ = 'default' 56 | 57 | options = {'doc': lambda: self.setContentFile(doc), 58 | 'url': lambda: self.setContentUrl(url), 59 | 'txt': lambda: self.setContentTxt(txt), 60 | 'default': lambda: self.setContentTxt(txt) 61 | } 62 | options[type_]() 63 | 64 | if otherparams: 65 | for key in otherparams: 66 | self.addParam(key, otherparams[key]) 67 | 68 | def sendReq(self): 69 | return self.sendRequest(self.extraheaders) 70 | -------------------------------------------------------------------------------- /meaningcloud/SentimentResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class SentimentResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | SentimentResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | # Getters for the different objects returned 19 | 20 | def getModel(self): 21 | """ 22 | Obtains the sentiment model used to obtain the response 23 | 24 | :return: 25 | Identifier of the model 26 | """ 27 | 28 | return (self._response['model'] 29 | if (('model' in self._response.keys()) and (self._response['model'] is not None)) 30 | else "") 31 | 32 | def getGlobalScoreTag(self): 33 | """ 34 | Obtains the global score tag of the response 35 | 36 | :return: 37 | Global score tag 38 | """ 39 | 40 | return self.getScoreTag(self._response) 41 | 42 | def getScoreTag(self, node): 43 | """ 44 | Obtains the score tag field of a node (if it applies) 45 | 46 | :param node: 47 | Node you want to obtain the score tag from 48 | :return: 49 | Score tag of the node 50 | """ 51 | 52 | return (node['score_tag'] 53 | if (('score_tag' in node.keys()) and (node['score_tag'] is not None)) 54 | else "") 55 | 56 | def getGlobalAgreement(self): 57 | """ 58 | Obtains the global agreement of the response 59 | 60 | :return: 61 | Global agreement 62 | """ 63 | 64 | return (self.getAgreement(self._response)) 65 | 66 | def getAgreement(self, node): 67 | """ 68 | Obtains the agreement field of a node (if it applies) 69 | 70 | :param node: 71 | Node you want to obtain the agreement from 72 | :return: 73 | Agreement of the node 74 | """ 75 | 76 | return (node['agreement'] 77 | if (('agreement' in node.keys()) and (node['agreement'] is not None)) 78 | else "") 79 | 80 | def getSubjectivity(self): 81 | """ 82 | Obtains the global subjectivity of the response 83 | 84 | :return: 85 | Global subjectivity 86 | """ 87 | 88 | return (self._response['subjectivity'] 89 | if (('subjectivity' in self._response.keys()) and (self._response['subjectivity'] is not None)) 90 | else "") 91 | 92 | def getGlobalConfidence(self): 93 | """ 94 | Obtains the global confidence of the response 95 | 96 | :return: 97 | Global confidence 98 | """ 99 | 100 | return (self.getConfidence(self._response)) 101 | 102 | def getConfidence(self, node): 103 | """ 104 | Obtains the confidence field of a node (if it applies) 105 | 106 | :param node: 107 | Node you want to obtain the confidence from 108 | :return: 109 | Confidence of the node 110 | """ 111 | return (node['confidence'] 112 | if (('confidence' in node.keys()) and (node['confidence'] is not None)) 113 | else "") 114 | 115 | def getIrony(self): 116 | """ 117 | Obtains the global irony of the response 118 | 119 | :return: 120 | Global irony 121 | """ 122 | 123 | return (self._response['irony'] 124 | if (('irony' in self._response.keys()) and (self._response['irony'] is not None)) 125 | else "") 126 | 127 | def getGlobalSentimentedEntities(self): 128 | """ 129 | Obtains the entities identified in the text with the global polarity associated to them 130 | 131 | :return: 132 | Sentimented entities 133 | """ 134 | 135 | return self.getSentimentedEntities(self._response) 136 | 137 | def getSentimentedEntities(self, node): 138 | """ 139 | Obtains the entities identified in the text with the polarity associated to them in the node 140 | 141 | :param node: 142 | Node you want to obtain entities from 143 | :return: 144 | Entities of the node 145 | """ 146 | 147 | return (node['sentimented_entity_list'] 148 | if ((len(node) > 0) and ('sentimented_entity_list' in node.keys()) and 149 | (node['sentimented_entity_list'] is not None)) else "") 150 | 151 | def getGlobalSentimentedConcepts(self): 152 | """ 153 | Obtains the concepts identified in the text with the global polarity associated to them 154 | 155 | :return: 156 | Sentimented concepts 157 | """ 158 | 159 | return self.getSentimentedConcepts(self._response) 160 | 161 | def getSentimentedConcepts(self, node): 162 | """ 163 | Obtains the concepts identified in the text with the polarity associated to them in the node 164 | 165 | :param node: 166 | Node you want to obtain concepts from 167 | :return: 168 | Concepts of the node 169 | """ 170 | 171 | return (node['sentimented_concept_list'] 172 | if ((len(node) > 0) and ('sentimented_concept_list' in node.keys()) and 173 | (node['sentimented_concept_list'] is not None)) else "") 174 | 175 | # Generic auxiliary functions 176 | 177 | def scoreTagToString(self, scoreTag): 178 | """ 179 | :param scoreTag: 180 | :return: 181 | """ 182 | 183 | scoreTagToString = "" 184 | if scoreTag == "P+": 185 | scoreTagToString = 'strong positive' 186 | elif scoreTag == "P": 187 | scoreTagToString = 'positive' 188 | elif scoreTag == "NEU": 189 | scoreTagToString = 'neutral' 190 | elif scoreTag == "N": 191 | scoreTagToString = 'negative' 192 | elif scoreTag == "N+": 193 | scoreTagToString = 'strong negative' 194 | elif scoreTag == "NONE": 195 | scoreTagToString = 'no sentiment' 196 | 197 | return scoreTagToString 198 | -------------------------------------------------------------------------------- /meaningcloud/SummarizationRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class SummarizationRequest(meaningcloud.Request): 5 | endpoint = 'summarization-1.0' 6 | otherparams = None 7 | extraheaders = None 8 | type_ = "" 9 | 10 | def __init__(self, key, sentences=5, txt=None, url=None, doc=None, otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 11 | """ 12 | SummarizationRequest constructor 13 | 14 | :param key: 15 | License key 16 | :param sentences: 17 | Number of sentences for the summary. 18 | :param txt: 19 | Text to use in the API calls 20 | :param url: 21 | Url to use in the API calls 22 | :param doc: 23 | File to use in the API calls 24 | :param otherparams: 25 | Array where other params can be added to be used in the API call 26 | :param extraheaders: 27 | Array where other headers can be added to be used in the request 28 | :param server: 29 | String with the server the requests will be sent to 30 | """ 31 | 32 | if server[len(server)-1] != '/': 33 | server += '/' 34 | 35 | self._params = {} 36 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 37 | self.otherarams = otherparams 38 | self.extraheaders = extraheaders 39 | self._url = server + self.endpoint 40 | 41 | self.addParam('key', key) 42 | self.addParam('sentences', sentences) 43 | 44 | if txt: 45 | type_ = 'txt' 46 | 47 | elif doc: 48 | type_ = 'doc' 49 | 50 | elif url: 51 | type_ = 'url' 52 | 53 | else: 54 | type_ = 'default' 55 | 56 | options = {'doc': lambda: self.setContentFile(doc), 57 | 'url': lambda: self.setContentUrl(url), 58 | 'txt': lambda: self.setContentTxt(txt), 59 | 'default': lambda: self.setContentTxt(txt) 60 | } 61 | options[type_]() 62 | if otherparams: 63 | for key in otherparams: 64 | self.addParam(key, otherparams[key]) 65 | 66 | def sendReq(self): 67 | return self.sendRequest(self.extraheaders) 68 | -------------------------------------------------------------------------------- /meaningcloud/SummarizationResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class SummarizationResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | SummarizationResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | meaningcloud.Response.__init__(self, response) 17 | 18 | # Getters for the different objects returned 19 | 20 | def getSummary(self): 21 | """ 22 | Obtains the summary returned 23 | 24 | :return: 25 | Text extracted as the summary 26 | """ 27 | 28 | return (self._response['summary'] 29 | if (('summary' in self._response.keys()) and (self._response['summary'] is not None)) 30 | else "") -------------------------------------------------------------------------------- /meaningcloud/TopicsRequest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Request 2 | 3 | 4 | class TopicsRequest(meaningcloud.Request): 5 | 6 | endpoint = 'topics-2.0' 7 | otherparams = None 8 | extraheaders = None 9 | type_ = "" 10 | 11 | def __init__(self, key, txt=None, doc=None, url=None, lang=None, topicType="a", otherparams=None, extraheaders=None, server='https://api.meaningcloud.com/'): 12 | """ 13 | TopicsRequest constructor 14 | 15 | :param key: 16 | License key 17 | :param txt: 18 | Text to use in the API calls 19 | :param doc: 20 | File to use in the API calls 21 | :param url: 22 | Url to use in the API calls 23 | :param lang: 24 | Language used in the request 25 | :param topicType: 26 | Topic types to be returned in the response 27 | :param otherparams: 28 | Array where other params can be added to be used in the API call 29 | :param extraheaders: 30 | Array where other headers can be added to be used in the request 31 | :param server: 32 | String with the server the requests will be sent to 33 | """ 34 | 35 | if server[len(server)-1] != '/': 36 | server += '/' 37 | 38 | self._params = {} 39 | meaningcloud.Request.__init__(self, (server + self.endpoint), key) 40 | self.otherarams = otherparams 41 | self.extraheaders = extraheaders 42 | self._url = server + self.endpoint 43 | 44 | self.addParam('key', key) 45 | self.addParam('lang', lang) 46 | self.addParam('tt', topicType) 47 | 48 | if txt: 49 | type_ = 'txt' 50 | elif doc: 51 | type_ = 'doc' 52 | elif url: 53 | type_ = 'url' 54 | else: 55 | type_ = 'default' 56 | 57 | options = {'doc': lambda: self.setContentFile(doc), 58 | 'url': lambda: self.setContentUrl(url), 59 | 'txt': lambda: self.setContentTxt(txt), 60 | 'default': lambda: self.setContentTxt(txt)} 61 | options[type_]() 62 | if otherparams: 63 | for key in otherparams: 64 | self.addParam(key, otherparams[key]) 65 | 66 | def sendReq(self): 67 | return self.sendRequest(self.extraheaders) 68 | -------------------------------------------------------------------------------- /meaningcloud/TopicsResponse.py: -------------------------------------------------------------------------------- 1 | import meaningcloud.Response 2 | 3 | 4 | class TopicsResponse(meaningcloud.Response): 5 | 6 | def __init__(self, response): 7 | """ 8 | TopicsResponse constructor 9 | 10 | :param response: 11 | String returned by the request 12 | """ 13 | 14 | if not response: 15 | raise Exception("The request sent did not return a response") 16 | 17 | meaningcloud.Response.__init__(self, response) 18 | 19 | # Getters for the different types of topics returned 20 | 21 | def getEntities(self): 22 | """ 23 | Obtains the entities detected in the text 24 | 25 | :return: 26 | Entities 27 | """ 28 | 29 | return (self._response['entity_list'] 30 | if(('entity_list' in self._response.keys()) and (self._response['entity_list'] is not None)) 31 | else {}) 32 | 33 | def getConcepts(self): 34 | """ 35 | Obtains the concepts detected in the text 36 | 37 | :return: 38 | Concepts 39 | """ 40 | 41 | return (self._response['concept_list'] 42 | if (('concept_list' in self._response.keys()) and (self._response['concept_list'] is not None)) 43 | else {}) 44 | 45 | def getTimeExpressions(self): 46 | """ 47 | Obtains the time expressions detected in the text 48 | 49 | :return: 50 | Time expressions 51 | """ 52 | 53 | return (self._response['time_expression_list'] 54 | if (('time_expression_list' in self._response.keys()) and 55 | (self._response['time_expression_list'] is not None)) else {}) 56 | 57 | def getMoneyExpressions(self): 58 | """ 59 | Obtains the money expressions detected in the text 60 | 61 | :return: 62 | Money expressions 63 | """ 64 | 65 | return (self._response['money_expression_list'] 66 | if (('money_expression_list' in self._response.keys()) and 67 | (self._response['money_expression_list'] is not None)) else {}) 68 | 69 | def getQuantityExpressions(self): 70 | """ 71 | Obtains the quantity expressions detected in the text 72 | 73 | :return: 74 | Quantity expressions 75 | """ 76 | 77 | return (self._response['quantity_expression_list'] 78 | if (('quantity_expression_list' in self._response.keys()) and 79 | (self._response['quantity_expression_list'] is not None)) else {}) 80 | 81 | def getOtherExpressions(self): 82 | """ 83 | Obtains other expressions detected in the text 84 | 85 | :return: 86 | Other expressions 87 | """ 88 | 89 | return (self._response['other_expression_list'] 90 | if (('other_expression_list' in self._response.keys()) and 91 | (self._response['other_expression_list'] is not None)) else {}) 92 | 93 | def getQuotations(self): 94 | """ 95 | Obtains quotations detected in the text 96 | 97 | :return: 98 | Quotations 99 | """ 100 | 101 | return (self._response['quotation_list'] 102 | if (('quotation_list' in self._response.keys()) and (self._response['quotation_list'] is not None)) 103 | else {}) 104 | 105 | def getRelations(self): 106 | """ 107 | Obtains relations detected in the text 108 | 109 | :return: 110 | Relations 111 | """ 112 | 113 | return (self._response['relation_list'] 114 | if (('relation_list' in self._response.keys()) and (self._response['relation_list'] is not None)) 115 | else {}) 116 | 117 | # Generic auxiliary functions 118 | 119 | def getTopicForm(self, topic): 120 | """ 121 | Obtains the form of a topic 122 | 123 | :param topic: 124 | Topic to obtain the form from 125 | :return: 126 | Topic form 127 | """ 128 | 129 | return (topic['form'] 130 | if (('form' in topic.keys()) and (topic['form'] is not None)) 131 | else "") 132 | 133 | def getTopicRelevance(self, topic): 134 | """ 135 | Obtains the relevance of a topic 136 | 137 | :param topic: 138 | Topic to obtain the relevance from 139 | :return: 140 | Topic relevance 141 | """ 142 | 143 | return (topic['relevance'] 144 | if (('relevance' in topic.keys()) and (topic['relevance'] is not None)) 145 | else "") 146 | 147 | def getOntoType(self, topic): 148 | """ 149 | Obtains the ontology type of a topic (if it applies) 150 | 151 | :param topic: 152 | Topic to obtain the ontology type from 153 | :return: 154 | Topic ontology type 155 | """ 156 | 157 | return (topic['sementity']['type'] 158 | if (('sementity' in topic.keys()) and ('type' in topic['sementity'].keys()) and 159 | (topic['sementity']['type'] is not None)) else "") 160 | 161 | def getTypeLastNode(self, type_): 162 | """ 163 | Obtains the last node or leaf of the type specified 164 | 165 | :param type_: 166 | Type we want to analize (sementity, semtheme) 167 | :return: 168 | Last node of the type 169 | """ 170 | 171 | lastNode = "" 172 | if type_ and (type(type_) is not list) and (type(type_) is not dict): 173 | aType = type_.split('>') 174 | lastNode = aType[len(aType) - 1] 175 | return lastNode 176 | 177 | def getTypeFirstNode(self, type_): 178 | """ 179 | Obtains the firstlevel node of the type specified 180 | :param type_: 181 | Type we want to analize (sementity, semtheme) 182 | :return: 183 | First node of the type (or Top if there's no first type) 184 | """ 185 | 186 | firstNode = "" 187 | if type_ and (type(type_) is not list) and (type(type_) is not dict): 188 | aType = type_.split('>') 189 | firstNode = aType[1] if len(aType)>1 else aType[0] 190 | return firstNode 191 | 192 | def getNumberOfAppearances(self, topic): 193 | """ 194 | Gets the number of appearances of a topic 195 | 196 | :param topic: 197 | Topic to analyze 198 | :return: 199 | Number of appearances 200 | """ 201 | 202 | if topic is not None: 203 | if('variant_list' in topic.keys()) and (topic['variant_list'] is not None): 204 | return len(topic['variant_list']) 205 | else: 206 | return 1 207 | else: 208 | return 0 209 | 210 | def isUserDefined(self, topic): 211 | """ 212 | Checks the field 'dictionary' to check if an entity/concept comes from a user dictionary 213 | 214 | :param topic: 215 | Topic to analyze 216 | :return: 217 | Boolean indicating if the topic comes from a user dictionary 218 | """ 219 | 220 | if ('dictionary' in topic.keys()) and (topic['dictionary']): 221 | return True 222 | else: 223 | return False 224 | -------------------------------------------------------------------------------- /meaningcloud/__init__.py: -------------------------------------------------------------------------------- 1 | from meaningcloud.Request import * 2 | from meaningcloud.TopicsRequest import * 3 | from meaningcloud.Response import * 4 | from meaningcloud.TopicsResponse import * 5 | from meaningcloud.ClassRequest import * 6 | from meaningcloud.ClassResponse import * 7 | from meaningcloud.SentimentRequest import * 8 | from meaningcloud.SentimentResponse import * 9 | from meaningcloud.LanguageRequest import * 10 | from meaningcloud.LanguageResponse import * 11 | from meaningcloud.ParserRequest import * 12 | from meaningcloud.ParserResponse import * 13 | from meaningcloud.SummarizationRequest import * 14 | from meaningcloud.SummarizationResponse import * 15 | from meaningcloud.DeepCategorizationRequest import * 16 | from meaningcloud.DeepCategorizationResponse import * 17 | from meaningcloud.ClusteringRequest import * 18 | from meaningcloud.ClusteringResponse import * 19 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env python 2 | 3 | # Always prefer setuptools over distutils 4 | from setuptools import setup, find_packages 5 | # To use a consistent encoding 6 | from codecs import open 7 | from os import path 8 | 9 | here = path.abspath(path.dirname(__file__)) 10 | 11 | with open('README.md') as readme_file: 12 | readme = readme_file.read() 13 | 14 | setup( 15 | 16 | name='MeaningCloud-python', 17 | version='2.0.0', 18 | description='Official Python SDK for MeaningCloud APIs', 19 | long_description=readme, 20 | long_description_content_type='text/markdown', 21 | url='https://github.com/MeaningCloud/meaningcloud-python', 22 | author='MeaningCloud', 23 | author_email='support@meaningcloud.com', 24 | keywords='nlp, MeaningCloud, text analytics', 25 | classifiers=[ 26 | 'Development Status :: 5 - Production/Stable', 27 | 'Programming Language :: Python :: 2', 28 | 'Programming Language :: Python :: 3', 29 | 'Intended Audience :: Developers', 30 | 'Intended Audience :: Information Technology', 31 | 'Intended Audience :: Science/Research', 32 | 'Topic :: Text Processing', 33 | 'Topic :: Text Processing :: General', 34 | 'Topic :: Text Processing :: Linguistic', 35 | 'Topic :: Scientific/Engineering', 36 | 'Topic :: Scientific/Engineering :: Artificial Intelligence', 37 | 'Topic :: Scientific/Engineering :: Information Analysis' 38 | ], 39 | packages=find_packages(exclude=['contrib', 'docs', 'tests']), 40 | install_requires=[ 41 | 'requests[security]' 42 | ], 43 | extras_require={ 44 | 'dev': ['check-manifest'], 45 | 'test': ['coverage'], 46 | }, 47 | ) 48 | -------------------------------------------------------------------------------- /tests/ClassRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class ClassRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/class-2.0' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | text = 'London is big' 11 | model = 'IAB_en' 12 | request = meaningcloud.ClassRequest(KEY, txt=text, model=model) 13 | 14 | def testConstruct(self): 15 | request = self.request 16 | self.assertEqual(self.URL, request.getUrl()) 17 | self.assertIsNotNone(request.getParams()) 18 | params = request.getParams() 19 | self.assertEqual('key' in params.keys(), True) 20 | self.assertEqual(params['key'], self.KEY) 21 | self.assertIsNotNone(request.getTimeout()) 22 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 23 | 24 | extraHeaders = ["Accept: application/json"] 25 | request2 = meaningcloud.ClassRequest(self.KEY, txt=self.text, model=self.model, extraheaders=extraHeaders) 26 | self.assertIsNotNone(request2.sendReq()) 27 | 28 | otherparams = {'key2': 'my_key2'} 29 | request3 = meaningcloud.ClassRequest(self.KEY, txt=self.text, model=self.model, extraheaders=extraHeaders, 30 | otherparams=otherparams) 31 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 32 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 33 | 34 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 35 | request4 = meaningcloud.ClassRequest(self.KEY, url=url, model=self.model, extraheaders=extraHeaders, 36 | otherparams=otherparams) 37 | 38 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 39 | self.assertEqual(request4.getParams()['url'], url) 40 | 41 | file = self.RESOURCES_DIR + 'file.txt' 42 | request5 = meaningcloud.ClassRequest(self.KEY, doc=file, model=self.model, extraheaders=extraHeaders, 43 | otherparams=otherparams) 44 | 45 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 46 | doc = request5._file['doc'].read().decode('utf-8') 47 | 48 | request5._file['doc'].close() 49 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 50 | aux_content = aux_doc.read().decode('utf-8') 51 | aux_doc.close() 52 | self.assertEqual(aux_content, doc) 53 | 54 | return request 55 | 56 | def testSendReq(self): 57 | request = self.request 58 | requestRq = request.sendReq() 59 | self.assertIsNotNone(requestRq) 60 | 61 | 62 | if __name__ == '__main__': 63 | unittest.main() 64 | -------------------------------------------------------------------------------- /tests/ClassResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class MyTestCase(unittest.TestCase): 7 | outputOK = '{"status": {"code": "0","msg": "OK","credits": "1","remaining_credits":"5000"},"category_list": [{"code": "01021001","label": "arts, culture and entertainment - entertainment (general) - entertainment award","abs_relevance": "0.48236102","relevance": "100"},{"code": "08006000","label": "human interest - award and prize","abs_relevance": "0.28744578","relevance": "60"}]}' 8 | response = meaningcloud.ClassResponse(outputOK) 9 | 10 | outputEmpty = '{"status": {"code": "0","msg": "OK","credits": "1","remaining_credits":"5000"}}' 11 | empty_response = meaningcloud.ClassResponse(outputEmpty) 12 | 13 | def testConstruct(self): 14 | self.assertIsNotNone(self.response.getResponse()) 15 | 16 | def testConstructWithWrongJson(self): 17 | outputWrong = 'malformed json' 18 | with self.assertRaises(json.JSONDecodeError): 19 | meaningcloud.ClassResponse(outputWrong) 20 | 21 | def testConstructWithEmptyParam(self): 22 | with self.assertRaises(Exception): 23 | meaningcloud.ClassResponse('') 24 | 25 | def testConstructEmptyResult(self): 26 | self.assertIsNotNone(self.empty_response.getResponse()) 27 | 28 | def testGetCategories(self): 29 | self.assertIsNotNone(self.response.getCategories()) 30 | self.assertTrue(isinstance(self.response.getCategories(), list)) 31 | 32 | def testGetNonexistentCategories(self): 33 | self.assertEqual(len(self.empty_response.getCategories()), 0) 34 | 35 | def testGetCategoryCode(self): 36 | categories = self.response.getCategories() 37 | category = categories[0] if((len(categories) > 0) and (categories[0] is not None)) else [] 38 | self.assertIsNotNone(self.response.getCategoryCode(category)) 39 | 40 | def testGetCategoryCodeWithEmptyInput(self): 41 | self.assertEqual(self.response.getCategoryCode([]), "") 42 | 43 | def testGetCategoryLabel(self): 44 | categories = self.response.getCategories() 45 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 46 | self.assertIsNotNone(self.response.getCategoryLabel(category)) 47 | 48 | def testGetCategoryLabelWithEmptyInput(self): 49 | self.assertEqual(self.response.getCategoryLabel([]), "") 50 | 51 | def testGetCategoryAbsRelevance(self): 52 | categories = self.response.getCategories() 53 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 54 | self.assertIsNotNone(self.response.getCategoryAbsRelevance(category)) 55 | 56 | def testGetCategoryAbsRelevanceWithEmptyInput(self): 57 | self.assertEqual(self.response.getCategoryAbsRelevance([]), "") 58 | 59 | def testGetCategoryRelevance(self): 60 | categories = self.response.getCategories() 61 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 62 | self.assertIsNotNone(self.response.getCategoryRelevance(category)) 63 | 64 | def testGetCategoryRelevanceWithEmptyInput(self): 65 | self.assertEqual(self.response.getCategoryRelevance([]), "") 66 | 67 | 68 | if __name__ == '__main__': 69 | unittest.main() 70 | -------------------------------------------------------------------------------- /tests/ClusteringRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class ClusteringRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/clustering-1.1' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | lang = 'en' 11 | texts = {'A01': 'London is big', 'A02': 'That city is fantastic'} 12 | mode = 'tm' 13 | request = meaningcloud.ClusteringRequest(KEY, lang=lang, texts=texts, mode=mode) 14 | 15 | def testConstruct(self): 16 | request = self.request 17 | self.assertEqual(self.URL, request.getUrl()) 18 | self.assertIsNotNone(request.getParams()) 19 | params = request.getParams() 20 | self.assertEqual('key' in params.keys(), True) 21 | self.assertEqual(params['key'], self.KEY) 22 | self.assertIsNotNone(request.getTimeout()) 23 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 24 | 25 | extraHeaders = ["Accept: application/json"] 26 | request2 = meaningcloud.ClusteringRequest(self.KEY, lang=self.lang, texts=self.texts, mode=self.mode, extraheaders=extraHeaders) 27 | self.assertIsNotNone(request2.sendReq()) 28 | 29 | otherparams = {'key2': 'my_key2'} 30 | request3 = meaningcloud.ClusteringRequest(self.KEY, lang=self.lang, texts=self.texts, mode=self.mode, extraheaders=extraHeaders, otherparams=otherparams) 31 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 32 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 33 | 34 | return request 35 | 36 | def testSendReq(self): 37 | request = self.request 38 | requestRq = request.sendReq() 39 | self.assertIsNotNone(requestRq) 40 | 41 | 42 | if __name__ == '__main__': 43 | unittest.main() 44 | -------------------------------------------------------------------------------- /tests/ClusteringResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class MyTestCase(unittest.TestCase): 7 | outputOK = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"31634"},"cluster_list":[{"title":"Girl","size":"2","score":"0.16","document_list":{"2":"the girl","3":"the girl and the giraffes."}},{"title":"Giraffe","size":"2","score":"0.13","document_list":{"1":"the giraffe","3":"the girl and the giraffes."}}]}' 8 | response = meaningcloud.ClusteringResponse(outputOK) 9 | 10 | outputEmpty = '{"status": {"code": "0","msg": "OK","credits": "1","remaining_credits":"5000"}}' 11 | empty_response = meaningcloud.ClusteringResponse(outputEmpty) 12 | 13 | def testConstruct(self): 14 | self.assertIsNotNone(self.response.getResponse()) 15 | 16 | def testConstructWithWrongJson(self): 17 | outputWrong = 'malformed json' 18 | with self.assertRaises(json.JSONDecodeError): 19 | meaningcloud.ClusteringResponse(outputWrong) 20 | 21 | def testConstructWithEmptyParam(self): 22 | with self.assertRaises(Exception): 23 | meaningcloud.ClusteringResponse('') 24 | 25 | def testConstructEmptyResult(self): 26 | self.assertIsNotNone(self.empty_response.getResponse()) 27 | 28 | def testGetClusters(self): 29 | self.assertIsNotNone(self.response.getClusters()) 30 | self.assertTrue(isinstance(self.response.getClusters(), list)) 31 | 32 | def testGetNonexistentClusters(self): 33 | self.assertEqual(len(self.empty_response.getClusters()), 0) 34 | 35 | def testGetClusterTitle(self): 36 | clusters = self.response.getClusters() 37 | cluster = clusters[0] if((len(clusters) > 0) and (clusters[0] is not None)) else [] 38 | self.assertIsNotNone(self.response.getClusterTitle(cluster)) 39 | 40 | def testGetClusterTitleWithEmptyInput(self): 41 | self.assertEqual(self.response.getClusterTitle([]), "") 42 | 43 | def testGetClusterSize(self): 44 | clusters = self.response.getClusters() 45 | cluster = clusters[0] if ((len(clusters) > 0) and (clusters[0] is not None)) else [] 46 | self.assertIsNotNone(self.response.getClusterSize(cluster)) 47 | 48 | def testGetClusterSizeWithEmptyInput(self): 49 | self.assertEqual(self.response.getClusterSize([]), "") 50 | 51 | def testGetClusterScore(self): 52 | clusters = self.response.getClusters() 53 | cluster = clusters[0] if ((len(clusters) > 0) and (clusters[0] is not None)) else [] 54 | self.assertIsNotNone(self.response.getClusterScore(cluster)) 55 | 56 | def testGetClusterScoreWithEmptyInput(self): 57 | self.assertEqual(self.response.getClusterScore([]), "") 58 | 59 | def testGetClusterDocuments(self): 60 | clusters = self.response.getClusters() 61 | cluster = clusters[0] if ((len(clusters) > 0) and (clusters[0] is not None)) else [] 62 | self.assertIsNotNone(self.response.getClusterDocuments(cluster)) 63 | 64 | def testGetClusterDocumentsWithEmptyInput(self): 65 | self.assertEqual(self.response.getClusterDocuments([]), {}) 66 | 67 | 68 | if __name__ == '__main__': 69 | unittest.main() 70 | -------------------------------------------------------------------------------- /tests/DeepCategorizationRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class DeepCategorizationRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/deepcategorization-1.0' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | text = 'London is big' 11 | model = 'IAB_2.0_en' 12 | polarity = 'n' 13 | request = meaningcloud.DeepCategorizationRequest(KEY, model=model, txt=text, polarity=polarity) 14 | 15 | def testConstruct(self): 16 | request = self.request 17 | self.assertEqual(self.URL, request.getUrl()) 18 | self.assertIsNotNone(request.getParams()) 19 | params = request.getParams() 20 | self.assertEqual('key' in params.keys(), True) 21 | self.assertEqual(params['key'], self.KEY) 22 | self.assertIsNotNone(request.getTimeout()) 23 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 24 | 25 | extraHeaders = ["Accept: application/json"] 26 | request2 = meaningcloud.DeepCategorizationRequest(self.KEY, model=self.model, txt=self.text, polarity=self.polarity, extraheaders=extraHeaders) 27 | self.assertIsNotNone(request2.sendReq()) 28 | 29 | otherparams = {'key2': 'my_key2'} 30 | request3 = meaningcloud.DeepCategorizationRequest(self.KEY, model=self.model, txt=self.text, polarity=self.polarity, extraheaders=extraHeaders, 31 | otherparams=otherparams) 32 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 33 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 34 | 35 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 36 | request4 = meaningcloud.DeepCategorizationRequest(self.KEY, model=self.model, url=url, polarity=self.polarity, extraheaders=extraHeaders, 37 | otherparams=otherparams) 38 | 39 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 40 | self.assertEqual(request4.getParams()['url'], url) 41 | 42 | file = self.RESOURCES_DIR + 'file.txt' 43 | request5 = meaningcloud.DeepCategorizationRequest(self.KEY, model=self.model, doc=file, polarity=self.polarity, extraheaders=extraHeaders, 44 | otherparams=otherparams) 45 | 46 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 47 | doc = request5._file['doc'].read().decode('utf-8') 48 | 49 | request5._file['doc'].close() 50 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 51 | aux_content = aux_doc.read().decode('utf-8') 52 | aux_doc.close() 53 | self.assertEqual(aux_content, doc) 54 | 55 | return request 56 | 57 | def testSendReq(self): 58 | request = self.request 59 | requestRq = request.sendReq() 60 | self.assertIsNotNone(requestRq) 61 | 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /tests/DeepCategorizationResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class MyTestCase(unittest.TestCase): 7 | outputOK = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"31885"},"category_list":[{"code":"Food&Drink>DiningOut","label":"Food and Drink>Dining Out","abs_relevance":"2","relevance":"100","polarity":"NONE"},{"code":"EventsAndAttractions>Bars&Restaurants","label":"Events and Attractions>Bars and Restaurants","abs_relevance":"1","relevance":"50","polarity":"NONE"}]}' 8 | response = meaningcloud.DeepCategorizationResponse(outputOK) 9 | 10 | outputEmpty = '{"status": {"code": "0","msg": "OK","credits": "1","remaining_credits":"5000"}}' 11 | empty_response = meaningcloud.DeepCategorizationResponse(outputEmpty) 12 | 13 | def testConstruct(self): 14 | self.assertIsNotNone(self.response.getResponse()) 15 | 16 | def testConstructWithWrongJson(self): 17 | outputWrong = 'malformed json' 18 | with self.assertRaises(json.JSONDecodeError): 19 | meaningcloud.DeepCategorizationResponse(outputWrong) 20 | 21 | def testConstructWithEmptyParam(self): 22 | with self.assertRaises(Exception): 23 | meaningcloud.DeepCategorizationResponse('') 24 | 25 | def testConstructEmptyResult(self): 26 | self.assertIsNotNone(self.empty_response.getResponse()) 27 | 28 | def testGetCategories(self): 29 | self.assertIsNotNone(self.response.getCategories()) 30 | self.assertTrue(isinstance(self.response.getCategories(), list)) 31 | 32 | def testGetNonexistentCategories(self): 33 | self.assertEqual(len(self.empty_response.getCategories()), 0) 34 | 35 | def testGetCategoryCode(self): 36 | categories = self.response.getCategories() 37 | category = categories[0] if((len(categories) > 0) and (categories[0] is not None)) else [] 38 | self.assertIsNotNone(self.response.getCategoryCode(category)) 39 | 40 | def testGetCategoryCodeWithEmptyInput(self): 41 | self.assertEqual(self.response.getCategoryCode([]), "") 42 | 43 | def testGetCategoryLabel(self): 44 | categories = self.response.getCategories() 45 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 46 | self.assertIsNotNone(self.response.getCategoryLabel(category)) 47 | 48 | def testGetCategoryLabelWithEmptyInput(self): 49 | self.assertEqual(self.response.getCategoryLabel([]), "") 50 | 51 | def testGetCategoryAbsRelevance(self): 52 | categories = self.response.getCategories() 53 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 54 | self.assertIsNotNone(self.response.getCategoryAbsRelevance(category)) 55 | 56 | def testGetCategoryAbsRelevanceWithEmptyInput(self): 57 | self.assertEqual(self.response.getCategoryAbsRelevance([]), "") 58 | 59 | def testGetCategoryRelevance(self): 60 | categories = self.response.getCategories() 61 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 62 | self.assertIsNotNone(self.response.getCategoryRelevance(category)) 63 | 64 | def testGetCategoryRelevanceWithEmptyInput(self): 65 | self.assertEqual(self.response.getCategoryRelevance([]), "") 66 | 67 | def testGetCategoryPolarity(self): 68 | categories = self.response.getCategories() 69 | category = categories[0] if ((len(categories) > 0) and (categories[0] is not None)) else [] 70 | self.assertIsNotNone(self.response.getCategoryPolarity(category)) 71 | 72 | def testGetCategoryPolarityWithEmptyInput(self): 73 | self.assertEqual(self.response.getCategoryPolarity([]), "") 74 | 75 | if __name__ == '__main__': 76 | unittest.main() 77 | -------------------------------------------------------------------------------- /tests/LanguageRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class LanguageRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/lang-2.0' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | text = 'London is big' 11 | 12 | request = meaningcloud.LanguageRequest(KEY, txt=text) 13 | 14 | def testConstruct(self): 15 | request = self.request 16 | self.assertEqual(self.URL, request.getUrl()) 17 | self.assertIsNotNone(request.getParams()) 18 | params = request.getParams() 19 | self.assertEqual('key' in params.keys(), True) 20 | self.assertEqual(params['key'], self.KEY) 21 | self.assertIsNotNone(request.getTimeout()) 22 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 23 | 24 | extraHeaders = ["Accept: application/json"] 25 | request2 = meaningcloud.LanguageRequest(self.KEY, txt=self.text, extraheaders=extraHeaders) 26 | self.assertIsNotNone(request2.sendReq()) 27 | 28 | otherparams = {'key2': 'my_key2'} 29 | request3 = meaningcloud.LanguageRequest(self.KEY, txt=self.text, extraheaders=extraHeaders, 30 | otherparams=otherparams) 31 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 32 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 33 | 34 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 35 | request4 = meaningcloud.LanguageRequest(self.KEY, url=url, extraheaders=extraHeaders, otherparams=otherparams) 36 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 37 | self.assertEqual(request4.getParams()['url'], url) 38 | 39 | file = self.RESOURCES_DIR + 'file.txt' 40 | request5 = meaningcloud.LanguageRequest(self.KEY, doc=file, extraheaders=extraHeaders, 41 | otherparams=otherparams) 42 | 43 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 44 | doc = request5._file['doc'].read().decode('utf-8') 45 | 46 | request5._file['doc'].close() 47 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 48 | aux_conten = aux_doc.read().decode('utf-8') 49 | aux_doc.close() 50 | self.assertEqual(aux_conten, doc) 51 | 52 | return request 53 | 54 | def testSendReq(self): 55 | request = self.request 56 | requestRq = request.sendReq() 57 | self.assertIsNotNone(requestRq) 58 | 59 | 60 | if __name__ == '__main__': 61 | unittest.main() 62 | -------------------------------------------------------------------------------- /tests/LanguageResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class LanguageResponseTest(unittest.TestCase): 7 | 8 | outputOK = {"status": {"code": "0", "msg": "OK", "credits": "1", "remaining_credits": "32033"}, "language_list":[{"language": "en", "relevance": 100, "name": "English", "iso639-3": "eng", "iso639-2": "en"}]} 9 | outputOK = json.dumps(outputOK) 10 | response = meaningcloud.LanguageResponse(outputOK) 11 | 12 | outputEmpty = {"status": {"code": "0", "msg": "OK", "credits": "1", "remaining_credits": "32033"}, 'language_list': []} 13 | empty_response = meaningcloud.LanguageResponse(json.dumps(outputEmpty)) 14 | 15 | def testConstruct(self): 16 | self.assertIsNotNone(self.response.getResponse()) 17 | 18 | def testConstructWithWrongJson(self): 19 | outputWrong = 'malformed json' 20 | with self.assertRaises(json.JSONDecodeError): 21 | meaningcloud.LanguageResponse(outputWrong) 22 | 23 | def testConstructWithEmptyParam(self): 24 | with self.assertRaises(Exception): 25 | meaningcloud.LanguageResponse('') 26 | 27 | def testGetLanguages(self): 28 | self.assertIsNotNone(self.response.getLanguages()) 29 | self.assertTrue(isinstance(self.response.getLanguages(), list)) 30 | 31 | def testGetNonexistentLanguages(self): 32 | self.assertEqual(len(self.empty_response.getLanguages()), 0) 33 | 34 | def testGetFirstLanguage(self): 35 | language = self.response.getFirstLanguage() 36 | self.assertIsNotNone(language) 37 | 38 | def testGetNonExistentFirstLanguage(self): 39 | language = self.empty_response.getFirstLanguage() 40 | self.assertEqual(len(language), 0) 41 | 42 | def testGetLanguageCode(self): 43 | languages = self.response.getLanguages() 44 | language = languages[0] if((len(languages) > 0) and (languages[0] is not None)) else [] 45 | self.assertIsNotNone(self.response.getLanguageCode(language)) 46 | 47 | def testGetLanguageCodeWithEmptyInput(self): 48 | self.assertEqual(self.response.getLanguageCode([]), "") 49 | 50 | def testGetLanguageName(self): 51 | languages = self.response.getLanguages() 52 | language = languages[0] if ((len(languages) > 0) and (languages[0] is not None)) else [] 53 | self.assertIsNotNone(self.response.getLanguageName(language)) 54 | 55 | def testGetLanguageNameWithEmptyInput(self): 56 | self.assertEqual(self.response.getLanguageName([]), "") 57 | 58 | if __name__ == '__main__': 59 | unittest.main() 60 | -------------------------------------------------------------------------------- /tests/ParserRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class ParserRequestTest(unittest.TestCase): 6 | 7 | URL = 'https://api.meaningcloud.com/parser-2.0' 8 | KEY = 'MY_KEY' 9 | TIMEOUT_DEFAULT = 60 10 | RESOURCES_DIR = './resources/' 11 | text = 'London is big' 12 | request = meaningcloud.ParserRequest(KEY, txt=text, lang="en") 13 | 14 | def testConstruct(self): 15 | request = self.request 16 | self.assertEqual(self.URL, request.getUrl()) 17 | self.assertIsNotNone(request.getParams()) 18 | params = request.getParams() 19 | self.assertEqual('key' in params.keys(), True) 20 | self.assertEqual(params['key'], self.KEY) 21 | self.assertIsNotNone(request.getTimeout()) 22 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 23 | 24 | extraHeaders = ["Accept: application/json"] 25 | request2 = meaningcloud.TopicsRequest(self.KEY, txt=self.text, lang="en", extraheaders=extraHeaders) 26 | self.assertIsNotNone(request2.sendReq()) 27 | 28 | otherparams = {'key2': 'my_key2'} 29 | request3 = meaningcloud.TopicsRequest(self.KEY, txt=self.text, lang="en", extraheaders=extraHeaders, 30 | otherparams=otherparams) 31 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 32 | self.assertEqual(request3.getParams()['key2'],'my_key2') 33 | 34 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 35 | request4 = meaningcloud.TopicsRequest(self.KEY, url=url, lang="en", extraheaders=extraHeaders, 36 | otherparams=otherparams) 37 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 38 | self.assertEqual(request4.getParams()['url'], url) 39 | 40 | file = self.RESOURCES_DIR+'file.txt' 41 | request5 = meaningcloud.TopicsRequest(self.KEY, doc=file, lang="en", extraheaders=extraHeaders, 42 | otherparams=otherparams) 43 | 44 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 45 | doc = request5._file['doc'].read().decode('utf-8') 46 | 47 | request5._file['doc'].close() 48 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 49 | aux_conten = aux_doc.read().decode('utf-8') 50 | aux_doc.close() 51 | self.assertEqual(aux_conten, doc) 52 | 53 | return request 54 | 55 | def testSendReq(self): 56 | request = self.request 57 | requestRq = request.sendReq() 58 | self.assertIsNotNone(requestRq) 59 | 60 | 61 | if __name__ == '__main__': 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /tests/ParserResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class ParserResponseTest(unittest.TestCase): 7 | 8 | outputOK = r'{"status":{"code":"0","msg":"OK","credits":"1"},"token_list":[{"type":"sentence","id":"8","inip":"0","endp":"21","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"A","quote_level":"0","affected_by_negation":"no","token_list":[{"type":"phrase","form":"London is a nice city","id":"12","inip":"0","endp":"20","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"_","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"Z-----------","lemma":"*","original_form":"London is a nice city"}],"topic_list":{"relation_list":[{"form":"London is a nice city.","inip":"0","endp":"20","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a nice city","type":"isAttribute"}],"degree":"1"}]},"token_list":[{"type":"phrase","form":"London","id":"10","inip":"0","endp":"5","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"_","quote_level":"0","affected_by_negation":"no","head":"1","syntactic_tree_relation_list":[{"id":"2","type":"isSubject"}],"analysis_list":[{"tag":"GN-S3S--","lemma":"London","original_form":"London"},{"tag":"GNUS3S--","lemma":"London","original_form":"London"}],"token_list":[{"form":"London","id":"1","inip":"0","endp":"5","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"_","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"NP-S-N-","lemma":"London","original_form":"London","sense_id_list":[{"sense_id":"01d0d69c7d"}]},{"tag":"NPUU-N-","lemma":"London","original_form":"London","sense_id_list":[{"sense_id":"76075d4877"}]}],"sense_list":[{"id":"01d0d69c7d","form":"London","info":"sementity/class=instance@fiction=nonfiction@id=ODENTITY_CITY@type=Top>Location>GeoPoliticalEntity>City\tsemgeo_list/adm1=England#id:98db781864@adm2=Greater London#id:ed00f6dec4@continent=Europe#id:0404ea4d6c@country=United Kingdom#id:d29f412b4b#ISO3166-1-a2:GB#ISO3166-1-a3:GBR\tsemld_list=http://en.wikipedia.org/wiki/London|http://ar.wikipedia.org/wiki/لندن|http://ca.wikipedia.org/wiki/Londres|http://cs.wikipedia.org/wiki/Londýn|http://da.wikipedia.org/wiki/London|http://de.wikipedia.org/wiki/London|http://es.wikipedia.org/wiki/Londres|http://fi.wikipedia.org/wiki/Lontoo|http://fr.wikipedia.org/wiki/Londres|http://he.wikipedia.org/wiki/לונדון|http://hi.wikipedia.org/wiki/लंदन|http://id.wikipedia.org/wiki/London|http://it.wikipedia.org/wiki/Londra|http://ja.wikipedia.org/wiki/ロンドン|http://ko.wikipedia.org/wiki/런던|http://nl.wikipedia.org/wiki/Londen|http://no.wikipedia.org/wiki/London|http://pl.wikipedia.org/wiki/Londyn|http://pt.wikipedia.org/wiki/Londres|http://ro.wikipedia.org/wiki/Londra|http://ru.wikipedia.org/wiki/Лондон|http://sv.wikipedia.org/wiki/London|http://th.wikipedia.org/wiki/ลอนดอน|http://tr.wikipedia.org/wiki/Londra|http://zh.wikipedia.org/wiki/伦敦|http://d-nb.info/gnd/4074335-4|http://linkedgeodata.org/triplify/node107775|http://linked-web-apis.fit.cvut.cz/resource/london_city|http://linked-web-apis.fit.cvut.cz/resource/london_uk_city|http://data.nytimes.com/14085781296239331901|http://sw.cyc.com/concept/Mx4rvVjWPJwpEbGdrcN5Y29ycA|http://umbel.org/umbel/rc/Location_Underspecified|http://umbel.org/umbel/rc/PopulatedPlace|http://umbel.org/umbel/rc/Village|http://sws.geonames.org/2643743/|@BBCLondres2012|@LDN|@OlimpicoCaracol|@TelevisaLondres|@TimeOutLondon|@visitlondon|sumo:City"},{"id":"76075d4877","form":"London","info":"sementity/class=instance@fiction=nonfiction@id=ODENTITY_LAST_NAME@type=Top>Person>LastName\tsemld_list=sumo:LastName"}],"topic_list":{"entity_list":[{"form":"London","id":"01d0d69c7d","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semgeo_list":[{"adm1":{"form":"England","id":"98db781864"},"adm2":{"form":"Greater London","id":"ed00f6dec4"},"continent":{"form":"Europe","id":"0404ea4d6c"},"country":{"form":"United Kingdom","id":"d29f412b4b","standard_list":[{"id":"ISO3166-1-a2","value":"GB"},{"id":"ISO3166-1-a3","value":"GBR"}]}}],"semld_list":["http://en.wikipedia.org/wiki/London","http://ar.wikipedia.org/wiki/لندن","http://ca.wikipedia.org/wiki/Londres","http://cs.wikipedia.org/wiki/Londýn","http://da.wikipedia.org/wiki/London","http://de.wikipedia.org/wiki/London","http://es.wikipedia.org/wiki/Londres","http://fi.wikipedia.org/wiki/Lontoo","http://fr.wikipedia.org/wiki/Londres","http://he.wikipedia.org/wiki/לונדון","http://hi.wikipedia.org/wiki/लंदन","http://id.wikipedia.org/wiki/London","http://it.wikipedia.org/wiki/Londra","http://ja.wikipedia.org/wiki/ロンドン","http://ko.wikipedia.org/wiki/런던","http://nl.wikipedia.org/wiki/Londen","http://no.wikipedia.org/wiki/London","http://pl.wikipedia.org/wiki/Londyn","http://pt.wikipedia.org/wiki/Londres","http://ro.wikipedia.org/wiki/Londra","http://ru.wikipedia.org/wiki/Лондон","http://sv.wikipedia.org/wiki/London","http://th.wikipedia.org/wiki/ลอนดอน","http://tr.wikipedia.org/wiki/Londra","http://zh.wikipedia.org/wiki/伦敦","http://d-nb.info/gnd/4074335-4","http://linkedgeodata.org/triplify/node107775","http://linked-web-apis.fit.cvut.cz/resource/london_city","http://linked-web-apis.fit.cvut.cz/resource/london_uk_city","http://data.nytimes.com/14085781296239331901","http://sw.cyc.com/concept/Mx4rvVjWPJwpEbGdrcN5Y29ycA","http://umbel.org/umbel/rc/Location_Underspecified","http://umbel.org/umbel/rc/PopulatedPlace","http://umbel.org/umbel/rc/Village","http://sws.geonames.org/2643743/","@BBCLondres2012","@LDN","@OlimpicoCaracol","@TelevisaLondres","@TimeOutLondon","@visitlondon","sumo:City"]},{"form":"London","id":"76075d4877","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_LAST_NAME","type":"Top>Person>LastName"},"semld_list":["sumo:LastName"]}]}}]},{"form":"is","id":"2","inip":"7","endp":"8","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"1","quote_level":"0","affected_by_negation":"no","syntactic_tree_relation_list":[{"id":"10","type":"iof_isSubject"},{"id":"11","type":"iof_isAttribute"}],"analysis_list":[{"tag":"VI-S3PSA-N-N9","lemma":"be","original_form":"is"}]},{"type":"phrase","form":"a nice city","id":"11","inip":"10","endp":"20","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"1","quote_level":"0","affected_by_negation":"no","head":"5","syntactic_tree_relation_list":[{"id":"2","type":"isAttribute"}],"analysis_list":[{"tag":"GN-S3A--","lemma":"city","original_form":"a nice city"}],"token_list":[{"form":"a","id":"3","inip":"10","endp":"10","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"1","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"QD-SPN9","lemma":"a","original_form":"a"}]},{"form":"nice","id":"4","inip":"12","endp":"15","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"1","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"AP-N6","lemma":"nice","original_form":"nice"}]},{"form":"city","id":"5","inip":"17","endp":"20","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"1","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"NC-S-N6","lemma":"city","original_form":"city","sense_id_list":[{"sense_id":"817857ee40"}]}],"sense_list":[{"id":"817857ee40","form":"city","info":"sementity/class=class@fiction=nonfiction@id=ODENTITY_CITY@type=Top>Location>GeoPoliticalEntity>City\tsemld_list=http://en.wikipedia.org/wiki/City|http://ar.wikipedia.org/wiki/مدينة|http://ca.wikipedia.org/wiki/Ciutat|http://cs.wikipedia.org/wiki/Město|http://de.wikipedia.org/wiki/Stadt|http://es.wikipedia.org/wiki/Ciudad|http://fi.wikipedia.org/wiki/Kaupunki|http://fr.wikipedia.org/wiki/Ville|http://he.wikipedia.org/wiki/עיר|http://hi.wikipedia.org/wiki/शहर|http://id.wikipedia.org/wiki/Kota|http://it.wikipedia.org/wiki/Città|http://ja.wikipedia.org/wiki/都市|http://ko.wikipedia.org/wiki/도시|http://nl.wikipedia.org/wiki/Stad|http://no.wikipedia.org/wiki/By|http://pl.wikipedia.org/wiki/Miasto|http://pt.wikipedia.org/wiki/Cidade|http://ro.wikipedia.org/wiki/Oraș|http://ru.wikipedia.org/wiki/Город|http://sv.wikipedia.org/wiki/Stad|http://th.wikipedia.org/wiki/นคร|http://tr.wikipedia.org/wiki/Şehir|http://zh.wikipedia.org/wiki/城市|http://d-nb.info/gnd/4056723-0|sumo:City"}],"topic_list":{"concept_list":[{"form":"city","id":"817857ee40","sementity":{"class":"class","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semld_list":["http://en.wikipedia.org/wiki/City","http://ar.wikipedia.org/wiki/مدينة","http://ca.wikipedia.org/wiki/Ciutat","http://cs.wikipedia.org/wiki/Město","http://de.wikipedia.org/wiki/Stadt","http://es.wikipedia.org/wiki/Ciudad","http://fi.wikipedia.org/wiki/Kaupunki","http://fr.wikipedia.org/wiki/Ville","http://he.wikipedia.org/wiki/עיר","http://hi.wikipedia.org/wiki/शहर","http://id.wikipedia.org/wiki/Kota","http://it.wikipedia.org/wiki/Città","http://ja.wikipedia.org/wiki/都市","http://ko.wikipedia.org/wiki/도시","http://nl.wikipedia.org/wiki/Stad","http://no.wikipedia.org/wiki/By","http://pl.wikipedia.org/wiki/Miasto","http://pt.wikipedia.org/wiki/Cidade","http://ro.wikipedia.org/wiki/Oraș","http://ru.wikipedia.org/wiki/Город","http://sv.wikipedia.org/wiki/Stad","http://th.wikipedia.org/wiki/นคร","http://tr.wikipedia.org/wiki/Şehir","http://zh.wikipedia.org/wiki/城市","http://d-nb.info/gnd/4056723-0","sumo:City"]}]}}]}]},{"form":".","id":"6","inip":"21","endp":"21","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"A","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"1D--","lemma":".","original_form":"."}]}]}]}' 9 | response = meaningcloud.ParserResponse(outputOK) 10 | 11 | def testConstruct(self): 12 | self.assertIsNotNone(self.response.getResponse()) 13 | 14 | def testConstructWithWrongJson(self): 15 | outputWrong = 'malformed json' 16 | with self.assertRaises(json.JSONDecodeError): 17 | meaningcloud.ParserResponse(outputWrong) 18 | 19 | def testConstructWithEmptyParam(self): 20 | with self.assertRaises(Exception): 21 | meaningcloud.ParserResponse('') 22 | 23 | def testGetLemmatization(self): 24 | expectedResult = '{"London":[{"lemma":"London","pos":"NP"},{"lemma":"London","pos":"NP"}],"is":[{"lemma":"be","pos":"VI"}],"a":[{"lemma":"a","pos":"QD"}],"nice":[{"lemma":"nice","pos":"AP"}],"city":[{"lemma":"city","pos":"NC"}],".":[{"lemma":".","pos":"1D"}]}' 25 | lemmas = self.response.getLemmatization() 26 | assert lemmas, 'Lemmas is empty' 27 | 28 | # London is a nice city. 29 | assert isinstance(lemmas, dict), 'The output is not a dictionary' 30 | self.assertEqual(json.loads(expectedResult), lemmas) 31 | 32 | def testGetCompleteLemmatization(self): 33 | expectedResult = '{"London":[{"lemma":"London","pos":"NP-S-N-"},{"lemma":"London","pos":"NPUU-N-"}],"is":[{"lemma":"be","pos":"VI-S3PSA-N-N9"}],"a":[{"lemma":"a","pos":"QD-SPN9"}],"nice":[{"lemma":"nice","pos":"AP-N6"}],"city":[{"lemma":"city","pos":"NC-S-N6"}],".":[{"lemma":".","pos":"1D--"}]}' 34 | lemmas = self.response.getLemmatization(True) 35 | assert lemmas, 'Lemmas is empty' 36 | 37 | # London is a nice city. 38 | assert isinstance(lemmas, dict), 'The output is not a dictionary' 39 | self.assertEqual(json.loads(expectedResult), lemmas) 40 | 41 | def testGetFilteredLemmatization(self): 42 | expectedResult = '{"London":[{"lemma":"London","pos":"NP"},{"lemma":"London","pos":"NP"}],"is":[{"lemma":"be","pos":"VI"}],"a":[{"lemma":"a","pos":"QD"}],"nice":[{"lemma":"nice","pos":"AP"}],"city":[{"lemma":"city","pos":"NC"}],".":[{"lemma":".","pos":"1D"}]}' 43 | lemmas = self.response.getLemmatization() 44 | assert lemmas, 'Lemmas is empty' 45 | 46 | # London is a nice city. 47 | assert isinstance(lemmas, dict), 'The output is not a dictionary' 48 | self.assertEqual(json.loads(expectedResult), lemmas) 49 | 50 | def testGetNonexistentLemmatization(self): 51 | responseWithNoLemmas = '{"status":{"code":"0","msg":"OK","credits":"1"},"token_list":[{"type":"sentence","id":"3","inip":"0","endp":"7","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"A","quote_level":"0","affected_by_negation":"no","token_list":[{"type":"phrase","form":"ajsahdsa","id":"5","inip":"0","endp":"7","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"_","quote_level":"0","affected_by_negation":"no","analysis_list":[{"tag":"Z-----------","lemma":"*","original_form":"ajsahdsa"}],"token_list":[{"form":"ajsahdsa","id":"1","inip":"0","endp":"7","style":{"isBold":"no","isItalics":"no","isUnderlined":"no","isTitle":"no"},"separation":"_","quote_level":"0","affected_by_negation":"no"}]}]}]}' 52 | 53 | responseWithNoLemmas = meaningcloud.ParserResponse(responseWithNoLemmas) 54 | lemmas = responseWithNoLemmas.getLemmatization(True) 55 | assert lemmas, 'Lemmas is empty' 56 | assert isinstance(lemmas, dict), 'The output is not a dictionary' 57 | self.assertEqual(json.loads('{"ajsahdsa":[]}'), lemmas) 58 | 59 | lemmas = responseWithNoLemmas.getLemmatization() 60 | assert lemmas, 'Lemmas is empty' 61 | assert isinstance(lemmas, dict), 'The output is not a dictionary' 62 | self.assertEqual(json.loads('{"ajsahdsa":[]}'), lemmas) 63 | 64 | 65 | if __name__ == '__main__': 66 | unittest.main() 67 | -------------------------------------------------------------------------------- /tests/RequestTest.py: -------------------------------------------------------------------------------- 1 | import meaningcloud 2 | import unittest 3 | 4 | 5 | class RequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/topics-2.0' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | request = meaningcloud.Request(URL, KEY) 11 | 12 | def testConstruct(self): 13 | request = self.request 14 | self.assertEqual(self.URL, request.getUrl()) 15 | self.assertIsNotNone(request.getParams()) 16 | params = request.getParams() 17 | self.assertEqual('key' in params.keys(), True) 18 | self.assertEqual(params['key'], self.KEY) 19 | self.assertIsNotNone(request.getTimeout()) 20 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 21 | return request 22 | 23 | def testConstructWithEmpyParams(self): 24 | with self.assertRaises(ValueError): 25 | meaningcloud.Request('', '') 26 | with self.assertRaises(ValueError): 27 | meaningcloud.Request(self.URL, '') 28 | with self.assertRaises(ValueError): 29 | meaningcloud.Request('', self.KEY) 30 | 31 | def testAddParam(self): 32 | request = self.request 33 | request.addParam('lang', 'en') 34 | params = request.getParams() 35 | self.assertEqual('lang' in params.keys(), True) 36 | self.assertEqual('en', params['lang']) 37 | 38 | request.addParam('of', 'json') 39 | params = request.getParams() 40 | self.assertEqual('of' in params.keys(), True) 41 | self.assertEqual('json', params['of']) 42 | 43 | def testAddParamWithEmptyName(self): 44 | request = self.request 45 | with self.assertRaises(ValueError): 46 | request.addParam('', 'en') 47 | 48 | def testSetContentTxt(self): 49 | request = self.request 50 | txt = 'This is MeaningCloud\'s official Python client' 51 | request.setContentTxt(txt) 52 | params = request.getParams() 53 | self.assertEqual('txt' in params.keys(), True) 54 | self.assertEqual(txt, params['txt']) 55 | 56 | def testSetContentUrl(self): 57 | request = self.request 58 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 59 | request.setContentUrl(url) 60 | params = request.getParams() 61 | self.assertEqual('url' in params.keys(), True) 62 | self.assertEqual(url, params['url']) 63 | 64 | def testSetContentFile(self): 65 | file = self.RESOURCES_DIR+'file.txt' 66 | self.request.setContentFile(file) 67 | file = self.request.getFile() 68 | params = self.request.getParams() 69 | self.assertFalse('doc' in params.keys()) 70 | self.assertTrue('doc' in file.keys()) 71 | self.assertIsNotNone(file['doc']) 72 | doc = file['doc'].read().decode('utf-8') 73 | file['doc'].close() 74 | aux_doc = open(self.RESOURCES_DIR+'file.txt', 'rb') 75 | aux_conten = aux_doc.read().decode('utf-8') 76 | aux_doc.close() 77 | self.assertEqual(aux_conten, doc) 78 | 79 | def testSetTimeout(self): 80 | timeout = 360 81 | request = self.request 82 | request.setTimeout(timeout) 83 | self.assertEqual(timeout, request.getTimeout()) 84 | 85 | def testSendRequest(self): 86 | request = self.request 87 | strResponse = request.sendRequest() 88 | response = meaningcloud.Response(strResponse) 89 | self.assertIsNotNone(response) 90 | self.assertIsNotNone(response.getResponse()) 91 | 92 | def testSendReqExtraHeaders(self): 93 | request = self.request 94 | extraHeaders = ["Accept: application/json"] 95 | strResponse = request.sendRequest(extraHeaders) 96 | response = meaningcloud.Response(strResponse) 97 | self.assertIsNotNone(response) 98 | self.assertIsNotNone(response.getResponse()) 99 | 100 | def testSetURL(self): 101 | url = 'https://myinstance.meaningcloud.com' 102 | request = self.request 103 | request.setUrl(url) 104 | self.assertEqual(url, request.getUrl()) 105 | 106 | 107 | if __name__ == '__main__': 108 | unittest.main() 109 | -------------------------------------------------------------------------------- /tests/ResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class ResponseTest(unittest.TestCase): 7 | outputOK = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"entity_list":[{"form":"London","id":"01d0d69c7d","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semgeo_list":[{"adm1":{"form":"England","id":"98db781864"},"adm2":{"form":"Greater London","id":"ed00f6dec4"},"continent":{"form":"Europe","id":"0404ea4d6c"},"country":{"form":"United Kingdom","id":"d29f412b4b","standard_list":[{"id":"ISO3166-1-a2","value":"GB"},{"id":"ISO3166-1-a3","value":"GBR"}]}}],"semld_list":["http:\/\/en.wikipedia.org\/wiki\/London","http:\/\/ar.wikipedia.org\/wiki\/لندن","http:\/\/ca.wikipedia.org\/wiki\/Londres","http:\/\/cs.wikipedia.org\/wiki\/Londýn","http:\/\/da.wikipedia.org\/wiki\/London","http:\/\/de.wikipedia.org\/wiki\/London","http:\/\/es.wikipedia.org\/wiki\/Londres","http:\/\/fi.wikipedia.org\/wiki\/Lontoo","http:\/\/fr.wikipedia.org\/wiki\/Londres","http:\/\/he.wikipedia.org\/wiki\/×œ×•× ×“×•×Ÿ","http:\/\/hi.wikipedia.org\/wiki\/लंदन","http:\/\/id.wikipedia.org\/wiki\/London","http:\/\/it.wikipedia.org\/wiki\/Londra","http:\/\/ja.wikipedia.org\/wiki\/ロンドン","http:\/\/ko.wikipedia.org\/wiki\/런던","http:\/\/nl.wikipedia.org\/wiki\/Londen","http:\/\/no.wikipedia.org\/wiki\/London","http:\/\/pl.wikipedia.org\/wiki\/Londyn","http:\/\/pt.wikipedia.org\/wiki\/Londres","http:\/\/ro.wikipedia.org\/wiki\/Londra","http:\/\/ru.wikipedia.org\/wiki\/Лондон","http:\/\/sv.wikipedia.org\/wiki\/London","http:\/\/th.wikipedia.org\/wiki\/ลอนดอน","http:\/\/tr.wikipedia.org\/wiki\/Londra","http:\/\/zh.wikipedia.org\/wiki\/伦敦","http:\/\/d-nb.info\/gnd\/4074335-4","http:\/\/linkedgeodata.org\/triplify\/node107775","http:\/\/linked-web-apis.fit.cvut.cz\/resource\/london_city","http:\/\/linked-web-apis.fit.cvut.cz\/resource\/london_uk_city","http:\/\/data.nytimes.com\/14085781296239331901","http:\/\/sw.cyc.com\/concept\/Mx4rvVjWPJwpEbGdrcN5Y29ycA","http:\/\/umbel.org\/umbel\/rc\/Location_Underspecified","http:\/\/umbel.org\/umbel\/rc\/PopulatedPlace","http:\/\/umbel.org\/umbel\/rc\/Village","http:\/\/sws.geonames.org\/2643743\/","@BBCLondres2012","@LDN","@OlimpicoCaracol","@TelevisaLondres","@TimeOutLondon","@visitlondon","sumo:City"],"variant_list":[{"form":"London","inip":"0","endp":"5"}],"relevance":"100"},{"form":"London","id":"76075d4877","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_LAST_NAME","type":"Top>Person>LastName"},"semld_list":["sumo:LastName"],"variant_list":[{"form":"London","inip":"0","endp":"5"}],"relevance":"100"}],"concept_list":[{"form":"city","id":"817857ee40","sementity":{"class":"class","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semld_list":["http:\/\/en.wikipedia.org\/wiki\/City","http:\/\/ar.wikipedia.org\/wiki\/مدينة","http:\/\/ca.wikipedia.org\/wiki\/Ciutat","http:\/\/cs.wikipedia.org\/wiki\/MÄ›sto","http:\/\/de.wikipedia.org\/wiki\/Stadt","http:\/\/es.wikipedia.org\/wiki\/Ciudad","http:\/\/fi.wikipedia.org\/wiki\/Kaupunki","http:\/\/fr.wikipedia.org\/wiki\/Ville","http:\/\/he.wikipedia.org\/wiki\/עיר","http:\/\/hi.wikipedia.org\/wiki\/शहर","http:\/\/id.wikipedia.org\/wiki\/Kota","http:\/\/it.wikipedia.org\/wiki\/Città ","http:\/\/ja.wikipedia.org\/wiki\/都市","http:\/\/ko.wikipedia.org\/wiki\/도시","http:\/\/nl.wikipedia.org\/wiki\/Stad","http:\/\/no.wikipedia.org\/wiki\/By","http:\/\/pl.wikipedia.org\/wiki\/Miasto","http:\/\/pt.wikipedia.org\/wiki\/Cidade","http:\/\/ro.wikipedia.org\/wiki\/OraÈ™","http:\/\/ru.wikipedia.org\/wiki\/Город","http:\/\/sv.wikipedia.org\/wiki\/Stad","http:\/\/th.wikipedia.org\/wiki\/นคร","http:\/\/tr.wikipedia.org\/wiki\/Åžehir","http:\/\/zh.wikipedia.org\/wiki\/城市","http:\/\/d-nb.info\/gnd\/4056723-0","sumo:City"],"variant_list":[{"form":"city","inip":"22","endp":"25"}],"relevance":"100"}],"time_expression_list":[],"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 8 | response = meaningcloud.Response(outputOK) 9 | 10 | def testConstruct(self): 11 | self.assertIsNotNone(self.response.getResponse()) 12 | 13 | def testConstructWithWrongJson(self): 14 | outputWrong = 'malformed json' 15 | with self.assertRaises(json.JSONDecodeError): 16 | meaningcloud.Response(outputWrong) 17 | 18 | def testConstructWithEmptyParam(self): 19 | with self.assertRaises(Exception): 20 | meaningcloud.Response('') 21 | 22 | def testResponseIsSuccessful(self): 23 | self.assertTrue(self.response.isSuccessful()) 24 | 25 | def testResponseIsNotSuccessful(self): 26 | operationDenied = '{"status":{"code":"100","msg":"Operation denied","credits":"0"}}' 27 | response2 = meaningcloud.Response(operationDenied) 28 | self.assertIsNotNone(response2.getResponse()) 29 | self.assertFalse(response2.isSuccessful()) 30 | 31 | def testGetStatusCode(self): 32 | self.assertEqual('0', self.response.getStatusCode()) 33 | 34 | def testGetStatusMsg(self): 35 | self.assertIsNotNone(self.response.getStatusMsg()) 36 | self.assertEqual('OK', self.response.getStatusMsg()) 37 | 38 | def testGetConsumedCredits(self): 39 | self.assertIsNotNone(self.response.getConsumedCredits()) 40 | self.assertEqual('1', self.response.getConsumedCredits()) 41 | 42 | def testGetRemainingCredits(self): 43 | self.assertIsNotNone(self.response.getRemainingCredits()) 44 | self.assertEqual('5000', self.response.getRemainingCredits()) 45 | 46 | def testGetResponse(self): 47 | self.assertIsNotNone(self.response.getStrResponse()) 48 | 49 | def testGetResult(self): 50 | self.assertIsNotNone(self.response.getResults()) 51 | 52 | 53 | if __name__ == '__main__': 54 | unittest.main() 55 | -------------------------------------------------------------------------------- /tests/SentimentRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class SentimentRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/sentiment-2.1' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | text = 'London is big' 11 | lang = 'en' 12 | txtf = 'plain' 13 | request = meaningcloud.SentimentRequest(KEY, lang=lang, txt=text, txtf=txtf) 14 | 15 | def testConstruct(self): 16 | request = self.request 17 | self.assertEqual(self.URL, request.getUrl()) 18 | self.assertIsNotNone(request.getParams()) 19 | params = request.getParams() 20 | self.assertEqual('key' in params.keys(), True) 21 | self.assertEqual(params['key'], self.KEY) 22 | self.assertIsNotNone(request.getTimeout()) 23 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 24 | 25 | extraHeaders = ["Accept: application/json"] 26 | request2 = meaningcloud.SentimentRequest(self.KEY, lang=self.lang, txt=self.text, txtf=self.txtf, 27 | extraheaders=extraHeaders) 28 | self.assertIsNotNone(request2.sendReq()) 29 | 30 | otherparams = {'key2': 'my_key2'} 31 | request3 = meaningcloud.SentimentRequest(self.KEY, lang=self.lang, txt=self.text, txtf=self.txtf, 32 | extraheaders=extraHeaders, otherparams=otherparams) 33 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 34 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 35 | 36 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 37 | request4 = meaningcloud.SentimentRequest(self.KEY, lang=self.lang, url=url, txtf=self.txtf, 38 | extraheaders=extraHeaders, otherparams=otherparams) 39 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 40 | self.assertEqual(request4.getParams()['url'], url) 41 | 42 | file = self.RESOURCES_DIR+'file.txt' 43 | request5 = meaningcloud.SentimentRequest(self.KEY, lang=self.lang, doc=file, txtf=self.txtf, 44 | extraheaders=extraHeaders, otherparams=otherparams) 45 | 46 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 47 | doc = request5._file['doc'].read().decode('utf-8') 48 | 49 | request5._file['doc'].close() 50 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 51 | aux_conten = aux_doc.read().decode('utf-8') 52 | aux_doc.close() 53 | self.assertEqual(aux_conten, doc) 54 | 55 | return request 56 | 57 | def testSendReq(self): 58 | request = self.request 59 | requestRq = request.sendReq() 60 | self.assertIsNotNone(requestRq) 61 | 62 | 63 | if __name__ == '__main__': 64 | unittest.main() 65 | -------------------------------------------------------------------------------- /tests/SentimentResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class SentimentResponseTest(unittest.TestCase): 7 | 8 | outputOK = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"model":"general_en","score_tag":"P+","agreement":"AGREEMENT","subjectivity":"SUBJECTIVE","confidence":"98","irony":"NONIRONIC","sentence_list":[{"text":"Main dishes were quite good, but desserts were too sweet for me.","inip":"0","endp":"65","bop":"y","confidence":"98","score_tag":"P+","agreement":"AGREEMENT","segment_list":[{"text":"Main dishes were quite good","segment_type":"main","inip":"0","endp":"27","confidence":"98","score_tag":"P+","agreement":"AGREEMENT","polarity_term_list":[{"text":"(quite) good","inip":"24","endp":"27","confidence":"98","score_tag":"P+"}]},{"text":"desserts were too sweet for me","segment_type":"main","inip":"34","endp":"63","confidence":"100","score_tag":"P","agreement":"AGREEMENT","polarity_term_list":[{"text":"sweet@A","inip":"52","endp":"56","confidence":"100","score_tag":"P","sentimented_concept_list":[{"form":"dessert","id":"0e15bbd941","variant":"desserts","inip":"34","endp":"41","type":"Top>Product>Food","score_tag":"P"}]}]},{"text":"","segment_type":"secondary","inip":"65","endp":"65","confidence":"100","score_tag":"NONE","agreement":"AGREEMENT","polarity_term_list":[],"sentimented_concept_list":[{"form":"dessert","id":"0e15bbd941","variant":"desserts","inip":"34","endp":"41","type":"Top>Product>Food","score_tag":"NONE"}]}],"sentimented_entity_list":[],"sentimented_concept_list":[{"form":"dessert","id":"0e15bbd941","type":"Top>Product>Food","score_tag":"P"}]}],"sentimented_entity_list":[],"sentimented_concept_list":[{"form":"dessert","id":"0e15bbd941","type":"Top>Product>Food","score_tag":"P"}]}' 9 | response = meaningcloud.SentimentResponse(outputOK) 10 | outputEmpty = '{"status": {"code": "0","msg": "OK","credits": "1","remaining_credits":"5000"}}' 11 | empty_response = meaningcloud.SentimentResponse(outputEmpty) 12 | 13 | def testConstruct(self): 14 | self.assertIsNotNone(self.response.getResponse()) 15 | 16 | def testConstructWithWrongJson(self): 17 | outputWrong = 'malformed json' 18 | with self.assertRaises(json.JSONDecodeError): 19 | meaningcloud.SentimentResponse(outputWrong) 20 | 21 | def testConstructWithEmptyParam(self): 22 | with self.assertRaises(Exception): 23 | meaningcloud.SentimentResponse('') 24 | 25 | def testConstructEmptyResult(self): 26 | self.assertIsNotNone(self.empty_response.getResponse()) 27 | 28 | def testGetGlobalModel(self): 29 | self.assertIsNotNone(self.response.getModel()) 30 | 31 | def testGetGlobalModelWithEmptyInput(self): 32 | self.assertEqual(self.empty_response.getModel(), '') 33 | 34 | def testGetGlobalScoreTag(self): 35 | self.assertIsNotNone(self.response.getGlobalScoreTag()) 36 | 37 | def testGetGlobalScoreTagWithEmptyInput(self): 38 | self.assertEqual(self.empty_response.getGlobalScoreTag(), '') 39 | 40 | def testGetGlobalAgreement(self): 41 | self.assertIsNotNone(self.response.getGlobalAgreement()) 42 | 43 | def testGetGlobalAgreementWithEmptyInput(self): 44 | self.assertEqual(self.empty_response.getGlobalAgreement(), '') 45 | 46 | def testGetAgreement(self): 47 | sentence_list = self.response.getResponse()['sentence_list'] 48 | self.assertIsNotNone(self.response.getAgreement(sentence_list[0])) 49 | 50 | def testGetAgreementWithEmptyInput(self): 51 | with self.assertRaises(AttributeError): 52 | self.empty_response.getAgreement([]) 53 | 54 | def testGetGlobalSubjectivity(self): 55 | self.assertIsNotNone(self.response.getSubjectivity()) 56 | 57 | def testGetGlobalSubjectivityWithEmptyInput(self): 58 | self.assertIsNotNone(self.empty_response.getSubjectivity()) 59 | 60 | def testGetGlobalConfidence(self): 61 | self.assertIsNotNone(self.response.getGlobalConfidence()) 62 | 63 | def testGetGlobalConfidenceWithEmptyInput(self): 64 | self.assertIsNotNone(self.empty_response.getGlobalConfidence()) 65 | 66 | def testGetConfidence(self): 67 | sentence_list = self.response.getResponse()['sentence_list'] 68 | self.assertIsNotNone(self.response.getConfidence(sentence_list[0])) 69 | 70 | def testGetConfidenceWithEmptyInput(self): 71 | with self.assertRaises(AttributeError): 72 | self.empty_response.getAgreement([]) 73 | 74 | def testGetGlobalIrony(self): 75 | self.assertIsNotNone(self.response.getIrony()) 76 | 77 | def testGetGlobalIronyWithEmptyInput(self): 78 | self.assertIsNotNone(self.empty_response.getIrony()) 79 | 80 | def testGetGlobalSentimentedEntities(self): 81 | self.assertEqual(isinstance(self.response.getGlobalSentimentedEntities(), list), True) 82 | 83 | def testGetGlobalSentimentedEntitiesWithEmptyInput(self): 84 | self.assertEqual(self.empty_response.getGlobalSentimentedEntities(), '') 85 | 86 | def testGetSentimentedEntities(self): 87 | sentence_list = self.response.getResponse()['sentence_list'] 88 | self.assertEqual(isinstance(self.response.getSentimentedEntities(sentence_list[0]), list), True) 89 | 90 | def testGetSentimentedEntitiesWithEmptyInput(self): 91 | self.assertEqual(self.empty_response.getSentimentedEntities([]), '') 92 | 93 | def testGetGlobalSentimentedConcepts(self): 94 | self.assertEqual(isinstance(self.response.getGlobalSentimentedConcepts(), list), True) 95 | 96 | def testGetGlobalSentimentedConceptsWithEmptyInput(self): 97 | self.assertEqual(self.empty_response.getGlobalSentimentedConcepts(), '') 98 | 99 | def testGetSentimentedConcepts(self): 100 | sentence_list = self.response.getResponse()['sentence_list'] 101 | self.assertEqual(isinstance(self.response.getSentimentedConcepts(sentence_list[0]), list), True) 102 | 103 | def testGetSentimentedConceptsWithEmptyInput(self): 104 | self.assertEqual(self.empty_response.getSentimentedConcepts([]), '') 105 | 106 | def testScoreTagToString(self): 107 | d = {'P+': 'strong positive', 'P': 'positive', 'NEU': 'neutral', 'N': 'negative', 108 | 'N+': 'strong negative', 'NONE': 'no sentiment'} 109 | for x in d.items(): 110 | self.assertEqual(x[1], self.response.scoreTagToString(x[0])) 111 | 112 | 113 | if __name__ == '__main__': 114 | unittest.main() 115 | -------------------------------------------------------------------------------- /tests/SummarizationRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class SummarizationRequestTest(unittest.TestCase): 6 | URL = 'https://api.meaningcloud.com/summarization-1.0' 7 | KEY = 'MY_KEY' 8 | TIMEOUT_DEFAULT = 60 9 | RESOURCES_DIR = './resources/' 10 | text = 'London is big. I love this city' 11 | sentences = 1 12 | 13 | request = meaningcloud.SummarizationRequest(KEY, txt=text, sentences=sentences) 14 | 15 | def testConstruct(self): 16 | request = self.request 17 | self.assertEqual(self.URL, request.getUrl()) 18 | self.assertIsNotNone(request.getParams()) 19 | params = request.getParams() 20 | self.assertEqual('key' in params.keys(), True) 21 | self.assertEqual(params['key'], self.KEY) 22 | self.assertIsNotNone(request.getTimeout()) 23 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 24 | 25 | extraHeaders = ["Accept: application/json"] 26 | request2 = meaningcloud.SummarizationRequest(self.KEY, sentences=self.sentences, txt=self.text, extraheaders=extraHeaders) 27 | self.assertIsNotNone(request2.sendReq()) 28 | 29 | otherparams = {'key2': 'my_key2'} 30 | request3 = meaningcloud.SummarizationRequest(self.KEY, sentences=self.sentences, txt=self.text, extraheaders=extraHeaders, 31 | otherparams=otherparams) 32 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 33 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 34 | 35 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 36 | request4 = meaningcloud.SummarizationRequest(self.KEY, sentences=self.sentences, url=url, extraheaders=extraHeaders, otherparams=otherparams) 37 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 38 | self.assertEqual(request4.getParams()['url'], url) 39 | 40 | file = self.RESOURCES_DIR + 'file.txt' 41 | request5 = meaningcloud.SummarizationRequest(self.KEY, sentences=self.sentences, doc=file, extraheaders=extraHeaders, 42 | otherparams=otherparams) 43 | 44 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 45 | doc = request5._file['doc'].read().decode('utf-8') 46 | 47 | request5._file['doc'].close() 48 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 49 | aux_conten = aux_doc.read().decode('utf-8') 50 | aux_doc.close() 51 | self.assertEqual(aux_conten, doc) 52 | 53 | return request 54 | 55 | def testSendReq(self): 56 | request = self.request 57 | requestRq = request.sendReq() 58 | self.assertIsNotNone(requestRq) 59 | 60 | 61 | if __name__ == '__main__': 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /tests/SummarizationResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class SummarizationResponseTest(unittest.TestCase): 7 | 8 | outputOK = {"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"32014"},"summary":"London is big."} 9 | outputOK = json.dumps(outputOK) 10 | response = meaningcloud.SummarizationResponse(outputOK) 11 | 12 | outputEmpty = {"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"32014"},"summary":""} 13 | empty_response = meaningcloud.SummarizationResponse(json.dumps(outputEmpty)) 14 | 15 | def testConstruct(self): 16 | self.assertIsNotNone(self.response.getResponse()) 17 | 18 | def testConstructWithWrongJson(self): 19 | outputWrong = 'malformed json' 20 | with self.assertRaises(json.JSONDecodeError): 21 | meaningcloud.SummarizationResponse(outputWrong) 22 | 23 | def testConstructWithEmptyParam(self): 24 | with self.assertRaises(Exception): 25 | meaningcloud.SummarizationResponse('') 26 | 27 | def testGetSummary(self): 28 | self.assertIsNotNone(self.response.getSummary()) 29 | 30 | def testGetSummaryWithEmptyInput(self): 31 | self.assertEqual(self.empty_response.getSummary(), '') 32 | 33 | if __name__ == '__main__': 34 | unittest.main() 35 | -------------------------------------------------------------------------------- /tests/TopicsRequestTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | 4 | 5 | class TopicsRequesTest(unittest.TestCase): 6 | 7 | URL = 'https://api.meaningcloud.com/topics-2.0' 8 | KEY = 'MY_KEY' 9 | TIMEOUT_DEFAULT = 60 10 | RESOURCES_DIR = './resources/' 11 | text = 'London is big' 12 | request = meaningcloud.TopicsRequest(KEY, txt=text, topicType="a") 13 | 14 | def testConstruct(self): 15 | request = self.request 16 | self.assertEqual(self.URL, request.getUrl()) 17 | self.assertIsNotNone(request.getParams()) 18 | params = request.getParams() 19 | self.assertEqual('key' in params.keys(), True) 20 | self.assertEqual(params['key'], self.KEY) 21 | self.assertIsNotNone(request.getTimeout()) 22 | self.assertEqual(self.TIMEOUT_DEFAULT, request.getTimeout()) 23 | 24 | extraHeaders = ["Accept: application/json"] 25 | request2 = meaningcloud.TopicsRequest(self.KEY, txt=self.text, topicType="a", extraheaders=extraHeaders) 26 | self.assertIsNotNone(request2.sendReq()) 27 | 28 | otherparams = {'key2': 'my_key2'} 29 | request3 = meaningcloud.TopicsRequest(self.KEY, txt=self.text, topicType="a", extraheaders=extraHeaders, 30 | otherparams=otherparams) 31 | self.assertIsNotNone('key2' in request3.getParams().keys(), True) 32 | self.assertEqual(request3.getParams()['key2'], 'my_key2') 33 | 34 | url = 'https://en.wikipedia.org/wiki/Star_Trek' 35 | request4 = meaningcloud.TopicsRequest(self.KEY, url=url, topicType="a", extraheaders=extraHeaders, 36 | otherparams=otherparams) 37 | self.assertIsNotNone('url' in request4.getParams().keys(), True) 38 | self.assertEqual(request4.getParams()['url'], url) 39 | 40 | file = self.RESOURCES_DIR+'file.txt' 41 | request5 = meaningcloud.TopicsRequest(self.KEY, doc=file, topicType="a", extraheaders=extraHeaders, 42 | otherparams=otherparams) 43 | 44 | self.assertIsNotNone('doc' in request5.getParams().keys(), False) 45 | doc = request5._file['doc'].read().decode('utf-8') 46 | 47 | request5._file['doc'].close() 48 | aux_doc = open(self.RESOURCES_DIR + 'file.txt', 'rb') 49 | aux_conten = aux_doc.read().decode('utf-8') 50 | aux_doc.close() 51 | self.assertEqual(aux_conten, doc) 52 | 53 | return request 54 | 55 | def testSendReq(self): 56 | request = self.request 57 | requestRq = request.sendReq() 58 | self.assertIsNotNone(requestRq) 59 | 60 | 61 | if __name__ == '__main__': 62 | unittest.main() 63 | -------------------------------------------------------------------------------- /tests/TopicsResponseTest.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import meaningcloud 3 | import json 4 | 5 | 6 | class TopicsResponseTest(unittest.TestCase): 7 | 8 | outputOK = '{"status":{"code":"0","msg":"OK","credits":"1"},"entity_list":[{"form":"London","id":"01d0d69c7d","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semgeo_list":[{"adm1":{"form":"England","id":"98db781864"},"adm2":{"form":"Greater London","id":"ed00f6dec4"},"continent":{"form":"Europe","id":"0404ea4d6c"},"country":{"form":"United Kingdom","id":"d29f412b4b","standard_list":[{"id":"ISO3166-1-a2","value":"GB"},{"id":"ISO3166-1-a3","value":"GBR"}]}}],"semld_list":["http://en.wikipedia.org/wiki/London","http://ar.wikipedia.org/wiki/لندن","http://ca.wikipedia.org/wiki/Londres","http://cs.wikipedia.org/wiki/Londýn","http://da.wikipedia.org/wiki/London","http://de.wikipedia.org/wiki/London","http://es.wikipedia.org/wiki/Londres","http://fi.wikipedia.org/wiki/Lontoo","http://fr.wikipedia.org/wiki/Londres","http://he.wikipedia.org/wiki/לונדון","http://hi.wikipedia.org/wiki/लंदन","http://id.wikipedia.org/wiki/London","http://it.wikipedia.org/wiki/Londra","http://ja.wikipedia.org/wiki/ロンドン","http://ko.wikipedia.org/wiki/런던","http://nl.wikipedia.org/wiki/Londen","http://no.wikipedia.org/wiki/London","http://pl.wikipedia.org/wiki/Londyn","http://pt.wikipedia.org/wiki/Londres","http://ro.wikipedia.org/wiki/Londra","http://ru.wikipedia.org/wiki/Лондон","http://sv.wikipedia.org/wiki/London","http://th.wikipedia.org/wiki/ลอนดอน","http://tr.wikipedia.org/wiki/Londra","http://zh.wikipedia.org/wiki/伦敦","http://d-nb.info/gnd/4074335-4","http://linkedgeodata.org/triplify/node107775","http://linked-web-apis.fit.cvut.cz/resource/london_city","http://linked-web-apis.fit.cvut.cz/resource/london_uk_city","http://data.nytimes.com/14085781296239331901","http://sw.cyc.com/concept/Mx4rvVjWPJwpEbGdrcN5Y29ycA","http://umbel.org/umbel/rc/Location_Underspecified","http://umbel.org/umbel/rc/PopulatedPlace","http://umbel.org/umbel/rc/Village","http://sws.geonames.org/2643743/","@BBCLondres2012","@LDN","@OlimpicoCaracol","@TelevisaLondres","@TimeOutLondon","@visitlondon","sumo:City"],"variant_list":[{"form":"London","inip":"0","endp":"5"}],"relevance":"100"},{"form":"London","id":"76075d4877","sementity":{"class":"instance","fiction":"nonfiction","id":"ODENTITY_LAST_NAME","type":"Top>Person>LastName"},"semld_list":["sumo:LastName"],"variant_list":[{"form":"London","inip":"0","endp":"5"}],"relevance":"100"}],"concept_list":[{"form":"city","id":"817857ee40","sementity":{"class":"class","fiction":"nonfiction","id":"ODENTITY_CITY","type":"Top>Location>GeoPoliticalEntity>City"},"semld_list":["http://en.wikipedia.org/wiki/City","http://ar.wikipedia.org/wiki/مدينة","http://ca.wikipedia.org/wiki/Ciutat","http://cs.wikipedia.org/wiki/Město","http://de.wikipedia.org/wiki/Stadt","http://es.wikipedia.org/wiki/Ciudad","http://fi.wikipedia.org/wiki/Kaupunki","http://fr.wikipedia.org/wiki/Ville","http://he.wikipedia.org/wiki/עיר","http://hi.wikipedia.org/wiki/शहर","http://id.wikipedia.org/wiki/Kota","http://it.wikipedia.org/wiki/Città","http://ja.wikipedia.org/wiki/都市","http://ko.wikipedia.org/wiki/도시","http://nl.wikipedia.org/wiki/Stad","http://no.wikipedia.org/wiki/By","http://pl.wikipedia.org/wiki/Miasto","http://pt.wikipedia.org/wiki/Cidade","http://ro.wikipedia.org/wiki/Oraș","http://ru.wikipedia.org/wiki/Город","http://sv.wikipedia.org/wiki/Stad","http://th.wikipedia.org/wiki/นคร","http://tr.wikipedia.org/wiki/Şehir","http://zh.wikipedia.org/wiki/城市","http://d-nb.info/gnd/4056723-0","sumo:City"],"variant_list":[{"form":"city","inip":"17","endp":"20"}],"relevance":"100"},{"form":"$","id":"__9145003407816029121","sementity":{"class":"class","type":"Top>Unit>Currency"},"variant_list":[{"form":"$","inip":"30","endp":"30"}],"relevance":"100"},{"form":"tortoise","id":"1019079343","sementity":{"class":"class","fiction":"nonfiction","id":"ODENTITY_REPTILE","type":"Top>LivingThing>Animal>Vertebrate>Reptile"},"semld_list":["http://en.wikipedia.org/wiki/Tortoise","http://ar.wikipedia.org/wiki/سلاحف_برية","http://ca.wikipedia.org/wiki/Testudínid","http://cs.wikipedia.org/wiki/Testudovití","http://de.wikipedia.org/wiki/Landschildkröten","http://es.wikipedia.org/wiki/Testudinidae","http://fi.wikipedia.org/wiki/Testudinidae","http://fr.wikipedia.org/wiki/Tortues_terrestres","http://he.wikipedia.org/wiki/צבים_יבשתיים","http://hi.wikipedia.org/wiki/स्थलीय_कछुआ","http://id.wikipedia.org/wiki/Kura-kura","http://it.wikipedia.org/wiki/Testudinidae","http://ja.wikipedia.org/wiki/リクガメ科","http://ko.wikipedia.org/wiki/땅거북과","http://nl.wikipedia.org/wiki/Landschildpadden","http://no.wikipedia.org/wiki/Landskilpadder","http://pl.wikipedia.org/wiki/Żółwie_lądowe","http://pt.wikipedia.org/wiki/Testudinidae","http://ro.wikipedia.org/wiki/Testudinidae","http://ru.wikipedia.org/wiki/Сухопутные_черепахи","http://sv.wikipedia.org/wiki/Landsköldpaddor","http://tr.wikipedia.org/wiki/Kara_kaplumbağası","http://zh.wikipedia.org/wiki/陸龜","sumo:Reptile"],"semtheme_list":[{"id":"ODTHEME_ZOOLOGY","type":"Top>NaturalSciences>Zoology"}],"variant_list":[{"form":"turtles","inip":"41","endp":"47"}],"relevance":"100"}],"time_expression_list":[{"form":"the 5th of November","normalized_form":"|||||11|5||||","actual_time":"2017-11-05","precision":"day","inip":"53","endp":"71"},{"form":"5th of November","normalized_form":"|||||11|5||||","actual_time":"2017-11-05","precision":"day","inip":"57","endp":"71"}],"money_expression_list":[{"form":"$5","amount_form":"5","numeric_value":"5","currency":"USD","inip":"30","endp":"31"}],"quantity_expression_list":[{"form":"two turtles","amount_form":"two","numeric_value":"2","unit":"turtle","inip":"37","endp":"47"}],"other_expression_list":[{"form":"1245FG","type":"unknown","inip":"104","endp":"109"}],"quotation_list":[{"form":"he was tired in flight 1245FG.","verb":{"form":"said","lemma":"say"},"inip":"81","endp":"110"}],"relation_list":[{"form":"On the 5th of November he said he was tired in flight 1245FG.","inip":"73","endp":"109","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"said","lemma_list":["say"],"sense_id_list":["ODENTITY_COMMUNICATION_PROCESS","ODENTITY_LINGUISTIC_COMMUNICATION","ODENTITY_PROCESS"]},"complement_list":[{"form":"he was tired in flight 1245FG","type":"isDirectObject"}],"degree":"1"},{"form":"London is a nice city.","inip":"0","endp":"20","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a nice city","type":"isAttribute"}],"degree":"1"},{"form":"I have $5 and two turtles.","inip":"23","endp":"47","subject":{"form":"I","lemma_list":["I"],"sense_id_list":["PRONHUMAN"]},"verb":{"form":"have","lemma_list":["have"]},"complement_list":[{"form":"$5 and two turtles","type":"isDirectObject"}],"degree":"1"},{"form":"On the 5th of November he said he was tired in flight 1245FG.","inip":"81","endp":"109","subject":{"form":"he","lemma_list":["he"],"sense_id_list":["PRONHUMAN"]},"verb":{"form":"was tired","lemma_list":["tire"]},"complement_list":[{"form":"in flight","type":"isComplement"}],"degree":"1"}]}' 9 | response = meaningcloud.TopicsResponse(outputOK) 10 | 11 | def testConstruct(self): 12 | self.assertIsNotNone(self.response.getResponse()) 13 | 14 | def testConstructWithWrongJson(self): 15 | outputWrong = 'malformed json' 16 | with self.assertRaises(json.JSONDecodeError): 17 | meaningcloud.TopicsResponse(outputWrong) 18 | 19 | def testConstructWithEmptyParam(self): 20 | with self.assertRaises(Exception): 21 | meaningcloud.TopicsResponse('') 22 | 23 | def testGetEntities(self): 24 | self.assertIsNotNone(self.response.getEntities()) 25 | self.assertTrue(isinstance(self.response.getEntities(), list)) 26 | 27 | def testGetNonexistentEntities(self): 28 | responseWithNoEntities = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 29 | local_response = meaningcloud.TopicsResponse(responseWithNoEntities) 30 | self.assertTrue(isinstance(local_response.getEntities(), dict)) 31 | self.assertEqual(local_response.getEntities(), {}) 32 | 33 | def testGetConcepts(self): 34 | self.assertIsNotNone(self.response.getConcepts()) 35 | self.assertTrue(isinstance(self.response.getConcepts(), list)) 36 | 37 | def testGetNonexistentConcepts(self): 38 | responseWithNoConcepts = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 39 | local_response = meaningcloud.TopicsResponse(responseWithNoConcepts) 40 | self.assertTrue(isinstance(local_response.getConcepts(), dict)) 41 | self.assertIsNotNone(local_response.getConcepts()) 42 | 43 | def testGetMoneyExpressions(self): 44 | self.assertIsNotNone(self.response.getMoneyExpressions()) 45 | self.assertTrue(isinstance(self.response.getMoneyExpressions(), list)) 46 | 47 | def testGetNonexistentMoneyExpressions(self): 48 | responseWithNoMoneyExpressions = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 49 | local_response = meaningcloud.TopicsResponse(responseWithNoMoneyExpressions) 50 | self.assertTrue(isinstance(local_response.getMoneyExpressions(), dict)) 51 | self.assertIsNotNone(local_response.getMoneyExpressions()) 52 | 53 | def testGetQuantityExpressions(self): 54 | self.assertIsNotNone(self.response.getQuantityExpressions()) 55 | self.assertTrue(isinstance(self.response.getQuantityExpressions(), list)) 56 | 57 | def testGetNonexistentQuantityExpressions(self): 58 | responseWithNoQuantityExpressions = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"money_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 59 | local_response = meaningcloud.TopicsResponse(responseWithNoQuantityExpressions) 60 | self.assertTrue(isinstance(local_response.getQuantityExpressions(), dict)) 61 | 62 | def testGetTimeExpressions(self): 63 | self.assertIsNotNone(self.response.getTimeExpressions()) 64 | self.assertTrue(isinstance(self.response.getTimeExpressions(), list)) 65 | 66 | def testGetNonexistentTimeExpressions(self): 67 | responseWithNoTimeExpressions = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[],"relation_list":[{"form":"London is a very nice city.","inip":"0","endp":"25","subject":{"form":"London","lemma_list":["London"],"sense_id_list":["01d0d69c7d","76075d4877"]},"verb":{"form":"is","lemma_list":["be"]},"complement_list":[{"form":"a very nice city","type":"isAttribute"}],"degree":"1"}]}' 68 | local_response = meaningcloud.TopicsResponse(responseWithNoTimeExpressions) 69 | self.assertTrue(isinstance(local_response.getTimeExpressions(), dict)) 70 | self.assertIsNotNone(self.response.getTimeExpressions()) 71 | 72 | def testGetQuotations(self): 73 | self.assertIsNotNone(self.response.getQuotations()) 74 | self.assertTrue(isinstance(self.response.getQuotations(), list)) 75 | 76 | def testGetNonexistentQuotations(self): 77 | responseWithNoQuotations = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[]}' 78 | local_response = meaningcloud.TopicsResponse(responseWithNoQuotations) 79 | self.assertTrue(isinstance(local_response.getQuotations(), dict)) 80 | self.assertIsNotNone(local_response.getQuotations()) 81 | 82 | def testGetRelations(self): 83 | self.assertIsNotNone(self.response.getRelations()) 84 | self.assertTrue(isinstance(self.response.getRelations(), list)) 85 | 86 | def testGetNonexistentRelations(self): 87 | responseWithNoRelations = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"time_expression_list":[],"money_expression_list":[],"quantity_expression_list":[],"other_expression_list":[],"quotation_list":[]}' 88 | local_response = meaningcloud.TopicsResponse(responseWithNoRelations) 89 | self.assertTrue(isinstance(local_response.getRelations(), dict)) 90 | self.assertIsNotNone(local_response.getRelations()) 91 | 92 | def testGetForm(self): 93 | self.assertIsNotNone(self.response.getTopicForm(self.response.getEntities()[0])) 94 | self.assertIsNotNone(self.response.getTopicForm(self.response.getConcepts()[0])) 95 | self.assertIsNotNone(self.response.getTopicForm(self.response.getTimeExpressions()[0])) 96 | self.assertIsNotNone(self.response.getTopicForm(self.response.getMoneyExpressions()[0])) 97 | self.assertIsNotNone(self.response.getTopicForm(self.response.getQuantityExpressions()[0])) 98 | self.assertIsNotNone(self.response.getTopicForm(self.response.getQuotations()[0])) 99 | self.assertIsNotNone(self.response.getTopicForm(self.response.getRelations()[0])) 100 | 101 | def testGetRelevance(self): 102 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getEntities()[0])) 103 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getConcepts()[0])) 104 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getTimeExpressions()[0])) 105 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getMoneyExpressions()[0])) 106 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getQuantityExpressions()[0])) 107 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getQuotations()[0])) 108 | self.assertIsNotNone(self.response.getTopicRelevance(self.response.getRelations()[0])) 109 | 110 | def testGetOntoType(self): 111 | # correct_values 112 | firstEntityOntoType = self.response.getOntoType(self.response.getEntities()[0]) 113 | self.assertIsNotNone(firstEntityOntoType) 114 | self.assertEqual(firstEntityOntoType, 'Top>Location>GeoPoliticalEntity>City') 115 | 116 | firstConceptOntoType = self.response.getOntoType(self.response.getConcepts()[0]) 117 | self.assertIsNotNone(firstConceptOntoType) 118 | self.assertEqual(firstConceptOntoType, 'Top>Location>GeoPoliticalEntity>City') 119 | 120 | # wrong_values 121 | with self.assertRaises(AttributeError): 122 | wrongFormatOntoType = self.response.getOntoType('dummy_value') 123 | 124 | wrongFormatArrayOntoType = self.response.getOntoType({'dummy_key': 'dummy_value'}) 125 | self.assertEqual(wrongFormatArrayOntoType, "") 126 | 127 | def testGetTypeLastNode(self): 128 | # correct_values 129 | firstEntityLastNode = self.response.getTypeLastNode(self.response.getOntoType(self.response.getEntities()[0])) 130 | self.assertIsNotNone(firstEntityLastNode) 131 | self.assertEqual(firstEntityLastNode, 'City') 132 | 133 | firstConceptLastNode = self.response.getTypeLastNode(self.response.getOntoType(self.response.getConcepts()[0])) 134 | self.assertIsNotNone(firstConceptLastNode) 135 | self.assertEqual(firstConceptLastNode, 'City') 136 | 137 | # wrong_values 138 | wrongFormat = self.response.getTypeLastNode('dummy_value') 139 | self.assertEqual(wrongFormat, 'dummy_value') 140 | 141 | wrongFormatArray = self.response.getTypeLastNode({'dummy_key': 'dummy_value'}) 142 | self.assertEqual(wrongFormatArray, "") 143 | 144 | def testGetTypeFirstNode(self): 145 | # correct_values 146 | firstEntityFirstNode = self.response.getTypeFirstNode(self.response.getOntoType(self.response.getEntities()[0])) 147 | self.assertIsNotNone(firstEntityFirstNode) 148 | self.assertEqual(firstEntityFirstNode, 'Location') 149 | 150 | firstConceptFirstNode = self.response.getTypeFirstNode(self.response.getOntoType(self.response.getConcepts()[0])) 151 | self.assertIsNotNone(firstConceptFirstNode) 152 | self.assertEqual(firstConceptFirstNode, 'Location') 153 | 154 | responseNoFirstNode = '{"status":{"code":"0","msg":"OK","credits":"1","remaining_credits":"5000"},"entity_list":[{"form":"DummyTopValue","id":"__madeUpID","sementity":{"class":"instance","id":"__madeupValue","type":"Top"},"variant_list":[{"form":"DummyTopValue","inip":"0","endp":"12"}],"relevance":"100"}]}' 155 | localResponse = meaningcloud.TopicsResponse(responseNoFirstNode) 156 | localFirstEntityFirstNode = localResponse.getTypeFirstNode(localResponse.getOntoType(localResponse.getEntities()[0])) 157 | self.assertIsNotNone(localFirstEntityFirstNode) 158 | self.assertEqual(localFirstEntityFirstNode, 'Top') 159 | 160 | # wrong_values 161 | wrongFormat = self.response.getTypeLastNode('dummy_value') 162 | self.assertEqual(wrongFormat, 'dummy_value') 163 | 164 | wrongFormatArray = self.response.getTypeLastNode({'dummy_key': 'dummy_value'}) 165 | self.assertEqual(wrongFormatArray, "") 166 | 167 | 168 | def testIsUserDefined(self): 169 | self.assertEqual(self.response.isUserDefined(self.response.getEntities()[0]), False) 170 | self.assertEqual(self.response.isUserDefined(self.response.getConcepts()[0]), False) 171 | self.assertEqual(self.response.isUserDefined(self.response.getTimeExpressions()[0]), False) 172 | self.assertEqual(self.response.isUserDefined(self.response.getMoneyExpressions()[0]), False) 173 | self.assertEqual(self.response.isUserDefined(self.response.getQuantityExpressions()[0]), False) 174 | self.assertEqual(self.response.isUserDefined(self.response.getOtherExpressions()[0]), False) 175 | self.assertEqual(self.response.isUserDefined(self.response.getQuotations()[0]), False) 176 | self.assertEqual(self.response.isUserDefined(self.response.getRelations()[0]), False) 177 | 178 | responseWithUserDefinedEntities = '{"status":{"code":"0","msg":"OK","credits":"1"},"entity_list":[{"form":"Lincoln Trikru","official_form":"Lincoln","dictionary":"test1","id":"ent_sin_tag","sementity":{"class":"instance","type":"Top>People>Grounders"},"variant_list":[{"form":"Lincoln","inip":"0","endp":"6"}],"relevance":"100"}],"concept_list":[{"form":"dropship","id":"concepto_sin_tag","dictionary":"test1","sementity":{"class":"class"},"variant_list":[{"form":"dropship","inip":"19","endp":"26"}],"relevance":"100"}]}' 179 | responseWithUD = meaningcloud.TopicsResponse(responseWithUserDefinedEntities) 180 | self.assertEqual(responseWithUD.isUserDefined(responseWithUD.getEntities()[0]), True) 181 | self.assertEqual(responseWithUD.isUserDefined(responseWithUD.getConcepts()[0]), True) 182 | 183 | def testGetNumberOfAppearances(self): 184 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getEntities()[0]), 1) 185 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getConcepts()[0]), 1) 186 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getTimeExpressions()[0]), 1) 187 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getMoneyExpressions()[0]), 1) 188 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getQuantityExpressions()[0]), 1) 189 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getOtherExpressions()[0]), 1) 190 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getQuotations()[0]), 1) 191 | self.assertEqual(self.response.getNumberOfAppearances(self.response.getRelations()[0]), 1) 192 | 193 | # wrong value 194 | self.assertEqual(self.response.getNumberOfAppearances(None), 0) 195 | 196 | 197 | if __name__ == '__main__': 198 | unittest.main() 199 | -------------------------------------------------------------------------------- /tests/resources/file.txt: -------------------------------------------------------------------------------- 1 | This is an input file --------------------------------------------------------------------------------