├── .gitignore ├── LICENSE ├── README.md ├── datamuse ├── __init__.py ├── datamuse.py ├── scripts.py ├── test_api.py └── test_scripts.py └── requirements.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 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | # VirtualEnv 62 | datamuse-env/ 63 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2016 Margaret Sy 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 8 | 9 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 10 | 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | :warning: THIS REPO IS NO LONGER MAINTAINED 2 | 3 | Please use https://github.com/gmarmstrong/python-datamuse/ instead, available on PyPI at https://pypi.python.org/pypi/python-datamuse 4 | 5 | # python-datamuse 6 | 7 | Basic Python (2) wrapper and scripts for the Datamuse API. I'm not associated with Datamuse or OneLook, but I thought the API looked interesting and spun this up to make querying it a bit easier. 8 | 9 | Docs at http://datamuse.com/api/ 10 | 11 | ## Dependencies 12 | 13 | This API requires the `requests` library. You can install the requests module with the command `pip install -r requirements.txt`. 14 | 15 | If you want to use the `dm_to_df` function in `datamuse/scripts.py`, you'll also need to install pandas separately, but presumably if you're going to use that you've got pandas installed already. 16 | 17 | ## Example 18 | 19 | Assuming this is run from the top level directory 20 | ```python 21 | >>> from datamuse import datamuse 22 | >>> api = datamuse.Datamuse() 23 | >>> orange_rhymes = api.words(rel_rhy='orange', max=5) 24 | >>> orange_rhymes 25 | [] 26 | >>> orange_near_rhymes = api.words(rel_nry='orange', max=5) 27 | >>> orange_near_rhymes 28 | [{'score': 973, 'word': 'storage'}, {'score': 858, 'word': 'knowledge'}, {'score': 615, 'word': 'homage'}, {'score': 560, 'word': 'warrant'}] 29 | >>> 30 | >>> 31 | >>> foo_complete = api.suggest(s='foo', max=10) 32 | >>> foo_complete 33 | [{u'score': 626, u'word': u'food'}, {u'score': 568, u'word': u'foot'}, {u'score': 520, u'word': u'fool'}, {u'score': 315, u'word': u'footage'}, {u'score': 297, u'word': u'foolish'}, {u'score': 279, u'word': u'football'}, {u'score': 272, u'word': u'footprint'}, {u'score': 232, u'word': u'footing'}, {u'score': 221, u'word': u'foof'}, {u'score': 185, u'word': u'foolproof'}] 34 | >>> from datamuse import scripts 35 | >>> foo_df = scripts.dm_to_df(foo_complete) 36 | >>> foo_df 37 | score word 38 | 0 626 food 39 | 1 568 foot 40 | 2 521 fool 41 | 3 315 footage 42 | 4 297 foolish 43 | 5 279 football 44 | 6 272 footprint 45 | 7 232 footing 46 | 8 221 foof 47 | 9 185 foolproof 48 | 49 | [10 rows x 2 columns] 50 | ``` 51 | 52 | Note that the default number of results is set to 100. You can set the default `max` to something else using the `set_max_default` method, e.g. `api.set_max_default(300)`. Datamuse only returns 1000 results max. 53 | 54 | ## To Do 55 | 56 | * Add support for Python 3 57 | * Add CI 58 | * Proper pacakging setup 59 | -------------------------------------------------------------------------------- /datamuse/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/margaret/python-datamuse/744e798c72a19bd8895fc60bbc5accc1f9ac05e5/datamuse/__init__.py -------------------------------------------------------------------------------- /datamuse/datamuse.py: -------------------------------------------------------------------------------- 1 | import json 2 | import requests 3 | 4 | 5 | WORD_PARAMS = [ 6 | 'ml', 7 | 'sl', 8 | 'sp', 9 | 'rel_jja', 10 | 'rel_jjb', 11 | 'rel_syn', 12 | 'rel_trg', 13 | 'rel_ant', 14 | 'rel_spc', 15 | 'rel_gen', 16 | 'rel_com', 17 | 'rel_par', 18 | 'rel_bga', 19 | 'rel_bgb', 20 | 'rel_rhy', 21 | 'rel_nry', 22 | 'rel_hom', 23 | 'rel_cns', 24 | 'v', 25 | 'topics', 26 | 'lc', 27 | 'rc', 28 | 'max', 29 | 'md', 30 | 'qe' 31 | ] 32 | 33 | SUGGEST_PARAMS = [ 34 | 's', 35 | 'max', 36 | 'v' 37 | ] 38 | 39 | 40 | class Datamuse(): 41 | def __init__(self, max_results=100): 42 | self.api_root = 'https://api.datamuse.com' 43 | self._validate_max(max_results) 44 | self.max = max_results 45 | 46 | 47 | def __repr__(self): 48 | return '\n'.join(['{0}: {1}'.format(k,v) for k,v in api.__dict__.items()]) 49 | 50 | 51 | def _validate_max(self, max_results): 52 | if not (0 < max_results <= 1000): 53 | raise ValueError("Datamuse only supports values of max in (0, 1000]") 54 | 55 | 56 | def _validate_args(self, args, param_set): 57 | for arg in args: 58 | if arg not in param_set: 59 | raise ValueError('{0} is not a valid parameter for this endpoint.'.format(arg)) 60 | if arg == 'max': 61 | self._validate_max(args[arg]) 62 | 63 | 64 | def _get_resource(self, endpoint, **kwargs): 65 | url = '/'.join([self.api_root, endpoint]) 66 | response = requests.get(url, params=kwargs) 67 | data = response.json() 68 | return data 69 | 70 | 71 | def set_max_default(self, max_results): 72 | self._validate_max(max_results) 73 | self.max = max_results 74 | 75 | 76 | def words(self, **kwargs): 77 | '''https://www.datamuse.com/api/ 78 | ''' 79 | self._validate_args(kwargs, WORD_PARAMS) 80 | if 'max' not in kwargs: 81 | kwargs.update({'max': self.max}) 82 | return self._get_resource('words', **kwargs) 83 | 84 | 85 | def suggest(self, **kwargs): 86 | '''https://www.datamuse.com/api/ 87 | ''' 88 | self._validate_args(kwargs, SUGGEST_PARAMS) 89 | return self._get_resource('sug', **kwargs) 90 | -------------------------------------------------------------------------------- /datamuse/scripts.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | def dm_to_df(datamuse_response): 4 | """Converts the json response of the datamuse API into a DataFrame 5 | :datamuse_response 6 | [{'word': 'foo', 'score': 100}, {'word': 'bar', 'score': 120}] 7 | """ 8 | reformatted = { 9 | 'word': [response['word'] for response in datamuse_response], 10 | 'score': [response['score'] for response in datamuse_response] 11 | } 12 | return pd.DataFrame.from_dict(reformatted) -------------------------------------------------------------------------------- /datamuse/test_api.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import datamuse 3 | from datamuse import Datamuse 4 | 5 | class DatamuseTestCase(unittest.TestCase): 6 | def setUp(self): 7 | self.api = Datamuse() 8 | self.max = 5 9 | 10 | # words endpoint 11 | def test_sounds_like(self): 12 | args = {'sl': 'orange', 'max': self.max} 13 | data = self.api.words(**args) 14 | self.assertTrue(type(data), list) 15 | print("sounds like", data) 16 | 17 | def test_rhymes(self): 18 | args = {'rel_rhy': 'orange', 'max': self.max} 19 | data = self.api.words(**args) 20 | self.assertTrue(len(data) <= self.max) 21 | print("rhyme", data) 22 | 23 | def test_near_rhymes(self): 24 | args = {'rel_nry': 'orange', 'max': self.max} 25 | data = self.api.words(**args) 26 | self.assertTrue(len(data) <= self.max) 27 | print("near rhyme", data) 28 | 29 | def test_bad_request(self): 30 | args = {'foo':42} 31 | with self.assertRaises(ValueError): 32 | data = self.api.words(**args) 33 | 34 | def test_set_max(self): 35 | self.assertTrue(self.api.max, 100) 36 | self.api.set_max_default(10) 37 | self.assertEquals(self.api.max, 10) 38 | data = self.api.words(ml='ringing in the ears') 39 | self.assertEquals(len(data), 10) 40 | 41 | def test_set_max_error(self): 42 | with self.assertRaises(ValueError): 43 | self.api.set_max_default(-2) 44 | self.api.set_max_default(0) 45 | self.api.set_max_default(1001) 46 | 47 | 48 | if __name__ == "__main__": 49 | unittest.main() 50 | -------------------------------------------------------------------------------- /datamuse/test_scripts.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | import datamuse 3 | from datamuse import Datamuse 4 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.9.1 2 | --------------------------------------------------------------------------------