├── setup.cfg ├── .gitignore ├── Makefile ├── leafly ├── metadata.py ├── __init__.py └── leafly.py ├── LICENSE ├── setup.py └── README.md /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_svn_revision = false 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | .DS_Store 3 | *.egg-info/ 4 | build/ 5 | dist/ 6 | *.un~ 7 | .tox 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | test: 2 | python setup.py test 3 | 4 | publish: 5 | python setup.py sdist upload --sign 6 | -------------------------------------------------------------------------------- /leafly/metadata.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.4" 2 | __author__ = "Dan Loewenherz" 3 | __copyright__ = "Copyright 2014, Lionheart Software" 4 | __maintainer__ = "Dan Loewenherz" 5 | __email__ = "dan@lionheartsw.com" 6 | __license__ = "Apache 2.0" 7 | 8 | -------------------------------------------------------------------------------- /leafly/__init__.py: -------------------------------------------------------------------------------- 1 | from .leafly import Leafly 2 | 3 | from .metadata import ( 4 | __author__, 5 | __copyright__, 6 | __email__, 7 | __license__, 8 | __maintainer__, 9 | __version__, 10 | ) 11 | 12 | __all__ = [ 13 | '__author__', 14 | '__copyright__', 15 | '__email__', 16 | '__license__', 17 | '__maintainer__', 18 | '__version__', 19 | 'Leafly', 20 | ] 21 | 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2014 Lionheart Software LLC 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. 14 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env/python 2 | # -*- coding: utf-8 -*- 3 | 4 | import unittest 5 | import os 6 | from leafly import metadata 7 | from distutils.cmd import Command 8 | import re 9 | 10 | try: 11 | from setuptools import setup 12 | except ImportError: 13 | from distutils.core import setup 14 | 15 | classifiers = [ 16 | "Development Status :: 5 - Production/Stable", 17 | "Environment :: Console", 18 | "Intended Audience :: Developers", 19 | "Natural Language :: English", 20 | "Operating System :: OS Independent", 21 | "Programming Language :: Python", 22 | "Topic :: Software Development :: Libraries :: Python Modules", 23 | "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", 24 | "Topic :: Utilities", 25 | "License :: OSI Approved :: Apache Software License", 26 | ] 27 | 28 | class TestCommand(Command): 29 | user_options = [] 30 | 31 | def initialize_options(self): 32 | pass 33 | 34 | def finalize_options(self): 35 | pass 36 | 37 | def run(self): 38 | from test_leafly import TestLeaflyAPI 39 | suite = unittest.TestLoader().loadTestsFromTestCase(TestLeaflyAPI) 40 | unittest.TextTestRunner(verbosity=2).run(suite) 41 | 42 | setup( 43 | name='leafly', 44 | version=metadata.__version__, 45 | url="http://github.com/lionheart/python-leafly", 46 | description="A Python wrapper for Leafly", 47 | classifiers=classifiers, 48 | keywords="leafly", 49 | license=metadata.__license__, 50 | author=metadata.__author__, 51 | author_email=metadata.__email__, 52 | packages=['leafly'], 53 | install_requires=["requests>=2.0.0"], 54 | package_data={'': ['LICENSE', 'README.md']}, 55 | cmdclass={'test': TestCommand}, 56 | ) 57 | 58 | -------------------------------------------------------------------------------- /leafly/leafly.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | import json 3 | import operator 4 | import logging 5 | import requests 6 | import exceptions 7 | import pprint 8 | 9 | LEAFLY_API_ENDPOINT = "http://data.leafly.com/" 10 | 11 | logger = logging.getLogger(__name__) 12 | 13 | class Leafly(object): 14 | BOOLEAN_FIELDS = [ 15 | "storefront", 16 | "delivery", 17 | "retail", 18 | "medical", 19 | "creditcards", 20 | "hasclones", 21 | "hasconcentrates", 22 | "hasedibles", 23 | "veterandiscount" 24 | ] 25 | 26 | def __init__(self, app_id, key): 27 | self.app_id = app_id 28 | self.key = key 29 | 30 | def __getattr__(self, k): 31 | return LeaflyCall(self.app_id, self.key, k) 32 | 33 | 34 | class LeaflyCall(object): 35 | def __init__(self, app_id, key, path): 36 | self.app_id = app_id 37 | self.key = key 38 | self.components = [path] 39 | 40 | def __getattr__(self, k): 41 | self.components.append(k) 42 | return self 43 | 44 | def __getitem__(self, k): 45 | self.components.append(str(k)) 46 | return self 47 | 48 | def __call__(self, *args, **kwargs): 49 | url = "{}{}".format(LEAFLY_API_ENDPOINT, "/".join(self.components)) 50 | 51 | params = kwargs.copy() 52 | 53 | for field in Leafly.BOOLEAN_FIELDS: 54 | if field in kwargs: 55 | if isinstance(kwargs[field], bool): 56 | if kwargs[field]: 57 | params[field] = "true" 58 | else: 59 | # Don't add the param if it is not True 60 | pass 61 | 62 | headers = { 63 | 'app_id': self.app_id, 64 | 'app_key': self.key 65 | } 66 | 67 | new_kwargs = { 68 | 'headers': headers 69 | } 70 | 71 | if self.components == ["strains"]: 72 | fun = requests.post 73 | new_kwargs['data'] = json.dumps(params) 74 | elif self.components == ["locations"]: 75 | fun = requests.post 76 | new_kwargs['data'] = params 77 | else: 78 | fun = requests.get 79 | new_kwargs['data'] = params 80 | 81 | response = fun(url, **new_kwargs) 82 | 83 | logger.debug(url) 84 | return response.json() 85 | 86 | if __name__ == "__main__": 87 | import sys 88 | leafly = Leafly(*sys.argv[1:]) 89 | 90 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | python-leafly 2 | ============= 3 | 4 | [Leafly API Documentation](https://developer.leafly.com/docs) 5 | 6 | Installation 7 | ------------ 8 | 9 | python-leafly is available for download through the Python Package Index (PyPi). You can install it right away using pip or easy_install. 10 | 11 | ``` 12 | pip install leafly 13 | ``` 14 | 15 | Usage 16 | ----- 17 | 18 | To get started, you're going to need to sign up as a developer on the Leafly developer site. Once you've got an application ID and a key, you're ready to go. 19 | 20 | ```python 21 | import leafly 22 | 23 | leafly = Leafly(app_id, key) 24 | ``` 25 | 26 | To turn on debug logging: 27 | 28 | ```python 29 | import logging 30 | logging.basicConfig(level=logging.DEBUG) 31 | ``` 32 | 33 | ### Strain Search 34 | 35 | python-leafly maps directly to the Leafly API itself. E.g., to get all available strains: 36 | 37 | ```python 38 | response = leafly.strains() 39 | strains = response['Strains'] 40 | for strain in strains: 41 | print strain['UrlName'] 42 | ``` 43 | 44 | ### Strain Details 45 | 46 | To retrieve strain details, just use the `UrlName` attribute (i.e., a slug) on a strain object and pass it in as a component to the leafly object. 47 | 48 | ```python 49 | response = leafly.strains['blue-dream']() 50 | ``` 51 | 52 | ### Reviews 53 | 54 | ```python 55 | response = leafly.strains['blue-dream'].reviews(take=10, page=0) 56 | for review in response['reviews']: 57 | print review['id'], review['text'] 58 | ``` 59 | 60 | ### Review Details 61 | 62 | ```python 63 | response = leafly.strains['blue-dream'].reviews[1234]() 64 | print response['rating'] 65 | ``` 66 | 67 | ### Strain Photos 68 | 69 | ```python 70 | response = leafly.strains['blue-dream'].photos(take=10, page=0) 71 | for photo in response['photos']: 72 | print photo['thumb'] 73 | ``` 74 | 75 | ### Strain Availability 76 | 77 | ```python 78 | response = leafly.strains['blue-dream'].availability(lat=47.606, lon=-122.333) 79 | for dispensary in response: 80 | print dispensary['name'] 81 | ``` 82 | 83 | ### Dispensary Search 84 | 85 | ```python 86 | response = leafly.locations(take=10, page=0, latitude=47.606, longitude=-122.333, hasedibles=True) 87 | for dispensary in response['stores']: 88 | print dispensary['name'] 89 | ``` 90 | 91 | ### Dispensary Details 92 | 93 | ```python 94 | response = leafly.locations['herbal-nation']() 95 | print response['permalink'] 96 | ``` 97 | 98 | ### Dispensary Menu 99 | 100 | ```python 101 | response = leafly.locations['herbal-nation'].menu() 102 | for item in response: 103 | print item['name'] 104 | ``` 105 | 106 | ### Dispensary Reviews 107 | 108 | ```python 109 | response = leafly.locations['herbal-nation'].reviews(skip=0, take=10) 110 | for review in response['reviews'] 111 | print review['comments'] 112 | ``` 113 | --------------------------------------------------------------------------------