├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── MANIFEST.in ├── README.rst ├── pycorpora ├── __init__.py └── data │ ├── hyphenated-dirname │ └── test.json │ └── pycorpora_test │ ├── subdir │ └── another_test.json │ ├── test-filename.json │ └── test.json ├── setup.py └── tests └── test_pycorpora.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | *.egg-info/ 23 | .installed.cfg 24 | *.egg 25 | 26 | # PyInstaller 27 | # Usually these files are written by a python script from a template 28 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 29 | *.manifest 30 | *.spec 31 | 32 | # Installer logs 33 | pip-log.txt 34 | pip-delete-this-directory.txt 35 | 36 | # Unit test / coverage reports 37 | htmlcov/ 38 | .tox/ 39 | .coverage 40 | .coverage.* 41 | .cache 42 | nosetests.xml 43 | coverage.xml 44 | *,cover 45 | 46 | # Translations 47 | *.mo 48 | *.pot 49 | 50 | # Django stuff: 51 | *.log 52 | 53 | # Sphinx documentation 54 | docs/_build/ 55 | 56 | # PyBuilder 57 | target/ 58 | 59 | # Project Corpora downloads 60 | corpora-download/ 61 | pycorpora/data/ 62 | 63 | # IDE 64 | .idea 65 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | matrix: 4 | fast_finish: true 5 | include: 6 | - python: pypy3 7 | - python: pypy 8 | - python: 3.7 9 | dist: xenial 10 | - python: 3.6 11 | - python: 3.5 12 | - python: 2.7 13 | 14 | install: 15 | - travis_retry pip install coverage 16 | - travis_retry python setup.py install 17 | 18 | script: 19 | - coverage run --include=pycorpora/* tests/test_pycorpora.py 20 | 21 | after_success: 22 | # Report coverage and send to coveralls.io 23 | - coverage report 24 | - pip install coveralls && coveralls 25 | 26 | # Static analysis 27 | - travis_retry pip install pep8 pyflakes 28 | - pep8 --statistics --count *.py 29 | - pep8 --statistics --count pycorpora/*.py 30 | - pep8 --statistics --count tests/*.py 31 | - pyflakes *.py | tee >(wc -l) 32 | - pyflakes pycorpora/*.py | tee >(wc -l) 33 | - pyflakes tests/*.py | tee >(wc -l) 34 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Allison Parrish 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 13 | all 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 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.rst 2 | include *.txt 3 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | pycorpora 2 | ========= 3 | 4 | .. image:: https://travis-ci.org/aparrish/pycorpora.svg?branch=master 5 | :target: https://travis-ci.org/aparrish/pycorpora 6 | 7 | A simple Python interface for Darius Kazemi's `Corpora Project 8 | `_, "a collection of static corpora 9 | (plural of 'corpus') that are potentially useful in the creation of weird 10 | internet stuff." The ``pycorpora`` interface makes it easy to use data from the 11 | Corpora Project in your program. Here's an example of how it works:: 12 | 13 | import pycorpora 14 | import random 15 | 16 | # print a random flower name 17 | print random.choice(pycorpora.plants.flowers['flowers']) 18 | 19 | # print a random word coined by Shakespeare 20 | print random.choice(pycorpora.words.literature.shakespeare_words['words']) 21 | 22 | `Allison Parrish `_ created the ``pycorpora`` 23 | interface. The source code for the package is `on GitHub 24 | `_. Contributions are welcome! 25 | 26 | Installation 27 | ------------ 28 | 29 | Installation by hand:: 30 | 31 | python setup.py install 32 | 33 | Installation with pip:: 34 | 35 | pip install --no-cache-dir pycorpora 36 | 37 | The package does not include data from the Corpora Project; instead, the data 38 | is downloaded when the package is installed (using either of the methods 39 | above). By default, the "master" branch of the `Corpora Project GitHub 40 | repository `_ is used as the source for the 41 | data. You can specify an alternative URL to download the data from using the 42 | argument ``--corpora-zip-url`` on the command line with either of the two 43 | methods above:: 44 | 45 | python setup.py install --corpora-zip-url=https://github.com/dariusk/corpora/archive/master.zip 46 | 47 | ... or, with ``pip``:: 48 | 49 | pip install pycorpora --install-option="--corpora-zip-url=https://github.com/dariusk/corpora/archive/master.zip" 50 | 51 | Alternatively, the ``CORPORA_ZIP_URL`` environment variable can be used for the 52 | same purpose (if both are set, the command line option will take precedence):: 53 | 54 | env CORPORA_ZIP_URL=https://github.com/dariusk/corpora/archive/master.zip pip install pycorpora 55 | 56 | (The intention of ``--corpora-zip-url`` is to let you install Corpora Project 57 | data from a particular branch, commit or fork, so that changes to the bleeding 58 | edge of the project don't break your code. Also, a ``file://`` URL can be used 59 | for a local/vendored zip file.) 60 | 61 | Update 62 | ------ 63 | 64 | Update Corpora Project data by reinstalling with pip:: 65 | 66 | pip install --upgrade --force-reinstall pycorpora 67 | 68 | Usage 69 | ----- 70 | 71 | Getting the data from a particular Corpora Project file is easy. Here's an 72 | example:: 73 | 74 | import pycorpora 75 | crayola_data = pycorpora.colors.crayola 76 | print crayola_data["colors"][0]["color"] # prints "Almond" 77 | 78 | The expression ``pycorpora.colors.crayola`` returns data deserialized from the 79 | JSON file located at ``data/colors/crayola.json`` in the Corpora Project (i.e., 80 | `this file 81 | `_). 82 | You can use this syntax even with more deeply nested subdirectories:: 83 | 84 | import pycorpora 85 | mr_men_little_miss_data = pycorpora.words.literature.mr_men_little_miss 86 | print mr_men_little_miss_data["little_miss"][-1] # prints "Wise" 87 | 88 | You can use ``from pycorpora import ...`` to import a particular Corpora Project 89 | category:: 90 | 91 | from pycorpora import governments 92 | print governments.nsa_projects["codenames"][0] # prints "ARTIFICE" 93 | 94 | from pycorpora import humans 95 | print humans.occupations["occupations"][0] # prints "accountant" 96 | 97 | You can also use square bracket indexing instead of attributes for accessing 98 | subcategories and individual corpora (just in case the Corpora Project ever adds 99 | files with names that aren't valid Python identifiers):: 100 | 101 | import pycorpora 102 | import random 103 | fruits = pycorpora.foods["fruits"] 104 | print random.choice(fruits["fruits"]) # prints "pomelo" maybe 105 | 106 | Additionally, ``pycorpora`` supports an API similar to that provided by the `Corpora Project node package `_:: 107 | 108 | import pycorpora 109 | 110 | # get a list of all categories 111 | pycorpora.get_categories() # ["animals", "archetypes"...] 112 | 113 | # get a list of subcategories for a particular category 114 | pycorpora.get_categories("words") # ["literature", "word_clues"...] 115 | 116 | # get a list of all files in a particular category 117 | pycorpora.get_files("animals") # ["birds_antarctica", "birds_uk", ...] 118 | 119 | # get data deserialized from the JSON data in a particular file 120 | pycorpora.get_file("animals", "birds_antarctica") # returns dict w/data 121 | 122 | # get file in a subcategory 123 | pycorpora.get_file("words/literature", "shakespeare_words") 124 | 125 | As an extension of this interface, you can also use the ``get_categories``, 126 | ``get_files`` and ``get_file`` methods on individual categories:: 127 | 128 | import pycorpora 129 | 130 | # get a list of files in the "archetypes" category 131 | pycorpora.archetypes.get_files() # ['artifact', 'character', 'event', ...] 132 | 133 | # get an individual file from the "archetypes" category 134 | pycorpora.archetypes.get_file("character") # returns dictionary w/data 135 | 136 | # get subcategories of a category 137 | pycorpora.words.get_categories() # ['literature', 'word_clues'] 138 | 139 | Examples 140 | -------- 141 | 142 | Here are a few quick examples of using data from the Corpora Project to do 143 | weird and fun stuff. 144 | 145 | Create a list of whimsically colored flowers:: 146 | 147 | from pycorpora import plants, colors 148 | import random 149 | 150 | random_flowers = random.sample(plants.flowers["flowers"], 10) 151 | random_colors = random.sample( 152 | [item['color'] for item in colors.crayola["colors"]], 10) 153 | for pair in zip(random_colors, random_flowers): 154 | print " ".join(pair).title() 155 | 156 | # outputs (e.g.): 157 | # Maroon Bergamot 158 | # Blue Bell Zinnia 159 | # Pink Flamingo Camellias 160 | # Tickle Me Pink Begonia 161 | # Burnt Orange Clover 162 | # Fuzzy Wuzzy Hibiscus 163 | # Outer Space Forget Me Not 164 | # Almond Petunia 165 | # Pine Green Ladys Slipper 166 | # Shadow Jasmine 167 | 168 | Create random biographies:: 169 | 170 | from pycorpora import humans, geography 171 | import random 172 | 173 | def a_biography(): 174 | return "{0} is a(n) {1} who lives in {2}.".format( 175 | random.choice(humans.firstNames["firstNames"]), 176 | random.choice(humans.occupations["occupations"]), 177 | random.choice(geography.us_cities["cities"])["city"]) 178 | 179 | for i in range(5): 180 | print a_biography() 181 | 182 | # outputs (e.g.): 183 | # Jessica is a(n) ceiling tile installer who lives in Grand Forks. 184 | # Kayla is a(n) substance abuse social worker who lives in Torrance. 185 | # Luis is a(n) hydrologist who lives in Saginaw. 186 | # Leah is a(n) heating installer who lives in Danville. 187 | # Grant is a(n) building inspector who lives in Vineland. 188 | 189 | Automated pizza topping-related boasts about your inebriation:: 190 | 191 | from pycorpora import words, foods 192 | import random 193 | 194 | # "I'm so smashed I could eat a pizza with spinach, cheese, *and* hot sauce." 195 | print "I'm so {0} I could eat a pizza with {1}, {2}, *and* {3}.".format( 196 | random.choice(words.states_of_drunkenness["states_of_drunkenness"]), 197 | *random.sample(foods.pizzaToppings["pizzaToppings"], 3)) 198 | 199 | The possibilities... are endless. 200 | 201 | History 202 | ------- 203 | 204 | * 0.1.2: Python 3 compatibility (contributed by Sam Raker); vastly improved 205 | build process (contributed by Hugo van Kemenade). 206 | 207 | License 208 | ------- 209 | 210 | The ``pycorpora`` package is MIT licensed (see LICENSE.txt). The data in the 211 | Corpora Project is itself in the public domain (CC0). 212 | 213 | Acknowledgements 214 | ---------------- 215 | 216 | Thanks to Darius Kazemi and all of the Corpora Project contributors! 217 | 218 | This package was developed as part of my Spring 2015 research fellowship at 219 | `ITP `_. Thank you to the program and its students for 220 | their interest and support! 221 | 222 | -------------------------------------------------------------------------------- /pycorpora/__init__.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from pkg_resources import resource_stream, resource_exists, resource_isdir, \ 3 | resource_listdir 4 | import json 5 | import re 6 | 7 | __version__ = '0.1.2' 8 | 9 | cache = dict() 10 | 11 | 12 | def fetch_resource(name): 13 | if name not in cache: 14 | cache[name] = json.loads(resource_stream( 15 | __name__, name).read().decode('utf-8')) 16 | return cache[name] 17 | 18 | 19 | def get_categories(category=None): 20 | if category is None: 21 | return resource_listdir(__name__, "data") 22 | else: 23 | return [item for item 24 | in resource_listdir(__name__, "data/" + category) 25 | if resource_isdir(__name__, "data/" + category + "/" + item)] 26 | 27 | 28 | def get_files(category): 29 | return [re.sub(r"\.json$", "", item) for item 30 | in resource_listdir(__name__, "data/" + category) 31 | if not resource_isdir(__name__, "data/" + category + "/" + item)] 32 | 33 | 34 | def get_file(*components): 35 | return fetch_resource("/".join(["data"] + list(components)) + ".json") 36 | 37 | 38 | class CorpusLoader(object): 39 | def __init__(self, directory): 40 | self.directory = directory 41 | 42 | def __getitem__(self, key): 43 | return self.__getattr__(key) 44 | 45 | def __getattr__(self, attr): 46 | file_loc = "data/" + self.directory + "/" + attr + ".json" 47 | dir_loc = "data/" + self.directory + "/" + attr 48 | if resource_exists(__name__, file_loc): 49 | return fetch_resource(file_loc) 50 | elif resource_exists(__name__, dir_loc) and \ 51 | resource_isdir(__name__, dir_loc): 52 | return CorpusLoader(self.directory + "/" + attr) 53 | else: 54 | raise AttributeError("no resource named " + attr) 55 | 56 | def get_categories(self): 57 | return get_categories(self.directory) 58 | 59 | def get_files(self): 60 | return get_files(self.directory) 61 | 62 | def get_file(self, *components): 63 | return get_file(self.directory, *components) 64 | 65 | 66 | module = sys.modules[__name__] 67 | for directory in resource_listdir(__name__, "data"): 68 | setattr(module, directory.replace("-", "_"), CorpusLoader(directory)) 69 | -------------------------------------------------------------------------------- /pycorpora/data/hyphenated-dirname/test.json: -------------------------------------------------------------------------------- 1 | {"description": "test", "tests": ["one", "two", "three"]} 2 | -------------------------------------------------------------------------------- /pycorpora/data/pycorpora_test/subdir/another_test.json: -------------------------------------------------------------------------------- 1 | {"description": "another test", "tests": ["four", "five", "six"]} 2 | -------------------------------------------------------------------------------- /pycorpora/data/pycorpora_test/test-filename.json: -------------------------------------------------------------------------------- 1 | {"description": "test filename!", "tests": ["one", "two", "three"]} 2 | -------------------------------------------------------------------------------- /pycorpora/data/pycorpora_test/test.json: -------------------------------------------------------------------------------- 1 | {"description": "test", "tests": ["one", "two", "three"]} 2 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | try: 3 | from setuptools import setup 4 | from setuptools.command.install import install 5 | except ImportError: 6 | from distutils.core import setup 7 | from distutils.command.install import install 8 | try: 9 | # For Python 3.0 and later 10 | from urllib.request import urlopen 11 | except ImportError: 12 | # Fall back to Python 2's urllib2 13 | from urllib2 import urlopen 14 | from distutils.dir_util import mkpath, copy_tree 15 | import glob 16 | import io 17 | import zipfile 18 | import os 19 | 20 | 21 | class DownloadAndInstall(install): 22 | user_options = install.user_options + [ 23 | ('corpora-zip-url=', None, 24 | 'URL pointing to .zip file of corpora data ' + 25 | '(defaults to current master on GitHub)') 26 | ] 27 | 28 | def initialize_options(self, *args, **kwargs): 29 | install.initialize_options(self, *args, **kwargs) 30 | self.corpora_zip_url = None 31 | 32 | def run(self): 33 | if self.corpora_zip_url is None: 34 | self.corpora_zip_url = os.environ.get( 35 | "CORPORA_ZIP_URL", 36 | "https://github.com/dariusk/corpora/archive/master.zip", 37 | ) 38 | print("Installing corpora data from " + self.corpora_zip_url) 39 | mkpath("./corpora-download") 40 | resp = urlopen(self.corpora_zip_url).read() 41 | remote = io.BytesIO(resp) 42 | zf = zipfile.ZipFile(remote, "r") 43 | zf.extractall("corpora-download") 44 | try: 45 | data_dir = glob.glob("./corpora-download/*/data")[0] 46 | except IndexError: 47 | raise IndexError( 48 | "malformed corpora archive: expecting a subdirectory '*/data'") 49 | copy_tree(data_dir, "pycorpora/data") 50 | install.run(self) 51 | 52 | 53 | setup( 54 | name="pycorpora", 55 | version="0.1.2", 56 | packages=['pycorpora'], 57 | package_data={'pycorpora': ['data/*/*.json', 'data/*/*/*.json']}, 58 | author="Allison Parrish", 59 | author_email="allison@decontextualize.com", 60 | description="A Python wrapper for Darius Kazemi's Corpora Project", 61 | url="https://github.com/aparrish/pycorpora", 62 | license="LICENSE.txt", 63 | long_description=open("README.rst").read(), 64 | keywords="nlp corpus text language", 65 | python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*", 66 | classifiers=[ 67 | "Development Status :: 3 - Alpha", 68 | "Intended Audience :: Developers", 69 | "Intended Audience :: Education", 70 | "Intended Audience :: Science/Research", 71 | "License :: OSI Approved :: MIT License", 72 | "Natural Language :: English", 73 | "Programming Language :: Python :: 2", 74 | "Programming Language :: Python :: 2.7", 75 | "Programming Language :: Python :: 3", 76 | "Programming Language :: Python :: 3.5", 77 | "Programming Language :: Python :: 3.6", 78 | "Programming Language :: Python :: 3.7", 79 | "Programming Language :: Python :: Implementation :: CPython", 80 | "Programming Language :: Python :: Implementation :: PyPy", 81 | "Topic :: Artistic Software", 82 | "Topic :: Scientific/Engineering :: Artificial Intelligence"], 83 | cmdclass={'install': DownloadAndInstall}, 84 | ) 85 | -------------------------------------------------------------------------------- /tests/test_pycorpora.py: -------------------------------------------------------------------------------- 1 | try: 2 | import unittest2 as unittest 3 | except ImportError: 4 | import unittest 5 | 6 | 7 | class TestPyCorpora(unittest.TestCase): 8 | 9 | def test_import(self): 10 | import pycorpora 11 | self.assertTrue(hasattr(pycorpora, 'pycorpora_test')) 12 | self.assertTrue(hasattr(pycorpora, 'hyphenated_dirname')) 13 | 14 | def test_load_corpus(self): 15 | import pycorpora 16 | self.assertEqual(type(pycorpora.pycorpora_test.test), dict) 17 | self.assertEqual(pycorpora.pycorpora_test.test['tests'], 18 | ["one", "two", "three"]) 19 | 20 | self.assertEqual(type(pycorpora.hyphenated_dirname.test), dict) 21 | self.assertEqual(pycorpora.hyphenated_dirname.test['tests'], 22 | ["one", "two", "three"]) 23 | 24 | def test_subdir(self): 25 | import pycorpora 26 | self.assertEqual(type(pycorpora.pycorpora_test.subdir.another_test), 27 | dict) 28 | self.assertEqual(pycorpora.pycorpora_test.subdir.another_test['tests'], 29 | ["four", "five", "six"]) 30 | 31 | def test_getitem(self): 32 | import pycorpora 33 | self.assertEqual(type(pycorpora.pycorpora_test['test-filename']), dict) 34 | self.assertEqual(pycorpora.pycorpora_test['test-filename']['tests'], 35 | ["one", "two", "three"]) 36 | self.assertEqual(pycorpora.pycorpora_test['test'], 37 | pycorpora.pycorpora_test.test) 38 | self.assertEqual(pycorpora.pycorpora_test['subdir']['another_test'], 39 | pycorpora.pycorpora_test.subdir.another_test) 40 | 41 | def test_attr_errors(self): 42 | import pycorpora 43 | self.assertRaises(AttributeError, lambda: pycorpora.pycorpora_schmest) 44 | self.assertRaises(AttributeError, 45 | lambda: pycorpora.pycorpora_test.not_here) 46 | self.assertRaises(AttributeError, 47 | lambda: pycorpora.pycorpora_test.subdir.not_here) 48 | 49 | def test_from_import(self): 50 | from pycorpora import pycorpora_test 51 | self.assertEqual(type(pycorpora_test.test), dict) 52 | self.assertEqual(pycorpora_test.test['tests'], ["one", "two", "three"]) 53 | 54 | def test_get_categories(self): 55 | import pycorpora 56 | cats = pycorpora.get_categories() 57 | self.assertIn('pycorpora_test', cats) 58 | subcats = pycorpora.get_categories("pycorpora_test") 59 | self.assertEqual(subcats, ['subdir']) 60 | 61 | def test_loader_get_categories(self): 62 | import pycorpora 63 | cats = pycorpora.pycorpora_test.get_categories() 64 | self.assertEqual(cats, ['subdir']) 65 | 66 | def test_get_files(self): 67 | import pycorpora 68 | files = pycorpora.get_files('pycorpora_test') 69 | self.assertEqual(set(files), set(['test-filename', 'test'])) 70 | subfiles = pycorpora.get_files('pycorpora_test/subdir') 71 | self.assertEqual(subfiles, ['another_test']) 72 | 73 | def test_loader_get_files(self): 74 | import pycorpora 75 | files = pycorpora.pycorpora_test.get_files() 76 | self.assertEqual(set(files), set(['test-filename', 'test'])) 77 | subfiles = pycorpora.pycorpora_test.subdir.get_files() 78 | self.assertEqual(subfiles, ['another_test']) 79 | 80 | def test_get_file(self): 81 | import pycorpora 82 | data = pycorpora.get_file('pycorpora_test', 'test') 83 | self.assertEqual(type(data), dict) 84 | self.assertEqual(data['tests'], ["one", "two", "three"]) 85 | subdata = pycorpora.get_file('pycorpora_test/subdir', 'another_test') 86 | self.assertIsNotNone(subdata) 87 | self.assertEqual(type(data), dict) 88 | self.assertEqual(data['tests'], ["one", "two", "three"]) 89 | 90 | def test_loader_get_file(self): 91 | import pycorpora 92 | data = pycorpora.pycorpora_test.get_file('test') 93 | self.assertEqual(type(data), dict) 94 | self.assertEqual(data['tests'], ["one", "two", "three"]) 95 | subdata = pycorpora.pycorpora_test.subdir.get_file('another_test') 96 | self.assertIsNotNone(subdata) 97 | self.assertEqual(type(data), dict) 98 | self.assertEqual(data['tests'], ["one", "two", "three"]) 99 | 100 | def test_cache(self): 101 | import pycorpora 102 | self.assertNotIn('data/pycorpora_test/test.json', pycorpora.cache) 103 | data = pycorpora.get_file('pycorpora_test', 'test') 104 | self.assertIn('data/pycorpora_test/test.json', pycorpora.cache) 105 | data = pycorpora.pycorpora_test.subdir.another_test 106 | self.assertIsNotNone(data) 107 | self.assertIn('data/pycorpora_test/subdir/another_test.json', 108 | pycorpora.cache) 109 | 110 | 111 | if __name__ == '__main__': 112 | unittest.main() 113 | --------------------------------------------------------------------------------