From fe534d5229de5e83dccdfa3e4ba3c1b29bd38a71 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Feb 2021 08:34:39 +0100 Subject: Adding upstream version 2020.1+dfsg. Signed-off-by: Daniel Baumann --- LICENSE | 20 ++ PKG-INFO | 88 +++++++ README.rst | 64 +++++ pyproject.toml | 34 +++ pytzdata/__init__.py | 122 +++++++++ pytzdata/_compat.py | 11 + pytzdata/_timezones.py | 597 ++++++++++++++++++++++++++++++++++++++++++ pytzdata/commands/__init__.py | 2 + pytzdata/commands/app.py | 15 ++ pytzdata/commands/make.py | 164 ++++++++++++ pytzdata/commands/zones.py | 36 +++ pytzdata/exceptions.py | 8 + pytzdata/version.py | 5 + setup.py | 47 ++++ 14 files changed, 1213 insertions(+) create mode 100644 LICENSE create mode 100644 PKG-INFO create mode 100644 README.rst create mode 100644 pyproject.toml create mode 100644 pytzdata/__init__.py create mode 100644 pytzdata/_compat.py create mode 100644 pytzdata/_timezones.py create mode 100644 pytzdata/commands/__init__.py create mode 100644 pytzdata/commands/app.py create mode 100644 pytzdata/commands/make.py create mode 100644 pytzdata/commands/zones.py create mode 100644 pytzdata/exceptions.py create mode 100644 pytzdata/version.py create mode 100644 setup.py diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..701df22 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2015 Sébastien Eustace + +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: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +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. diff --git a/PKG-INFO b/PKG-INFO new file mode 100644 index 0000000..89db2e0 --- /dev/null +++ b/PKG-INFO @@ -0,0 +1,88 @@ +Metadata-Version: 2.1 +Name: pytzdata +Version: 2020.1 +Summary: The Olson timezone database for Python. +Home-page: https://github.com/sdispater/pytzdata +License: MIT +Author: Sébastien Eustace +Author-email: sebastien@eustace.io +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* +Classifier: License :: OSI Approved :: MIT License +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 +Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Project-URL: Repository, https://github.com/sdispater/pytzdata +Description-Content-Type: text/x-rst + +Pytzdata +######## + +.. image:: https://travis-ci.org/sdispater/pytzdata.png + :alt: Pytzdata Build status + :target: https://travis-ci.org/sdispater/pytzdata + +The Olson timezone database for Python. + +Supports Python **2.7+** and **3.5+**. + + +Installation +============ + + pip install pytzdata + + +Usage +===== + +You can access the content of a specific timezone file by using the `tz_file()` function: + +.. code-block:: python + + from pytzdata import tz_file + + with tz_file('Europe/Paris') as f: + # Do something with the file + +If you just want to know the path to a specific timezone file, you may use the `tz_path()` function: + +.. code-block:: python + + from pytzdata import tz_path + + tz_path('Europe/Paris') + +By default, ``pytzdata`` will use the bundled timezone database, however you can set +a custom directory that holds the timezone files using the ``set_directory`` function: + +.. code-block:: python + + import pytzdata + + pytzdata.set_directory('/custom/zoneinfo') + +You can also set the ``PYTZDATA_TZDATADIR`` environment variable to set a custom directory. + + +Release +======= + +To make a new release just follow these steps: + +- ``make data`` +- Update version numbers in ``pytzdata/version.py`` and ``tests/test_version.py`` +- ``make tox`` + + +Resources +========= + +* `Issue Tracker `_ + diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..af97029 --- /dev/null +++ b/README.rst @@ -0,0 +1,64 @@ +Pytzdata +######## + +.. image:: https://travis-ci.org/sdispater/pytzdata.png + :alt: Pytzdata Build status + :target: https://travis-ci.org/sdispater/pytzdata + +The Olson timezone database for Python. + +Supports Python **2.7+** and **3.5+**. + + +Installation +============ + + pip install pytzdata + + +Usage +===== + +You can access the content of a specific timezone file by using the `tz_file()` function: + +.. code-block:: python + + from pytzdata import tz_file + + with tz_file('Europe/Paris') as f: + # Do something with the file + +If you just want to know the path to a specific timezone file, you may use the `tz_path()` function: + +.. code-block:: python + + from pytzdata import tz_path + + tz_path('Europe/Paris') + +By default, ``pytzdata`` will use the bundled timezone database, however you can set +a custom directory that holds the timezone files using the ``set_directory`` function: + +.. code-block:: python + + import pytzdata + + pytzdata.set_directory('/custom/zoneinfo') + +You can also set the ``PYTZDATA_TZDATADIR`` environment variable to set a custom directory. + + +Release +======= + +To make a new release just follow these steps: + +- ``make data`` +- Update version numbers in ``pytzdata/version.py`` and ``tests/test_version.py`` +- ``make tox`` + + +Resources +========= + +* `Issue Tracker `_ diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..975111d --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,34 @@ +[tool.poetry] +name = "pytzdata" +version = "2020.1" +description = "The Olson timezone database for Python." +authors = [ + "Sébastien Eustace " +] +license = "MIT" + +readme = "README.rst" + +homepage = "https://github.com/sdispater/pytzdata" +repository = "https://github.com/sdispater/pytzdata" + +classifiers = [ + "Operating System :: OS Independent", + "Topic :: Software Development :: Libraries :: Python Modules" +] + +[tool.poetry.dependencies] +python = "~2.7 || ^3.4" + + +[tool.poetry.dev-dependencies] +autopep8 = "^1.3" +cleo = "^0.6.5" +pytest = "^3.5" +tox = "^3.0" +black = {version = "^19.10b0", python = "^3.6"} + + +[build-system] +requires = ["poetry>=1.0.0"] +build-backend = "poetry.masonry.api" diff --git a/pytzdata/__init__.py b/pytzdata/__init__.py new file mode 100644 index 0000000..22940da --- /dev/null +++ b/pytzdata/__init__.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- + +import os + +from .exceptions import TimezoneNotFound +from ._timezones import timezones +from ._compat import FileNotFoundError + + +DEFAULT_DIRECTORY = os.path.join( + os.path.dirname(__file__), + 'zoneinfo' +) + +_DIRECTORY = os.getenv('PYTZDATA_TZDATADIR', DEFAULT_DIRECTORY) + +_TIMEZONES = {} + +INVALID_ZONES = ['Factory', 'leapseconds', 'localtime', 'posixrules'] + + +def tz_file(name): + """ + Open a timezone file from the zoneinfo subdir for reading. + + :param name: The name of the timezone. + :type name: str + + :rtype: file + """ + try: + filepath = tz_path(name) + + return open(filepath, 'rb') + except TimezoneNotFound: + # http://bugs.launchpad.net/bugs/383171 - we avoid using this + # unless absolutely necessary to help when a broken version of + # pkg_resources is installed. + try: + from pkg_resources import resource_stream + except ImportError: + resource_stream = None + + if resource_stream is not None: + try: + return resource_stream(__name__, 'zoneinfo/' + name) + except FileNotFoundError: + return tz_path(name) + + raise + + +def tz_path(name): + """ + Return the path to a timezone file. + + :param name: The name of the timezone. + :type name: str + + :rtype: str + """ + if not name: + raise ValueError('Invalid timezone') + + name_parts = name.lstrip('/').split('/') + + for part in name_parts: + if part == os.path.pardir or os.path.sep in part: + raise ValueError('Bad path segment: %r' % part) + + filepath = os.path.join(_DIRECTORY, *name_parts) + + if not os.path.exists(filepath): + raise TimezoneNotFound('Timezone {} not found at {}'.format(name, filepath)) + + return filepath + + +def set_directory(directory=None): + global _DIRECTORY + + if directory is None: + directory = os.getenv('PYTZDATA_TZDATADIR', DEFAULT_DIRECTORY) + + _DIRECTORY = directory + + +def get_timezones(): + """ + Get the supported timezones. + + The list will be cached unless you set the "fresh" attribute to True. + + :param fresh: Whether to get a fresh list or not + :type fresh: bool + + :rtype: tuple + """ + base_dir = _DIRECTORY + zones = () + + for root, dirs, files in os.walk(base_dir): + for basename in files: + zone = os.path.join(root, basename) + if os.path.isdir(zone): + continue + + zone = os.path.relpath(zone, base_dir) + + with open(os.path.join(root, basename), 'rb') as fd: + if fd.read(4) == b'TZif' and zone not in INVALID_ZONES: + zones = zones + (zone,) + + return tuple(sorted(zones)) + + +def _get_suffix(name): + i = name.rfind('.') + if 0 < i < len(name) - 1: + return name[i:] + else: + return '' diff --git a/pytzdata/_compat.py b/pytzdata/_compat.py new file mode 100644 index 0000000..0fee1d7 --- /dev/null +++ b/pytzdata/_compat.py @@ -0,0 +1,11 @@ +# -*- coding: utf-8 -*- + +import sys + +PY33 = sys.version_info >= (3, 3) + + +if PY33: + FileNotFoundError = FileNotFoundError +else: + FileNotFoundError = IOError # cf PEP-3151 diff --git a/pytzdata/_timezones.py b/pytzdata/_timezones.py new file mode 100644 index 0000000..7c42a92 --- /dev/null +++ b/pytzdata/_timezones.py @@ -0,0 +1,597 @@ +# -*- coding: utf-8 -*- + +timezones = ( + "Africa/Abidjan", + "Africa/Accra", + "Africa/Addis_Ababa", + "Africa/Algiers", + "Africa/Asmara", + "Africa/Asmera", + "Africa/Bamako", + "Africa/Bangui", + "Africa/Banjul", + "Africa/Bissau", + "Africa/Blantyre", + "Africa/Brazzaville", + "Africa/Bujumbura", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Ceuta", + "Africa/Conakry", + "Africa/Dakar", + "Africa/Dar_es_Salaam", + "Africa/Djibouti", + "Africa/Douala", + "Africa/El_Aaiun", + "Africa/Freetown", + "Africa/Gaborone", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Juba", + "Africa/Kampala", + "Africa/Khartoum", + "Africa/Kigali", + "Africa/Kinshasa", + "Africa/Lagos", + "Africa/Libreville", + "Africa/Lome", + "Africa/Luanda", + "Africa/Lubumbashi", + "Africa/Lusaka", + "Africa/Malabo", + "Africa/Maputo", + "Africa/Maseru", + "Africa/Mbabane", + "Africa/Mogadishu", + "Africa/Monrovia", + "Africa/Nairobi", + "Africa/Ndjamena", + "Africa/Niamey", + "Africa/Nouakchott", + "Africa/Ouagadougou", + "Africa/Porto-Novo", + "Africa/Sao_Tome", + "Africa/Timbuktu", + "Africa/Tripoli", + "Africa/Tunis", + "Africa/Windhoek", + "America/Adak", + "America/Anchorage", + "America/Anguilla", + "America/Antigua", + "America/Araguaina", + "America/Argentina/Buenos_Aires", + "America/Argentina/Catamarca", + "America/Argentina/ComodRivadavia", + "America/Argentina/Cordoba", + "America/Argentina/Jujuy", + "America/Argentina/La_Rioja", + "America/Argentina/Mendoza", + "America/Argentina/Rio_Gallegos", + "America/Argentina/Salta", + "America/Argentina/San_Juan", + "America/Argentina/San_Luis", + "America/Argentina/Tucuman", + "America/Argentina/Ushuaia", + "America/Aruba", + "America/Asuncion", + "America/Atikokan", + "America/Atka", + "America/Bahia", + "America/Bahia_Banderas", + "America/Barbados", + "America/Belem", + "America/Belize", + "America/Blanc-Sablon", + "America/Boa_Vista", + "America/Bogota", + "America/Boise", + "America/Buenos_Aires", + "America/Cambridge_Bay", + "America/Campo_Grande", + "America/Cancun", + "America/Caracas", + "America/Catamarca", + "America/Cayenne", + "America/Cayman", + "America/Chicago", + "America/Chihuahua", + "America/Coral_Harbour", + "America/Cordoba", + "America/Costa_Rica", + "America/Creston", + "America/Cuiaba", + "America/Curacao", + "America/Danmarkshavn", + "America/Dawson", + "America/Dawson_Creek", + "America/Denver", + "America/Detroit", + "America/Dominica", + "America/Edmonton", + "America/Eirunepe", + "America/El_Salvador", + "America/Ensenada", + "America/Fort_Nelson", + "America/Fort_Wayne", + "America/Fortaleza", + "America/Glace_Bay", + "America/Godthab", + "America/Goose_Bay", + "America/Grand_Turk", + "America/Grenada", + "America/Guadeloupe", + "America/Guatemala", + "America/Guayaquil", + "America/Guyana", + "America/Halifax", + "America/Havana", + "America/Hermosillo", + "America/Indiana/Indianapolis", + "America/Indiana/Knox", + "America/Indiana/Marengo", + "America/Indiana/Petersburg", + "America/Indiana/Tell_City", + "America/Indiana/Vevay", + "America/Indiana/Vincennes", + "America/Indiana/Winamac", + "America/Indianapolis", + "America/Inuvik", + "America/Iqaluit", + "America/Jamaica", + "America/Jujuy", + "America/Juneau", + "America/Kentucky/Louisville", + "America/Kentucky/Monticello", + "America/Knox_IN", + "America/Kralendijk", + "America/La_Paz", + "America/Lima", + "America/Los_Angeles", + "America/Louisville", + "America/Lower_Princes", + "America/Maceio", + "America/Managua", + "America/Manaus", + "America/Marigot", + "America/Martinique", + "America/Matamoros", + "America/Mazatlan", + "America/Mendoza", + "America/Menominee", + "America/Merida", + "America/Metlakatla", + "America/Mexico_City", + "America/Miquelon", + "America/Moncton", + "America/Monterrey", + "America/Montevideo", + "America/Montreal", + "America/Montserrat", + "America/Nassau", + "America/New_York", + "America/Nipigon", + "America/Nome", + "America/Noronha", + "America/North_Dakota/Beulah", + "America/North_Dakota/Center", + "America/North_Dakota/New_Salem", + "America/Nuuk", + "America/Ojinaga", + "America/Panama", + "America/Pangnirtung", + "America/Paramaribo", + "America/Phoenix", + "America/Port-au-Prince", + "America/Port_of_Spain", + "America/Porto_Acre", + "America/Porto_Velho", + "America/Puerto_Rico", + "America/Punta_Arenas", + "America/Rainy_River", + "America/Rankin_Inlet", + "America/Recife", + "America/Regina", + "America/Resolute", + "America/Rio_Branco", + "America/Rosario", + "America/Santa_Isabel", + "America/Santarem", + "America/Santiago", + "America/Santo_Domingo", + "America/Sao_Paulo", + "America/Scoresbysund", + "America/Shiprock", + "America/Sitka", + "America/St_Barthelemy", + "America/St_Johns", + "America/St_Kitts", + "America/St_Lucia", + "America/St_Thomas", + "America/St_Vincent", + "America/Swift_Current", + "America/Tegucigalpa", + "America/Thule", + "America/Thunder_Bay", + "America/Tijuana", + "America/Toronto", + "America/Tortola", + "America/Vancouver", + "America/Virgin", + "America/Whitehorse", + "America/Winnipeg", + "America/Yakutat", + "America/Yellowknife", + "Antarctica/Casey", + "Antarctica/Davis", + "Antarctica/DumontDUrville", + "Antarctica/Macquarie", + "Antarctica/Mawson", + "Antarctica/McMurdo", + "Antarctica/Palmer", + "Antarctica/Rothera", + "Antarctica/South_Pole", + "Antarctica/Syowa", + "Antarctica/Troll", + "Antarctica/Vostok", + "Arctic/Longyearbyen", + "Asia/Aden", + "Asia/Almaty", + "Asia/Amman", + "Asia/Anadyr", + "Asia/Aqtau", + "Asia/Aqtobe", + "Asia/Ashgabat", + "Asia/Ashkhabad", + "Asia/Atyrau", + "Asia/Baghdad", + "Asia/Bahrain", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Barnaul", + "Asia/Beirut", + "Asia/Bishkek", + "Asia/Brunei", + "Asia/Calcutta", + "Asia/Chita", + "Asia/Choibalsan", + "Asia/Chongqing", + "Asia/Chungking", + "Asia/Colombo", + "Asia/Dacca", + "Asia/Damascus", + "Asia/Dhaka", + "Asia/Dili", + "Asia/Dubai", + "Asia/Dushanbe", + "Asia/Famagusta", + "Asia/Gaza", + "Asia/Harbin", + "Asia/Hebron", + "Asia/Ho_Chi_Minh", + "Asia/Hong_Kong", + "Asia/Hovd", + "Asia/Irkutsk", + "Asia/Istanbul", + "Asia/Jakarta", + "Asia/Jayapura", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Kashgar", + "Asia/Kathmandu", + "Asia/Katmandu", + "Asia/Khandyga", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuching", + "Asia/Kuwait", + "Asia/Macao", + "Asia/Macau", + "Asia/Magadan", + "Asia/Makassar", + "Asia/Manila", + "Asia/Muscat", + "Asia/Nicosia", + "Asia/Novokuznetsk", + "Asia/Novosibirsk", + "Asia/Omsk", + "Asia/Oral", + "Asia/Phnom_Penh", + "Asia/Pontianak", + "Asia/Pyongyang", + "Asia/Qatar", + "Asia/Qostanay", + "Asia/Qyzylorda", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Saigon", + "Asia/Sakhalin", + "Asia/Samarkand", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tel_Aviv", + "Asia/Thimbu", + "Asia/Thimphu", + "Asia/Tokyo", + "Asia/Tomsk", + "Asia/Ujung_Pandang", + "Asia/Ulaanbaatar", + "Asia/Ulan_Bator", + "Asia/Urumqi", + "Asia/Ust-Nera", + "Asia/Vientiane", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yangon", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Bermuda", + "Atlantic/Canary", + "Atlantic/Cape_Verde", + "Atlantic/Faeroe", + "Atlantic/Faroe", + "Atlantic/Jan_Mayen", + "Atlantic/Madeira", + "Atlantic/Reykjavik", + "Atlantic/South_Georgia", + "Atlantic/St_Helena", + "Atlantic/Stanley", + "Australia/ACT", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Broken_Hill", + "Australia/Canberra", + "Australia/Currie", + "Australia/Darwin", + "Australia/Eucla", + "Australia/Hobart", + "Australia/LHI", + "Australia/Lindeman", + "Australia/Lord_Howe", + "Australia/Melbourne", + "Australia/NSW", + "Australia/North", + "Australia/Perth", + "Australia/Queensland", + "Australia/South", + "Australia/Sydney", + "Australia/Tasmania", + "Australia/Victoria", + "Australia/West", + "Australia/Yancowinna", + "Brazil/Acre", + "Brazil/DeNoronha", + "Brazil/East", + "Brazil/West", + "CET", + "CST6CDT", + "Canada/Atlantic", + "Canada/Central", + "Canada/Eastern", + "Canada/Mountain", + "Canada/Newfoundland", + "Canada/Pacific", + "Canada/Saskatchewan", + "Canada/Yukon", + "Chile/Continental", + "Chile/EasterIsland", + "Cuba", + "EET", + "EST", + "EST5EDT", + "Egypt", + "Eire", + "Etc/GMT", + "Etc/GMT+0", + "Etc/GMT+1", + "Etc/GMT+10", + "Etc/GMT+11", + "Etc/GMT+12", + "Etc/GMT+2", + "Etc/GMT+3", + "Etc/GMT+4", + "Etc/GMT+5", + "Etc/GMT+6", + "Etc/GMT+7", + "Etc/GMT+8", + "Etc/GMT+9", + "Etc/GMT-0", + "Etc/GMT-1", + "Etc/GMT-10", + "Etc/GMT-11", + "Etc/GMT-12", + "Etc/GMT-13", + "Etc/GMT-14", + "Etc/GMT-2", + "Etc/GMT-3", + "Etc/GMT-4", + "Etc/GMT-5", + "Etc/GMT-6", + "Etc/GMT-7", + "Etc/GMT-8", + "Etc/GMT-9", + "Etc/GMT0", + "Etc/Greenwich", + "Etc/UCT", + "Etc/UTC", + "Etc/Universal", + "Etc/Zulu", + "Europe/Amsterdam", + "Europe/Andorra", + "Europe/Astrakhan", + "Europe/Athens", + "Europe/Belfast", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Busingen", + "Europe/Chisinau", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Gibraltar", + "Europe/Guernsey", + "Europe/Helsinki", + "Europe/Isle_of_Man", + "Europe/Istanbul", + "Europe/Jersey", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Kirov", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/Luxembourg", + "Europe/Madrid", + "Europe/Malta", + "Europe/Mariehamn", + "Europe/Minsk", + "Europe/Monaco", + "Europe/Moscow", + "Europe/Nicosia", + "Europe/Oslo", + "Europe/Paris", + "Europe/Podgorica", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/San_Marino", + "Europe/Sarajevo", + "Europe/Saratov", + "Europe/Simferopol", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Tirane", + "Europe/Tiraspol", + "Europe/Ulyanovsk", + "Europe/Uzhgorod", + "Europe/Vaduz", + "Europe/Vatican", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Europe/Zaporozhye", + "Europe/Zurich", + "GB", + "GB-Eire", + "GMT", + "GMT+0", + "GMT-0", + "GMT0", + "Greenwich", + "HST", + "Hongkong", + "Iceland", + "Indian/Antananarivo", + "Indian/Chagos", + "Indian/Christmas", + "Indian/Cocos", + "Indian/Comoro", + "Indian/Kerguelen", + "Indian/Mahe", + "Indian/Maldives", + "Indian/Mauritius", + "Indian/Mayotte", + "Indian/Reunion", + "Iran", + "Israel", + "Jamaica", + "Japan", + "Kwajalein", + "Libya", + "MET", + "MST", + "MST7MDT", + "Mexico/BajaNorte", + "Mexico/BajaSur", + "Mexico/General", + "NZ", + "NZ-CHAT", + "Navajo", + "PRC", + "PST8PDT", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Bougainville", + "Pacific/Chatham", + "Pacific/Chuuk", + "Pacific/Easter", + "Pacific/Efate", + "Pacific/Enderbury", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Funafuti", + "Pacific/Galapagos", + "Pacific/Gambier", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Johnston", + "Pacific/Kiritimati", + "Pacific/Kosrae", + "Pacific/Kwajalein", + "Pacific/Majuro", + "Pacific/Marquesas", + "Pacific/Midway", + "Pacific/Nauru", + "Pacific/Niue", + "Pacific/Norfolk", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Palau", + "Pacific/Pitcairn", + "Pacific/Pohnpei", + "Pacific/Ponape", + "Pacific/Port_Moresby", + "Pacific/Rarotonga", + "Pacific/Saipan", + "Pacific/Samoa", + "Pacific/Tahiti", + "Pacific/Tarawa", + "Pacific/Tongatapu", + "Pacific/Truk", + "Pacific/Wake", + "Pacific/Wallis", + "Pacific/Yap", + "Poland", + "Portugal", + "ROC", + "ROK", + "Singapore", + "Turkey", + "UCT", + "US/Alaska", + "US/Aleutian", + "US/Arizona", + "US/Central", + "US/East-Indiana", + "US/Eastern", + "US/Hawaii", + "US/Indiana-Starke", + "US/Michigan", + "US/Mountain", + "US/Pacific", + "US/Samoa", + "UTC", + "Universal", + "W-SU", + "WET", + "Zulu", +) diff --git a/pytzdata/commands/__init__.py b/pytzdata/commands/__init__.py new file mode 100644 index 0000000..633f866 --- /dev/null +++ b/pytzdata/commands/__init__.py @@ -0,0 +1,2 @@ +# -*- coding: utf-8 -*- + diff --git a/pytzdata/commands/app.py b/pytzdata/commands/app.py new file mode 100644 index 0000000..0d09a43 --- /dev/null +++ b/pytzdata/commands/app.py @@ -0,0 +1,15 @@ +# -*- coding: utf-8 -*- + +from cleo import Application + +from .make import MakeCommand +from .zones import ZonesCommand + +app = Application('pytzdata') + +app.add(MakeCommand()) +app.add(ZonesCommand()) + + +if __name__ == '__main__': + app.run() diff --git a/pytzdata/commands/make.py b/pytzdata/commands/make.py new file mode 100644 index 0000000..e0a7b4b --- /dev/null +++ b/pytzdata/commands/make.py @@ -0,0 +1,164 @@ +# -*- coding: utf-8 -*- + +import os +import errno +import shutil +import tarfile +import subprocess + +from urllib.request import urlopen +from contextlib import closing +from distutils.dir_util import copy_tree, remove_tree +from cleo import Command + + +class MakeCommand(Command): + """ + Make tzdata files. + + make + {version? : The version to make.} + {--path= : The destination directory.} + """ + + FILES = ["tzcode-latest.tar.gz", "tzdata-latest.tar.gz"] + + BASE_URL = "http://www.iana.org/time-zones/repository" + + def __init__(self): + super(MakeCommand, self).__init__() + + self.path = None + + def handle(self): + self.path = self.option("path") or self.get_build_dir() + + self.mkdir(self.path) + + self.download() + self.line("") + self.uncompress() + self.line("") + self.build() + self.line("") + self.copy() + self.line("") + self.clean() + self.line("") + self.call("zones:dump") + + def download(self): + if not self.argument("version"): + files = self.FILES + base_url = self.BASE_URL + else: + files = [ + "tzcode{}.tar.gz".format(self.argument("version")), + "tzdata{}.tar.gz".format(self.argument("version")), + ] + base_url = "https://data.iana.org/time-zones/releases" + + self.line("[Downloading archives]") + for filename in files: + url = os.path.join(base_url, filename) + self.write("Downloading {}".format(filename)) + dest = os.path.join(self.path, filename) + with closing(urlopen(url)) as r: + with open(dest, "wb") as f: + shutil.copyfileobj(r, f) + + self.overwrite("Downloaded {} ".format(filename)) + self.line("") + + def uncompress(self): + self.line("[Uncompressing archives]") + dest_path = os.path.join(self.path, "tz") + self.mkdir(dest_path) + + if not self.argument("version"): + files = self.FILES + else: + files = [ + "tzcode{}.tar.gz".format(self.argument("version")), + "tzdata{}.tar.gz".format(self.argument("version")), + ] + + for filename in files: + filepath = os.path.join(self.path, filename) + self.write("Uncompressing {}".format(filename)) + with closing(tarfile.open(filepath)) as f: + f.extractall(dest_path) + + self.overwrite("Uncompressed {} ".format(filename)) + self.line("") + + def build(self): + self.line("[Building tzdata]") + dest_path = os.path.join(self.path, "tz") + + # Getting VERSION + with open(os.path.join(dest_path, "version")) as f: + version = f.read().strip() + + self.write("Building version {}".format(version)) + os.chdir(dest_path) + + with open(os.devnull, "w") as temp: + subprocess.call( + ["make", "TOPDIR={}".format(dest_path), "install"], + stdout=temp, + stderr=temp, + ) + + self.overwrite("Built version {}".format(version)) + self.line("") + + def copy(self): + self.line("[Copying tzdata]") + tzdata_dir = os.path.realpath( + os.path.join(self.path, "tz", "usr", "share", "zoneinfo") + ) + local_dir = os.path.realpath( + os.path.join(os.path.dirname(__file__), "..", "zoneinfo") + ) + self.line( + "Copying {} to {}".format( + tzdata_dir, local_dir + ) + ) + remove_tree(local_dir) + copy_tree(tzdata_dir, local_dir) + + def clean(self): + self.line("[Cleaning up]") + if not self.argument("version"): + files = self.FILES + else: + files = [ + "tzcode{}.tar.gz".format(self.argument("version")), + "tzdata{}.tar.gz".format(self.argument("version")), + ] + + for filename in files: + filepath = os.path.join(self.path, filename) + self.write("Removing {}".format(filename)) + os.remove(filepath) + + self.overwrite("Removed {} ".format(filename)) + self.line("") + + self.write("Removing tz/*") + shutil.rmtree(os.path.join(self.path, "tz")) + self.overwrite("Removed tz/*") + + def get_build_dir(self): + return os.path.join(os.path.dirname(__file__), "..", "..", "_build") + + def mkdir(self, path, mode=0o777): + try: + os.makedirs(path, mode) + except OSError as exc: + if exc.errno == errno.EEXIST and os.path.isdir(path): + pass + else: + raise diff --git a/pytzdata/commands/zones.py b/pytzdata/commands/zones.py new file mode 100644 index 0000000..ef3e33a --- /dev/null +++ b/pytzdata/commands/zones.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- + +import os +import pprint +import pytzdata + +from cleo import Command + + +class ZonesCommand(Command): + """ + Dumps available timezones to the _timezone.py file. + + zones:dump + """ + + TEMPLATE = """# -*- coding: utf-8 -*- + +timezones = {} +""" + + def handle(self): + zones = pytzdata.get_timezones() + + tz_file = os.path.join( + os.path.dirname(__file__), + '..', + '_timezones.py' + ) + + with open(tz_file, 'w') as fd: + fd.write( + self.TEMPLATE.format(pprint.pformat(zones)) + ) + + self.info('Dumped {} timezones'.format(len(zones))) diff --git a/pytzdata/exceptions.py b/pytzdata/exceptions.py new file mode 100644 index 0000000..e6744a6 --- /dev/null +++ b/pytzdata/exceptions.py @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +from ._compat import FileNotFoundError + + +class TimezoneNotFound(FileNotFoundError): + + pass diff --git a/pytzdata/version.py b/pytzdata/version.py new file mode 100644 index 0000000..3fd846d --- /dev/null +++ b/pytzdata/version.py @@ -0,0 +1,5 @@ +# -*- coding: utf-8 -*- + +VERSION = "2020.1" + +OLSON_VERSION = "2020a" diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..147849f --- /dev/null +++ b/setup.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- +from setuptools import setup + +packages = \ +['pytzdata', 'pytzdata.commands'] + +package_data = \ +{'': ['*'], + 'pytzdata': ['zoneinfo/*', + 'zoneinfo/Africa/*', + 'zoneinfo/America/*', + 'zoneinfo/America/Argentina/*', + 'zoneinfo/America/Indiana/*', + 'zoneinfo/America/Kentucky/*', + 'zoneinfo/America/North_Dakota/*', + 'zoneinfo/Antarctica/*', + 'zoneinfo/Arctic/*', + 'zoneinfo/Asia/*', + 'zoneinfo/Atlantic/*', + 'zoneinfo/Australia/*', + 'zoneinfo/Brazil/*', + 'zoneinfo/Canada/*', + 'zoneinfo/Chile/*', + 'zoneinfo/Etc/*', + 'zoneinfo/Europe/*', + 'zoneinfo/Indian/*', + 'zoneinfo/Mexico/*', + 'zoneinfo/Pacific/*', + 'zoneinfo/US/*']} + +setup_kwargs = { + 'name': 'pytzdata', + 'version': '2020.1', + 'description': 'The Olson timezone database for Python.', + 'long_description': "Pytzdata\n########\n\n.. image:: https://travis-ci.org/sdispater/pytzdata.png\n :alt: Pytzdata Build status\n :target: https://travis-ci.org/sdispater/pytzdata\n\nThe Olson timezone database for Python.\n\nSupports Python **2.7+** and **3.5+**.\n\n\nInstallation\n============\n\n pip install pytzdata\n\n\nUsage\n=====\n\nYou can access the content of a specific timezone file by using the `tz_file()` function:\n\n.. code-block:: python\n\n from pytzdata import tz_file\n\n with tz_file('Europe/Paris') as f:\n # Do something with the file\n\nIf you just want to know the path to a specific timezone file, you may use the `tz_path()` function:\n\n.. code-block:: python\n\n from pytzdata import tz_path\n\n tz_path('Europe/Paris')\n\nBy default, ``pytzdata`` will use the bundled timezone database, however you can set\na custom directory that holds the timezone files using the ``set_directory`` function:\n\n.. code-block:: python\n\n import pytzdata\n\n pytzdata.set_directory('/custom/zoneinfo')\n\nYou can also set the ``PYTZDATA_TZDATADIR`` environment variable to set a custom directory.\n\n\nRelease\n=======\n\nTo make a new release just follow these steps:\n\n- ``make data``\n- Update version numbers in ``pytzdata/version.py`` and ``tests/test_version.py``\n- ``make tox``\n\n\nResources\n=========\n\n* `Issue Tracker `_\n", + 'author': 'Sébastien Eustace', + 'author_email': 'sebastien@eustace.io', + 'maintainer': None, + 'maintainer_email': None, + 'url': 'https://github.com/sdispater/pytzdata', + 'packages': packages, + 'package_data': package_data, + 'python_requires': '>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', +} + + +setup(**setup_kwargs) -- cgit v1.2.3