├── _config.yml ├── cuba_weather ├── __init__.py ├── weather.py ├── api.py ├── finder.py ├── console.py └── locations.py ├── setup.py ├── CONTRIBUTING.md ├── README.md ├── .gitignore └── LICENSE /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /cuba_weather/__init__.py: -------------------------------------------------------------------------------- 1 | from .api import InvalidLocation, RCApiClient, URL 2 | from .console import main 3 | from .finder import distance, get_location, get_suggestion 4 | from .locations import locations 5 | from .weather import Weather 6 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | from cuba_weather.console import __version__ 4 | 5 | setup( 6 | name='cuba_weather', 7 | version=__version__, 8 | packages=['cuba_weather'], 9 | entry_points={'console_scripts': ['cuba-weather=cuba_weather.console:main'],}, 10 | url='https://github.com/daxslab/cuba-weather', 11 | license='MIT', 12 | author='Cuban Open Source Community', 13 | description='Python3 client for (https://www.redcuba.cu) weather API', 14 | long_description=open('README.md').read(), 15 | long_description_content_type='text/markdown', 16 | classifiers=[ 17 | 'Programming Language :: Python :: 3', 18 | 'License :: OSI Approved :: MIT License', 19 | 'Operating System :: OS Independent', 20 | ], 21 | python_requires='>=3.6', 22 | ) 23 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How to contribute to cuba-weather 2 | 3 | #### **Did you find a bug?** 4 | 5 | * **Ensure the bug was not already reported** by searching on GitHub under [Issues](https://github.com/daxslab/cuba-weather/issues). 6 | 7 | * If you're unable to find an open issue addressing the problem, [open a new one](https://github.com/daxslab/cuba-weather/issues/new). Be sure to include a **title and clear description**, as much relevant information as possible, and a **code sample** or an **executable test case** demonstrating the expected behavior that is not occurring. 8 | 9 | #### **Did you write a patch that fixes a bug?** 10 | 11 | * Open a new GitHub pull request with the patch. 12 | 13 | * Ensure the PR description clearly describes the problem and solution. Include the relevant issue number if applicable. 14 | 15 | #### **Do you intend to add a new feature or change an existing one?** 16 | 17 | * Suggest your change in the [discussion group](https://t.me/blogswlx) on Telegram and start writing code. 18 | 19 | #### **Do you have questions about the source code?** 20 | 21 | * Ask any question about how to use cuba-weather in the [discussion group](https://t.me/blogswlx) on Telegram. 22 | 23 | cuba-weather is a volunteer effort. We encourage you to pitch in and [join the team](https://t.me/blogswlx) on Telegram! 24 | 25 | Thanks! :heart: :heart: :heart: 26 | 27 | cuba-weather team 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Cuba Weather Python 2 | 3 | [![License: MIT](https://img.shields.io/badge/License-MIT-brightgreen.svg)](https://opensource.org/licenses/MIT) 4 | 5 | Application programming interface of the Cuba Weather project implemented in Python. 6 | 7 | Currently the weather information is obtained from the Cuban search engine [www.redcuba.cu](https://www.redcuba.cu). 8 | 9 | ## Install 10 | 11 | ```bash 12 | pip install git+https://github.com/cuba-weather/cuba-weather-python 13 | ``` 14 | 15 | You can also clone or download this repository and at the root of the project do: 16 | 17 | ```bash 18 | python setup.py install 19 | ``` 20 | 21 | ## Usage 22 | 23 | ### CLI 24 | 25 | ```bash 26 | usage: cuba-weather.py [-h] [-v] [-c] [-t] [-d] [-u] [-p] [-w] [-g] location 27 | 28 | positional arguments: 29 | location location name 30 | 31 | optional arguments: 32 | -h, --help show this help message and exit 33 | -v, --version show program version 34 | -c, --city-name show location city name 35 | -t, --temperature show location temperature 36 | -d, --timestamp show location timestamp 37 | -u, --humidity show location humidity 38 | -p, --pressure show location pressure 39 | -w, --wind show location wind 40 | -g, --general show location general information 41 | ``` 42 | 43 | When just speciying the location and no other arguments, all the available information is displayed. 44 | 45 | ### Package 46 | 47 | ```python3 48 | from cuba_weather import RCApiClient 49 | 50 | location_input = input() 51 | 52 | api = RCApiClient() 53 | 54 | weather = api.get(location_input, suggestion=True) 55 | 56 | print(weather) 57 | ``` 58 | -------------------------------------------------------------------------------- /cuba_weather/weather.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | 4 | class Weather: 5 | ''' 6 | Model class for mapping the json returned by the https://www.redcuba.cu 7 | weather API. 8 | ''' 9 | 10 | def __init__(self, data: dict): 11 | self.data = data 12 | 13 | @property 14 | def city_name(self) -> str: 15 | return self.data['cityName'] 16 | 17 | @property 18 | def timestamp(self) -> datetime: 19 | datetime_str = self.data['dt']['date'] 20 | return datetime.strptime(datetime_str, '%Y-%m-%d %H:%M:%S.%f') 21 | 22 | @property 23 | def temperature(self) -> str: 24 | return self.data['temp'] 25 | 26 | @property 27 | def temperature_fahrenheit(self) -> str: 28 | return (self.data['temp'] * 9/5) + 32 29 | 30 | @property 31 | def humidity(self) -> str: 32 | return self.data['humidity'] 33 | 34 | @property 35 | def pressure(self) -> str: 36 | return self.data['pressure'] 37 | 38 | @property 39 | def wind(self) -> str: 40 | return self.data['windstring'] 41 | 42 | @property 43 | def general(self) -> str: 44 | return self.data['descriptionWeather'] 45 | 46 | def __str__(self): 47 | return self.__repr__() 48 | 49 | def __repr__(self): 50 | result = 'City Name: {city_name}\n' 51 | result += 'Temperature: {temp}°C / {temp_f}°F\n' 52 | result += 'Timestamp: {timestamp}\n' 53 | result += 'Humidity: {hum}%\n' 54 | result += 'Pressure: {hpa} hpa\n' 55 | result += 'Wind: {wind}\n' 56 | result += '{general}' 57 | result = result.format( 58 | city_name=self.city_name, 59 | temp=self.temperature, 60 | temp_f=self.temperature_fahrenheit, 61 | timestamp=self.timestamp, 62 | hum=self.humidity, 63 | hpa=self.pressure, 64 | wind=self.wind, 65 | general=self.general) 66 | return result 67 | -------------------------------------------------------------------------------- /cuba_weather/api.py: -------------------------------------------------------------------------------- 1 | from json import loads 2 | from urllib.error import HTTPError 3 | from urllib.parse import quote 4 | from urllib.request import urlopen 5 | 6 | try: 7 | from .finder import get_location, get_suggestion 8 | except: 9 | from finder import get_location, get_suggestion 10 | try: 11 | from .weather import Weather 12 | except: 13 | from weather import Weather 14 | 15 | URL = 'https://www.redcuba.cu/api/weather_get_summary/{location}' 16 | 17 | class RCApiClient: 18 | ''' 19 | Class to provide the functionality of making API requests. 20 | ''' 21 | 22 | def get(self, location: str, suggestion=False) -> Weather: 23 | ''' 24 | Method that given a location of the user searches the known locations to 25 | find the best match and returns the weather information. The best match 26 | is considered as the known location of shorter length that contains the 27 | given location. 28 | ''' 29 | try: 30 | location = get_location(location) 31 | if suggestion: 32 | location = get_suggestion(location) 33 | escaped_location = quote(location) 34 | url = URL.format(location=escaped_location) 35 | response = urlopen(url) 36 | content = response.read() 37 | if type(content) == bytes: 38 | content = content.decode() 39 | data = loads(content)['data'] 40 | return Weather(data) 41 | except HTTPError as ex: 42 | if ex.code == 404: 43 | raise InvalidLocation(ex) 44 | else: 45 | raise Exception(ex) 46 | 47 | def suggestion(self, location: str) -> str: 48 | ''' 49 | Method that returns the best match of the given location with the known 50 | locations. The best match is calculated using the Damerau-Levenshtein 51 | distance. 52 | ''' 53 | return get_suggestion(get_location(location)) 54 | 55 | 56 | class InvalidLocation(Exception): 57 | pass 58 | -------------------------------------------------------------------------------- /cuba_weather/finder.py: -------------------------------------------------------------------------------- 1 | try: 2 | from .locations import locations 3 | except: 4 | from locations import locations 5 | 6 | locations = sorted(locations, key=len) 7 | 8 | 9 | def distance(s1, s2): 10 | ''' 11 | Implementation of Damerau-Levenshtein distance with transposition (also 12 | sometimes calls unrestricted Damerau-Levenshtein distance). 13 | 14 | It is the minimum number of operations needed to transform one string into 15 | the other, where an operation is defined as an insertion, deletion, or 16 | substitution of a single character, or a transposition of two adjacent 17 | characters. 18 | ''' 19 | d = {} 20 | for i in range(-1, len(s1) + 1): 21 | d[i, -1] = i + 1 22 | for j in range(-1, len(s2) + 1): 23 | d[-1, j] = j + 1 24 | for i, cs1 in enumerate(s1): 25 | for j, cs2 in enumerate(s2): 26 | cost = int(cs1 != cs2) 27 | d[i, j] = min(d[i - 1, j] + 1, d[i, j - 1] + 1, d[i - 1, j - 1] + cost) 28 | if not i or not j: 29 | continue 30 | if cs1 != cs2: 31 | continue 32 | d[i, j] = min(d[i, j], d[i - 2, j - 2] + cost) 33 | return d[len(s1) - 1, len(s2) - 1] 34 | 35 | 36 | def get_location(user_input: str) -> str: 37 | ''' 38 | Method that returns the best match of the given location with the known 39 | locations. The best match is considered as the known location of shorter 40 | length that contains the given location. 41 | ''' 42 | lower_input = user_input.lower() 43 | for location in locations: 44 | if lower_input in location.lower(): 45 | return location 46 | return user_input 47 | 48 | 49 | def get_suggestion(user_input: str) -> str: 50 | ''' 51 | Method that returns the best match of the given location with the known 52 | locations. The best match is calculated using the Damerau-Levenshtein 53 | distance. 54 | ''' 55 | lower_input = user_input.lower() 56 | best_location = locations[0].lower() 57 | best_distance = distance(lower_input, best_location) 58 | for i in range(1, len(locations)): 59 | actual_location = locations[i] 60 | actual_distance = distance(user_input, actual_location) 61 | if actual_distance < best_distance: 62 | best_location = actual_location 63 | best_distance = actual_distance 64 | return best_location 65 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # IDE 2 | .idea/* 3 | .vscode/* 4 | *.code-workspace 5 | 6 | # Byte-compiled / optimized / DLL files 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | 11 | # C extensions 12 | *.so 13 | 14 | # Distribution / packaging 15 | .Python 16 | build/ 17 | develop-eggs/ 18 | dist/ 19 | downloads/ 20 | eggs/ 21 | .eggs/ 22 | lib/ 23 | lib64/ 24 | parts/ 25 | sdist/ 26 | var/ 27 | wheels/ 28 | pip-wheel-metadata/ 29 | share/python-wheels/ 30 | *.egg-info/ 31 | .installed.cfg 32 | *.egg 33 | MANIFEST 34 | 35 | # PyInstaller 36 | # Usually these files are written by a python script from a template 37 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 38 | *.manifest 39 | *.spec 40 | 41 | # Installer logs 42 | pip-log.txt 43 | pip-delete-this-directory.txt 44 | 45 | # Unit test / coverage reports 46 | htmlcov/ 47 | .tox/ 48 | .nox/ 49 | .coverage 50 | .coverage.* 51 | .cache 52 | nosetests.xml 53 | coverage.xml 54 | *.cover 55 | *.py,cover 56 | .hypothesis/ 57 | .pytest_cache/ 58 | 59 | # Translations 60 | *.mo 61 | *.pot 62 | 63 | # Django stuff: 64 | *.log 65 | local_settings.py 66 | db.sqlite3 67 | db.sqlite3-journal 68 | 69 | # Flask stuff: 70 | instance/ 71 | .webassets-cache 72 | 73 | # Scrapy stuff: 74 | .scrapy 75 | 76 | # Sphinx documentation 77 | docs/_build/ 78 | 79 | # PyBuilder 80 | target/ 81 | 82 | # Jupyter Notebook 83 | .ipynb_checkpoints 84 | 85 | # IPython 86 | profile_default/ 87 | ipython_config.py 88 | 89 | # pyenv 90 | .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 96 | # install all needed dependencies. 97 | #Pipfile.lock 98 | 99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 100 | __pypackages__/ 101 | 102 | # Celery stuff 103 | celerybeat-schedule 104 | celerybeat.pid 105 | 106 | # SageMath parsed files 107 | *.sage.py 108 | 109 | # Environments 110 | .env 111 | .venv 112 | env/ 113 | venv/ 114 | ENV/ 115 | env.bak/ 116 | venv.bak/ 117 | 118 | # Spyder project settings 119 | .spyderproject 120 | .spyproject 121 | 122 | # Rope project settings 123 | .ropeproject 124 | 125 | # mkdocs documentation 126 | /site 127 | 128 | # mypy 129 | .mypy_cache/ 130 | .dmypy.json 131 | dmypy.json 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | -------------------------------------------------------------------------------- /cuba_weather/console.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | from argparse import ArgumentParser 4 | 5 | try: 6 | from .api import InvalidLocation, RCApiClient 7 | except: 8 | from api import InvalidLocation, RCApiClient 9 | 10 | __version__ = '0.0.10' 11 | 12 | 13 | def main(): 14 | api = RCApiClient() 15 | 16 | parser = ArgumentParser() 17 | parser.add_argument('location', type=str, help='location name') 18 | parser.add_argument('-v', '--version', help='show program version', action='store_true') 19 | parser.add_argument('-c', '--city-name', help='show location city name', action='store_true') 20 | parser.add_argument('-t', '--temperature', help='show location temperature', action='store_true') 21 | parser.add_argument('-d', '--timestamp', help='show location timestamp', action='store_true') 22 | parser.add_argument('-u', '--humidity', help='show location humidity', action='store_true') 23 | parser.add_argument('-p', '--pressure', help='show location pressure', action='store_true') 24 | parser.add_argument('-w', '--wind', help='show location wind', action='store_true') 25 | parser.add_argument('-g', '--general', help='show location general information', action='store_true') 26 | 27 | args = parser.parse_args() 28 | 29 | if args.version: 30 | print(__version__) 31 | return 32 | 33 | try: 34 | weather = api.get(args.location) 35 | except InvalidLocation: 36 | suggestion = api.suggestion(args.location) 37 | print('Location not found, maybe you are asking about {suggestion}.'.format(suggestion=suggestion)) 38 | return 39 | 40 | if args.general: 41 | print(weather.general) 42 | if args.city_name: 43 | print('City Name: {city_name}'.format(city_name=weather.city_name)) 44 | if args.temperature: 45 | print('Temperature: {temp}°C'.format(temp=weather.temperature)) 46 | if args.timestamp: 47 | print('Timestamp: {timestamp}'.format(timestamp=weather.timestamp)) 48 | if args.humidity: 49 | print('Humidity: {hum}%'.format(hum=weather.humidity)) 50 | if args.pressure: 51 | print('Pressure: {hpa} hpa'.format(hpa=weather.pressure)) 52 | if args.wind: 53 | print('Wind: {wind}'.format(wind=weather.wind)) 54 | 55 | params = [ 56 | args.version, 57 | args.city_name, 58 | args.temperature, 59 | args.timestamp, 60 | args.humidity, 61 | args.pressure, 62 | args.wind, 63 | args.general 64 | ] 65 | 66 | if args.location and not any(params): 67 | print(weather) 68 | 69 | 70 | if __name__ == '__main__': 71 | main() 72 | -------------------------------------------------------------------------------- /cuba_weather/locations.py: -------------------------------------------------------------------------------- 1 | # Known locations 2 | locations = [ 3 | 'Consolación del Sur', 4 | 'Guane', 5 | 'Mantua', 6 | 'Pinar del Río', 7 | 'Viñales', 8 | 'Los Palacios', 9 | 'Mariel', 10 | 'Guanajay', 11 | 'Bauta', 12 | 'San Antonio de los Baños', 13 | 'Güira de Melena', 14 | 'Alquízar', 15 | 'Artemisa', 16 | 'Bahía Honda', 17 | 'Candelaria', 18 | 'San Cristóbal', 19 | 'Habana', 20 | 'Centro Habana', 21 | 'Bejucal', 22 | 'San José de las Lajas', 23 | 'Jaruco', 24 | 'Santa Cruz del Norte', 25 | 'Madruga', 26 | 'Melena del Sur', 27 | 'Batabanó', 28 | 'Quivicán', 29 | 'Calimete', 30 | 'Cárdenas', 31 | 'Colón', 32 | 'Jagüey Grande', 33 | 'Jovellanos', 34 | 'Los Arabos', 35 | 'Martí', 36 | 'Matanzas', 37 | 'Perico', 38 | 'Unión de Reyes', 39 | 'Cienfuegos', 40 | 'Cruces', 41 | 'Palmira', 42 | 'Rodas', 43 | 'Abreus', 44 | 'Aguada de pasajeros', 45 | 'Cumanayagüa', 46 | 'Caibarién', 47 | 'Camajuaní', 48 | 'Cifuentes', 49 | 'Corralillo', 50 | 'Encrucijada', 51 | 'Manicaragua', 52 | 'Placetas', 53 | 'Quemado de Güines', 54 | 'Remedios', 55 | 'Sagüa la Grande', 56 | 'Santa Clara', 57 | 'Santo Domingo', 58 | 'Sancti Spíritus', 59 | 'Trinidad', 60 | 'Cabaiguán', 61 | 'Yaguajay', 62 | 'Jatibonico', 63 | 'Fomento', 64 | 'Ciego de Ávila', 65 | 'Morón', 66 | 'Chambas', 67 | 'Venezuela', 68 | 'Baraguá', 69 | 'Primero de Enero', 70 | 'Camagüey', 71 | 'Guáimaro', 72 | 'Nuevitas', 73 | 'Sibanicú', 74 | 'Esmeralda', 75 | 'Minas', 76 | 'Florida', 77 | 'Vertientes', 78 | 'Santa Cruz del Sur', 79 | 'Manatí', 80 | 'Puerto Padre', 81 | 'Las Tunas', 82 | 'Jobabo', 83 | 'Colombia', 84 | 'Bayamo', 85 | 'Campechuela', 86 | 'Guisa', 87 | 'Jiguaní', 88 | 'Manzanillo', 89 | 'Media Luna', 90 | 'Niquero', 91 | 'Río Cauto', 92 | 'Yara', 93 | 'Baracoa', 94 | 'Guantánamo', 95 | 'Contramaestre', 96 | 'Palma Soriano', 97 | 'San Luis', 98 | 'Santiago de Cuba', 99 | 'Báguanos', 100 | 'Banes', 101 | 'Cueto', 102 | 'Gibara', 103 | 'Holguín', 104 | 'Moa', 105 | 'Sagüa de Tánamo', 106 | 'Buenavista', 107 | 'Varadero', 108 | 'El Cobre', 109 | 'Mayabeque', 110 | 'Aguada de Pasajeros', 111 | 'Cumanayagua', 112 | 'Ranchuelo', 113 | 'Sagua la Grande', 114 | 'Sagua de Tánamo', 115 | 'Nueva Gerona', 116 | 'Provincia de Pinar del Río', 117 | 'Provincia de Matanzas', 118 | 'Provincia de Cienfuegos', 119 | 'Provincia de Villa Clara', 120 | 'Provincia de Sancti Spíritus', 121 | 'Provincia de Ciego de Ávila', 122 | 'Provincia de Holguín', 123 | 'Provincia Granma', 124 | 'Provincia de Santiago de Cuba', 125 | 'Provincia de Guantánamo', 126 | 'Municipio Especial Isla de la Juventud', 127 | ] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. 166 | --------------------------------------------------------------------------------