summaryrefslogtreecommitdiff
path: root/libre
diff options
context:
space:
mode:
Diffstat (limited to 'libre')
-rw-r--r--libre/iceweasel/PKGBUILD333
-rw-r--r--libre/iceweasel/firefox-70.0-add-distro.patch6965
-rw-r--r--libre/iceweasel/libre.patch328
-rw-r--r--libre/iceweasel/vendor.js.in317
4 files changed, 492 insertions, 7451 deletions
diff --git a/libre/iceweasel/PKGBUILD b/libre/iceweasel/PKGBUILD
index c3ff85b28..61c4fd39a 100644
--- a/libre/iceweasel/PKGBUILD
+++ b/libre/iceweasel/PKGBUILD
@@ -69,18 +69,18 @@ source=(https://archive.mozilla.org/pub/firefox/releases/$pkgver/source/firefox-
0001-Use-remoting-name-for-GDK-application-names.patch
$pkgname.desktop)
source+=(https://repo.parabola.nu/other/iceweasel/${pkgname}_${_brandingver}-${_brandingrel}.branding.tar.xz{,.sig}
- firefox-70.0-add-distro.patch
libre.patch
- libre-searchengines.patch)
+ libre-searchengines.patch
+ vendor.js.in)
sha256sums=('1fa59aedc8469c3e6ffb12449ab7de2f93776f7679eedebfb74aa309b694956f'
'SKIP'
'5f7ac724a5c5afd9322b1e59006f4170ea5354ca1e0e60dab08b7784c2d8463c'
'f573d00835afe066ef1887bfea35099933ee07aeadc4c0d603972127e600cfc4'
'e90956067d8549f02864d612369ed8714d7173f0ee07bbfb4374a7323b4a733e'
'SKIP'
- '41ab298519dfdf86e1599990cd2a2e4d939a2a1d77de829caa0593d0d2e8f0e8'
- '497b0b7d15364acec4b8706ab41ce4aefd4fd1d7f1baa7980a46d14cca8aedd8'
- 'dfed11d97f1d4198a3dc608be159b6b53a11054f376cdb73bb0fe9a487ae9418')
+ '1169ccda88642881e0ba024f0c82fce9ac3064d3587517f9960e88cae479ce3e'
+ 'dfed11d97f1d4198a3dc608be159b6b53a11054f376cdb73bb0fe9a487ae9418'
+ '4979e733215492372c196cdb93ec61eac1fbbd44f44e637dbd420040c8d9affe')
validpgpkeys=('14F26682D0916CDD81E37B6D61B7B526D98F0353') # Mozilla Software Releases <release@mozilla.com>
validpgpkeys+=('BFA8008A8265677063B11BF47171986E4B745536') # Andreas Grapentin
@@ -92,10 +92,6 @@ prepare() {
msg "applying 0001-Use-remoting-name-for-GDK-application-names.patch"
patch -Np1 -i ../0001-Use-remoting-name-for-GDK-application-names.patch
- # https://bugzilla.mozilla.org/show_bug.cgi?id=1212502
- msg "applying firefox-70.0-add-distro.patch"
- patch -Np1 -i ../firefox-70.0-add-distro.patch
-
cat >../mozconfig <<END
ac_add_options --enable-application=browser
@@ -239,6 +235,10 @@ build() {
CFLAGS="${CFLAGS/-fno-plt/}"
CXXFLAGS="${CXXFLAGS/-fno-plt/}"
+ # DEBUG: clang-9: error: unknown argument: '-fvar-tracking-assignments'
+ CFLAGS="${CFLAGS/-fvar-tracking-assignments/}"
+ CXXFLAGS="${CXXFLAGS/-fvar-tracking-assignments/}"
+
# Do 3-tier PGO
msg2 "Building instrumented browser..."
cat >.mozconfig ../mozconfig - <<END
@@ -304,320 +304,9 @@ pref("extensions.shownSelectionUI", true);
END
# Parabola additions to vendor.js
- #
- # TODO: Go through this and figure out what's nescessary, remove
- # most of it. This is mostly cargo-cult BS. For example, disabling
- # all the EME stuff... that's already off because of `--disable-eme`
- # in `.mozconfig`. Some of these settings no longer exist. Some of
- # these settings don't do anything on GNU/Linux.
- #
- # However, they don't seem to be causing any of the critical issues.
local _shortver=$(cut -d. -f1,2 <<<"$pkgver")
- cat >> "$vendorjs" <<END
-// Disable "alt" as a shortcut key to open full menu bar. Conflicts with "alt" as a modifier
-pref("ui.key.menuAccessKeyFocuses", false);
-
-// Disable the GeoLocation API for content
-pref("geo.enabled", false);
-
-// Make sure that the request URL of the GeoLocation backend is empty
-pref("geo.wifi.uri", "");
-
-// Google Widevine DRM
-// https://blog.mozilla.org/futurereleases/2016/04/08/mozilla-to-test-widevine-cdm-in-firefox-nightly/
-// https://wiki.mozilla.org/QA/Widevine_CDM
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1288580
-pref("media.gmp-widevinecdm.visible", false);
-pref("media.gmp-widevinecdm.enabled", false);
-pref("media.gmp-widevinecdm.autoupdate", false);
-
-// Default sites for about:newtab
-pref("browser.newtabpage.activity-stream.default.sites", "https://wiki.parabola.nu/,https://labs.parabola.nu/,https://www.gnu.org/,https://libreplanet.org/,https://www.wikipedia.org/");
-
-// Poodle attack
-pref("security.tls.version.min", 1);
-
-// Don't call home for blacklisting
-pref("extensions.blocklist.enabled", false);
-
-// Disable plugin installer
-pref("plugins.hide_infobar_for_missing_plugin", true);
-pref("plugins.hide_infobar_for_outdated_plugin", true);
-pref("plugins.notifyMissingFlash", false);
-
-//https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
-//pref("media.mediasource.enabled",true);
-
-// Speeding it up
-pref("network.http.pipelining", true);
-pref("network.http.proxy.pipelining", true);
-pref("network.http.pipelining.maxrequests", 10);
-pref("nglayout.initialpaint.delay", 0);
-
-// Disable third party cookies
-pref("network.cookie.cookieBehavior", 1);
-
-// Prevent EULA dialog to popup on first run
-pref("browser.EULA.override", true);
-
-// Set useragent to Firefox compatible
-//pref("general.useragent.compatMode.firefox", true);
-// Spoof the useragent to a generic one
-pref("general.useragent.compatMode.firefox", true);
-// Spoof the useragent to a generic one
-pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:$_shortver) Gecko/20100101 Firefox/$_shortver");
-pref("general.appname.override", "Netscape");
-pref("general.appversion.override", "$_shortver");
-pref("general.buildID.override", "Gecko/20100101");
-pref("general.oscpu.override", "Windows NT 6.1");
-pref("general.platform.override", "Win32");
-
-// Privacy & Freedom Issues
-// https://webdevelopmentaid.wordpress.com/2013/10/21/customize-privacy-settings-in-mozilla-firefox-part-1-aboutconfig/
-// https://panopticlick.eff.org
-// http://ip-check.info
-// http://browserspy.dk
-// https://wiki.mozilla.org/Fingerprinting
-// http://www.browserleaks.com
-// http://fingerprint.pet-portal.eu
-pref("privacy.donottrackheader.enabled", true);
-pref("privacy.donottrackheader.value", 1);
-pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
-
-// CIS 2.1.1 Disable Auto Update / Balrog
-pref("app.update.auto", false);
-pref("app.update.checkInstallTime", false);
-pref("app.update.enabled", false);
-pref("app.update.staging.enabled", false);
-pref("app.update.url", "about:blank");
-pref("media.gmp-manager.certs.1.commonName", "");
-pref("media.gmp-manager.certs.2.commonName", "");
-// Disable Gecko media plugins: https://wiki.mozilla.org/GeckoMediaPlugins
-pref("media.gmp-manager.url", "http://127.0.0.1/");
-pref("media.gmp-manager.url.override", "data:text/plain,");
-pref("media.gmp-provider.enabled", false);
-// Don't install openh264 codec
-pref("media.gmp-gmpopenh264.enabled", false);
-pref("media.gmp-eme-adobe.enabled", false);
-pref("media.peerconnection.video.h264_enabled", false);
-
-// CIS 2.3.4 Block Reported Web Forgeries
-// http://kb.mozillazine.org/Browser.safebrowsing.enabled
-// http://kb.mozillazine.org/Safe_browsing
-// https://support.mozilla.org/en-US/kb/how-does-phishing-and-malware-protection-work
-// http://forums.mozillazine.org/viewtopic.php?f=39&t=2711237&p=12896849#p12896849
-pref("browser.safebrowsing.enabled", false);
-
-// CIS 2.3.5 Block Reported Attack Sites
-// http://kb.mozillazine.org/Browser.safebrowsing.malware.enabled
-pref("browser.safebrowsing.malware.enabled", false);
-
-// Disable safe browsing remote lookups for downloaded files.
-// This leaks information to google.
-// https://www.mozilla.org/en-US/firefox/39.0/releasenotes/
-// https://wiki.mozilla.org/Security/Application_Reputation
-pref("browser.safebrowsing.downloads.remote.enabled", false);
-pref("browser.safebrowsing.appRepURL", "about:blank");
-pref("browser.safebrowsing.provider.mozilla.gethashURL", "about:blank");
-pref("browser.safebrowsing.provider.mozilla.updateURL", "about:blank");
-pref("browser.safebrowsing.downloads.remote.block_dangerous", false);
-pref("browser.safebrowsing.downloads.remote.block_dangerous_host", false);
-pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
-pref("browser.safebrowsing.downloads.remote.block_uncommon", false);
-pref("browser.safebrowsing.downloads.remote.enabled", false);
-pref("browser.safebrowsing.downloads.remote.url", "about:blank");
-pref("browser.safebrowsing.provider.google.gethashURL", "about:blank");
-pref("browser.safebrowsing.provider.google.updateURL", "about:blank");
-pref("browser.safebrowsing.provider.google.lists", "about:blank");
-
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1025965
-pref("browser.safebrowsing.phishing.enabled", false);
-pref("browser.safebrowsing.provider.google4.lists", "about:blank");
-pref("browser.safebrowsing.provider.google4.updateURL", "about:blank");
-pref("browser.safebrowsing.provider.google4.gethashURL", "about:blank");
-pref("browser.safebrowsing.provider.google4.reportURL", "about:blank");
-pref("browser.safebrowsing.provider.mozilla.lists", "about:blank");
-
-// Disable Microsoft Family Safety MiTM support
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1239166
-// https://wiki.mozilla.org/SecurityEngineering/Untrusted_Certificates_in_Windows_Child_Mode
-// https://hg.mozilla.org/releases/mozilla-release/file/ddb37c386bb2ffa180117b4d30ca3b41a8af233c/security/manager/ssl/nsNSSComponent.cpp#l782
-pref("security.family_safety.mode", 0);
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1265113
-// https://hg.mozilla.org/releases/mozilla-release/rev/d9659c22b3c5
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1298883
-pref("security.enterprise_roots.enabled", false);
-
-//pref("services.sync.privacyURL", "https://www.gnu.org/software/gnuzilla/");
-pref("social.enabled", false);
-pref("social.remote-install.enabled", false);
-pref("datareporting.healthreport.uploadEnabled", false);
-pref("datareporting.healthreport.about.reportUrl", "127.0.0.1");
-pref("datareporting.healthreport.documentServerURI", "127.0.0.1");
-pref("healthreport.uploadEnabled", false);
-pref("social.toast-notifications.enabled", false);
-pref("datareporting.policy.dataSubmissionEnabled", false);
-pref("datareporting.healthreport.service.enabled", false);
-pref("browser.slowStartup.notificationDisabled", true);
-pref("network.http.sendRefererHeader", 2);
-//pref("network.http.referer.spoofSource", true);
-//http://grack.com/blog/2010/01/06/3rd-party-cookies-dom-storage-and-privacy/
-//pref("dom.storage.enabled", false);
-pref("dom.event.clipboardevents.enabled",false);
-pref("network.prefetch-next", false);
-pref("network.dns.disablePrefetch", true);
-pref("network.http.sendSecureXSiteReferrer", false);
-pref("toolkit.telemetry.archive.enabled", false);
-pref("toolkit.telemetry.bhrPing.enabled", false);
-pref("toolkit.telemetry.enabled", false);
-pref("toolkit.telemetry.unified", false);
-pref("toolkit.telemetry.newProfilePing.enabled", false);
-pref("toolkit.telemetry.firstShutdownPing.enabled", false);
-pref("toolkit.telemetry.server", "127.0.0.1");
-pref("app.shield.optoutstudies.enabled", false);
-pref("experiments.enabled", false);
-pref("experiments.manifest.uri", "127.0.0.1");
-pref("extensions.pocket.enabled", false);
-pref("extensions.pocket.api", "127.0.0.1");
-// Do not tell what plugins do we have enabled: https://mail.mozilla.org/pipermail/firefox-dev/2013-November/001186.html
-pref("plugins.enumerable_names", "");
-pref("plugin.state.flash", 0);
-// Do not autoupdate search engines
-pref("browser.search.update", false);
-// Warn when the page tries to redirect or refresh
-//pref("accessibility.blockautorefresh", true);
-pref("dom.battery.enabled", false);
-pref("device.sensors.enabled", false);
-pref("camera.control.face_detection.enabled", false);
-pref("camera.control.autofocus_moving_callback.enabled", false);
-pref("network.http.speculative-parallel-limit", 0);
-// No search suggestions
-pref("browser.urlbar.userMadeSearchSuggestionsChoice", true);
-pref("browser.search.suggest.enabled", false);
-
-// Crypto hardening
-// https://gist.github.com/haasn/69e19fc2fe0e25f3cff5
-// General settings
-//pref("security.tls.unrestricted_rc4_fallback", false);
-//pref("security.tls.insecure_fallback_hosts.use_static_list", false);
-//pref("security.tls.version.min", 1);
-//pref("security.ssl.require_safe_negotiation", true);
-//pref("security.ssl.treat_unsafe_negotiation_as_broken", true);
-//pref("security.ssl3.rsa_seed_sha", true);
-//pref("security.OCSP.enabled", 1);
-//pref("security.OCSP.require", true);
-
-
-// WebRTC
-pref("media.peerconnection.enabled", false);
-pref("media.peerconnection.ice.default_address_only", true);
-
-pref("font.default.x-western", "sans-serif");
-
-// Preferences for the Get Add-ons panel and search engines
-pref("extensions.webservice.discoverURL", "https://directory.fsf.org/wiki/GNU_IceCat");
-pref("extensions.getAddons.search.url", "https://directory.fsf.org/wiki/GNU_IceCat");
-pref("browser.search.searchEnginesURL", "https://directory.fsf.org/wiki/GNU_IceCat");
-
-// Mobile
-pref("privacy.announcements.enabled", false);
-pref("browser.snippets.enabled", false);
-pref("browser.snippets.syncPromo.enabled", false);
-pref("identity.mobilepromo.android", "https://f-droid.org/repository/browse/?fdid=org.gnu.icecat&");
-pref("browser.snippets.geoUrl", "http://127.0.0.1/");
-pref("browser.snippets.updateUrl", "http://127.0.0.1/");
-pref("browser.snippets.statsUrl", "http://127.0.0.1/");
-pref("datareporting.policy.firstRunTime", 0);
-pref("datareporting.policy.dataSubmissionPolicyVersion", 2);
-pref("browser.webapps.checkForUpdates", 0);
-pref("browser.webapps.updateCheckUrl", "http://127.0.0.1/");
-pref("app.faqURL", "http://libreplanet.org/wiki/Group:IceCat/FAQ");
-
-// PFS url
-pref("pfs.datasource.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
-pref("pfs.filehint.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
-
-// Geolocation depends on third party services
-pref("geo.enabled", false);
-pref("geo.wifi.uri", "");
-
-// Disable heartbeat
-pref("browser.selfsupport.url", "");
-
-// Disable Link to FireFox Marketplace, currently loaded with non-free "apps"
-pref("browser.apps.URL", "");
-
-// Use old style preferences, that allow javascript to be disabled
-pref("browser.preferences.inContent",false);
-
-// Don't download ads for the newtab page
-pref("browser.newtabpage.directory.source", "");
-pref("browser.newtabpage.directory.ping", "");
-pref("browser.newtabpage.introShown", true);
-
-// Disable home snippets
-pref("browser.aboutHomeSnippets.updateUrl", "data:text/html");
-
-// Disable hardware acceleration and WebGL
-//pref("layers.acceleration.disabled", false);
-pref("webgl.disabled", false);
-
-// Disable SSDP
-pref("browser.casting.enabled", false);
-
-// Disable directory service
-pref("social.directories", "");
-pref("social.whitelist", "");
-pref("social.shareDirectory", "");
-
-// Disable Pocket integration
-pref("browser.pocket.api", "about:blank");
-pref("browser.pocket.enabled", false);
-pref("browser.pocket.enabledLocales", "about:blank");
-pref("browser.pocket.oAuthConsumerKey", "about:blank");
-pref("browser.pocket.site", "about:blank");
-pref("browser.pocket.useLocaleList", false);
-pref("extensions.pocket.enabled", false);
-
-// Do not require xpi extensions to be signed by Mozilla
-pref("xpinstall.signatures.required", false);
-
-// Disable File and Directory Entries API (Imported from Edge/Chromium)
-// https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories
-// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API
-// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Introduction
-// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Firefox_support
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1265767
-pref("dom.webkitBlink.filesystem.enabled", false);
-// https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1258489
-// https://hg.mozilla.org/releases/mozilla-release/rev/133af19777be
-pref("dom.webkitBlink.dirPicker.enabled", false);
-
-// Directory Upload API, webkitdirectory
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1188880
-// https://bugzilla.mozilla.org/show_bug.cgi?id=907707
-// https://wicg.github.io/directory-upload/proposal.html
-pref("dom.input.dirpicker", false);
-
-// fix alsa sound sandbox issue for iceweasel-58
-// https://labs.parabola.nu/issues/1628
-pref("security.sandbox.content.syscall_whitelist", "16");
-
-// Disable recommendations of extensions and themes on about:addons page
-// https://labs.parabola.nu/issues/2409
-pref("extensions.htmlaboutaddons.discover.enabled", false);
-pref("extensions.htmlaboutaddons.recommendations.enabled", false);
-
-// Disable "Recommend extensions as you browse" in about:preferences#general
-pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false);
-
-// URL for 'Find more extensions / themes' in about:addons page
-pref("extensions.getAddons.search.browseURL", "https://www.parabola.nu/packages/?q=%TERMS%");
-
-// Make extensions work on Mozilla domains
-pref("extensions.webextensions.restrictedDomains", "");
-END
+ cat "${srcdir}"/vendor.js.in >> "$vendorjs"
+ sed -i "s|@_SHORTVER_@|$_shortver|g" "$vendorjs"
local distini="$pkgdir/usr/lib/$pkgname/distribution/distribution.ini"
install -Dvm644 /dev/stdin "$distini" <<END
diff --git a/libre/iceweasel/firefox-70.0-add-distro.patch b/libre/iceweasel/firefox-70.0-add-distro.patch
deleted file mode 100644
index 8db8ce5dc..000000000
--- a/libre/iceweasel/firefox-70.0-add-distro.patch
+++ /dev/null
@@ -1,6965 +0,0 @@
-
-# HG changeset patch
-# User Edwin Takahashi <egao@mozilla.com>
-# Date 1572468170 0
-# Node ID d2d9fe01fc33af4538940e833a6696d973ebea74
-# Parent eddb9fcaaa4bd4fdb4e32024f92f969abfe92f58
-Bug 1212502 - Switch mozinfo to using the 'distro' package to get linux distribution info r=ahal,KWierso
-
-Differential Revision: https://phabricator.services.mozilla.com/D49366
-
-diff --git a/build/virtualenv_packages.txt b/build/virtualenv_packages.txt
---- a/build/virtualenv_packages.txt
-+++ b/build/virtualenv_packages.txt
-@@ -10,16 +10,17 @@ mozilla.pth:third_party/python/atomicwri
- mozilla.pth:third_party/python/attrs/src
- python2:mozilla.pth:third_party/python/backports
- mozilla.pth:third_party/python/biplist
- mozilla.pth:third_party/python/blessings
- mozilla.pth:third_party/python/Click
- mozilla.pth:third_party/python/compare-locales
- mozilla.pth:third_party/python/configobj
- mozilla.pth:third_party/python/cram
-+mozilla.pth:third_party/python/distro
- mozilla.pth:third_party/python/dlmanager
- mozilla.pth:third_party/python/enum34
- mozilla.pth:third_party/python/fluent
- mozilla.pth:third_party/python/funcsigs
- python2:mozilla.pth:third_party/python/futures
- mozilla.pth:third_party/python/mohawk
- mozilla.pth:third_party/python/more-itertools
- mozilla.pth:third_party/python/mozilla-version
-diff --git a/python/mozbuild/mozbuild/action/test_archive.py b/python/mozbuild/mozbuild/action/test_archive.py
---- a/python/mozbuild/mozbuild/action/test_archive.py
-+++ b/python/mozbuild/mozbuild/action/test_archive.py
-@@ -245,16 +245,22 @@ ARCHIVE_FILES = {
- },
- {
- 'source': buildconfig.topsrcdir,
- 'base': 'third_party/python/six',
- 'pattern': '**',
- 'dest': 'tools/six',
- },
- {
-+ 'source': buildconfig.topsrcdir,
-+ 'base': 'third_party/python/distro',
-+ 'pattern': '**',
-+ 'dest': 'tools/distro',
-+ },
-+ {
- 'source': buildconfig.topobjdir,
- 'base': '',
- 'pattern': 'mozinfo.json',
- },
- {
- 'source': buildconfig.topobjdir,
- 'base': 'dist/bin',
- 'patterns': [
-@@ -431,16 +437,22 @@ ARCHIVE_FILES = {
- 'dest': 'mozharness',
- },
- {
- 'source': buildconfig.topsrcdir,
- 'base': 'third_party/python/six',
- 'pattern': 'six.py',
- 'dest': 'mozharness',
- },
-+ {
-+ 'source': buildconfig.topsrcdir,
-+ 'base': 'third_party/python/distro',
-+ 'pattern': 'distro.py',
-+ 'dest': 'mozharness',
-+ },
- ],
- 'reftest': [
- {
- 'source': buildconfig.topobjdir,
- 'base': '_tests',
- 'pattern': 'reftest/**',
- },
- {
-diff --git a/testing/mozbase/mozinfo/mozinfo/mozinfo.py b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
---- a/testing/mozbase/mozinfo/mozinfo/mozinfo.py
-+++ b/testing/mozbase/mozinfo/mozinfo/mozinfo.py
-@@ -9,16 +9,17 @@
- # information and having behaviour depend on it
-
- from __future__ import absolute_import, print_function
-
- import os
- import platform
- import re
- import sys
-+
- from .string_version import StringVersion
- from ctypes.util import find_library
-
- # keep a copy of the os module since updating globals overrides this
- _os = os
-
-
- class unknown(object):
-@@ -93,35 +94,45 @@ if system in ["Microsoft", "Windows"]:
- version = "%d.%d.%d" % (major, minor, build_number)
-
- os_version = "%d.%d" % (major, minor)
- elif system.startswith(('MINGW', 'MSYS_NT')):
- # windows/mingw python build (msys)
- info['os'] = 'win'
- os_version = version = unknown
- elif system == "Linux":
-- if hasattr(platform, "linux_distribution"):
-- (distro, os_version, codename) = platform.linux_distribution()
-+ # Only attempt to import distro for Linux.
-+ # https://github.com/nir0s/distro/issues/177
-+ try:
-+ import distro
-+ except ImportError:
-+ pass
-+ # First use distro package, then fall back to platform.
-+ # This will only until Mozilla upgrades python to 3.8.
-+ if hasattr(distro, "linux_distribution"):
-+ (distribution, os_version, codename) = distro.linux_distribution()
-+ elif hasattr(platform, "linux_distribution"):
-+ (distribution, os_version, codename) = platform.linux_distribution()
- else:
-- (distro, os_version, codename) = platform.dist()
-+ (distribution, os_version, codename) = platform.dist()
- if not processor:
- processor = machine
-- version = "%s %s" % (distro, os_version)
-+ version = "%s %s" % (distribution, os_version)
-
- # Bug in Python 2's `platform` library:
- # It will return a triple of empty strings if the distribution is not supported.
- # It works on Python 3. If we don't have an OS version,
- # the unit tests fail to run.
-- if not distro and not os_version and not codename:
-- distro = 'lfs'
-+ if not distribution and not os_version and not codename:
-+ distribution = 'lfs'
- version = release
- os_version = release
-
- info['os'] = 'linux'
-- info['linux_distro'] = distro
-+ info['linux_distro'] = distribution
- elif system in ['DragonFly', 'FreeBSD', 'NetBSD', 'OpenBSD']:
- info['os'] = 'bsd'
- version = os_version = sys.platform
- elif system == "Darwin":
- (release, versioninfo, machine) = platform.mac_ver()
- version = "OS X %s" % release
- versionNums = release.split('.')[:2]
- os_version = "%s.%s" % (versionNums[0], versionNums[1])
-diff --git a/testing/mozbase/mozinfo/setup.py b/testing/mozbase/mozinfo/setup.py
---- a/testing/mozbase/mozinfo/setup.py
-+++ b/testing/mozbase/mozinfo/setup.py
-@@ -4,17 +4,20 @@
-
- from __future__ import absolute_import
-
- from setuptools import setup
-
- PACKAGE_VERSION = "1.1.0"
-
- # dependencies
--deps = ["mozfile >= 0.12"]
-+deps = [
-+ "distro == 1.4.0",
-+ "mozfile >= 0.12",
-+]
-
- setup(
- name="mozinfo",
- version=PACKAGE_VERSION,
- description="Library to get system information for use in Mozilla testing",
- long_description="see https://firefox-source-docs.mozilla.org/mozbase/index.html",
- classifiers=[
- "Programming Language :: Python :: 2.7",
-diff --git a/testing/mozharness/tox.ini b/testing/mozharness/tox.ini
---- a/testing/mozharness/tox.ini
-+++ b/testing/mozharness/tox.ini
-@@ -1,14 +1,15 @@
- [tox]
- envlist = py27-hg4.3
-
- [base]
- deps =
- coverage
-+ distro
- nose
- rednose
- {toxinidir}/../mozbase/mozlog
- mozbase = {toxinidir}/../mozbase/
-
-
- [testenv]
- basepython = python2.7
-diff --git a/third_party/python/distro/CHANGELOG.md b/third_party/python/distro/CHANGELOG.md
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/CHANGELOG.md
-@@ -0,0 +1,147 @@
-+## 1.4.0 (2019.2.4)
-+
-+BACKWARD COMPATIBILITY:
-+* Prefer the VERSION_CODENAME field of os-release to parsing it from VERSION [[#230](https://github.com/nir0s/distro/pull/230)]
-+
-+BUG FIXES:
-+* Return _uname_info from the uname_info() method [[#233](https://github.com/nir0s/distro/pull/233)]
-+* Fixed CloudLinux id discovery [[#234](https://github.com/nir0s/distro/pull/234)]
-+* Update Oracle matching [[#224](https://github.com/nir0s/distro/pull/224)]
-+
-+DOCS:
-+* Update Fedora package link [[#225](https://github.com/nir0s/distro/pull/225)]
-+* Distro is the recommended replacement for platform.linux_distribution [[#220](https://github.com/nir0s/distro/pull/220)]
-+
-+RELEASE:
-+* Use Markdown for long description in setup.py [[#219](https://github.com/nir0s/distro/pull/219)]
-+
-+Additionally, The Python2.6 branch was fixed and rebased on top of master. It is now passing all tests. Thanks [abadger](https://github.com/abadger)!
-+
-+## 1.3.0 (2018.05.09)
-+
-+ENHANCEMENTS:
-+* Added support for OpenBSD, FreeBSD, and NetBSD [[#207](https://github.com/nir0s/distro/issues/207)]
-+
-+TESTS:
-+* Add test for Kali Linux Rolling [[#214](https://github.com/nir0s/distro/issues/214)]
-+
-+DOCS:
-+* Update docs with regards to #207 [[#209](https://github.com/nir0s/distro/issues/209)]
-+* Add Ansible reference implementation and fix arch-linux link [[#213](https://github.com/nir0s/distro/issues/213)]
-+* Add facter reference implementation [[#213](https://github.com/nir0s/distro/issues/213)]
-+
-+## 1.2.0 (2017.12.24)
-+
-+BACKWARD COMPATIBILITY:
-+* Don't raise ImportError on non-linux platforms [[#202](https://github.com/nir0s/distro/issues/202)]
-+
-+ENHANCEMENTS:
-+* Lazily load the LinuxDistribution data [[#201](https://github.com/nir0s/distro/issues/201)]
-+
-+BUG FIXES:
-+* Stdout of shell should be decoded with sys.getfilesystemencoding() [[#203](https://github.com/nir0s/distro/issues/203)]
-+
-+TESTS:
-+* Explicitly set Python versions on Travis for flake [[#204](https://github.com/nir0s/distro/issues/204)]
-+
-+
-+## 1.1.0 (2017.11.28)
-+
-+BACKWARD COMPATIBILITY:
-+* Drop python3.3 support [[#199](https://github.com/nir0s/distro/issues/199)]
-+* Remove Official Python26 support [[#195](https://github.com/nir0s/distro/issues/195)]
-+
-+TESTS:
-+* Add MandrivaLinux test case [[#181](https://github.com/nir0s/distro/issues/181)]
-+* Add test cases for CloudLinux 5, 6, and 7 [[#180](https://github.com/nir0s/distro/issues/180)]
-+
-+RELEASE:
-+* Modify MANIFEST to include resources for tests and docs in source tarballs [[97c91a1](97c91a1)]
-+
-+## 1.0.4 (2017.04.01)
-+
-+BUG FIXES:
-+* Guess common *-release files if /etc not readable [[#175](https://github.com/nir0s/distro/issues/175)]
-+
-+## 1.0.3 (2017.03.19)
-+
-+ENHANCEMENTS:
-+* Show keys for empty values when running distro from the CLI [[#160](https://github.com/nir0s/distro/issues/160)]
-+* Add manual mapping for `redhatenterpriseserver` (previously only redhatenterpriseworkstation was mapped) [[#148](https://github.com/nir0s/distro/issues/148)]
-+* Race condition in `_parse_distro_release_file` [[#163](https://github.com/nir0s/distro/issues/163)]
-+
-+TESTS:
-+* Add RHEL5 test case [[#165](https://github.com/nir0s/distro/issues/165)]
-+* Add OpenELEC test case [[#166](https://github.com/nir0s/distro/issues/166)]
-+* Replace nose with pytest [[#158](https://github.com/nir0s/distro/issues/158)]
-+
-+RELEASE:
-+* Update classifiers
-+* Update supported Python versions (with py36)
-+
-+## 1.0.2 (2017.01.12)
-+
-+TESTS:
-+* Test on py33, py36 and py3 based flake8
-+
-+RELEASE:
-+* Add MANIFEST file (which also includes the LICENSE as part of Issue [[#139](https://github.com/nir0s/distro/issues/139)])
-+* Default to releasing using Twine [[#121](https://github.com/nir0s/distro/issues/121)]
-+* Add setup.cfg file [[#145](https://github.com/nir0s/distro/issues/145)]
-+* Update license in setup.py
-+
-+## 1.0.1 (2016-11-03)
-+
-+ENHANCEMENTS:
-+* Prettify distro -j's output and add more elaborate docs [[#147](https://github.com/nir0s/distro/issues/147)]
-+* Decode output of `lsb_release` as utf-8 [[#144](https://github.com/nir0s/distro/issues/144)]
-+* Logger now uses `message %s, string` form to not-evaulate log messages if unnecessary [[#145](https://github.com/nir0s/distro/issues/145)]
-+
-+TESTS:
-+* Increase code-coverage [[#146](https://github.com/nir0s/distro/issues/146)]
-+* Fix landscape code-quality warnings [[#145](https://github.com/nir0s/distro/issues/145)]
-+
-+RELEASE:
-+* Add CONTRIBUTING.md
-+
-+## 1.0.0 (2016-09-25)
-+
-+BACKWARD COMPATIBILITY:
-+* raise exception when importing on non-supported platforms [[#129](https://github.com/nir0s/distro/issues/129)]
-+
-+ENHANCEMENTS:
-+* Use `bytes` invariantly [[#135](https://github.com/nir0s/distro/issues/135)]
-+* Some minor code adjustments plus a CLI [[#134](https://github.com/nir0s/distro/issues/134)]
-+* Emit stderr if `lsb_release` fails
-+
-+BUG FIXES:
-+* Fix some encoding related issues
-+
-+TESTS:
-+* Add many test cases (e.g. Raspbian 8, CoreOS, Amazon Linux, Scientific Linux, Gentoo, Manjaro)
-+* Completely redo the testing framework to make it easier to add tests
-+* Test on pypy
-+
-+RELEASE:
-+* Remove six as a dependency
-+
-+## 0.6.0 (2016-04-21)
-+
-+This is the first release of `distro`.
-+All previous work was done on `ld` and therefore unmentioned here. See the release log in GitHub if you want the entire log.
-+
-+BACKWARD COMPATIBILITY:
-+* No longer a package. constants.py has been removed and distro is now a single module
-+
-+ENHANCEMENTS:
-+* distro.info() now receives best and pretty flags
-+* Removed get_ prefix from get_*_release_attr functions
-+* Codename is now passed in distro.info()
-+
-+TESTS:
-+* Added Linux Mint test case
-+* Now testing on Python 3.4
-+
-+DOCS:
-+* Documentation fixes
-+
-diff --git a/third_party/python/distro/CONTRIBUTING.md b/third_party/python/distro/CONTRIBUTING.md
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/CONTRIBUTING.md
-@@ -0,0 +1,54 @@
-+# General
-+
-+* Contributing to distro identification currently doesn't have any specific standards and rather depends on the specific implementation.
-+* A 100% coverage is expected for each PR unless explicitly authorized by the reviewer.
-+* Please try to maintain maximum code-health (via landscape.io).
-+
-+# Contributing distro specific tests
-+
-+Distro's tests are implemented via a standardized framework under `tests/test_distro.py`
-+
-+For each distribution, tests should be added in the relevant class according to which distribution file(s) exists on it, so, for example, tests should be added under `TestOSRelease` where `/etc/os-release` is available.
-+
-+The tests must be self-contained, meaning that the release files for the distribution should be maintained in the repository under `tests/resources/distros/distribution_name+distribution_version`.
-+
-+A tests method would like somewhat like this:
-+
-+```python
-+def test_centos7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS Linux',
-+ 'pretty_name': 'CentOS Linux 7 (Core)',
-+ 'version': '7',
-+ 'pretty_version': '7 (Core)',
-+ 'best_version': '7',
-+ 'like': 'rhel fedora',
-+ 'codename': 'Core'
-+ }
-+ self._test_outcome(desired_outcome)
-+```
-+
-+The framework will automatically try to pick up the relevant file according to the method's name (`centos7` meaning the folder should be named `centos7` as well) and compare the `desired_outcome` with the parsed files found under the test dir.
-+
-+The exception to the rule is under the `TestDistroRelease` test class which should look somewhat like this:
-+
-+```python
-+def test_centos5_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS',
-+ 'pretty_name': 'CentOS 5.11 (Final)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Final)',
-+ 'best_version': '5.11',
-+ 'codename': 'Final',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome, 'centos', '5')
-+```
-+
-+Where the name of the method is not indicative of the lookup folder but rather tha two last arguments in `_test_outcome`.
-+
-+A test case is mandatory under `TestOverall` for a PR to be complete.
-\ No newline at end of file
-diff --git a/third_party/python/distro/CONTRIBUTORS.md b/third_party/python/distro/CONTRIBUTORS.md
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/CONTRIBUTORS.md
-@@ -0,0 +1,13 @@
-+Thanks!
-+
-+* https://github.com/andy-maier
-+* https://github.com/SethMichaelLarson
-+* https://github.com/asottile
-+* https://github.com/MartijnBraam
-+* https://github.com/funkyfuture
-+* https://github.com/adamjstewart
-+* https://github.com/xavfernandez
-+* https://github.com/xsuchy
-+* https://github.com/marcoceppi
-+* https://github.com/tgamblin
-+* https://github.com/sebix
-diff --git a/third_party/python/distro/LICENSE b/third_party/python/distro/LICENSE
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/LICENSE
-@@ -0,0 +1,202 @@
-+Apache License
-+ Version 2.0, January 2004
-+ http://www.apache.org/licenses/
-+
-+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-+
-+ 1. Definitions.
-+
-+ "License" shall mean the terms and conditions for use, reproduction,
-+ and distribution as defined by Sections 1 through 9 of this document.
-+
-+ "Licensor" shall mean the copyright owner or entity authorized by
-+ the copyright owner that is granting the License.
-+
-+ "Legal Entity" shall mean the union of the acting entity and all
-+ other entities that control, are controlled by, or are under common
-+ control with that entity. For the purposes of this definition,
-+ "control" means (i) the power, direct or indirect, to cause the
-+ direction or management of such entity, whether by contract or
-+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
-+ outstanding shares, or (iii) beneficial ownership of such entity.
-+
-+ "You" (or "Your") shall mean an individual or Legal Entity
-+ exercising permissions granted by this License.
-+
-+ "Source" form shall mean the preferred form for making modifications,
-+ including but not limited to software source code, documentation
-+ source, and configuration files.
-+
-+ "Object" form shall mean any form resulting from mechanical
-+ transformation or translation of a Source form, including but
-+ not limited to compiled object code, generated documentation,
-+ and conversions to other media types.
-+
-+ "Work" shall mean the work of authorship, whether in Source or
-+ Object form, made available under the License, as indicated by a
-+ copyright notice that is included in or attached to the work
-+ (an example is provided in the Appendix below).
-+
-+ "Derivative Works" shall mean any work, whether in Source or Object
-+ form, that is based on (or derived from) the Work and for which the
-+ editorial revisions, annotations, elaborations, or other modifications
-+ represent, as a whole, an original work of authorship. For the purposes
-+ of this License, Derivative Works shall not include works that remain
-+ separable from, or merely link (or bind by name) to the interfaces of,
-+ the Work and Derivative Works thereof.
-+
-+ "Contribution" shall mean any work of authorship, including
-+ the original version of the Work and any modifications or additions
-+ to that Work or Derivative Works thereof, that is intentionally
-+ submitted to Licensor for inclusion in the Work by the copyright owner
-+ or by an individual or Legal Entity authorized to submit on behalf of
-+ the copyright owner. For the purposes of this definition, "submitted"
-+ means any form of electronic, verbal, or written communication sent
-+ to the Licensor or its representatives, including but not limited to
-+ communication on electronic mailing lists, source code control systems,
-+ and issue tracking systems that are managed by, or on behalf of, the
-+ Licensor for the purpose of discussing and improving the Work, but
-+ excluding communication that is conspicuously marked or otherwise
-+ designated in writing by the copyright owner as "Not a Contribution."
-+
-+ "Contributor" shall mean Licensor and any individual or Legal Entity
-+ on behalf of whom a Contribution has been received by Licensor and
-+ subsequently incorporated within the Work.
-+
-+ 2. Grant of Copyright License. Subject to the terms and conditions of
-+ this License, each Contributor hereby grants to You a perpetual,
-+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-+ copyright license to reproduce, prepare Derivative Works of,
-+ publicly display, publicly perform, sublicense, and distribute the
-+ Work and such Derivative Works in Source or Object form.
-+
-+ 3. Grant of Patent License. Subject to the terms and conditions of
-+ this License, each Contributor hereby grants to You a perpetual,
-+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
-+ (except as stated in this section) patent license to make, have made,
-+ use, offer to sell, sell, import, and otherwise transfer the Work,
-+ where such license applies only to those patent claims licensable
-+ by such Contributor that are necessarily infringed by their
-+ Contribution(s) alone or by combination of their Contribution(s)
-+ with the Work to which such Contribution(s) was submitted. If You
-+ institute patent litigation against any entity (including a
-+ cross-claim or counterclaim in a lawsuit) alleging that the Work
-+ or a Contribution incorporated within the Work constitutes direct
-+ or contributory patent infringement, then any patent licenses
-+ granted to You under this License for that Work shall terminate
-+ as of the date such litigation is filed.
-+
-+ 4. Redistribution. You may reproduce and distribute copies of the
-+ Work or Derivative Works thereof in any medium, with or without
-+ modifications, and in Source or Object form, provided that You
-+ meet the following conditions:
-+
-+ (a) You must give any other recipients of the Work or
-+ Derivative Works a copy of this License; and
-+
-+ (b) You must cause any modified files to carry prominent notices
-+ stating that You changed the files; and
-+
-+ (c) You must retain, in the Source form of any Derivative Works
-+ that You distribute, all copyright, patent, trademark, and
-+ attribution notices from the Source form of the Work,
-+ excluding those notices that do not pertain to any part of
-+ the Derivative Works; and
-+
-+ (d) If the Work includes a "NOTICE" text file as part of its
-+ distribution, then any Derivative Works that You distribute must
-+ include a readable copy of the attribution notices contained
-+ within such NOTICE file, excluding those notices that do not
-+ pertain to any part of the Derivative Works, in at least one
-+ of the following places: within a NOTICE text file distributed
-+ as part of the Derivative Works; within the Source form or
-+ documentation, if provided along with the Derivative Works; or,
-+ within a display generated by the Derivative Works, if and
-+ wherever such third-party notices normally appear. The contents
-+ of the NOTICE file are for informational purposes only and
-+ do not modify the License. You may add Your own attribution
-+ notices within Derivative Works that You distribute, alongside
-+ or as an addendum to the NOTICE text from the Work, provided
-+ that such additional attribution notices cannot be construed
-+ as modifying the License.
-+
-+ You may add Your own copyright statement to Your modifications and
-+ may provide additional or different license terms and conditions
-+ for use, reproduction, or distribution of Your modifications, or
-+ for any such Derivative Works as a whole, provided Your use,
-+ reproduction, and distribution of the Work otherwise complies with
-+ the conditions stated in this License.
-+
-+ 5. Submission of Contributions. Unless You explicitly state otherwise,
-+ any Contribution intentionally submitted for inclusion in the Work
-+ by You to the Licensor shall be under the terms and conditions of
-+ this License, without any additional terms or conditions.
-+ Notwithstanding the above, nothing herein shall supersede or modify
-+ the terms of any separate license agreement you may have executed
-+ with Licensor regarding such Contributions.
-+
-+ 6. Trademarks. This License does not grant permission to use the trade
-+ names, trademarks, service marks, or product names of the Licensor,
-+ except as required for reasonable and customary use in describing the
-+ origin of the Work and reproducing the content of the NOTICE file.
-+
-+ 7. Disclaimer of Warranty. Unless required by applicable law or
-+ agreed to in writing, Licensor provides the Work (and each
-+ Contributor provides its Contributions) on an "AS IS" BASIS,
-+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
-+ implied, including, without limitation, any warranties or conditions
-+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
-+ PARTICULAR PURPOSE. You are solely responsible for determining the
-+ appropriateness of using or redistributing the Work and assume any
-+ risks associated with Your exercise of permissions under this License.
-+
-+ 8. Limitation of Liability. In no event and under no legal theory,
-+ whether in tort (including negligence), contract, or otherwise,
-+ unless required by applicable law (such as deliberate and grossly
-+ negligent acts) or agreed to in writing, shall any Contributor be
-+ liable to You for damages, including any direct, indirect, special,
-+ incidental, or consequential damages of any character arising as a
-+ result of this License or out of the use or inability to use the
-+ Work (including but not limited to damages for loss of goodwill,
-+ work stoppage, computer failure or malfunction, or any and all
-+ other commercial damages or losses), even if such Contributor
-+ has been advised of the possibility of such damages.
-+
-+ 9. Accepting Warranty or Additional Liability. While redistributing
-+ the Work or Derivative Works thereof, You may choose to offer,
-+ and charge a fee for, acceptance of support, warranty, indemnity,
-+ or other liability obligations and/or rights consistent with this
-+ License. However, in accepting such obligations, You may act only
-+ on Your own behalf and on Your sole responsibility, not on behalf
-+ of any other Contributor, and only if You agree to indemnify,
-+ defend, and hold each Contributor harmless for any liability
-+ incurred by, or claims asserted against, such Contributor by reason
-+ of your accepting any such warranty or additional liability.
-+
-+ END OF TERMS AND CONDITIONS
-+
-+ APPENDIX: How to apply the Apache License to your work.
-+
-+ To apply the Apache License to your work, attach the following
-+ boilerplate notice, with the fields enclosed by brackets "{}"
-+ replaced with your own identifying information. (Don't include
-+ the brackets!) The text should be enclosed in the appropriate
-+ comment syntax for the file format. We also recommend that a
-+ file or class name and description of purpose be included on the
-+ same "printed page" as the copyright notice for easier
-+ identification within third-party archives.
-+
-+ Copyright {yyyy} {name of copyright owner}
-+
-+ Licensed under the Apache License, Version 2.0 (the "License");
-+ you may not use this file except in compliance with the License.
-+ You may obtain a copy of the License at
-+
-+ http://www.apache.org/licenses/LICENSE-2.0
-+
-+ Unless required by applicable law or agreed to in writing, software
-+ distributed under the License is distributed on an "AS IS" BASIS,
-+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+ See the License for the specific language governing permissions and
-+ limitations under the License.
-+
-diff --git a/third_party/python/distro/MANIFEST.in b/third_party/python/distro/MANIFEST.in
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/MANIFEST.in
-@@ -0,0 +1,12 @@
-+include *.md
-+include *.py
-+include *.txt
-+include LICENSE
-+include CHANGES
-+include Makefile
-+
-+graft tests
-+
-+include docs/*
-+
-+global-exclude *.py[co]
-diff --git a/third_party/python/distro/Makefile b/third_party/python/distro/Makefile
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/Makefile
-@@ -0,0 +1,145 @@
-+# Copyright 2015,2016 Nir Cohen
-+#
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+#
-+# http://www.apache.org/licenses/LICENSE-2.0
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+
-+# Name of this package
-+PACKAGENAME = distro
-+
-+# Additional options for Sphinx
-+SPHINXOPTS = -v
-+
-+# Paper format for the Sphinx LaTex/PDF builder.
-+# Valid values: a4, letter
-+SPHINXPAPER = a4
-+
-+# Sphinx build subtree.
-+SPHINXBUILDDIR = build_docs
-+
-+# Directory where conf.py is located
-+SPHINXCONFDIR = docs
-+
-+# Directory where input files for Sphinx are located
-+SPHINXSOURCEDIR = .
-+
-+# Sphinx build command (Use 'pip install sphinx' to get it)
-+SPHINXBUILD = sphinx-build
-+
-+# Internal variables for Sphinx
-+SPHINXPAPEROPT_a4 = -D latex_paper_size=a4
-+SPHINXPAPEROPT_letter = -D latex_paper_size=letter
-+ALLSPHINXOPTS = -d $(SPHINXBUILDDIR)/doctrees -c $(SPHINXCONFDIR) \
-+ $(SPHINXPAPEROPT_$(SPHINXPAPER)) $(SPHINXOPTS) \
-+ $(SPHINXSOURCEDIR)
-+
-+.PHONY: help
-+help:
-+ @echo 'Please use "make <target>" where <target> is one of'
-+ @echo " release - build a release and publish it"
-+ @echo " dev - prepare a development environment (includes tests)"
-+ @echo " instdev - prepare a development environment (no tests)"
-+ @echo " install - install into current Python environment"
-+ @echo " html - generate docs as standalone HTML files in: $(SPHINXBUILDDIR)/html"
-+ @echo " pdf - generate docs as PDF (via LaTeX) for paper format: $(SPHINXPAPER) in: $(SPHINXBUILDDIR)/pdf"
-+ @echo " man - generate docs as manual pages in: $(SPHINXBUILDDIR)/man"
-+ @echo " docchanges - generate an overview of all changed/added/deprecated items in docs"
-+ @echo " doclinkcheck - check all external links in docs for integrity"
-+ @echo " doccoverage - run coverage check of the documentation"
-+ @echo " clobber - remove any build products"
-+ @echo " build - build the package"
-+ @echo " test - test from this directory using tox, including test coverage"
-+ @echo " publish - upload to PyPI"
-+ @echo " clean - remove any temporary build products"
-+ @echo " dry-run - perform all action required for a release without actually releasing"
-+
-+.PHONY: release
-+release: test clean build publish
-+ @echo "$@ done."
-+
-+.PHONY: test
-+test:
-+ pip install 'tox>=1.7.2'
-+ tox
-+ @echo "$@ done."
-+
-+.PHONY: clean
-+clean:
-+ rm -rf dist build $(PACKAGENAME).egg-info
-+ @echo "$@ done."
-+
-+.PHONY: build
-+build:
-+ python setup.py sdist bdist_wheel
-+
-+.PHONY: publish
-+publish:
-+ twine upload -r pypi dist/$(PACKAGENAME)-*
-+ @echo "$@ done."
-+
-+.PHONY: dry-run
-+dry-run: test clean build
-+ @echo "$@ done."
-+
-+.PHONY: dev
-+dev: instdev test
-+ @echo "$@ done."
-+
-+.PHONY: instdev
-+instdev:
-+ pip install -r dev-requirements.txt
-+ python setup.py develop
-+ @echo "$@ done."
-+
-+.PHONY: install
-+install:
-+ python setup.py install
-+ @echo "$@ done."
-+
-+.PHONY: html
-+html:
-+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/html
-+ @echo "$@ done; the HTML pages are in $(SPHINXBUILDDIR)/html."
-+
-+.PHONY: pdf
-+pdf:
-+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/pdf
-+ @echo "Running LaTeX files through pdflatex..."
-+ $(MAKE) -C $(SPHINXBUILDDIR)/pdf all-pdf
-+ @echo "$@ done; the PDF files are in $(SPHINXBUILDDIR)/pdf."
-+
-+.PHONY: man
-+man:
-+ $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/man
-+ @echo "$@ done; the manual pages are in $(SPHINXBUILDDIR)/man."
-+
-+.PHONY: docchanges
-+docchanges:
-+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/changes
-+ @echo
-+ @echo "$@ done; the doc changes overview file is in $(SPHINXBUILDDIR)/changes."
-+
-+.PHONY: doclinkcheck
-+doclinkcheck:
-+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/linkcheck
-+ @echo
-+ @echo "$@ done; look for any errors in the above output " \
-+ "or in $(SPHINXBUILDDIR)/linkcheck/output.txt."
-+
-+.PHONY: doccoverage
-+doccoverage:
-+ $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(SPHINXBUILDDIR)/coverage
-+ @echo "$@ done; the doc coverage results are in $(SPHINXBUILDDIR)/coverage/python.txt."
-+
-+.PHONY: clobber
-+clobber: clean
-+ rm -rf $(SPHINXBUILDDIR)
-+ @echo "$@ done."
-diff --git a/third_party/python/distro/PKG-INFO b/third_party/python/distro/PKG-INFO
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/PKG-INFO
-@@ -0,0 +1,168 @@
-+Metadata-Version: 2.1
-+Name: distro
-+Version: 1.4.0
-+Summary: Distro - an OS platform information API
-+Home-page: https://github.com/nir0s/distro
-+Author: Nir Cohen
-+Author-email: nir36g@gmail.com
-+License: Apache License, Version 2.0
-+Description: Distro - an OS platform information API
-+ =======================================
-+
-+ [![Build Status](https://travis-ci.org/nir0s/distro.svg?branch=master)](https://travis-ci.org/nir0s/distro)
-+ [![Build status](https://ci.appveyor.com/api/projects/status/e812qjk1gf0f74r5/branch/master?svg=true)](https://ci.appveyor.com/project/nir0s/distro/branch/master)
-+ [![PyPI version](http://img.shields.io/pypi/v/distro.svg)](https://pypi.python.org/pypi/distro)
-+ [![Supported Python Versions](https://img.shields.io/pypi/pyversions/distro.svg)](https://img.shields.io/pypi/pyversions/distro.svg)
-+ [![Requirements Status](https://requires.io/github/nir0s/distro/requirements.svg?branch=master)](https://requires.io/github/nir0s/distro/requirements/?branch=master)
-+ [![Code Coverage](https://codecov.io/github/nir0s/distro/coverage.svg?branch=master)](https://codecov.io/github/nir0s/distro?branch=master)
-+ [![Code Quality](https://landscape.io/github/nir0s/distro/master/landscape.svg?style=flat)](https://landscape.io/github/nir0s/distro)
-+ [![Is Wheel](https://img.shields.io/pypi/wheel/distro.svg?style=flat)](https://pypi.python.org/pypi/distro)
-+ [![Latest Github Release](https://readthedocs.org/projects/distro/badge/?version=stable)](http://distro.readthedocs.io/en/latest/)
-+ [![Join the chat at https://gitter.im/nir0s/distro](https://badges.gitter.im/nir0s/distro.svg)](https://gitter.im/nir0s/distro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-+
-+ `distro` provides information about the
-+ OS distribution it runs on, such as a reliable machine-readable ID, or
-+ version information.
-+
-+ It is the recommended replacement for Python's original
-+ [`platform.linux_distribution`](https://docs.python.org/3.7/library/platform.html#platform.linux_distribution)
-+ function (which will be removed in Python 3.8).
-+ It also provides much more functionality which isn't necessarily Python bound,
-+ like a command-line interface.
-+
-+ Distro currently supports Linux and BSD based systems but [Windows and OS X support](https://github.com/nir0s/distro/issues/177) is also planned.
-+
-+ For Python 2.6 support, see https://github.com/nir0s/distro/tree/python2.6-support
-+
-+ ## Installation
-+
-+ Installation of the latest released version from PyPI:
-+
-+ ```shell
-+ pip install distro
-+ ```
-+
-+ Installation of the latest development version:
-+
-+ ```shell
-+ pip install https://github.com/nir0s/distro/archive/master.tar.gz
-+ ```
-+
-+
-+ ## Usage
-+
-+ ```bash
-+ $ distro
-+ Name: Antergos Linux
-+ Version: 2015.10 (ISO-Rolling)
-+ Codename: ISO-Rolling
-+
-+ $ distro -j
-+ {
-+ "codename": "ISO-Rolling",
-+ "id": "antergos",
-+ "like": "arch",
-+ "version": "16.9",
-+ "version_parts": {
-+ "build_number": "",
-+ "major": "16",
-+ "minor": "9"
-+ }
-+ }
-+
-+
-+ $ python
-+ >>> import distro
-+ >>> distro.linux_distribution(full_distribution_name=False)
-+ ('centos', '7.1.1503', 'Core')
-+ ```
-+
-+
-+ ## Documentation
-+
-+ On top of the aforementioned API, several more functions are available. For a complete description of the
-+ API, see the [latest API documentation](http://distro.readthedocs.org/en/latest/).
-+
-+ ## Background
-+
-+ An alternative implementation became necessary because Python 3.5 deprecated
-+ this function, and Python 3.8 will remove it altogether.
-+ Its predecessor function `platform.dist` was already deprecated since
-+ Python 2.6 and will also be removed in Python 3.8.
-+ Still, there are many cases in which access to that information is needed.
-+ See [Python issue 1322](https://bugs.python.org/issue1322) for more
-+ information.
-+
-+ The `distro` package implements a robust and inclusive way of retrieving the
-+ information about a distribution based on new standards and old methods,
-+ namely from these data sources (from high to low precedence):
-+
-+ * The os-release file `/etc/os-release`, if present.
-+ * The output of the `lsb_release` command, if available.
-+ * The distro release file (`/etc/*(-|_)(release|version)`), if present.
-+ * The `uname` command for BSD based distrubtions.
-+
-+
-+ ## Python and Distribution Support
-+
-+ `distro` is supported and tested on Python 2.7, 3.4+ and PyPy and on
-+ any distribution that provides one or more of the data sources
-+ covered.
-+
-+ This package is tested with test data that mimics the exact behavior of the data sources of [a number of Linux distributions](https://github.com/nir0s/distro/tree/master/tests/resources/distros).
-+
-+
-+ ## Testing
-+
-+ ```shell
-+ git clone git@github.com:nir0s/distro.git
-+ cd distro
-+ pip install tox
-+ tox
-+ ```
-+
-+
-+ ## Contributions
-+
-+ Pull requests are always welcome to deal with specific distributions or just
-+ for general merriment.
-+
-+ See [CONTRIBUTIONS](https://github.com/nir0s/distro/blob/master/CONTRIBUTING.md) for contribution info.
-+
-+ Reference implementations for supporting additional distributions and file
-+ formats can be found here:
-+
-+ * https://github.com/saltstack/salt/blob/develop/salt/grains/core.py#L1172
-+ * https://github.com/chef/ohai/blob/master/lib/ohai/plugins/linux/platform.rb
-+ * https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts/system/distribution.py
-+ * https://github.com/puppetlabs/facter/blob/master/lib/src/facts/linux/os_linux.cc
-+
-+ ## Package manager distributions
-+
-+ * https://src.fedoraproject.org/rpms/python-distro
-+ * https://www.archlinux.org/packages/community/any/python-distro/
-+ * https://launchpad.net/ubuntu/+source/python-distro
-+ * https://packages.debian.org/sid/python-distro
-+ * https://packages.gentoo.org/packages/dev-python/distro
-+ * https://pkgs.org/download/python2-distro
-+ * https://slackbuilds.org/repository/14.2/python/python-distro/
-+
-+Platform: All
-+Classifier: Development Status :: 5 - Production/Stable
-+Classifier: Intended Audience :: Developers
-+Classifier: Intended Audience :: System Administrators
-+Classifier: License :: OSI Approved :: Apache Software License
-+Classifier: Operating System :: POSIX :: Linux
-+Classifier: Operating System :: POSIX :: BSD
-+Classifier: Operating System :: POSIX :: BSD :: FreeBSD
-+Classifier: Operating System :: POSIX :: BSD :: NetBSD
-+Classifier: Operating System :: POSIX :: BSD :: OpenBSD
-+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: Topic :: Software Development :: Libraries :: Python Modules
-+Classifier: Topic :: System :: Operating System
-+Description-Content-Type: text/markdown
-diff --git a/third_party/python/distro/README.md b/third_party/python/distro/README.md
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/README.md
-@@ -0,0 +1,140 @@
-+Distro - an OS platform information API
-+=======================================
-+
-+[![Build Status](https://travis-ci.org/nir0s/distro.svg?branch=master)](https://travis-ci.org/nir0s/distro)
-+[![Build status](https://ci.appveyor.com/api/projects/status/e812qjk1gf0f74r5/branch/master?svg=true)](https://ci.appveyor.com/project/nir0s/distro/branch/master)
-+[![PyPI version](http://img.shields.io/pypi/v/distro.svg)](https://pypi.python.org/pypi/distro)
-+[![Supported Python Versions](https://img.shields.io/pypi/pyversions/distro.svg)](https://img.shields.io/pypi/pyversions/distro.svg)
-+[![Requirements Status](https://requires.io/github/nir0s/distro/requirements.svg?branch=master)](https://requires.io/github/nir0s/distro/requirements/?branch=master)
-+[![Code Coverage](https://codecov.io/github/nir0s/distro/coverage.svg?branch=master)](https://codecov.io/github/nir0s/distro?branch=master)
-+[![Code Quality](https://landscape.io/github/nir0s/distro/master/landscape.svg?style=flat)](https://landscape.io/github/nir0s/distro)
-+[![Is Wheel](https://img.shields.io/pypi/wheel/distro.svg?style=flat)](https://pypi.python.org/pypi/distro)
-+[![Latest Github Release](https://readthedocs.org/projects/distro/badge/?version=stable)](http://distro.readthedocs.io/en/latest/)
-+[![Join the chat at https://gitter.im/nir0s/distro](https://badges.gitter.im/nir0s/distro.svg)](https://gitter.im/nir0s/distro?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
-+
-+`distro` provides information about the
-+OS distribution it runs on, such as a reliable machine-readable ID, or
-+version information.
-+
-+It is the recommended replacement for Python's original
-+[`platform.linux_distribution`](https://docs.python.org/3.7/library/platform.html#platform.linux_distribution)
-+function (which will be removed in Python 3.8).
-+It also provides much more functionality which isn't necessarily Python bound,
-+like a command-line interface.
-+
-+Distro currently supports Linux and BSD based systems but [Windows and OS X support](https://github.com/nir0s/distro/issues/177) is also planned.
-+
-+For Python 2.6 support, see https://github.com/nir0s/distro/tree/python2.6-support
-+
-+## Installation
-+
-+Installation of the latest released version from PyPI:
-+
-+```shell
-+pip install distro
-+```
-+
-+Installation of the latest development version:
-+
-+```shell
-+pip install https://github.com/nir0s/distro/archive/master.tar.gz
-+```
-+
-+
-+## Usage
-+
-+```bash
-+$ distro
-+Name: Antergos Linux
-+Version: 2015.10 (ISO-Rolling)
-+Codename: ISO-Rolling
-+
-+$ distro -j
-+{
-+ "codename": "ISO-Rolling",
-+ "id": "antergos",
-+ "like": "arch",
-+ "version": "16.9",
-+ "version_parts": {
-+ "build_number": "",
-+ "major": "16",
-+ "minor": "9"
-+ }
-+}
-+
-+
-+$ python
-+>>> import distro
-+>>> distro.linux_distribution(full_distribution_name=False)
-+('centos', '7.1.1503', 'Core')
-+```
-+
-+
-+## Documentation
-+
-+On top of the aforementioned API, several more functions are available. For a complete description of the
-+API, see the [latest API documentation](http://distro.readthedocs.org/en/latest/).
-+
-+## Background
-+
-+An alternative implementation became necessary because Python 3.5 deprecated
-+this function, and Python 3.8 will remove it altogether.
-+Its predecessor function `platform.dist` was already deprecated since
-+Python 2.6 and will also be removed in Python 3.8.
-+Still, there are many cases in which access to that information is needed.
-+See [Python issue 1322](https://bugs.python.org/issue1322) for more
-+information.
-+
-+The `distro` package implements a robust and inclusive way of retrieving the
-+information about a distribution based on new standards and old methods,
-+namely from these data sources (from high to low precedence):
-+
-+* The os-release file `/etc/os-release`, if present.
-+* The output of the `lsb_release` command, if available.
-+* The distro release file (`/etc/*(-|_)(release|version)`), if present.
-+* The `uname` command for BSD based distrubtions.
-+
-+
-+## Python and Distribution Support
-+
-+`distro` is supported and tested on Python 2.7, 3.4+ and PyPy and on
-+any distribution that provides one or more of the data sources
-+covered.
-+
-+This package is tested with test data that mimics the exact behavior of the data sources of [a number of Linux distributions](https://github.com/nir0s/distro/tree/master/tests/resources/distros).
-+
-+
-+## Testing
-+
-+```shell
-+git clone git@github.com:nir0s/distro.git
-+cd distro
-+pip install tox
-+tox
-+```
-+
-+
-+## Contributions
-+
-+Pull requests are always welcome to deal with specific distributions or just
-+for general merriment.
-+
-+See [CONTRIBUTIONS](https://github.com/nir0s/distro/blob/master/CONTRIBUTING.md) for contribution info.
-+
-+Reference implementations for supporting additional distributions and file
-+formats can be found here:
-+
-+* https://github.com/saltstack/salt/blob/develop/salt/grains/core.py#L1172
-+* https://github.com/chef/ohai/blob/master/lib/ohai/plugins/linux/platform.rb
-+* https://github.com/ansible/ansible/blob/devel/lib/ansible/module_utils/facts/system/distribution.py
-+* https://github.com/puppetlabs/facter/blob/master/lib/src/facts/linux/os_linux.cc
-+
-+## Package manager distributions
-+
-+* https://src.fedoraproject.org/rpms/python-distro
-+* https://www.archlinux.org/packages/community/any/python-distro/
-+* https://launchpad.net/ubuntu/+source/python-distro
-+* https://packages.debian.org/sid/python-distro
-+* https://packages.gentoo.org/packages/dev-python/distro
-+* https://pkgs.org/download/python2-distro
-+* https://slackbuilds.org/repository/14.2/python/python-distro/
-diff --git a/third_party/python/distro/dev-requirements.txt b/third_party/python/distro/dev-requirements.txt
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/dev-requirements.txt
-@@ -0,0 +1,3 @@
-+pytest
-+pytest-cov
-+sphinx>=1.1
-\ No newline at end of file
-diff --git a/third_party/python/distro/distro.py b/third_party/python/distro/distro.py
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/distro.py
-@@ -0,0 +1,1216 @@
-+# Copyright 2015,2016,2017 Nir Cohen
-+#
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+#
-+# http://www.apache.org/licenses/LICENSE-2.0
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+
-+"""
-+The ``distro`` package (``distro`` stands for Linux Distribution) provides
-+information about the Linux distribution it runs on, such as a reliable
-+machine-readable distro ID, or version information.
-+
-+It is the recommended replacement for Python's original
-+:py:func:`platform.linux_distribution` function, but it provides much more
-+functionality. An alternative implementation became necessary because Python
-+3.5 deprecated this function, and Python 3.8 will remove it altogether.
-+Its predecessor function :py:func:`platform.dist` was already
-+deprecated since Python 2.6 and will also be removed in Python 3.8.
-+Still, there are many cases in which access to OS distribution information
-+is needed. See `Python issue 1322 <https://bugs.python.org/issue1322>`_ for
-+more information.
-+"""
-+
-+import os
-+import re
-+import sys
-+import json
-+import shlex
-+import logging
-+import argparse
-+import subprocess
-+
-+
-+_UNIXCONFDIR = os.environ.get('UNIXCONFDIR', '/etc')
-+_OS_RELEASE_BASENAME = 'os-release'
-+
-+#: Translation table for normalizing the "ID" attribute defined in os-release
-+#: files, for use by the :func:`distro.id` method.
-+#:
-+#: * Key: Value as defined in the os-release file, translated to lower case,
-+#: with blanks translated to underscores.
-+#:
-+#: * Value: Normalized value.
-+NORMALIZED_OS_ID = {
-+ 'ol': 'oracle', # Oracle Enterprise Linux
-+}
-+
-+#: Translation table for normalizing the "Distributor ID" attribute returned by
-+#: the lsb_release command, for use by the :func:`distro.id` method.
-+#:
-+#: * Key: Value as returned by the lsb_release command, translated to lower
-+#: case, with blanks translated to underscores.
-+#:
-+#: * Value: Normalized value.
-+NORMALIZED_LSB_ID = {
-+ 'enterpriseenterprise': 'oracle', # Oracle Enterprise Linux
-+ 'redhatenterpriseworkstation': 'rhel', # RHEL 6, 7 Workstation
-+ 'redhatenterpriseserver': 'rhel', # RHEL 6, 7 Server
-+}
-+
-+#: Translation table for normalizing the distro ID derived from the file name
-+#: of distro release files, for use by the :func:`distro.id` method.
-+#:
-+#: * Key: Value as derived from the file name of a distro release file,
-+#: translated to lower case, with blanks translated to underscores.
-+#:
-+#: * Value: Normalized value.
-+NORMALIZED_DISTRO_ID = {
-+ 'redhat': 'rhel', # RHEL 6.x, 7.x
-+}
-+
-+# Pattern for content of distro release file (reversed)
-+_DISTRO_RELEASE_CONTENT_REVERSED_PATTERN = re.compile(
-+ r'(?:[^)]*\)(.*)\()? *(?:STL )?([\d.+\-a-z]*\d) *(?:esaeler *)?(.+)')
-+
-+# Pattern for base file name of distro release file
-+_DISTRO_RELEASE_BASENAME_PATTERN = re.compile(
-+ r'(\w+)[-_](release|version)$')
-+
-+# Base file names to be ignored when searching for distro release file
-+_DISTRO_RELEASE_IGNORE_BASENAMES = (
-+ 'debian_version',
-+ 'lsb-release',
-+ 'oem-release',
-+ _OS_RELEASE_BASENAME,
-+ 'system-release'
-+)
-+
-+
-+def linux_distribution(full_distribution_name=True):
-+ """
-+ Return information about the current OS distribution as a tuple
-+ ``(id_name, version, codename)`` with items as follows:
-+
-+ * ``id_name``: If *full_distribution_name* is false, the result of
-+ :func:`distro.id`. Otherwise, the result of :func:`distro.name`.
-+
-+ * ``version``: The result of :func:`distro.version`.
-+
-+ * ``codename``: The result of :func:`distro.codename`.
-+
-+ The interface of this function is compatible with the original
-+ :py:func:`platform.linux_distribution` function, supporting a subset of
-+ its parameters.
-+
-+ The data it returns may not exactly be the same, because it uses more data
-+ sources than the original function, and that may lead to different data if
-+ the OS distribution is not consistent across multiple data sources it
-+ provides (there are indeed such distributions ...).
-+
-+ Another reason for differences is the fact that the :func:`distro.id`
-+ method normalizes the distro ID string to a reliable machine-readable value
-+ for a number of popular OS distributions.
-+ """
-+ return _distro.linux_distribution(full_distribution_name)
-+
-+
-+def id():
-+ """
-+ Return the distro ID of the current distribution, as a
-+ machine-readable string.
-+
-+ For a number of OS distributions, the returned distro ID value is
-+ *reliable*, in the sense that it is documented and that it does not change
-+ across releases of the distribution.
-+
-+ This package maintains the following reliable distro ID values:
-+
-+ ============== =========================================
-+ Distro ID Distribution
-+ ============== =========================================
-+ "ubuntu" Ubuntu
-+ "debian" Debian
-+ "rhel" RedHat Enterprise Linux
-+ "centos" CentOS
-+ "fedora" Fedora
-+ "sles" SUSE Linux Enterprise Server
-+ "opensuse" openSUSE
-+ "amazon" Amazon Linux
-+ "arch" Arch Linux
-+ "cloudlinux" CloudLinux OS
-+ "exherbo" Exherbo Linux
-+ "gentoo" GenToo Linux
-+ "ibm_powerkvm" IBM PowerKVM
-+ "kvmibm" KVM for IBM z Systems
-+ "linuxmint" Linux Mint
-+ "mageia" Mageia
-+ "mandriva" Mandriva Linux
-+ "parallels" Parallels
-+ "pidora" Pidora
-+ "raspbian" Raspbian
-+ "oracle" Oracle Linux (and Oracle Enterprise Linux)
-+ "scientific" Scientific Linux
-+ "slackware" Slackware
-+ "xenserver" XenServer
-+ "openbsd" OpenBSD
-+ "netbsd" NetBSD
-+ "freebsd" FreeBSD
-+ ============== =========================================
-+
-+ If you have a need to get distros for reliable IDs added into this set,
-+ or if you find that the :func:`distro.id` function returns a different
-+ distro ID for one of the listed distros, please create an issue in the
-+ `distro issue tracker`_.
-+
-+ **Lookup hierarchy and transformations:**
-+
-+ First, the ID is obtained from the following sources, in the specified
-+ order. The first available and non-empty value is used:
-+
-+ * the value of the "ID" attribute of the os-release file,
-+
-+ * the value of the "Distributor ID" attribute returned by the lsb_release
-+ command,
-+
-+ * the first part of the file name of the distro release file,
-+
-+ The so determined ID value then passes the following transformations,
-+ before it is returned by this method:
-+
-+ * it is translated to lower case,
-+
-+ * blanks (which should not be there anyway) are translated to underscores,
-+
-+ * a normalization of the ID is performed, based upon
-+ `normalization tables`_. The purpose of this normalization is to ensure
-+ that the ID is as reliable as possible, even across incompatible changes
-+ in the OS distributions. A common reason for an incompatible change is
-+ the addition of an os-release file, or the addition of the lsb_release
-+ command, with ID values that differ from what was previously determined
-+ from the distro release file name.
-+ """
-+ return _distro.id()
-+
-+
-+def name(pretty=False):
-+ """
-+ Return the name of the current OS distribution, as a human-readable
-+ string.
-+
-+ If *pretty* is false, the name is returned without version or codename.
-+ (e.g. "CentOS Linux")
-+
-+ If *pretty* is true, the version and codename are appended.
-+ (e.g. "CentOS Linux 7.1.1503 (Core)")
-+
-+ **Lookup hierarchy:**
-+
-+ The name is obtained from the following sources, in the specified order.
-+ The first available and non-empty value is used:
-+
-+ * If *pretty* is false:
-+
-+ - the value of the "NAME" attribute of the os-release file,
-+
-+ - the value of the "Distributor ID" attribute returned by the lsb_release
-+ command,
-+
-+ - the value of the "<name>" field of the distro release file.
-+
-+ * If *pretty* is true:
-+
-+ - the value of the "PRETTY_NAME" attribute of the os-release file,
-+
-+ - the value of the "Description" attribute returned by the lsb_release
-+ command,
-+
-+ - the value of the "<name>" field of the distro release file, appended
-+ with the value of the pretty version ("<version_id>" and "<codename>"
-+ fields) of the distro release file, if available.
-+ """
-+ return _distro.name(pretty)
-+
-+
-+def version(pretty=False, best=False):
-+ """
-+ Return the version of the current OS distribution, as a human-readable
-+ string.
-+
-+ If *pretty* is false, the version is returned without codename (e.g.
-+ "7.0").
-+
-+ If *pretty* is true, the codename in parenthesis is appended, if the
-+ codename is non-empty (e.g. "7.0 (Maipo)").
-+
-+ Some distributions provide version numbers with different precisions in
-+ the different sources of distribution information. Examining the different
-+ sources in a fixed priority order does not always yield the most precise
-+ version (e.g. for Debian 8.2, or CentOS 7.1).
-+
-+ The *best* parameter can be used to control the approach for the returned
-+ version:
-+
-+ If *best* is false, the first non-empty version number in priority order of
-+ the examined sources is returned.
-+
-+ If *best* is true, the most precise version number out of all examined
-+ sources is returned.
-+
-+ **Lookup hierarchy:**
-+
-+ In all cases, the version number is obtained from the following sources.
-+ If *best* is false, this order represents the priority order:
-+
-+ * the value of the "VERSION_ID" attribute of the os-release file,
-+ * the value of the "Release" attribute returned by the lsb_release
-+ command,
-+ * the version number parsed from the "<version_id>" field of the first line
-+ of the distro release file,
-+ * the version number parsed from the "PRETTY_NAME" attribute of the
-+ os-release file, if it follows the format of the distro release files.
-+ * the version number parsed from the "Description" attribute returned by
-+ the lsb_release command, if it follows the format of the distro release
-+ files.
-+ """
-+ return _distro.version(pretty, best)
-+
-+
-+def version_parts(best=False):
-+ """
-+ Return the version of the current OS distribution as a tuple
-+ ``(major, minor, build_number)`` with items as follows:
-+
-+ * ``major``: The result of :func:`distro.major_version`.
-+
-+ * ``minor``: The result of :func:`distro.minor_version`.
-+
-+ * ``build_number``: The result of :func:`distro.build_number`.
-+
-+ For a description of the *best* parameter, see the :func:`distro.version`
-+ method.
-+ """
-+ return _distro.version_parts(best)
-+
-+
-+def major_version(best=False):
-+ """
-+ Return the major version of the current OS distribution, as a string,
-+ if provided.
-+ Otherwise, the empty string is returned. The major version is the first
-+ part of the dot-separated version string.
-+
-+ For a description of the *best* parameter, see the :func:`distro.version`
-+ method.
-+ """
-+ return _distro.major_version(best)
-+
-+
-+def minor_version(best=False):
-+ """
-+ Return the minor version of the current OS distribution, as a string,
-+ if provided.
-+ Otherwise, the empty string is returned. The minor version is the second
-+ part of the dot-separated version string.
-+
-+ For a description of the *best* parameter, see the :func:`distro.version`
-+ method.
-+ """
-+ return _distro.minor_version(best)
-+
-+
-+def build_number(best=False):
-+ """
-+ Return the build number of the current OS distribution, as a string,
-+ if provided.
-+ Otherwise, the empty string is returned. The build number is the third part
-+ of the dot-separated version string.
-+
-+ For a description of the *best* parameter, see the :func:`distro.version`
-+ method.
-+ """
-+ return _distro.build_number(best)
-+
-+
-+def like():
-+ """
-+ Return a space-separated list of distro IDs of distributions that are
-+ closely related to the current OS distribution in regards to packaging
-+ and programming interfaces, for example distributions the current
-+ distribution is a derivative from.
-+
-+ **Lookup hierarchy:**
-+
-+ This information item is only provided by the os-release file.
-+ For details, see the description of the "ID_LIKE" attribute in the
-+ `os-release man page
-+ <http://www.freedesktop.org/software/systemd/man/os-release.html>`_.
-+ """
-+ return _distro.like()
-+
-+
-+def codename():
-+ """
-+ Return the codename for the release of the current OS distribution,
-+ as a string.
-+
-+ If the distribution does not have a codename, an empty string is returned.
-+
-+ Note that the returned codename is not always really a codename. For
-+ example, openSUSE returns "x86_64". This function does not handle such
-+ cases in any special way and just returns the string it finds, if any.
-+
-+ **Lookup hierarchy:**
-+
-+ * the codename within the "VERSION" attribute of the os-release file, if
-+ provided,
-+
-+ * the value of the "Codename" attribute returned by the lsb_release
-+ command,
-+
-+ * the value of the "<codename>" field of the distro release file.
-+ """
-+ return _distro.codename()
-+
-+
-+def info(pretty=False, best=False):
-+ """
-+ Return certain machine-readable information items about the current OS
-+ distribution in a dictionary, as shown in the following example:
-+
-+ .. sourcecode:: python
-+
-+ {
-+ 'id': 'rhel',
-+ 'version': '7.0',
-+ 'version_parts': {
-+ 'major': '7',
-+ 'minor': '0',
-+ 'build_number': ''
-+ },
-+ 'like': 'fedora',
-+ 'codename': 'Maipo'
-+ }
-+
-+ The dictionary structure and keys are always the same, regardless of which
-+ information items are available in the underlying data sources. The values
-+ for the various keys are as follows:
-+
-+ * ``id``: The result of :func:`distro.id`.
-+
-+ * ``version``: The result of :func:`distro.version`.
-+
-+ * ``version_parts -> major``: The result of :func:`distro.major_version`.
-+
-+ * ``version_parts -> minor``: The result of :func:`distro.minor_version`.
-+
-+ * ``version_parts -> build_number``: The result of
-+ :func:`distro.build_number`.
-+
-+ * ``like``: The result of :func:`distro.like`.
-+
-+ * ``codename``: The result of :func:`distro.codename`.
-+
-+ For a description of the *pretty* and *best* parameters, see the
-+ :func:`distro.version` method.
-+ """
-+ return _distro.info(pretty, best)
-+
-+
-+def os_release_info():
-+ """
-+ Return a dictionary containing key-value pairs for the information items
-+ from the os-release file data source of the current OS distribution.
-+
-+ See `os-release file`_ for details about these information items.
-+ """
-+ return _distro.os_release_info()
-+
-+
-+def lsb_release_info():
-+ """
-+ Return a dictionary containing key-value pairs for the information items
-+ from the lsb_release command data source of the current OS distribution.
-+
-+ See `lsb_release command output`_ for details about these information
-+ items.
-+ """
-+ return _distro.lsb_release_info()
-+
-+
-+def distro_release_info():
-+ """
-+ Return a dictionary containing key-value pairs for the information items
-+ from the distro release file data source of the current OS distribution.
-+
-+ See `distro release file`_ for details about these information items.
-+ """
-+ return _distro.distro_release_info()
-+
-+
-+def uname_info():
-+ """
-+ Return a dictionary containing key-value pairs for the information items
-+ from the distro release file data source of the current OS distribution.
-+ """
-+ return _distro.uname_info()
-+
-+
-+def os_release_attr(attribute):
-+ """
-+ Return a single named information item from the os-release file data source
-+ of the current OS distribution.
-+
-+ Parameters:
-+
-+ * ``attribute`` (string): Key of the information item.
-+
-+ Returns:
-+
-+ * (string): Value of the information item, if the item exists.
-+ The empty string, if the item does not exist.
-+
-+ See `os-release file`_ for details about these information items.
-+ """
-+ return _distro.os_release_attr(attribute)
-+
-+
-+def lsb_release_attr(attribute):
-+ """
-+ Return a single named information item from the lsb_release command output
-+ data source of the current OS distribution.
-+
-+ Parameters:
-+
-+ * ``attribute`` (string): Key of the information item.
-+
-+ Returns:
-+
-+ * (string): Value of the information item, if the item exists.
-+ The empty string, if the item does not exist.
-+
-+ See `lsb_release command output`_ for details about these information
-+ items.
-+ """
-+ return _distro.lsb_release_attr(attribute)
-+
-+
-+def distro_release_attr(attribute):
-+ """
-+ Return a single named information item from the distro release file
-+ data source of the current OS distribution.
-+
-+ Parameters:
-+
-+ * ``attribute`` (string): Key of the information item.
-+
-+ Returns:
-+
-+ * (string): Value of the information item, if the item exists.
-+ The empty string, if the item does not exist.
-+
-+ See `distro release file`_ for details about these information items.
-+ """
-+ return _distro.distro_release_attr(attribute)
-+
-+
-+def uname_attr(attribute):
-+ """
-+ Return a single named information item from the distro release file
-+ data source of the current OS distribution.
-+
-+ Parameters:
-+
-+ * ``attribute`` (string): Key of the information item.
-+
-+ Returns:
-+
-+ * (string): Value of the information item, if the item exists.
-+ The empty string, if the item does not exist.
-+ """
-+ return _distro.uname_attr(attribute)
-+
-+
-+class cached_property(object):
-+ """A version of @property which caches the value. On access, it calls the
-+ underlying function and sets the value in `__dict__` so future accesses
-+ will not re-call the property.
-+ """
-+ def __init__(self, f):
-+ self._fname = f.__name__
-+ self._f = f
-+
-+ def __get__(self, obj, owner):
-+ assert obj is not None, 'call {} on an instance'.format(self._fname)
-+ ret = obj.__dict__[self._fname] = self._f(obj)
-+ return ret
-+
-+
-+class LinuxDistribution(object):
-+ """
-+ Provides information about a OS distribution.
-+
-+ This package creates a private module-global instance of this class with
-+ default initialization arguments, that is used by the
-+ `consolidated accessor functions`_ and `single source accessor functions`_.
-+ By using default initialization arguments, that module-global instance
-+ returns data about the current OS distribution (i.e. the distro this
-+ package runs on).
-+
-+ Normally, it is not necessary to create additional instances of this class.
-+ However, in situations where control is needed over the exact data sources
-+ that are used, instances of this class can be created with a specific
-+ distro release file, or a specific os-release file, or without invoking the
-+ lsb_release command.
-+ """
-+
-+ def __init__(self,
-+ include_lsb=True,
-+ os_release_file='',
-+ distro_release_file='',
-+ include_uname=True):
-+ """
-+ The initialization method of this class gathers information from the
-+ available data sources, and stores that in private instance attributes.
-+ Subsequent access to the information items uses these private instance
-+ attributes, so that the data sources are read only once.
-+
-+ Parameters:
-+
-+ * ``include_lsb`` (bool): Controls whether the
-+ `lsb_release command output`_ is included as a data source.
-+
-+ If the lsb_release command is not available in the program execution
-+ path, the data source for the lsb_release command will be empty.
-+
-+ * ``os_release_file`` (string): The path name of the
-+ `os-release file`_ that is to be used as a data source.
-+
-+ An empty string (the default) will cause the default path name to
-+ be used (see `os-release file`_ for details).
-+
-+ If the specified or defaulted os-release file does not exist, the
-+ data source for the os-release file will be empty.
-+
-+ * ``distro_release_file`` (string): The path name of the
-+ `distro release file`_ that is to be used as a data source.
-+
-+ An empty string (the default) will cause a default search algorithm
-+ to be used (see `distro release file`_ for details).
-+
-+ If the specified distro release file does not exist, or if no default
-+ distro release file can be found, the data source for the distro
-+ release file will be empty.
-+
-+ * ``include_name`` (bool): Controls whether uname command output is
-+ included as a data source. If the uname command is not available in
-+ the program execution path the data source for the uname command will
-+ be empty.
-+
-+ Public instance attributes:
-+
-+ * ``os_release_file`` (string): The path name of the
-+ `os-release file`_ that is actually used as a data source. The
-+ empty string if no distro release file is used as a data source.
-+
-+ * ``distro_release_file`` (string): The path name of the
-+ `distro release file`_ that is actually used as a data source. The
-+ empty string if no distro release file is used as a data source.
-+
-+ * ``include_lsb`` (bool): The result of the ``include_lsb`` parameter.
-+ This controls whether the lsb information will be loaded.
-+
-+ * ``include_uname`` (bool): The result of the ``include_uname``
-+ parameter. This controls whether the uname information will
-+ be loaded.
-+
-+ Raises:
-+
-+ * :py:exc:`IOError`: Some I/O issue with an os-release file or distro
-+ release file.
-+
-+ * :py:exc:`subprocess.CalledProcessError`: The lsb_release command had
-+ some issue (other than not being available in the program execution
-+ path).
-+
-+ * :py:exc:`UnicodeError`: A data source has unexpected characters or
-+ uses an unexpected encoding.
-+ """
-+ self.os_release_file = os_release_file or \
-+ os.path.join(_UNIXCONFDIR, _OS_RELEASE_BASENAME)
-+ self.distro_release_file = distro_release_file or '' # updated later
-+ self.include_lsb = include_lsb
-+ self.include_uname = include_uname
-+
-+ def __repr__(self):
-+ """Return repr of all info
-+ """
-+ return \
-+ "LinuxDistribution(" \
-+ "os_release_file={self.os_release_file!r}, " \
-+ "distro_release_file={self.distro_release_file!r}, " \
-+ "include_lsb={self.include_lsb!r}, " \
-+ "include_uname={self.include_uname!r}, " \
-+ "_os_release_info={self._os_release_info!r}, " \
-+ "_lsb_release_info={self._lsb_release_info!r}, " \
-+ "_distro_release_info={self._distro_release_info!r}, " \
-+ "_uname_info={self._uname_info!r})".format(
-+ self=self)
-+
-+ def linux_distribution(self, full_distribution_name=True):
-+ """
-+ Return information about the OS distribution that is compatible
-+ with Python's :func:`platform.linux_distribution`, supporting a subset
-+ of its parameters.
-+
-+ For details, see :func:`distro.linux_distribution`.
-+ """
-+ return (
-+ self.name() if full_distribution_name else self.id(),
-+ self.version(),
-+ self.codename()
-+ )
-+
-+ def id(self):
-+ """Return the distro ID of the OS distribution, as a string.
-+
-+ For details, see :func:`distro.id`.
-+ """
-+ def normalize(distro_id, table):
-+ distro_id = distro_id.lower().replace(' ', '_')
-+ return table.get(distro_id, distro_id)
-+
-+ distro_id = self.os_release_attr('id')
-+ if distro_id:
-+ return normalize(distro_id, NORMALIZED_OS_ID)
-+
-+ distro_id = self.lsb_release_attr('distributor_id')
-+ if distro_id:
-+ return normalize(distro_id, NORMALIZED_LSB_ID)
-+
-+ distro_id = self.distro_release_attr('id')
-+ if distro_id:
-+ return normalize(distro_id, NORMALIZED_DISTRO_ID)
-+
-+ distro_id = self.uname_attr('id')
-+ if distro_id:
-+ return normalize(distro_id, NORMALIZED_DISTRO_ID)
-+
-+ return ''
-+
-+ def name(self, pretty=False):
-+ """
-+ Return the name of the OS distribution, as a string.
-+
-+ For details, see :func:`distro.name`.
-+ """
-+ name = self.os_release_attr('name') \
-+ or self.lsb_release_attr('distributor_id') \
-+ or self.distro_release_attr('name') \
-+ or self.uname_attr('name')
-+ if pretty:
-+ name = self.os_release_attr('pretty_name') \
-+ or self.lsb_release_attr('description')
-+ if not name:
-+ name = self.distro_release_attr('name') \
-+ or self.uname_attr('name')
-+ version = self.version(pretty=True)
-+ if version:
-+ name = name + ' ' + version
-+ return name or ''
-+
-+ def version(self, pretty=False, best=False):
-+ """
-+ Return the version of the OS distribution, as a string.
-+
-+ For details, see :func:`distro.version`.
-+ """
-+ versions = [
-+ self.os_release_attr('version_id'),
-+ self.lsb_release_attr('release'),
-+ self.distro_release_attr('version_id'),
-+ self._parse_distro_release_content(
-+ self.os_release_attr('pretty_name')).get('version_id', ''),
-+ self._parse_distro_release_content(
-+ self.lsb_release_attr('description')).get('version_id', ''),
-+ self.uname_attr('release')
-+ ]
-+ version = ''
-+ if best:
-+ # This algorithm uses the last version in priority order that has
-+ # the best precision. If the versions are not in conflict, that
-+ # does not matter; otherwise, using the last one instead of the
-+ # first one might be considered a surprise.
-+ for v in versions:
-+ if v.count(".") > version.count(".") or version == '':
-+ version = v
-+ else:
-+ for v in versions:
-+ if v != '':
-+ version = v
-+ break
-+ if pretty and version and self.codename():
-+ version = u'{0} ({1})'.format(version, self.codename())
-+ return version
-+
-+ def version_parts(self, best=False):
-+ """
-+ Return the version of the OS distribution, as a tuple of version
-+ numbers.
-+
-+ For details, see :func:`distro.version_parts`.
-+ """
-+ version_str = self.version(best=best)
-+ if version_str:
-+ version_regex = re.compile(r'(\d+)\.?(\d+)?\.?(\d+)?')
-+ matches = version_regex.match(version_str)
-+ if matches:
-+ major, minor, build_number = matches.groups()
-+ return major, minor or '', build_number or ''
-+ return '', '', ''
-+
-+ def major_version(self, best=False):
-+ """
-+ Return the major version number of the current distribution.
-+
-+ For details, see :func:`distro.major_version`.
-+ """
-+ return self.version_parts(best)[0]
-+
-+ def minor_version(self, best=False):
-+ """
-+ Return the minor version number of the current distribution.
-+
-+ For details, see :func:`distro.minor_version`.
-+ """
-+ return self.version_parts(best)[1]
-+
-+ def build_number(self, best=False):
-+ """
-+ Return the build number of the current distribution.
-+
-+ For details, see :func:`distro.build_number`.
-+ """
-+ return self.version_parts(best)[2]
-+
-+ def like(self):
-+ """
-+ Return the IDs of distributions that are like the OS distribution.
-+
-+ For details, see :func:`distro.like`.
-+ """
-+ return self.os_release_attr('id_like') or ''
-+
-+ def codename(self):
-+ """
-+ Return the codename of the OS distribution.
-+
-+ For details, see :func:`distro.codename`.
-+ """
-+ try:
-+ # Handle os_release specially since distros might purposefully set
-+ # this to empty string to have no codename
-+ return self._os_release_info['codename']
-+ except KeyError:
-+ return self.lsb_release_attr('codename') \
-+ or self.distro_release_attr('codename') \
-+ or ''
-+
-+ def info(self, pretty=False, best=False):
-+ """
-+ Return certain machine-readable information about the OS
-+ distribution.
-+
-+ For details, see :func:`distro.info`.
-+ """
-+ return dict(
-+ id=self.id(),
-+ version=self.version(pretty, best),
-+ version_parts=dict(
-+ major=self.major_version(best),
-+ minor=self.minor_version(best),
-+ build_number=self.build_number(best)
-+ ),
-+ like=self.like(),
-+ codename=self.codename(),
-+ )
-+
-+ def os_release_info(self):
-+ """
-+ Return a dictionary containing key-value pairs for the information
-+ items from the os-release file data source of the OS distribution.
-+
-+ For details, see :func:`distro.os_release_info`.
-+ """
-+ return self._os_release_info
-+
-+ def lsb_release_info(self):
-+ """
-+ Return a dictionary containing key-value pairs for the information
-+ items from the lsb_release command data source of the OS
-+ distribution.
-+
-+ For details, see :func:`distro.lsb_release_info`.
-+ """
-+ return self._lsb_release_info
-+
-+ def distro_release_info(self):
-+ """
-+ Return a dictionary containing key-value pairs for the information
-+ items from the distro release file data source of the OS
-+ distribution.
-+
-+ For details, see :func:`distro.distro_release_info`.
-+ """
-+ return self._distro_release_info
-+
-+ def uname_info(self):
-+ """
-+ Return a dictionary containing key-value pairs for the information
-+ items from the uname command data source of the OS distribution.
-+
-+ For details, see :func:`distro.uname_info`.
-+ """
-+ return self._uname_info
-+
-+ def os_release_attr(self, attribute):
-+ """
-+ Return a single named information item from the os-release file data
-+ source of the OS distribution.
-+
-+ For details, see :func:`distro.os_release_attr`.
-+ """
-+ return self._os_release_info.get(attribute, '')
-+
-+ def lsb_release_attr(self, attribute):
-+ """
-+ Return a single named information item from the lsb_release command
-+ output data source of the OS distribution.
-+
-+ For details, see :func:`distro.lsb_release_attr`.
-+ """
-+ return self._lsb_release_info.get(attribute, '')
-+
-+ def distro_release_attr(self, attribute):
-+ """
-+ Return a single named information item from the distro release file
-+ data source of the OS distribution.
-+
-+ For details, see :func:`distro.distro_release_attr`.
-+ """
-+ return self._distro_release_info.get(attribute, '')
-+
-+ def uname_attr(self, attribute):
-+ """
-+ Return a single named information item from the uname command
-+ output data source of the OS distribution.
-+
-+ For details, see :func:`distro.uname_release_attr`.
-+ """
-+ return self._uname_info.get(attribute, '')
-+
-+ @cached_property
-+ def _os_release_info(self):
-+ """
-+ Get the information items from the specified os-release file.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ if os.path.isfile(self.os_release_file):
-+ with open(self.os_release_file) as release_file:
-+ return self._parse_os_release_content(release_file)
-+ return {}
-+
-+ @staticmethod
-+ def _parse_os_release_content(lines):
-+ """
-+ Parse the lines of an os-release file.
-+
-+ Parameters:
-+
-+ * lines: Iterable through the lines in the os-release file.
-+ Each line must be a unicode string or a UTF-8 encoded byte
-+ string.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ props = {}
-+ lexer = shlex.shlex(lines, posix=True)
-+ lexer.whitespace_split = True
-+
-+ # The shlex module defines its `wordchars` variable using literals,
-+ # making it dependent on the encoding of the Python source file.
-+ # In Python 2.6 and 2.7, the shlex source file is encoded in
-+ # 'iso-8859-1', and the `wordchars` variable is defined as a byte
-+ # string. This causes a UnicodeDecodeError to be raised when the
-+ # parsed content is a unicode object. The following fix resolves that
-+ # (... but it should be fixed in shlex...):
-+ if sys.version_info[0] == 2 and isinstance(lexer.wordchars, bytes):
-+ lexer.wordchars = lexer.wordchars.decode('iso-8859-1')
-+
-+ tokens = list(lexer)
-+ for token in tokens:
-+ # At this point, all shell-like parsing has been done (i.e.
-+ # comments processed, quotes and backslash escape sequences
-+ # processed, multi-line values assembled, trailing newlines
-+ # stripped, etc.), so the tokens are now either:
-+ # * variable assignments: var=value
-+ # * commands or their arguments (not allowed in os-release)
-+ if '=' in token:
-+ k, v = token.split('=', 1)
-+ if isinstance(v, bytes):
-+ v = v.decode('utf-8')
-+ props[k.lower()] = v
-+ else:
-+ # Ignore any tokens that are not variable assignments
-+ pass
-+
-+ if 'version_codename' in props:
-+ # os-release added a version_codename field. Use that in
-+ # preference to anything else Note that some distros purposefully
-+ # do not have code names. They should be setting
-+ # version_codename=""
-+ props['codename'] = props['version_codename']
-+ elif 'ubuntu_codename' in props:
-+ # Same as above but a non-standard field name used on older Ubuntus
-+ props['codename'] = props['ubuntu_codename']
-+ elif 'version' in props:
-+ # If there is no version_codename, parse it from the version
-+ codename = re.search(r'(\(\D+\))|,(\s+)?\D+', props['version'])
-+ if codename:
-+ codename = codename.group()
-+ codename = codename.strip('()')
-+ codename = codename.strip(',')
-+ codename = codename.strip()
-+ # codename appears within paranthese.
-+ props['codename'] = codename
-+
-+ return props
-+
-+ @cached_property
-+ def _lsb_release_info(self):
-+ """
-+ Get the information items from the lsb_release command output.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ if not self.include_lsb:
-+ return {}
-+ with open(os.devnull, 'w') as devnull:
-+ try:
-+ cmd = ('lsb_release', '-a')
-+ stdout = subprocess.check_output(cmd, stderr=devnull)
-+ except OSError: # Command not found
-+ return {}
-+ content = stdout.decode(sys.getfilesystemencoding()).splitlines()
-+ return self._parse_lsb_release_content(content)
-+
-+ @staticmethod
-+ def _parse_lsb_release_content(lines):
-+ """
-+ Parse the output of the lsb_release command.
-+
-+ Parameters:
-+
-+ * lines: Iterable through the lines of the lsb_release output.
-+ Each line must be a unicode string or a UTF-8 encoded byte
-+ string.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ props = {}
-+ for line in lines:
-+ kv = line.strip('\n').split(':', 1)
-+ if len(kv) != 2:
-+ # Ignore lines without colon.
-+ continue
-+ k, v = kv
-+ props.update({k.replace(' ', '_').lower(): v.strip()})
-+ return props
-+
-+ @cached_property
-+ def _uname_info(self):
-+ with open(os.devnull, 'w') as devnull:
-+ try:
-+ cmd = ('uname', '-rs')
-+ stdout = subprocess.check_output(cmd, stderr=devnull)
-+ except OSError:
-+ return {}
-+ content = stdout.decode(sys.getfilesystemencoding()).splitlines()
-+ return self._parse_uname_content(content)
-+
-+ @staticmethod
-+ def _parse_uname_content(lines):
-+ props = {}
-+ match = re.search(r'^([^\s]+)\s+([\d\.]+)', lines[0].strip())
-+ if match:
-+ name, version = match.groups()
-+
-+ # This is to prevent the Linux kernel version from
-+ # appearing as the 'best' version on otherwise
-+ # identifiable distributions.
-+ if name == 'Linux':
-+ return {}
-+ props['id'] = name.lower()
-+ props['name'] = name
-+ props['release'] = version
-+ return props
-+
-+ @cached_property
-+ def _distro_release_info(self):
-+ """
-+ Get the information items from the specified distro release file.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ if self.distro_release_file:
-+ # If it was specified, we use it and parse what we can, even if
-+ # its file name or content does not match the expected pattern.
-+ distro_info = self._parse_distro_release_file(
-+ self.distro_release_file)
-+ basename = os.path.basename(self.distro_release_file)
-+ # The file name pattern for user-specified distro release files
-+ # is somewhat more tolerant (compared to when searching for the
-+ # file), because we want to use what was specified as best as
-+ # possible.
-+ match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
-+ if 'name' in distro_info \
-+ and 'cloudlinux' in distro_info['name'].lower():
-+ distro_info['id'] = 'cloudlinux'
-+ elif match:
-+ distro_info['id'] = match.group(1)
-+ return distro_info
-+ else:
-+ try:
-+ basenames = os.listdir(_UNIXCONFDIR)
-+ # We sort for repeatability in cases where there are multiple
-+ # distro specific files; e.g. CentOS, Oracle, Enterprise all
-+ # containing `redhat-release` on top of their own.
-+ basenames.sort()
-+ except OSError:
-+ # This may occur when /etc is not readable but we can't be
-+ # sure about the *-release files. Check common entries of
-+ # /etc for information. If they turn out to not be there the
-+ # error is handled in `_parse_distro_release_file()`.
-+ basenames = ['SuSE-release',
-+ 'arch-release',
-+ 'base-release',
-+ 'centos-release',
-+ 'fedora-release',
-+ 'gentoo-release',
-+ 'mageia-release',
-+ 'mandrake-release',
-+ 'mandriva-release',
-+ 'mandrivalinux-release',
-+ 'manjaro-release',
-+ 'oracle-release',
-+ 'redhat-release',
-+ 'sl-release',
-+ 'slackware-version']
-+ for basename in basenames:
-+ if basename in _DISTRO_RELEASE_IGNORE_BASENAMES:
-+ continue
-+ match = _DISTRO_RELEASE_BASENAME_PATTERN.match(basename)
-+ if match:
-+ filepath = os.path.join(_UNIXCONFDIR, basename)
-+ distro_info = self._parse_distro_release_file(filepath)
-+ if 'name' in distro_info:
-+ # The name is always present if the pattern matches
-+ self.distro_release_file = filepath
-+ distro_info['id'] = match.group(1)
-+ if 'cloudlinux' in distro_info['name'].lower():
-+ distro_info['id'] = 'cloudlinux'
-+ return distro_info
-+ return {}
-+
-+ def _parse_distro_release_file(self, filepath):
-+ """
-+ Parse a distro release file.
-+
-+ Parameters:
-+
-+ * filepath: Path name of the distro release file.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ try:
-+ with open(filepath) as fp:
-+ # Only parse the first line. For instance, on SLES there
-+ # are multiple lines. We don't want them...
-+ return self._parse_distro_release_content(fp.readline())
-+ except (OSError, IOError):
-+ # Ignore not being able to read a specific, seemingly version
-+ # related file.
-+ # See https://github.com/nir0s/distro/issues/162
-+ return {}
-+
-+ @staticmethod
-+ def _parse_distro_release_content(line):
-+ """
-+ Parse a line from a distro release file.
-+
-+ Parameters:
-+ * line: Line from the distro release file. Must be a unicode string
-+ or a UTF-8 encoded byte string.
-+
-+ Returns:
-+ A dictionary containing all information items.
-+ """
-+ if isinstance(line, bytes):
-+ line = line.decode('utf-8')
-+ matches = _DISTRO_RELEASE_CONTENT_REVERSED_PATTERN.match(
-+ line.strip()[::-1])
-+ distro_info = {}
-+ if matches:
-+ # regexp ensures non-None
-+ distro_info['name'] = matches.group(3)[::-1]
-+ if matches.group(2):
-+ distro_info['version_id'] = matches.group(2)[::-1]
-+ if matches.group(1):
-+ distro_info['codename'] = matches.group(1)[::-1]
-+ elif line:
-+ distro_info['name'] = line.strip()
-+ return distro_info
-+
-+
-+_distro = LinuxDistribution()
-+
-+
-+def main():
-+ logger = logging.getLogger(__name__)
-+ logger.setLevel(logging.DEBUG)
-+ logger.addHandler(logging.StreamHandler(sys.stdout))
-+
-+ parser = argparse.ArgumentParser(description="OS distro info tool")
-+ parser.add_argument(
-+ '--json',
-+ '-j',
-+ help="Output in machine readable format",
-+ action="store_true")
-+ args = parser.parse_args()
-+
-+ if args.json:
-+ logger.info(json.dumps(info(), indent=4, sort_keys=True))
-+ else:
-+ logger.info('Name: %s', name(pretty=True))
-+ distribution_version = version(pretty=True)
-+ logger.info('Version: %s', distribution_version)
-+ distribution_codename = codename()
-+ logger.info('Codename: %s', distribution_codename)
-+
-+
-+if __name__ == '__main__':
-+ main()
-diff --git a/third_party/python/distro/docs/conf.py b/third_party/python/distro/docs/conf.py
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/docs/conf.py
-@@ -0,0 +1,342 @@
-+# -*- coding: utf-8 -*-
-+#
-+# Configuration file for Sphinx builds, created by
-+# sphinx-quickstart on Wed Mar 2 11:33:06 2016.
-+#
-+# This file is execfile()d with the current directory set to its
-+# containing dir.
-+#
-+# Note that not all possible configuration values are present in this
-+# autogenerated file.
-+#
-+# All configuration values have a default; values that are commented out
-+# serve to show the default.
-+
-+import sys
-+import os
-+import re
-+
-+# If extensions (or modules to document with autodoc) are in another directory,
-+# add these directories to sys.path here. If the directory is relative to the
-+# documentation root, use os.path.abspath to make it absolute, like shown here.
-+sys.path.insert(0, os.path.abspath('..'))
-+
-+# -- General configuration ------------------------------------------------
-+
-+# If your documentation needs a minimal Sphinx version, state it here.
-+needs_sphinx = '1.1'
-+
-+# Add any Sphinx extension module names here, as strings. They can be
-+# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
-+# ones.
-+extensions = [
-+ 'sphinx.ext.autodoc',
-+ 'sphinx.ext.intersphinx',
-+ 'sphinx.ext.todo',
-+ 'sphinx.ext.coverage',
-+ 'sphinx.ext.viewcode',
-+]
-+
-+# Add any paths that contain templates here, relative to this directory.
-+templates_path = ['_templates']
-+
-+# The suffix(es) of source filenames.
-+# You can specify multiple suffix as a list of string:
-+# source_suffix = ['.rst', '.md']
-+source_suffix = '.rst'
-+
-+# The encoding of source files.
-+source_encoding = 'utf-8'
-+
-+# The master toctree document.
-+on_rtd = os.environ.get('READTHEDOCS', None) == 'True'
-+if on_rtd:
-+ master_doc = 'index'
-+else:
-+ master_doc = 'docs/index'
-+
-+# General information about the project.
-+project = u'distro'
-+copyright = u'2015,2016, Nir Cohen, Andreas Maier'
-+author = u'Nir Cohen, Andreas Maier'
-+
-+# The short description of the package.
-+_short_description = u'Linux Distribution - a Linux OS platform information API'
-+
-+# The version info for the project you're documenting, acts as replacement for
-+# |version| and |release|, also used in various other places throughout the
-+# built documents.
-+
-+def parse_version():
-+ with open('../setup.py', 'r') as _fp:
-+ _lines = _fp.readlines()
-+ for _line in _lines:
-+ m = re.match(r'^package_version *= *[\'"](.+)[\'"].*$', _line)
-+ if m:
-+ break
-+ if m:
-+ return m.group(1)
-+ else:
-+ return 'unknown'
-+
-+# The short X.Y version.
-+# Note: We use the full version in both cases.
-+version = parse_version()
-+
-+# The full version, including alpha/beta/rc tags.
-+release = version
-+
-+# The language for content autogenerated by Sphinx. Refer to documentation
-+# for a list of supported languages.
-+#
-+# This is also used if you do content translation via gettext catalogs.
-+# Usually you set "language" from the command line for these cases.
-+language = None
-+
-+# There are two options for replacing |today|: either, you set today to some
-+# non-false value, then it is used:
-+#today = ''
-+# Else, today_fmt is used as the format for a strftime call.
-+#today_fmt = '%B %d, %Y'
-+
-+# List of patterns, relative to source directory, that match files and
-+# directories to ignore when looking for source files.
-+exclude_patterns = ["tests", ".tox", ".git", "build_docs", "ld.egg-info"]
-+
-+# The reST default role (used for this markup: `text`) to use for all
-+# documents.
-+#default_role = None
-+
-+# If true, '()' will be appended to :func: etc. cross-reference text.
-+add_function_parentheses = True
-+
-+# If true, the current module name will be prepended to all description
-+# unit titles (such as .. function::).
-+#add_module_names = True
-+
-+# If true, sectionauthor and moduleauthor directives will be shown in the
-+# output. They are ignored by default.
-+#show_authors = False
-+
-+# The name of the Pygments (syntax highlighting) style to use.
-+pygments_style = 'sphinx'
-+
-+# A list of ignored prefixes for module index sorting.
-+#modindex_common_prefix = []
-+
-+# If true, keep warnings as "system message" paragraphs in the built documents.
-+#keep_warnings = False
-+
-+# If true, `todo` and `todoList` produce output, else they produce nothing.
-+todo_include_todos = True
-+
-+
-+# -- Options for HTML output ----------------------------------------------
-+
-+# The theme to use for HTML and HTML Help pages.
-+# See http://www.sphinx-doc.org/en/stable/theming.html for built-in themes.
-+html_theme = "classic"
-+
-+# Theme options are theme-specific and customize the look and feel of a theme
-+# further.
-+# See http://www.sphinx-doc.org/en/stable/theming.html for the options
-+# available for built-in themes.
-+html_theme_options = {
-+}
-+
-+# Add any paths that contain custom themes here, relative to this directory.
-+#html_theme_path = []
-+
-+# The name for this set of Sphinx documents. If not defined, it defaults to
-+# "<project> v<release> documentation".
-+#html_title = None
-+
-+# A shorter title for the navigation bar. Default is the same as html_title.
-+#html_short_title = 'distro'
-+
-+# The name of an image file (relative to this directory) to place at the top
-+# of the sidebar.
-+#html_logo = None
-+
-+# The name of an image file (relative to this directory) to use as a favicon of
-+# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
-+# pixels large.
-+#html_favicon = None
-+
-+# Add any paths that contain custom static files (such as style sheets) here,
-+# relative to this directory. They are copied after the builtin static files,
-+# so a file named "default.css" will overwrite the builtin "default.css".
-+html_static_path = ['html_static']
-+
-+# Add any extra paths that contain custom files (such as robots.txt or
-+# .htaccess) here, relative to this directory. These files are copied
-+# directly to the root of the documentation.
-+html_extra_path = ['html_extra']
-+
-+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
-+# using the given strftime format.
-+#html_last_updated_fmt = '%b %d, %Y'
-+
-+# If true, SmartyPants will be used to convert quotes and dashes to
-+# typographically correct entities.
-+#html_use_smartypants = True
-+
-+# Custom sidebar templates, maps document names to template names.
-+#html_sidebars = {}
-+
-+# Additional templates that should be rendered to pages, maps page names to
-+# template names.
-+#html_additional_pages = {}
-+
-+# If false, no module index is generated.
-+#html_domain_indices = True
-+
-+# If false, no index is generated.
-+#html_use_index = True
-+
-+# If true, the index is split into individual pages for each letter.
-+#html_split_index = False
-+
-+# If true, links to the reST sources are added to the pages.
-+#html_show_sourcelink = True
-+
-+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
-+#html_show_sphinx = True
-+
-+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
-+#html_show_copyright = True
-+
-+# If true, an OpenSearch description file will be output, and all pages will
-+# contain a <link> tag referring to it. The value of this option must be the
-+# base URL from which the finished HTML is served.
-+#html_use_opensearch = ''
-+
-+# This is the file name suffix for HTML files (e.g. ".xhtml").
-+#html_file_suffix = None
-+
-+# Language to be used for generating the HTML full-text search index.
-+# Sphinx supports the following languages:
-+# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
-+# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
-+#html_search_language = 'en'
-+
-+# A dictionary with options for the search language support, empty by default.
-+# Now only 'ja' uses this config value
-+#html_search_options = {'type': 'default'}
-+
-+# The name of a javascript file (relative to the configuration directory) that
-+# implements a search results scorer. If empty, the default will be used.
-+#html_search_scorer = 'scorer.js'
-+
-+# Output file base name for HTML help builder.
-+htmlhelp_basename = 'distro_doc'
-+
-+# -- Options for LaTeX output ---------------------------------------------
-+
-+latex_elements = {
-+# The paper size ('letterpaper' or 'a4paper').
-+#'papersize': 'letterpaper',
-+
-+# The font size ('10pt', '11pt' or '12pt').
-+#'pointsize': '10pt',
-+
-+# Additional stuff for the LaTeX preamble.
-+#'preamble': '',
-+
-+# Latex figure (float) alignment
-+#'figure_align': 'htbp',
-+}
-+
-+# Grouping the document tree into LaTeX files. List of tuples
-+# (source start file, target name, title,
-+# author, documentclass [howto, manual, or own class]).
-+latex_documents = [
-+ (master_doc, 'ld.tex', _short_description, author, 'manual'),
-+]
-+
-+# The name of an image file (relative to this directory) to place at the top of
-+# the title page.
-+#latex_logo = None
-+
-+# For "manual" documents, if this is true, then toplevel headings are parts,
-+# not chapters.
-+#latex_use_parts = False
-+
-+# If true, show page references after internal links.
-+#latex_show_pagerefs = False
-+
-+# If true, show URL addresses after external links.
-+#latex_show_urls = False
-+
-+# Documents to append as an appendix to all manuals.
-+#latex_appendices = []
-+
-+# If false, no module index is generated.
-+#latex_domain_indices = True
-+
-+
-+# -- Options for manual page output ---------------------------------------
-+
-+# One entry per manual page. List of tuples
-+# (source start file, name, description, authors, manual section).
-+man_pages = [
-+ (master_doc, 'ld', _short_description, [author], 1)
-+]
-+
-+# If true, show URL addresses after external links.
-+#man_show_urls = False
-+
-+
-+# -- Options for Texinfo output -------------------------------------------
-+
-+# Grouping the document tree into Texinfo files. List of tuples
-+# (source start file, target name, title, author,
-+# dir menu entry, description, category)
-+texinfo_documents = [
-+ (master_doc, 'LinuxDistribution', _short_description,
-+ author, 'LinuxDistribution', _short_description,
-+ 'Miscellaneous'),
-+]
-+
-+# Documents to append as an appendix to all manuals.
-+#texinfo_appendices = []
-+
-+# If false, no module index is generated.
-+#texinfo_domain_indices = True
-+
-+# How to display URL addresses: 'footnote', 'no', or 'inline'.
-+#texinfo_show_urls = 'footnote'
-+
-+# If true, do not generate a @detailmenu in the "Top" node's menu.
-+#texinfo_no_detailmenu = False
-+
-+
-+# -- Options for autodoc extension ----------------------------------------
-+# For documentation, see
-+# http://www.sphinx-doc.org/en/stable/ext/autodoc.html
-+
-+# Selects what content will be inserted into a class description.
-+# The possible values are:
-+# "class" - Only the class’ docstring is inserted. This is the default.
-+# "both" - Both the class’ and the __init__ method’s docstring are
-+# concatenated and inserted.
-+# "init" - Only the __init__ method’s docstring is inserted.
-+autoclass_content = "both"
-+
-+# Selects if automatically documented members are sorted alphabetically
-+# (value 'alphabetical'), by member type (value 'groupwise') or by source
-+# order (value 'bysource'). The default is alphabetical.
-+autodoc_member_order = "bysource"
-+
-+# -- Options for intersphinx extension ------------------------------------
-+# For documentation, see
-+# http://www.sphinx-doc.org/en/stable/ext/intersphinx.html
-+
-+# Defines the prefixes for intersphinx links, and the targets they resolve
-+# to. Example RST source for 'py' prefix:
-+# :py:func:`platform.dist`
-+intersphinx_mapping = {
-+ 'py': ('https://docs.python.org/3.5', None)
-+}
-+
-+intersphinx_cache_limit = 5
-diff --git a/third_party/python/distro/docs/index.rst b/third_party/python/distro/docs/index.rst
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/docs/index.rst
-@@ -0,0 +1,476 @@
-+
-+.. _distro official repo: https://github.com/nir0s/distro
-+.. _distro issue tracker: https://github.com/nir0s/distro/issues
-+.. _open issues on missing test data: https://github.com/nir0s/distro/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22>
-+
-+
-+**distro** package (Linux Distribution) version |version|
-+*********************************************************
-+
-+Official distro repository: `distro official repo`_
-+
-+Overview and motivation
-+=======================
-+
-+.. automodule:: distro
-+
-+If you want to jump into the API description right away, read about the
-+`consolidated accessor functions`_.
-+
-+Compatibility
-+=============
-+
-+The ``distro`` package is supported on Python 2.7, 3.4+ and PyPy, and on
-+any Linux or *BSD distribution that provides one or more of the `data sources`_
-+used by this package.
-+
-+This package is tested on Python 2.7, 3.4+ and PyPy, with test data that
-+mimics the exact behavior of the data sources of
-+`a number of Linux distributions <https://github.com/nir0s/distro/tree/master/tests/resources/distros>`_.
-+
-+If you want to add test data for more distributions, please
-+create an issue in the `distro issue tracker`_
-+and provide the following information in the issue:
-+
-+* The content of the `/etc/os-release` file, if any.
-+* The file names and content of the `/etc/*release` and `/etc/*version` files, if any.
-+* The output of the command: `lsb_release -a`, if available.
-+* The file names and content of any other files you are aware of that provide
-+ useful information about the distro.
-+
-+There are already some `open issues on missing test data`_.
-+
-+
-+Data sources
-+============
-+
-+The ``distro`` package implements a robust and inclusive way of retrieving the
-+information about a Linux distribution based on new standards and old methods,
-+namely from these data sources:
-+
-+* The `os-release file`_, if present.
-+
-+* The `lsb_release command output`_, if the lsb_release command is available.
-+
-+* The `distro release file`_, if present.
-+
-+* The `uname command output`_, if present.
-+
-+
-+Access to the information
-+=========================
-+
-+This package provides three ways to access the information about a Linux
-+distribution:
-+
-+* `Consolidated accessor functions`_
-+
-+ These are module-global functions that take into account all data sources in
-+ a priority order, and that return information about the current Linux
-+ distribution.
-+
-+ These functions should be the normal way to access the information.
-+
-+ The precedence of data sources is applied for each information item
-+ separately. Therefore, it is possible that not all information items returned
-+ by these functions come from the same data source. For example, on a
-+ distribution that has an lsb_release command that returns the
-+ "Distributor ID" field but not the "Codename" field, and that has a distro
-+ release file that specifies a codename inside, the distro ID will come from
-+ the lsb_release command (because it has higher precedence), and the codename
-+ will come from the distro release file (because it is not provided by the
-+ lsb_release command).
-+
-+ Examples: :func:`distro.id` for retrieving
-+ the distro ID, or :func:`ld.info` to get the machine-readable part of the
-+ information in a more aggregated way, or :func:`distro.linux_distribution` with
-+ an interface that is compatible to the original
-+ :py:func:`platform.linux_distribution` function, supporting a subset of its
-+ parameters.
-+
-+* `Single source accessor functions`_
-+
-+ These are module-global functions that take into account a single data
-+ source, and that return information about the current Linux distribution.
-+
-+ They are useful for distributions that provide multiple inconsistent data
-+ sources, or for retrieving information items that are not provided by the
-+ consolidated accessor functions.
-+
-+ Examples: :func:`distro.os_release_attr` for retrieving a single information
-+ item from the os-release data source, or :func:`distro.lsb_release_info` for
-+ retrieving all information items from the lsb_release command output data
-+ source.
-+
-+* `LinuxDistribution class`_
-+
-+ The :class:`distro.LinuxDistribution` class provides the main code of this
-+ package.
-+
-+ This package contains a private module-global :class:`distro.LinuxDistribution`
-+ instance with default initialization arguments, that is used by the
-+ consolidated and single source accessor functions.
-+
-+ A user-defined instance of the :class:`distro.LinuxDistribution` class allows
-+ specifying the path names of the os-release file and distro release file and
-+ whether the lsb_release command should be used or not. That is useful for
-+ example when the distribution information from a chrooted environment
-+ is to be retrieved, or when a distro has multiple distro release files and
-+ the default algorithm uses the wrong one.
-+
-+
-+Consolidated accessor functions
-+===============================
-+
-+This section describes the consolidated accessor functions.
-+See `access to the information`_ for a discussion of the different kinds of
-+accessor functions.
-+
-+.. autofunction:: distro.linux_distribution
-+.. autofunction:: distro.id
-+.. autofunction:: distro.name
-+.. autofunction:: distro.version
-+.. autofunction:: distro.version_parts
-+.. autofunction:: distro.major_version
-+.. autofunction:: distro.minor_version
-+.. autofunction:: distro.build_number
-+.. autofunction:: distro.like
-+.. autofunction:: distro.codename
-+.. autofunction:: distro.info
-+
-+Single source accessor functions
-+================================
-+
-+This section describes the single source accessor functions.
-+See `access to the information`_ for a discussion of the different kinds of
-+accessor functions.
-+
-+.. autofunction:: distro.os_release_info
-+.. autofunction:: distro.lsb_release_info
-+.. autofunction:: distro.distro_release_info
-+.. autofunction:: distro.os_release_attr
-+.. autofunction:: distro.lsb_release_attr
-+.. autofunction:: distro.distro_release_attr
-+
-+LinuxDistribution class
-+=======================
-+
-+This section describes the access via the :class:`distro.LinuxDistribution` class.
-+See `access to the information`_ for a discussion of the different kinds of
-+accessor functions.
-+
-+.. autoclass:: distro.LinuxDistribution
-+ :members:
-+ :undoc-members:
-+
-+Normalization tables
-+====================
-+
-+These translation tables are used to normalize the parsed distro ID values
-+into reliable IDs. See :func:`distro.id` for details.
-+
-+They are documented in order to show for which distros a normalization is
-+currently defined.
-+
-+As a quick fix, these tables can also be extended by the user by appending new
-+entries, should the need arise. If you have a need to get these tables
-+extended, please make an according request in the `distro issue tracker`_.
-+
-+.. autodata:: distro.NORMALIZED_OS_ID
-+.. autodata:: distro.NORMALIZED_LSB_ID
-+.. autodata:: distro.NORMALIZED_DISTRO_ID
-+
-+Os-release file
-+===============
-+
-+The os-release file is looked up using the path name ``/etc/os-release``. Its
-+optional additional location ``/usr/lib/os-release`` is ignored.
-+
-+The os-release file is expected to be encoded in UTF-8.
-+
-+It is parsed using the standard Python :py:mod:`shlex` package, which treats it
-+like a shell script.
-+
-+The attribute names found in the file are translated to lower case and then
-+become the keys of the information items from the os-release file data source.
-+These keys can be used to retrieve single items with the
-+:func:`distro.os_release_attr` function, and they are also used as keys in the
-+dictionary returned by :func:`distro.os_release_info`.
-+
-+The attribute values found in the file are processed using shell rules (e.g.
-+for whitespace, escaping, and quoting) before they become the values of the
-+information items from the os-release file data source.
-+
-+If the attribute "VERSION" is found in the file, the distro codename is
-+extracted from its value if it can be found there. If a codename is found, it
-+becomes an additional information item with key "codename".
-+
-+See the `os-release man page
-+<http://www.freedesktop.org/software/systemd/man/os-release.html>`_
-+for a list of possible attributes in the file.
-+
-+**Examples:**
-+
-+1. The following os-release file content:
-+
-+ .. sourcecode:: shell
-+
-+ NAME='Ubuntu'
-+ VERSION="14.04.3 LTS, Trusty Tahr"
-+ ID=ubuntu
-+ ID_LIKE=debian
-+ PRETTY_NAME="Ubuntu 14.04.3 LTS"
-+ VERSION_ID="14.04"
-+ HOME_URL="http://www.ubuntu.com/"
-+ SUPPORT_URL="http://help.ubuntu.com/"
-+ BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ name "Ubuntu"
-+ version "14.04.3 LTS, Trusty Tahr"
-+ id "ubuntu"
-+ id_like "debian"
-+ pretty_name "Ubuntu 14.04.3 LTS"
-+ version_id "14.04"
-+ home_url "http://www.ubuntu.com/"
-+ support_url "http://help.ubuntu.com/"
-+ bug_report_url "http://bugs.launchpad.net/ubuntu/"
-+ codename "Trusty Tahr"
-+ =============================== ==========================================
-+
-+2. The following os-release file content:
-+
-+ .. sourcecode:: shell
-+
-+ NAME="Red Hat Enterprise Linux Server"
-+ VERSION="7.0 (Maipo)"
-+ ID="rhel"
-+ ID_LIKE="fedora"
-+ VERSION_ID="7.0"
-+ PRETTY_NAME="Red Hat Enterprise Linux Server 7.0 (Maipo)"
-+ ANSI_COLOR="0;31"
-+ CPE_NAME="cpe:/o:redhat:enterprise_linux:7.0:GA:server"
-+ HOME_URL="https://www.redhat.com/"
-+ BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+
-+ REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
-+ REDHAT_BUGZILLA_PRODUCT_VERSION=7.0
-+ REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
-+ REDHAT_SUPPORT_PRODUCT_VERSION=7.0
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ name "Red Hat Enterprise Linux Server"
-+ version "7.0 (Maipo)"
-+ id "rhel"
-+ id_like "fedora"
-+ version_id "7.0"
-+ pretty_name "Red Hat Enterprise Linux Server 7.0 (Maipo)"
-+ ansi_color "0;31"
-+ cpe_name "cpe:/o:redhat:enterprise_linux:7.0:GA:server"
-+ home_url "https://www.redhat.com/"
-+ bug_report_url "https://bugzilla.redhat.com/"
-+ redhat_bugzilla_product "Red Hat Enterprise Linux 7"
-+ redhat_bugzilla_product_version "7.0"
-+ redhat_support_product "Red Hat Enterprise Linux"
-+ redhat_support_product_version "7.0"
-+ codename "Maipo"
-+ =============================== ==========================================
-+
-+Lsb_release command output
-+==========================
-+
-+The lsb_release command is expected to be in the PATH, and is invoked as
-+follows:
-+
-+.. sourcecode:: shell
-+
-+ lsb_release -a
-+
-+The command output is expected to be encoded in UTF-8.
-+
-+Only lines in the command output with the following format will be used:
-+
-+ ``<attr-name>: <attr-value>``
-+
-+Where:
-+
-+* ``<attr-name>`` is the name of the attribute, and
-+* ``<attr-value>`` is the attribute value.
-+
-+The attribute names are stripped from surrounding blanks, any remaining blanks
-+are translated to underscores, they are translated to lower case, and then
-+become the keys of the information items from the lsb_release command output
-+data source.
-+
-+The attribute values are stripped from surrounding blanks, and then become the
-+values of the information items from the lsb_release command output data
-+source.
-+
-+See the `lsb_release man page
-+<http://refspecs.linuxfoundation.org/LSB_5.0.0/LSB-Core-generic/
-+LSB-Core-generic/lsbrelease.html>`_
-+for a description of standard attributes returned by the lsb_release command.
-+
-+**Examples:**
-+
-+1. The following lsb_release command output:
-+
-+ .. sourcecode:: text
-+
-+ No LSB modules are available.
-+ Distributor ID: Ubuntu
-+ Description: Ubuntu 14.04.3 LTS
-+ Release: 14.04
-+ Codename: trusty
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ distributor_id "Ubuntu"
-+ description "Ubuntu 14.04.3 LTS"
-+ release "14.04"
-+ codename "trusty"
-+ =============================== ==========================================
-+
-+2. The following lsb_release command output:
-+
-+ .. sourcecode:: text
-+
-+ LSB Version: n/a
-+ Distributor ID: SUSE LINUX
-+ Description: SUSE Linux Enterprise Server 12 SP1
-+ Release: 12.1
-+ Codename: n/a
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ lsb_version "n/a"
-+ distributor_id "SUSE LINUX"
-+ description "SUSE Linux Enterprise Server 12 SP1"
-+ release "12.1"
-+ codename "n/a"
-+ =============================== ==========================================
-+
-+Distro release file
-+===================
-+
-+Unless specified with a particular path name when using the
-+:class:`distro.LinuxDistribution` class, the distro release file is found by using
-+the first match in the alphabetically sorted list of the files matching the
-+following path name patterns:
-+
-+* ``/etc/*-release``
-+* ``/etc/*_release``
-+* ``/etc/*-version``
-+* ``/etc/*_version``
-+
-+where the following special path names are excluded:
-+
-+* ``/etc/debian_version``
-+* ``/etc/system-release``
-+* ``/etc/os-release``
-+
-+and where the first line within the file has the expected format.
-+
-+The algorithm to sort the files alphabetically is far from perfect, but the
-+distro release file has the least priority as a data source, and it is expected
-+that distributions provide one of the other data sources.
-+
-+The distro release file is expected to be encoded in UTF-8.
-+
-+Only its first line is used, and it is expected to have the following format:
-+
-+ ``<name> [[[release] <version_id>] (<codename>)]``
-+
-+Where:
-+
-+* square brackets indicate optionality,
-+* ``<name>`` is the distro name,
-+* ``<version_id>`` is the distro version, and
-+* ``<codename>`` is the distro codename.
-+
-+The following information items can be found in a distro release file
-+(shown with their keys and data types):
-+
-+* ``id`` (string): Distro ID, taken from the first part of the file name
-+ before the hyphen (``-``) or underscore (``_``).
-+
-+ Note that the distro ID is not normalized or translated to lower case at this
-+ point; this happens only for the result of the :func:`distro.id` function.
-+
-+* ``name`` (string): Distro name, as found in the first line of the file.
-+
-+* ``version_id`` (string): Distro version, as found in the first line of the
-+ file. If not found, this information item will not exist.
-+
-+* ``codename`` (string): Distro codename, as found in the first line of the
-+ file. If not found, this information item will not exist.
-+
-+ Note that the string in the codename field is not always really a
-+ codename. For example, openSUSE returns "x86_64".
-+
-+**Examples:**
-+
-+1. The following distro release file ``/etc/centos-release``:
-+
-+ .. sourcecode:: text
-+
-+ CentOS Linux release 7.1.1503 (Core)
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ id "centos"
-+ name "CentOS Linux"
-+ version_id "7.1.1503"
-+ codename "Core"
-+ =============================== ==========================================
-+
-+2. The following distro release file ``/etc/oracle-release``:
-+
-+ .. sourcecode:: text
-+
-+ Oracle Linux Server release 7.1
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ id "oracle"
-+ name "Oracle Linux Server"
-+ version_id "7.1"
-+ =============================== ==========================================
-+
-+3. The following distro release file ``/etc/SuSE-release``:
-+
-+ .. sourcecode:: text
-+
-+ openSUSE 42.1 (x86_64)
-+
-+ results in these information items:
-+
-+ =============================== ==========================================
-+ Key Value
-+ =============================== ==========================================
-+ id "SuSE"
-+ name "openSUSE"
-+ version_id "42.1"
-+ codename "x86_64"
-+ =============================== ==========================================
-+
-diff --git a/third_party/python/distro/query_local_distro.py b/third_party/python/distro/query_local_distro.py
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/query_local_distro.py
-@@ -0,0 +1,45 @@
-+#!/usr/bin/env python
-+# Copyright 2015,2016 Nir Cohen
-+#
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+#
-+# http://www.apache.org/licenses/LICENSE-2.0
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+
-+from __future__ import print_function
-+
-+from pprint import pformat
-+
-+import distro
-+
-+
-+def pprint(obj):
-+ for line in pformat(obj).split('\n'):
-+ print(4 * ' ' + line)
-+
-+
-+print('os_release_info:')
-+pprint(distro.os_release_info())
-+print('lsb_release_info:')
-+pprint(distro.lsb_release_info())
-+print('distro_release_info:')
-+pprint(distro.distro_release_info())
-+print('id: {0}'.format(distro.id()))
-+print('name: {0}'.format(distro.name()))
-+print('name_pretty: {0}'.format(distro.name(True)))
-+print('version: {0}'.format(distro.version()))
-+print('version_pretty: {0}'.format(distro.version(True)))
-+print('like: {0}'.format(distro.like()))
-+print('codename: {0}'.format(distro.codename()))
-+print('linux_distribution_full: {0}'.format(distro.linux_distribution()))
-+print('linux_distribution: {0}'.format(distro.linux_distribution(False)))
-+print('major_version: {0}'.format(distro.major_version()))
-+print('minor_version: {0}'.format(distro.minor_version()))
-+print('build_number: {0}'.format(distro.build_number()))
-diff --git a/third_party/python/distro/setup.cfg b/third_party/python/distro/setup.cfg
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/setup.cfg
-@@ -0,0 +1,10 @@
-+[bdist_wheel]
-+universal = 1
-+
-+[metadata]
-+license_file = LICENSE
-+
-+[egg_info]
-+tag_build =
-+tag_date = 0
-+
-diff --git a/third_party/python/distro/setup.py b/third_party/python/distro/setup.py
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/setup.py
-@@ -0,0 +1,67 @@
-+# Copyright 2015,2016 Nir Cohen
-+#
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+#
-+# http://www.apache.org/licenses/LICENSE-2.0
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+
-+import os
-+import codecs
-+from setuptools import setup
-+
-+# The following version is parsed by other parts of this package.
-+# Don't change the format of the line, or the variable name.
-+package_version = "1.4.0"
-+
-+here = os.path.abspath(os.path.dirname(__file__))
-+
-+
-+def read(*parts):
-+ # intentionally *not* adding an encoding option to open
-+ return codecs.open(os.path.join(here, *parts), 'r').read()
-+
-+
-+setup(
-+ name='distro',
-+ version=package_version,
-+ url='https://github.com/nir0s/distro',
-+ author='Nir Cohen',
-+ author_email='nir36g@gmail.com',
-+ license='Apache License, Version 2.0',
-+ platforms='All',
-+ description='Distro - an OS platform information API',
-+ long_description=read('README.md'),
-+ long_description_content_type='text/markdown',
-+ py_modules=['distro'],
-+ entry_points={
-+ 'console_scripts': [
-+ 'distro = distro:main',
-+ ]
-+ },
-+ classifiers=[
-+ 'Development Status :: 5 - Production/Stable',
-+ 'Intended Audience :: Developers',
-+ 'Intended Audience :: System Administrators',
-+ 'License :: OSI Approved :: Apache Software License',
-+ 'Operating System :: POSIX :: Linux',
-+ 'Operating System :: POSIX :: BSD',
-+ 'Operating System :: POSIX :: BSD :: FreeBSD',
-+ 'Operating System :: POSIX :: BSD :: NetBSD',
-+ 'Operating System :: POSIX :: BSD :: OpenBSD',
-+ 'Programming Language :: Python :: 2',
-+ 'Programming Language :: Python :: 2.7',
-+ 'Programming Language :: Python :: 3',
-+ 'Programming Language :: Python :: 3.4',
-+ 'Programming Language :: Python :: 3.5',
-+ 'Programming Language :: Python :: 3.6',
-+ 'Topic :: Software Development :: Libraries :: Python Modules',
-+ 'Topic :: System :: Operating System',
-+ ]
-+)
-diff --git a/third_party/python/distro/tests/__init__.py b/third_party/python/distro/tests/__init__.py
-new file mode 100644
-diff --git a/third_party/python/distro/tests/resources/distros/__shared__/bin/lsb_release b/third_party/python/distro/tests/resources/distros/__shared__/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/__shared__/bin/lsb_release
-@@ -0,0 +1,43 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+if [[ -n $LSB_VERSION ]]; then
-+ echo "LSB Version: $LSB_VERSION"
-+else
-+ echo "No LSB modules are available."
-+fi
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/amazon2014/etc/system-release b/third_party/python/distro/tests/resources/distros/amazon2014/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/amazon2014/etc/system-release
-@@ -0,0 +1,1 @@
-+Amazon Linux AMI release 2014.03
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/amazon2016/etc/os-release b/third_party/python/distro/tests/resources/distros/amazon2016/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/amazon2016/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME="Amazon Linux AMI"
-+VERSION="2016.03"
-+ID="amzn"
-+ID_LIKE="rhel fedora"
-+VERSION_ID="2016.03"
-+PRETTY_NAME="Amazon Linux AMI 2016.03"
-+ANSI_COLOR="0;33"
-+CPE_NAME="cpe:/o:amazon:linux:2016.03:ga"
-+HOME_URL="http://aws.amazon.com/amazon-linux-ami/"
-diff --git a/third_party/python/distro/tests/resources/distros/amazon2016/etc/system-release b/third_party/python/distro/tests/resources/distros/amazon2016/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/amazon2016/etc/system-release
-@@ -0,0 +1,1 @@
-+Amazon Linux AMI release 2016.03
-diff --git a/third_party/python/distro/tests/resources/distros/arch/etc/arch-release b/third_party/python/distro/tests/resources/distros/arch/etc/arch-release
-new file mode 100644
-diff --git a/third_party/python/distro/tests/resources/distros/arch/etc/os-release b/third_party/python/distro/tests/resources/distros/arch/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/arch/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME="Arch Linux"
-+ID=arch
-+PRETTY_NAME="Arch Linux"
-+ANSI_COLOR="0;36"
-+HOME_URL="https://www.archlinux.org/"
-+SUPPORT_URL="https://bbs.archlinux.org/"
-+BUG_REPORT_URL="https://bugs.archlinux.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/arch/usr/lib/os-release b/third_party/python/distro/tests/resources/distros/arch/usr/lib/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/arch/usr/lib/os-release
-@@ -0,0 +1,7 @@
-+NAME="Arch Linux"
-+ID=arch
-+PRETTY_NAME="Arch Linux"
-+ANSI_COLOR="0;36"
-+HOME_URL="https://www.archlinux.org/"
-+SUPPORT_URL="https://bbs.archlinux.org/"
-+BUG_REPORT_URL="https://bugs.archlinux.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/centos5/etc/centos-release b/third_party/python/distro/tests/resources/distros/centos5/etc/centos-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos5/etc/centos-release
-@@ -0,0 +1,1 @@
-+CentOS release 5.11 (Final)
-diff --git a/third_party/python/distro/tests/resources/distros/centos5/etc/redhat-release b/third_party/python/distro/tests/resources/distros/centos5/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos5/etc/redhat-release
-@@ -0,0 +1,1 @@
-+CentOS release 5.11 (Final)
-diff --git a/third_party/python/distro/tests/resources/distros/centos5/etc/system-release b/third_party/python/distro/tests/resources/distros/centos5/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos5/etc/system-release
-@@ -0,0 +1,1 @@
-+CentOS release 5.11 (Final)
-diff --git a/third_party/python/distro/tests/resources/distros/centos7/etc/centos-release b/third_party/python/distro/tests/resources/distros/centos7/etc/centos-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos7/etc/centos-release
-@@ -0,0 +1,1 @@
-+CentOS Linux release 7.1.1503 (Core)
-diff --git a/third_party/python/distro/tests/resources/distros/centos7/etc/os-release b/third_party/python/distro/tests/resources/distros/centos7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos7/etc/os-release
-@@ -0,0 +1,16 @@
-+NAME="CentOS Linux"
-+VERSION="7 (Core)"
-+ID="centos"
-+ID_LIKE="rhel fedora"
-+VERSION_ID="7"
-+PRETTY_NAME="CentOS Linux 7 (Core)"
-+ANSI_COLOR="0;31"
-+CPE_NAME="cpe:/o:centos:centos:7"
-+HOME_URL="https://www.centos.org/"
-+BUG_REPORT_URL="https://bugs.centos.org/"
-+
-+CENTOS_MANTISBT_PROJECT="CentOS-7"
-+CENTOS_MANTISBT_PROJECT_VERSION="7"
-+REDHAT_SUPPORT_PRODUCT="centos"
-+REDHAT_SUPPORT_PRODUCT_VERSION="7"
-+
-diff --git a/third_party/python/distro/tests/resources/distros/centos7/etc/redhat-release b/third_party/python/distro/tests/resources/distros/centos7/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos7/etc/redhat-release
-@@ -0,0 +1,1 @@
-+CentOS Linux release 7.1.1503 (Core)
-diff --git a/third_party/python/distro/tests/resources/distros/centos7/etc/system-release b/third_party/python/distro/tests/resources/distros/centos7/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/centos7/etc/system-release
-@@ -0,0 +1,1 @@
-+CentOS Linux release 7.1.1503 (Core)
-diff --git a/third_party/python/distro/tests/resources/distros/cloudlinux5/etc/redhat-release b/third_party/python/distro/tests/resources/distros/cloudlinux5/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/cloudlinux5/etc/redhat-release
-@@ -0,0 +1,1 @@
-+CloudLinux Server release 5.11 (Vladislav Volkov)
-diff --git a/third_party/python/distro/tests/resources/distros/cloudlinux6/etc/redhat-release b/third_party/python/distro/tests/resources/distros/cloudlinux6/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/cloudlinux6/etc/redhat-release
-@@ -0,0 +1,1 @@
-+CloudLinux Server release 6.8 (Oleg Makarov)
-diff --git a/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/os-release b/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/os-release
-@@ -0,0 +1,10 @@
-+NAME="CloudLinux"
-+VERSION="7.3 (Yury Malyshev)"
-+ID="cloudlinux"
-+ID_LIKE="rhel fedora centos"
-+VERSION_ID="7.3"
-+PRETTY_NAME="CloudLinux 7.3 (Yury Malyshev)"
-+ANSI_COLOR="0:31"
-+CPE_NAME="cpe:/o:cloudlinux:cloudlinux:7.3:GA:server"
-+HOME_URL="https://www.cloudlinux.com/"
-+BUG_REPORT_URL="https://helpdesk.cloudlinux.com/"
-diff --git a/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/redhat-release b/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/cloudlinux7/etc/redhat-release
-@@ -0,0 +1,1 @@
-+CloudLinux release 7.3 (Yury Malyshev)
-diff --git a/third_party/python/distro/tests/resources/distros/coreos/etc/oem-release b/third_party/python/distro/tests/resources/distros/coreos/etc/oem-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/coreos/etc/oem-release
-@@ -0,0 +1,5 @@
-+ID=digitalocean
-+VERSION_ID=0.0.4
-+NAME="DigitalOcean"
-+HOME_URL="https://www.digitalocean.com/"
-+BUG_REPORT_URL="https://github.com/coreos/bugs/issues"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/coreos/etc/os-release b/third_party/python/distro/tests/resources/distros/coreos/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/coreos/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME=CoreOS
-+ID=coreos
-+VERSION=899.15.0
-+VERSION_ID=899.15.0
-+BUILD_ID=2016-04-05-1035
-+PRETTY_NAME="CoreOS 899.15.0"
-+ANSI_COLOR="1;32"
-+HOME_URL="https://coreos.com/"
-+BUG_REPORT_URL="https://github.com/coreos/bugs/issues"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/debian8/bin/lsb_release b/third_party/python/distro/tests/resources/distros/debian8/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/debian8/bin/lsb_release
-@@ -0,0 +1,21 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command works without a corresponding
-+# etc/lsb-release file.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+echo "No LSB modules are available."
-+echo "Distributor ID: Debian"
-+echo "Description: Debian GNU/Linux 8.2 (jessie)"
-+echo "Release: 8.2"
-+echo "Codename: jessie"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/debian8/etc/debian_version b/third_party/python/distro/tests/resources/distros/debian8/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/debian8/etc/debian_version
-@@ -0,0 +1,1 @@
-+8.2
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/debian8/etc/os-release b/third_party/python/distro/tests/resources/distros/debian8/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/debian8/etc/os-release
-@@ -0,0 +1,8 @@
-+PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
-+NAME="Debian GNU/Linux"
-+VERSION_ID="8"
-+VERSION="8 (jessie)"
-+ID=debian
-+HOME_URL="http://www.debian.org/"
-+SUPPORT_URL="http://www.debian.org/support/"
-+BUG_REPORT_URL="https://bugs.debian.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/exherbo/etc/os-release b/third_party/python/distro/tests/resources/distros/exherbo/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/exherbo/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME="Exherbo"
-+PRETTY_NAME="Exherbo Linux"
-+ID="exherbo"
-+ANSI_COLOR="0;32"
-+HOME_URL="https://www.exherbo.org/"
-+SUPPORT_URL="irc://irc.freenode.net/#exherbo"
-+BUG_REPORT_URL="https://bugs.exherbo.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/fedora-release b/third_party/python/distro/tests/resources/distros/fedora19/etc/fedora-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/fedora-release
-@@ -0,0 +1,1 @@
-+Fedora release 19 (Schrödinger’s Cat)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/issue b/third_party/python/distro/tests/resources/distros/fedora19/etc/issue
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/issue
-@@ -0,0 +1,3 @@
-+Fedora release 19 (Schrödinger’s Cat)
-+Kernel \r on an \m (\l)
-+
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/issue.net b/third_party/python/distro/tests/resources/distros/fedora19/etc/issue.net
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/issue.net
-@@ -0,0 +1,2 @@
-+Fedora release 19 (Schrödinger’s Cat)
-+Kernel \r on an \m (\l)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/os-release b/third_party/python/distro/tests/resources/distros/fedora19/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME=Fedora
-+VERSION="19 (Schrödinger’s Cat)"
-+ID=fedora
-+VERSION_ID=19
-+PRETTY_NAME="Fedora 19 (Schrödinger’s Cat)"
-+ANSI_COLOR="0;34"
-+CPE_NAME="cpe:/o:fedoraproject:fedora:19"
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/redhat-release b/third_party/python/distro/tests/resources/distros/fedora19/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Fedora release 19 (Schrödinger’s Cat)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release b/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release
-@@ -0,0 +1,1 @@
-+Fedora release 19 (Schrödinger’s Cat)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release-cpe b/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release-cpe
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora19/etc/system-release-cpe
-@@ -0,0 +1,1 @@
-+cpe:/o:fedoraproject:fedora:19
-diff --git a/third_party/python/distro/tests/resources/distros/fedora23/etc/fedora-release b/third_party/python/distro/tests/resources/distros/fedora23/etc/fedora-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora23/etc/fedora-release
-@@ -0,0 +1,1 @@
-+Fedora release 23 (Twenty Three)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora23/etc/os-release b/third_party/python/distro/tests/resources/distros/fedora23/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora23/etc/os-release
-@@ -0,0 +1,14 @@
-+NAME=Fedora
-+VERSION="23 (Twenty Three)"
-+ID=fedora
-+VERSION_ID=23
-+PRETTY_NAME="Fedora 23 (Twenty Three)"
-+ANSI_COLOR="0;34"
-+CPE_NAME="cpe:/o:fedoraproject:fedora:23"
-+HOME_URL="https://fedoraproject.org/"
-+BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+REDHAT_BUGZILLA_PRODUCT="Fedora"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=23
-+REDHAT_SUPPORT_PRODUCT="Fedora"
-+REDHAT_SUPPORT_PRODUCT_VERSION=23
-+PRIVACY_POLICY_URL=https://fedoraproject.org/wiki/Legal:PrivacyPolicy
-diff --git a/third_party/python/distro/tests/resources/distros/fedora23/etc/redhat-release b/third_party/python/distro/tests/resources/distros/fedora23/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora23/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Fedora release 23 (Twenty Three)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora23/etc/system-release b/third_party/python/distro/tests/resources/distros/fedora23/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora23/etc/system-release
-@@ -0,0 +1,1 @@
-+Fedora release 23 (Twenty Three)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora23/usr/lib/os-release b/third_party/python/distro/tests/resources/distros/fedora23/usr/lib/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora23/usr/lib/os-release
-@@ -0,0 +1,14 @@
-+NAME=Fedora
-+VERSION="23 (Twenty Three)"
-+ID=fedora
-+VERSION_ID=23
-+PRETTY_NAME="Fedora 23 (Twenty Three)"
-+ANSI_COLOR="0;34"
-+CPE_NAME="cpe:/o:fedoraproject:fedora:23"
-+HOME_URL="https://fedoraproject.org/"
-+BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+REDHAT_BUGZILLA_PRODUCT="Fedora"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=23
-+REDHAT_SUPPORT_PRODUCT="Fedora"
-+REDHAT_SUPPORT_PRODUCT_VERSION=23
-+PRIVACY_POLICY_URL=https://fedoraproject.org/wiki/Legal:PrivacyPolicy
-diff --git a/third_party/python/distro/tests/resources/distros/fedora30/etc/fedora-release b/third_party/python/distro/tests/resources/distros/fedora30/etc/fedora-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora30/etc/fedora-release
-@@ -0,0 +1,1 @@
-+Fedora release 30 (Thirty)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora30/etc/os-release b/third_party/python/distro/tests/resources/distros/fedora30/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora30/etc/os-release
-@@ -0,0 +1,19 @@
-+NAME=Fedora
-+VERSION="30 (Thirty)"
-+ID=fedora
-+VERSION_ID=30
-+VERSION_CODENAME=""
-+PLATFORM_ID="platform:f30"
-+PRETTY_NAME="Fedora 30 (Thirty)"
-+ANSI_COLOR="0;34"
-+LOGO=fedora-logo-icon
-+CPE_NAME="cpe:/o:fedoraproject:fedora:30"
-+HOME_URL="https://fedoraproject.org/"
-+DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/30/system-administrators-guide/"
-+SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
-+BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+REDHAT_BUGZILLA_PRODUCT="Fedora"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=30
-+REDHAT_SUPPORT_PRODUCT="Fedora"
-+REDHAT_SUPPORT_PRODUCT_VERSION=30
-+PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
-diff --git a/third_party/python/distro/tests/resources/distros/fedora30/etc/redhat-release b/third_party/python/distro/tests/resources/distros/fedora30/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora30/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Fedora release 30 (Thirty)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora30/etc/system-release b/third_party/python/distro/tests/resources/distros/fedora30/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora30/etc/system-release
-@@ -0,0 +1,1 @@
-+Fedora release 30 (Thirty)
-diff --git a/third_party/python/distro/tests/resources/distros/fedora30/usr/lib/os-release b/third_party/python/distro/tests/resources/distros/fedora30/usr/lib/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/fedora30/usr/lib/os-release
-@@ -0,0 +1,19 @@
-+NAME=Fedora
-+VERSION="30 (Thirty)"
-+ID=fedora
-+VERSION_ID=30
-+VERSION_CODENAME=""
-+PLATFORM_ID="platform:f30"
-+PRETTY_NAME="Fedora 30 (Thirty)"
-+ANSI_COLOR="0;34"
-+LOGO=fedora-logo-icon
-+CPE_NAME="cpe:/o:fedoraproject:fedora:30"
-+HOME_URL="https://fedoraproject.org/"
-+DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/30/system-administrators-guide/"
-+SUPPORT_URL="https://fedoraproject.org/wiki/Communicating_and_getting_help"
-+BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+REDHAT_BUGZILLA_PRODUCT="Fedora"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=30
-+REDHAT_SUPPORT_PRODUCT="Fedora"
-+REDHAT_SUPPORT_PRODUCT_VERSION=30
-+PRIVACY_POLICY_URL="https://fedoraproject.org/wiki/Legal:PrivacyPolicy"
-diff --git a/third_party/python/distro/tests/resources/distros/freebsd111/bin/uname b/third_party/python/distro/tests/resources/distros/freebsd111/bin/uname
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/freebsd111/bin/uname
-@@ -0,0 +1,4 @@
-+#!/bin/sh
-+
-+echo "FreeBSD 11.1-RELEASE"
-+
-diff --git a/third_party/python/distro/tests/resources/distros/gentoo/etc/gentoo-release b/third_party/python/distro/tests/resources/distros/gentoo/etc/gentoo-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/gentoo/etc/gentoo-release
-@@ -0,0 +1,1 @@
-+Gentoo Base System release 2.2
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/gentoo/etc/os-release b/third_party/python/distro/tests/resources/distros/gentoo/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/gentoo/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME=Gentoo
-+ID=gentoo
-+PRETTY_NAME="Gentoo/Linux"
-+ANSI_COLOR="1;32"
-+HOME_URL="http://www.gentoo.org/"
-+SUPPORT_URL="http://www.gentoo.org/main/en/support.xml"
-+BUG_REPORT_URL="https://bugs.gentoo.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/kali/etc/os-release b/third_party/python/distro/tests/resources/distros/kali/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kali/etc/os-release
-@@ -0,0 +1,10 @@
-+PRETTY_NAME="Kali GNU/Linux Rolling"
-+NAME="Kali GNU/Linux"
-+ID=kali
-+VERSION="2017.1"
-+VERSION_ID="2017.1"
-+ID_LIKE=debian
-+ANSI_COLOR="1;31"
-+HOME_URL="http://www.kali.org/"
-+SUPPORT_URL="http://forums.kali.org/"
-+BUG_REPORT_URL="http://bugs.kali.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/kvmibm1/bin/lsb_release b/third_party/python/distro/tests/resources/distros/kvmibm1/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kvmibm1/bin/lsb_release
-@@ -0,0 +1,21 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command works without a corresponding
-+# etc/lsb-release file.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+echo "LSB Version: :core-4.1-noarch:core-4.1-s390x"
-+echo "Distributor ID: kvmibm"
-+echo "Description: KVM for IBM z Systems release 1.1.1 (Z) "
-+echo "Release: 1.1.1"
-+echo "Codename: Z"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/kvmibm1/etc/base-release b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/base-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/base-release
-@@ -0,0 +1,1 @@
-+KVM for IBM z Systems release 1.1.1 (Z)
-diff --git a/third_party/python/distro/tests/resources/distros/kvmibm1/etc/os-release b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME="KVM for IBM z Systems"
-+VERSION="1.1.1 (Z)"
-+ID="kvmibm"
-+ID_LIKE="rhel fedora"
-+VERSION_ID="1.1.1"
-+PRETTY_NAME="KVM for IBM z Systems 1.1.1 (Z)"
-+ANSI_COLOR="0;34"
-+CPE_NAME="cpe:/o:ibm:kvmibm:1.1.1"
-+BUILD_ID="20160316"
-diff --git a/third_party/python/distro/tests/resources/distros/kvmibm1/etc/redhat-release b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/redhat-release
-@@ -0,0 +1,1 @@
-+KVM for IBM z Systems release 1.1.1 (Z)
-diff --git a/third_party/python/distro/tests/resources/distros/kvmibm1/etc/system-release b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/kvmibm1/etc/system-release
-@@ -0,0 +1,1 @@
-+KVM for IBM z Systems release 1.1.1 (Z)
-diff --git a/third_party/python/distro/tests/resources/distros/linuxmint17/bin/lsb_release b/third_party/python/distro/tests/resources/distros/linuxmint17/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/linuxmint17/bin/lsb_release
-@@ -0,0 +1,43 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+if [[ -n $LSB_VERSION ]]; then
-+ echo "LSB Version: $LSB_VERSION"
-+else
-+ echo "No LSB modules are available."
-+fi
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/linuxmint17/etc/debian_version b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/debian_version
-@@ -0,0 +1,1 @@
-+jessie/sid
-diff --git a/third_party/python/distro/tests/resources/distros/linuxmint17/etc/lsb-release b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/lsb-release
-@@ -0,0 +1,4 @@
-+DISTRIB_ID=LinuxMint
-+DISTRIB_RELEASE=17.3
-+DISTRIB_CODENAME=rosa
-+DISTRIB_DESCRIPTION="Linux Mint 17.3 Rosa"
-diff --git a/third_party/python/distro/tests/resources/distros/linuxmint17/etc/os-release b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME="Ubuntu"
-+VERSION="14.04.3 LTS, Trusty Tahr"
-+ID=ubuntu
-+ID_LIKE=debian
-+PRETTY_NAME="Ubuntu 14.04.3 LTS"
-+VERSION_ID="14.04"
-+HOME_URL="http://www.ubuntu.com/"
-+SUPPORT_URL="http://help.ubuntu.com/"
-+BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
-diff --git a/third_party/python/distro/tests/resources/distros/linuxmint17/etc/upstream-release/lsb-release b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/upstream-release/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/linuxmint17/etc/upstream-release/lsb-release
-@@ -0,0 +1,4 @@
-+DISTRIB_ID=Ubuntu
-+DISTRIB_RELEASE=14.04
-+DISTRIB_CODENAME=trusty
-+DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS"
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/bin/lsb_release b/third_party/python/distro/tests/resources/distros/mageia5/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/bin/lsb_release
-@@ -0,0 +1,39 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+echo "LSB Version: ${LSB_VERSION:-*}"
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/lsb-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/lsb-release
-@@ -0,0 +1,5 @@
-+LSB_VERSION=
-+DISTRIB_ID="Mageia"
-+DISTRIB_RELEASE=5
-+DISTRIB_CODENAME=thornicroft
-+DISTRIB_DESCRIPTION="Mageia 5"
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/mageia-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/mageia-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/mageia-release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrake-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrake-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrake-release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrakelinux-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrakelinux-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandrakelinux-release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/mandriva-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandriva-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/mandriva-release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/os-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/os-release
-@@ -0,0 +1,10 @@
-+NAME="Mageia"
-+VERSION="5"
-+ID=mageia
-+VERSION_ID=5
-+ID_LIKE="mandriva fedora"
-+PRETTY_NAME="Mageia 5"
-+ANSI_COLOR="1;36"
-+HOME_URL="http://www.mageia.org/"
-+SUPPORT_URL="http://www.mageia.org/support/"
-+BUG_REPORT_URL="https://bugs.mageia.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/redhat-release b/third_party/python/distro/tests/resources/distros/mageia5/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/release b/third_party/python/distro/tests/resources/distros/mageia5/etc/release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/release
-@@ -0,0 +1,1 @@
-+Mageia release 5 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/etc/version b/third_party/python/distro/tests/resources/distros/mageia5/etc/version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/etc/version
-@@ -0,0 +1,1 @@
-+5 2 official
-diff --git a/third_party/python/distro/tests/resources/distros/mageia5/usr/lib/os-release b/third_party/python/distro/tests/resources/distros/mageia5/usr/lib/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mageia5/usr/lib/os-release
-@@ -0,0 +1,10 @@
-+NAME="Mageia"
-+VERSION="5"
-+ID=mageia
-+VERSION_ID=5
-+ID_LIKE="mandriva fedora"
-+PRETTY_NAME="Mageia 5"
-+ANSI_COLOR="1;36"
-+HOME_URL="http://www.mageia.org/"
-+SUPPORT_URL="http://www.mageia.org/support/"
-+BUG_REPORT_URL="https://bugs.mageia.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/bin/lsb_release b/third_party/python/distro/tests/resources/distros/mandriva2011/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/bin/lsb_release
-@@ -0,0 +1,39 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+echo "LSB Version: ${LSB_VERSION:-*}"
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/lsb-release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/lsb-release
-@@ -0,0 +1,5 @@
-+LSB_VERSION=
-+DISTRIB_ID=MandrivaLinux
-+DISTRIB_RELEASE=2011.0
-+DISTRIB_CODENAME=turtle
-+DISTRIB_DESCRIPTION="Mandriva Linux 2011.0"
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrake-release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrake-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrake-release
-@@ -0,0 +1,1 @@
-+Mandriva Linux release 2011.0 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrakelinux-release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrakelinux-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandrakelinux-release
-@@ -0,0 +1,1 @@
-+Mandriva Linux release 2011.0 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandriva-release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandriva-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/mandriva-release
-@@ -0,0 +1,1 @@
-+Mandriva Linux release 2011.0 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/redhat-release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Mandriva Linux release 2011.0 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/release b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/release
-@@ -0,0 +1,1 @@
-+Mandriva Linux release 2011.0 (Official) for x86_64
-diff --git a/third_party/python/distro/tests/resources/distros/mandriva2011/etc/version b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/mandriva2011/etc/version
-@@ -0,0 +1,1 @@
-+2011.0.0 2 cooker
-diff --git a/third_party/python/distro/tests/resources/distros/manjaro1512/bin/lsb_release b/third_party/python/distro/tests/resources/distros/manjaro1512/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/manjaro1512/bin/lsb_release
-@@ -0,0 +1,43 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+if [[ -n $LSB_VERSION ]]; then
-+ echo "LSB Version: $LSB_VERSION"
-+else
-+ echo "No LSB modules are available."
-+fi
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/manjaro1512/etc/lsb-release b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/lsb-release
-@@ -0,0 +1,4 @@
-+DISTRIB_ID=ManjaroLinux
-+DISTRIB_RELEASE=15.12
-+DISTRIB_CODENAME=Capella
-+DISTRIB_DESCRIPTION="Manjaro Linux"
-diff --git a/third_party/python/distro/tests/resources/distros/manjaro1512/etc/manjaro-release b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/manjaro-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/manjaro-release
-@@ -0,0 +1,1 @@
-+Manjaro Linux
-diff --git a/third_party/python/distro/tests/resources/distros/manjaro1512/etc/os-release b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/manjaro1512/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME="Manjaro Linux"
-+ID=manjaro
-+PRETTY_NAME="Manjaro Linux"
-+ANSI_COLOR="1;32"
-+HOME_URL="http://www.manjaro.org/"
-+SUPPORT_URL="http://www.manjaro.org/"
-+BUG_REPORT_URL="http://bugs.manjaro.org/"
-diff --git a/third_party/python/distro/tests/resources/distros/netbsd711/bin/uname b/third_party/python/distro/tests/resources/distros/netbsd711/bin/uname
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/netbsd711/bin/uname
-@@ -0,0 +1,4 @@
-+#!/bin/sh
-+
-+echo "NetBSD 7.1.1"
-+
-diff --git a/third_party/python/distro/tests/resources/distros/openbsd62/bin/uname b/third_party/python/distro/tests/resources/distros/openbsd62/bin/uname
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/openbsd62/bin/uname
-@@ -0,0 +1,4 @@
-+#!/bin/sh
-+
-+echo "OpenBSD 6.2"
-+
-diff --git a/third_party/python/distro/tests/resources/distros/openelec6/etc/os-release b/third_party/python/distro/tests/resources/distros/openelec6/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/openelec6/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME="OpenELEC"
-+VERSION="6.0.3"
-+ID="openelec"
-+VERSION_ID="6.0"
-+PRETTY_NAME="OpenELEC (official) - Version: 6.0.3"
-+HOME_URL="http://www.openelec.tv"
-+BUG_REPORT_URL="https://github.com/OpenELEC/OpenELEC.tv"
-+OPENELEC_ARCH="imx6.arm"
-+OPENELEC_BUILD="official"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/opensuse42/etc/SuSE-release b/third_party/python/distro/tests/resources/distros/opensuse42/etc/SuSE-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/opensuse42/etc/SuSE-release
-@@ -0,0 +1,1 @@
-+openSUSE 42.1 (x86_64)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/opensuse42/etc/os-release b/third_party/python/distro/tests/resources/distros/opensuse42/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/opensuse42/etc/os-release
-@@ -0,0 +1,10 @@
-+NAME="openSUSE Leap"
-+VERSION="42.1"
-+VERSION_ID="42.1"
-+PRETTY_NAME="openSUSE Leap 42.1 (x86_64)"
-+ID=opensuse
-+ANSI_COLOR="0;32"
-+CPE_NAME="cpe:/o:opensuse:opensuse:42.1"
-+BUG_REPORT_URL="https://bugs.opensuse.org"
-+HOME_URL="https://opensuse.org/"
-+ID_LIKE="suse"
-diff --git a/third_party/python/distro/tests/resources/distros/oracle7/etc/oracle-release b/third_party/python/distro/tests/resources/distros/oracle7/etc/oracle-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/oracle7/etc/oracle-release
-@@ -0,0 +1,1 @@
-+Oracle Linux Server release 7.5
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/oracle7/etc/os-release b/third_party/python/distro/tests/resources/distros/oracle7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/oracle7/etc/os-release
-@@ -0,0 +1,14 @@
-+NAME="Oracle Linux Server"
-+VERSION="7.5"
-+ID="ol"
-+VERSION_ID="7.5"
-+PRETTY_NAME="Oracle Linux Server 7.5"
-+ANSI_COLOR="0;31"
-+CPE_NAME="cpe:/o:oracle:linux:7:5:server"
-+HOME_URL="https://linux.oracle.com/"
-+BUG_REPORT_URL="https://bugzilla.oracle.com/"
-+
-+ORACLE_BUGZILLA_PRODUCT="Oracle Linux 7"
-+ORACLE_BUGZILLA_PRODUCT_VERSION=7.5
-+ORACLE_SUPPORT_PRODUCT="Oracle Linux"
-+ORACLE_SUPPORT_PRODUCT_VERSION=7.5
-diff --git a/third_party/python/distro/tests/resources/distros/raspbian7/etc/debian_version b/third_party/python/distro/tests/resources/distros/raspbian7/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/raspbian7/etc/debian_version
-@@ -0,0 +1,1 @@
-+7.1
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release b/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release
-@@ -0,0 +1,10 @@
-+PRETTY_NAME="Raspbian GNU/Linux 7 (wheezy)"
-+NAME="Raspbian GNU/Linux"
-+VERSION_ID="7"
-+VERSION="7 (wheezy)"
-+ID=raspbian
-+ID_LIKE=debian
-+ANSI_COLOR="1;31"
-+HOME_URL="http://www.raspbian.org/"
-+SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
-+BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release.orig b/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release.orig
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/raspbian7/etc/os-release.orig
-@@ -0,0 +1,9 @@
-+PRETTY_NAME="Debian #OSNAME# 7 (wheezy)"
-+NAME="Debian #OSNAME#"
-+VERSION_ID="7"
-+VERSION="7 (wheezy)"
-+ID=debian
-+ANSI_COLOR="1;31"
-+HOME_URL="http://www.debian.org/"
-+SUPPORT_URL="http://www.debian.org/support/"
-+BUG_REPORT_URL="http://bugs.debian.org/"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/raspbian8/etc/debian_version b/third_party/python/distro/tests/resources/distros/raspbian8/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/raspbian8/etc/debian_version
-@@ -0,0 +1,1 @@
-+8.0
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/raspbian8/etc/os-release b/third_party/python/distro/tests/resources/distros/raspbian8/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/raspbian8/etc/os-release
-@@ -0,0 +1,9 @@
-+PRETTY_NAME="Raspbian GNU/Linux 8 (jessie)"
-+NAME="Raspbian GNU/Linux"
-+VERSION_ID="8"
-+VERSION="8 (jessie)"
-+ID=raspbian
-+ID_LIKE=debian
-+HOME_URL="http://www.raspbian.org/"
-+SUPPORT_URL="http://www.raspbian.org/RaspbianForums"
-+BUG_REPORT_URL="http://www.raspbian.org/RaspbianBugs"
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/rhel5/etc/redhat-release b/third_party/python/distro/tests/resources/distros/rhel5/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel5/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Red Hat Enterprise Linux Server release 5.11 (Tikanga)
-diff --git a/third_party/python/distro/tests/resources/distros/rhel6/etc/redhat-release b/third_party/python/distro/tests/resources/distros/rhel6/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel6/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Red Hat Enterprise Linux Server release 6.5 (Santiago)
-diff --git a/third_party/python/distro/tests/resources/distros/rhel6/etc/system-release b/third_party/python/distro/tests/resources/distros/rhel6/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel6/etc/system-release
-@@ -0,0 +1,1 @@
-+Red Hat Enterprise Linux Server release 6.5 (Santiago)
-diff --git a/third_party/python/distro/tests/resources/distros/rhel7/etc/os-release b/third_party/python/distro/tests/resources/distros/rhel7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel7/etc/os-release
-@@ -0,0 +1,15 @@
-+NAME="Red Hat Enterprise Linux Server"
-+VERSION="7.0 (Maipo)"
-+ID="rhel"
-+ID_LIKE="fedora"
-+VERSION_ID="7.0"
-+PRETTY_NAME="Red Hat Enterprise Linux Server 7.0 (Maipo)"
-+ANSI_COLOR="0;31"
-+CPE_NAME="cpe:/o:redhat:enterprise_linux:7.0:GA:server"
-+HOME_URL="https://www.redhat.com/"
-+BUG_REPORT_URL="https://bugzilla.redhat.com/"
-+
-+REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 7"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=7.0
-+REDHAT_SUPPORT_PRODUCT="Red Hat Enterprise Linux"
-+REDHAT_SUPPORT_PRODUCT_VERSION=7.0
-diff --git a/third_party/python/distro/tests/resources/distros/rhel7/etc/redhat-release b/third_party/python/distro/tests/resources/distros/rhel7/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel7/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Red Hat Enterprise Linux Server release 7.0 (Maipo)
-diff --git a/third_party/python/distro/tests/resources/distros/rhel7/etc/system-release b/third_party/python/distro/tests/resources/distros/rhel7/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/rhel7/etc/system-release
-@@ -0,0 +1,1 @@
-+Red Hat Enterprise Linux Server release 7.0 (Maipo)
-diff --git a/third_party/python/distro/tests/resources/distros/scientific6/etc/redhat-release b/third_party/python/distro/tests/resources/distros/scientific6/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific6/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Scientific Linux release 6.4 (Carbon)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/scientific6/etc/system-release b/third_party/python/distro/tests/resources/distros/scientific6/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific6/etc/system-release
-@@ -0,0 +1,1 @@
-+Scientific Linux release 6.4 (Carbon)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/scientific7/etc/os-release b/third_party/python/distro/tests/resources/distros/scientific7/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific7/etc/os-release
-@@ -0,0 +1,15 @@
-+NAME="Scientific Linux"
-+VERSION="7.2 (Nitrogen)"
-+ID="rhel"
-+ID_LIKE="fedora"
-+VERSION_ID="7.2"
-+PRETTY_NAME="Scientific Linux 7.2 (Nitrogen)"
-+ANSI_COLOR="0;31"
-+CPE_NAME="cpe:/o:scientificlinux:scientificlinux:7.2:GA"
-+HOME_URL="http://www.scientificlinux.org//"
-+BUG_REPORT_URL="mailto:scientific-linux-devel@listserv.fnal.gov"
-+
-+REDHAT_BUGZILLA_PRODUCT="Scientific Linux 7"
-+REDHAT_BUGZILLA_PRODUCT_VERSION=7.2
-+REDHAT_SUPPORT_PRODUCT="Scientific Linux"
-+REDHAT_SUPPORT_PRODUCT_VERSION="7.2"
-diff --git a/third_party/python/distro/tests/resources/distros/scientific7/etc/redhat-release b/third_party/python/distro/tests/resources/distros/scientific7/etc/redhat-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific7/etc/redhat-release
-@@ -0,0 +1,1 @@
-+Scientific Linux release 7.2 (Nitrogen)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/scientific7/etc/sl-release b/third_party/python/distro/tests/resources/distros/scientific7/etc/sl-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific7/etc/sl-release
-@@ -0,0 +1,1 @@
-+Scientific Linux release 7.2 (Nitrogen)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/scientific7/etc/system-release b/third_party/python/distro/tests/resources/distros/scientific7/etc/system-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/scientific7/etc/system-release
-@@ -0,0 +1,1 @@
-+Scientific Linux release 7.2 (Nitrogen)
-\ No newline at end of file
-diff --git a/third_party/python/distro/tests/resources/distros/slackware14/etc/os-release b/third_party/python/distro/tests/resources/distros/slackware14/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/slackware14/etc/os-release
-@@ -0,0 +1,10 @@
-+NAME=Slackware
-+VERSION="14.1"
-+ID=slackware
-+VERSION_ID=14.1
-+PRETTY_NAME="Slackware 14.1"
-+ANSI_COLOR="0;34"
-+CPE_NAME="cpe:/o:slackware:slackware_linux:14.1"
-+HOME_URL="http://slackware.com/"
-+SUPPORT_URL="http://www.linuxquestions.org/questions/slackware-14/"
-+BUG_REPORT_URL="http://www.linuxquestions.org/questions/slackware-14/"
-diff --git a/third_party/python/distro/tests/resources/distros/slackware14/etc/slackware-version b/third_party/python/distro/tests/resources/distros/slackware14/etc/slackware-version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/slackware14/etc/slackware-version
-@@ -0,0 +1,1 @@
-+Slackware 14.1
-diff --git a/third_party/python/distro/tests/resources/distros/sles12/bin/lsb_release b/third_party/python/distro/tests/resources/distros/sles12/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/sles12/bin/lsb_release
-@@ -0,0 +1,21 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command works without a corresponding
-+# etc/lsb-release file.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+echo "LSB Version: n/a"
-+echo "Distributor ID: SUSE LINUX"
-+echo "Description: SUSE Linux Enterprise Server 12 SP1"
-+echo "Release: 12.1"
-+echo "Codename: n/a"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/sles12/etc/SuSE-release b/third_party/python/distro/tests/resources/distros/sles12/etc/SuSE-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/sles12/etc/SuSE-release
-@@ -0,0 +1,5 @@
-+SUSE Linux Enterprise Server 12 (s390x)
-+VERSION = 12
-+PATCHLEVEL = 1
-+# This file is deprecated and will be removed in a future service pack or release.
-+# Please check /etc/os-release for details about this release.
-diff --git a/third_party/python/distro/tests/resources/distros/sles12/etc/os-release b/third_party/python/distro/tests/resources/distros/sles12/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/sles12/etc/os-release
-@@ -0,0 +1,7 @@
-+NAME="SLES"
-+VERSION="12-SP1"
-+VERSION_ID="12.1"
-+PRETTY_NAME="SUSE Linux Enterprise Server 12 SP1"
-+ID="sles"
-+ANSI_COLOR="0;32"
-+CPE_NAME="cpe:/o:suse:sles:12:sp1"
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu14/bin/lsb_release b/third_party/python/distro/tests/resources/distros/ubuntu14/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu14/bin/lsb_release
-@@ -0,0 +1,39 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+echo "No LSB modules are available."
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu14/etc/debian_version b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/debian_version
-@@ -0,0 +1,1 @@
-+jessie/sid
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu14/etc/lsb-release b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/lsb-release
-@@ -0,0 +1,4 @@
-+DISTRIB_ID=Ubuntu
-+DISTRIB_RELEASE=14.04
-+DISTRIB_CODENAME=trusty
-+DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu14/etc/os-release b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu14/etc/os-release
-@@ -0,0 +1,9 @@
-+NAME="Ubuntu"
-+VERSION="14.04.3 LTS, Trusty Tahr"
-+ID=ubuntu
-+ID_LIKE=debian
-+PRETTY_NAME="Ubuntu 14.04.3 LTS"
-+VERSION_ID="14.04"
-+HOME_URL="http://www.ubuntu.com/"
-+SUPPORT_URL="http://help.ubuntu.com/"
-+BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu16/bin/lsb_release b/third_party/python/distro/tests/resources/distros/ubuntu16/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu16/bin/lsb_release
-@@ -0,0 +1,39 @@
-+#!/bin/bash
-+#
-+# lsb_release command for testing the ld module.
-+# Only the -a option is supported.
-+#
-+# This version of the lsb_release command reads an lsb-release file.
-+#
-+# The lsb-release file has the usual format, e.g.:
-+# DISTRIB_ID=Ubuntu
-+# DISTRIB_RELEASE=14.04
-+# DISTRIB_CODENAME=trusty
-+# DISTRIB_DESCRIPTION="Ubuntu 14.04.3 LTS"
-+# Where each line is optional. If a line is missing, the default value
-+# will be the empty string.
-+#
-+
-+if [[ "$@" != "-a" ]]; then
-+ echo "Usage: lsb_release -a"
-+ exit 2
-+fi
-+
-+# Because the PATH is set to just this directory, we cannot use 'dirname'
-+# or other external programs, but need to use built-in abilities of bash.
-+LSB_FILE="${0%/*}/../etc/lsb-release"
-+
-+if [[ ! -f $LSB_FILE ]]; then
-+ echo "Error: LSB release file does not exist: $LSB_FILE"
-+ exit 1
-+fi
-+
-+source $LSB_FILE
-+
-+echo "No LSB modules are available."
-+echo "Distributor ID: ${DISTRIB_ID:-}"
-+echo "Description: ${DISTRIB_DESCRIPTION:-}"
-+echo "Release: ${DISTRIB_RELEASE:-}"
-+echo "Codename: ${DISTRIB_CODENAME:-}"
-+
-+exit 0
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu16/etc/debian_version b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/debian_version
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/debian_version
-@@ -0,0 +1,1 @@
-+stretch/sid
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu16/etc/lsb-release b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/lsb-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/lsb-release
-@@ -0,0 +1,4 @@
-+DISTRIB_ID=Ubuntu
-+DISTRIB_RELEASE=16.04
-+DISTRIB_CODENAME=xenial
-+DISTRIB_DESCRIPTION="Ubuntu 16.04.1 LTS"
-diff --git a/third_party/python/distro/tests/resources/distros/ubuntu16/etc/os-release b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/os-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/distros/ubuntu16/etc/os-release
-@@ -0,0 +1,10 @@
-+NAME="Ubuntu"
-+VERSION="16.04.1 LTS (Xenial Xerus)"
-+ID=ubuntu
-+ID_LIKE=debian
-+PRETTY_NAME="Ubuntu 16.04.1 LTS"
-+VERSION_ID="16.04"
-+HOME_URL="http://www.ubuntu.com/"
-+SUPPORT_URL="http://help.ubuntu.com/"
-+BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
-+UBUNTU_CODENAME=xenial
-diff --git a/third_party/python/distro/tests/resources/special/empty-release b/third_party/python/distro/tests/resources/special/empty-release
-new file mode 100644
-diff --git a/third_party/python/distro/tests/resources/testdistros/distro/baduname/bin/uname b/third_party/python/distro/tests/resources/testdistros/distro/baduname/bin/uname
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/distro/baduname/bin/uname
-@@ -0,0 +1,2 @@
-+#!/bin/sh
-+echo "I'm a bad uname file!"
-diff --git a/third_party/python/distro/tests/resources/testdistros/distro/unknowndistro/etc/unknowndistro-release b/third_party/python/distro/tests/resources/testdistros/distro/unknowndistro/etc/unknowndistro-release
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/distro/unknowndistro/etc/unknowndistro-release
-@@ -0,0 +1,1 @@
-+Unknown Distro release 1.0 (Unknown Codename)
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc001/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc001/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc001/bin/lsb_release
-@@ -0,0 +1,5 @@
-+#!/bin/bash
-+rc=1
-+msg="General error"
-+echo "Test failure - exiting with $rc ($msg)"
-+exit $rc
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc002/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc002/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc002/bin/lsb_release
-@@ -0,0 +1,5 @@
-+#!/bin/bash
-+rc=2
-+msg="Misuse of shell builtins, or missing keyword or command"
-+echo "Test failure - exiting with $rc ($msg)"
-+exit $rc
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc126/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc126/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc126/bin/lsb_release
-@@ -0,0 +1,5 @@
-+#!/bin/bash
-+rc=126
-+msg="Cannot execute command"
-+echo "Test failure - exiting with $rc ($msg)"
-+exit $rc
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc130/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc130/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc130/bin/lsb_release
-@@ -0,0 +1,5 @@
-+#!/bin/bash
-+rc=130
-+msg="Signal 2 - Script terminated with Ctrl-C"
-+echo "Test failure - exiting with $rc ($msg)"
-+exit $rc
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc255/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc255/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/lsb_rc255/bin/lsb_release
-@@ -0,0 +1,5 @@
-+#!/bin/bash
-+rc=255
-+msg="Exit code out of range"
-+echo "Test failure - exiting with $rc ($msg)"
-+exit $rc
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_nomodules/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_nomodules/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_nomodules/bin/lsb_release
-@@ -0,0 +1,8 @@
-+#!/bin/bash
-+/bin/cat <<'EOT'
-+No LSB modules are available.
-+Distributor ID: Ubuntu
-+Description: Ubuntu 14.04.3 LTS
-+Release: 14.04
-+Codename: trusty
-+EOT
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_normal/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_normal/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_normal/bin/lsb_release
-@@ -0,0 +1,7 @@
-+#!/bin/bash
-+/bin/cat <<'EOT'
-+Distributor ID: Ubuntu
-+Description: Ubuntu 14.04.3 LTS
-+Release: 14.04
-+Codename: trusty
-+EOT
-diff --git a/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_trailingblanks/bin/lsb_release b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_trailingblanks/bin/lsb_release
-new file mode 100755
---- /dev/null
-+++ b/third_party/python/distro/tests/resources/testdistros/lsb/ubuntu14_trailingblanks/bin/lsb_release
-@@ -0,0 +1,8 @@
-+#!/bin/bash
-+/bin/cat <<'EOT'
-+No LSB modules are available.
-+Distributor ID: Ubuntu
-+Description: Ubuntu 14.04.3 LTS
-+Release: 14.04
-+Codename: trusty
-+EOT
-diff --git a/third_party/python/distro/tests/test_distro.py b/third_party/python/distro/tests/test_distro.py
-new file mode 100644
---- /dev/null
-+++ b/third_party/python/distro/tests/test_distro.py
-@@ -0,0 +1,2062 @@
-+# Copyright 2015,2016 Nir Cohen
-+#
-+# Licensed under the Apache License, Version 2.0 (the "License");
-+# you may not use this file except in compliance with the License.
-+# You may obtain a copy of the License at
-+#
-+# http://www.apache.org/licenses/LICENSE-2.0
-+#
-+# Unless required by applicable law or agreed to in writing, software
-+# distributed under the License is distributed on an "AS IS" BASIS,
-+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-+# See the License for the specific language governing permissions and
-+# limitations under the License.
-+
-+import os
-+import sys
-+import ast
-+import subprocess
-+try:
-+ from StringIO import StringIO # Python 2.x
-+except ImportError:
-+ from io import StringIO # Python 3.x
-+
-+import pytest
-+
-+
-+BASE = os.path.abspath(os.path.dirname(__file__))
-+RESOURCES = os.path.join(BASE, 'resources')
-+DISTROS_DIR = os.path.join(RESOURCES, 'distros')
-+TESTDISTROS = os.path.join(RESOURCES, 'testdistros')
-+SPECIAL = os.path.join(RESOURCES, 'special')
-+DISTROS = [dist for dist in os.listdir(DISTROS_DIR) if dist != '__shared__']
-+
-+
-+IS_LINUX = sys.platform.startswith('linux')
-+if IS_LINUX:
-+ import distro
-+
-+ RELATIVE_UNIXCONFDIR = distro._UNIXCONFDIR[1:]
-+ MODULE_DISTRO = distro._distro
-+
-+
-+class TestNonLinuxPlatform:
-+ """Obviously, this only tests Windows. Will add OS X tests on Travis
-+ Later
-+ """
-+
-+ def test_cant_use_on_windows(self):
-+ try:
-+ import distro # NOQA
-+ except ImportError as ex:
-+ assert 'Unsupported platform' in str(ex)
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestCli:
-+
-+ def _parse(self, command):
-+ sys.argv = command.split()
-+ distro.main()
-+
-+ def _run(self, command):
-+ stdout, _ = subprocess.Popen(
-+ command,
-+ stdout=subprocess.PIPE,
-+ stderr=subprocess.PIPE).communicate()
-+ # Need to decode or we get bytes in Python 3.x
-+ return stdout.decode('utf-8')
-+
-+ def test_cli_for_coverage_yuch(self):
-+ self._parse('distro')
-+ self._parse('distro -j')
-+
-+ def test_cli(self):
-+ command = [sys.executable, '-m', 'distro']
-+ desired_output = 'Name: ' + distro.name(pretty=True)
-+ distro_version = distro.version(pretty=True)
-+ distro_codename = distro.codename()
-+ desired_output += '\n' + 'Version: ' + distro_version
-+ desired_output += '\n' + 'Codename: ' + distro_codename
-+ desired_output += '\n'
-+ assert self._run(command) == desired_output
-+
-+ def test_cli_json(self):
-+ command = [sys.executable, '-m', 'distro', '-j']
-+ assert ast.literal_eval(self._run(command)) == distro.info()
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class DistroTestCase(object):
-+ """A base class for any testcase classes that test the distributions
-+ represented in the `DISTROS` subtree.
-+ """
-+
-+ def setup_method(self, test_method):
-+ # The environment stays the same across all testcases, so we
-+ # save and restore the PATH env var in each test case that
-+ # changes it:
-+ self._saved_path = os.environ["PATH"]
-+ self._saved_UNIXCONFDIR = distro._UNIXCONFDIR
-+
-+ def teardown_method(self, test_method):
-+ os.environ["PATH"] = self._saved_path
-+ distro._UNIXCONFDIR = self._saved_UNIXCONFDIR
-+
-+ def _setup_for_distro(self, distro_root):
-+ distro_bin = os.path.join(distro_root, 'bin')
-+ # We don't want to pick up a possibly present lsb_release in the
-+ # distro that runs this test, so we use a PATH with only one entry:
-+ os.environ["PATH"] = distro_bin
-+ distro._UNIXCONFDIR = os.path.join(distro_root, RELATIVE_UNIXCONFDIR)
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestOSRelease:
-+
-+ def setup_method(self, test_method):
-+ dist = test_method.__name__.split('_')[1]
-+ os_release = os.path.join(DISTROS_DIR, dist, 'etc', 'os-release')
-+ self.distro = distro.LinuxDistribution(False, os_release, 'non')
-+
-+ def _test_outcome(self, outcome):
-+ assert self.distro.id() == outcome.get('id', '')
-+ assert self.distro.name() == outcome.get('name', '')
-+ assert self.distro.name(pretty=True) == outcome.get('pretty_name', '')
-+ assert self.distro.version() == outcome.get('version', '')
-+ assert self.distro.version(pretty=True) == \
-+ outcome.get('pretty_version', '')
-+ assert self.distro.version(best=True) == \
-+ outcome.get('best_version', '')
-+ assert self.distro.like() == outcome.get('like', '')
-+ assert self.distro.codename() == outcome.get('codename', '')
-+
-+ def test_arch_os_release(self):
-+ desired_outcome = {
-+ 'id': 'arch',
-+ 'name': 'Arch Linux',
-+ 'pretty_name': 'Arch Linux',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_kali_os_release(self):
-+ desired_outcome = {
-+ 'id': 'kali',
-+ 'name': 'Kali GNU/Linux',
-+ 'pretty_name': 'Kali GNU/Linux Rolling',
-+ 'version': '2017.1',
-+ 'pretty_version': '2017.1',
-+ 'best_version': '2017.1',
-+ 'like': 'debian'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_centos7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS Linux',
-+ 'pretty_name': 'CentOS Linux 7 (Core)',
-+ 'version': '7',
-+ 'pretty_version': '7 (Core)',
-+ 'best_version': '7',
-+ 'like': 'rhel fedora',
-+ 'codename': 'Core'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_coreos_os_release(self):
-+ desired_outcome = {
-+ 'id': 'coreos',
-+ 'name': 'CoreOS',
-+ 'pretty_name': 'CoreOS 899.15.0',
-+ 'version': '899.15.0',
-+ 'pretty_version': '899.15.0',
-+ 'best_version': '899.15.0'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_debian8_os_release(self):
-+ desired_outcome = {
-+ 'id': 'debian',
-+ 'name': 'Debian GNU/Linux',
-+ 'pretty_name': 'Debian GNU/Linux 8 (jessie)',
-+ 'version': '8',
-+ 'pretty_version': '8 (jessie)',
-+ 'best_version': '8',
-+ 'codename': 'jessie'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_fedora19_os_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': u'Fedora 19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'version': '19',
-+ 'pretty_version': u'19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'best_version': '19',
-+ 'codename': u'Schr\u00F6dinger\u2019s Cat'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_fedora23_os_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 23 (Twenty Three)',
-+ 'version': '23',
-+ 'pretty_version': '23 (Twenty Three)',
-+ 'best_version': '23',
-+ 'codename': 'Twenty Three'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_fedora30_os_release(self):
-+ # Fedora 21 and above no longer have code names but the metadata in os-release was only
-+ # changed in a detectable way in Fedora 30+. The piece in parenthesis in the pretty_name
-+ # field contains the VARIANT and differs depending on the variant which was installed.
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 30 (Thirty)',
-+ 'version': '30',
-+ 'pretty_version': '30',
-+ 'best_version': '30',
-+ 'codename': ''
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_kvmibm1_os_release(self):
-+ desired_outcome = {
-+ 'id': 'kvmibm',
-+ 'name': 'KVM for IBM z Systems',
-+ 'pretty_name': 'KVM for IBM z Systems 1.1.1 (Z)',
-+ 'version': '1.1.1',
-+ 'pretty_version': '1.1.1 (Z)',
-+ 'best_version': '1.1.1',
-+ 'like': 'rhel fedora',
-+ 'codename': 'Z'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_linuxmint17_os_release(self):
-+ # Note: LinuxMint 17 actually *does* have Ubuntu 14.04 data in its
-+ # os-release file. See discussion in GitHub issue #78.
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (Trusty Tahr)',
-+ 'best_version': '14.04.3',
-+ 'like': 'debian',
-+ 'codename': 'Trusty Tahr'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_mageia5_os_release(self):
-+ desired_outcome = {
-+ 'id': 'mageia',
-+ 'name': 'Mageia',
-+ 'pretty_name': 'Mageia 5',
-+ 'version': '5',
-+ 'pretty_version': '5',
-+ 'best_version': '5',
-+ 'like': 'mandriva fedora',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_manjaro1512_os_release(self):
-+ self._test_outcome({
-+ 'id': 'manjaro',
-+ 'name': 'Manjaro Linux',
-+ 'pretty_name': 'Manjaro Linux',
-+ })
-+
-+ def test_opensuse42_os_release(self):
-+ desired_outcome = {
-+ 'id': 'opensuse',
-+ 'name': 'openSUSE Leap',
-+ 'pretty_name': 'openSUSE Leap 42.1 (x86_64)',
-+ 'version': '42.1',
-+ 'pretty_version': '42.1',
-+ 'best_version': '42.1',
-+ 'like': 'suse',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_raspbian7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'raspbian',
-+ 'name': 'Raspbian GNU/Linux',
-+ 'pretty_name': 'Raspbian GNU/Linux 7 (wheezy)',
-+ 'version': '7',
-+ 'pretty_version': '7 (wheezy)',
-+ 'best_version': '7',
-+ 'like': 'debian',
-+ 'codename': 'wheezy'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_raspbian8_os_release(self):
-+ desired_outcome = {
-+ 'id': 'raspbian',
-+ 'name': 'Raspbian GNU/Linux',
-+ 'pretty_name': 'Raspbian GNU/Linux 8 (jessie)',
-+ 'version': '8',
-+ 'pretty_version': '8 (jessie)',
-+ 'best_version': '8',
-+ 'like': 'debian',
-+ 'codename': 'jessie'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_rhel7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 7.0 (Maipo)',
-+ 'version': '7.0',
-+ 'pretty_version': '7.0 (Maipo)',
-+ 'best_version': '7.0',
-+ 'like': 'fedora',
-+ 'codename': 'Maipo'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_slackware14_os_release(self):
-+ desired_outcome = {
-+ 'id': 'slackware',
-+ 'name': 'Slackware',
-+ 'pretty_name': 'Slackware 14.1',
-+ 'version': '14.1',
-+ 'pretty_version': '14.1',
-+ 'best_version': '14.1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_sles12_os_release(self):
-+ desired_outcome = {
-+ 'id': 'sles',
-+ 'name': 'SLES',
-+ 'pretty_name': 'SUSE Linux Enterprise Server 12 SP1',
-+ 'version': '12.1',
-+ 'pretty_version': '12.1',
-+ 'best_version': '12.1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_ubuntu14_os_release(self):
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (Trusty Tahr)',
-+ 'best_version': '14.04.3',
-+ 'like': 'debian',
-+ 'codename': 'Trusty Tahr'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_ubuntu16_os_release(self):
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 16.04.1 LTS',
-+ 'version': '16.04',
-+ 'pretty_version': '16.04 (xenial)',
-+ 'best_version': '16.04.1',
-+ 'like': 'debian',
-+ 'codename': 'xenial'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_amazon2016_os_release(self):
-+ desired_outcome = {
-+ 'id': 'amzn',
-+ 'name': 'Amazon Linux AMI',
-+ 'pretty_name': 'Amazon Linux AMI 2016.03',
-+ 'version': '2016.03',
-+ 'pretty_version': '2016.03',
-+ 'best_version': '2016.03',
-+ 'like': 'rhel fedora'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_scientific7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Scientific Linux',
-+ 'pretty_name': 'Scientific Linux 7.2 (Nitrogen)',
-+ 'version': '7.2',
-+ 'pretty_version': '7.2 (Nitrogen)',
-+ 'best_version': '7.2',
-+ 'like': 'fedora',
-+ 'codename': 'Nitrogen'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_gentoo_os_release(self):
-+ desired_outcome = {
-+ 'id': 'gentoo',
-+ 'name': 'Gentoo',
-+ 'pretty_name': 'Gentoo/Linux',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_openelec6_os_release(self):
-+ desired_outcome = {
-+ 'id': 'openelec',
-+ 'name': 'OpenELEC',
-+ 'pretty_name': 'OpenELEC (official) - Version: 6.0.3',
-+ 'version': '6.0',
-+ 'pretty_version': '6.0',
-+ 'best_version': '6.0.3',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_cloudlinux7_os_release(self):
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Yury Malyshev',
-+ 'name': 'CloudLinux',
-+ 'pretty_name': 'CloudLinux 7.3 (Yury Malyshev)',
-+ 'like': 'rhel fedora centos',
-+ 'version': '7.3',
-+ 'pretty_version': '7.3 (Yury Malyshev)',
-+ 'best_version': '7.3',
-+ 'major_version': '7',
-+ 'minor_version': '3'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestLSBRelease(DistroTestCase):
-+
-+ def setup_method(self, test_method):
-+ super(TestLSBRelease, self).setup_method(test_method)
-+ dist = test_method.__name__.split('_')[1]
-+ self._setup_for_distro(os.path.join(DISTROS_DIR, dist))
-+ self.distro = distro.LinuxDistribution(True, 'non', 'non')
-+
-+ def _test_outcome(self, outcome):
-+ assert self.distro.id() == outcome.get('id', '')
-+ assert self.distro.name() == outcome.get('name', '')
-+ assert self.distro.name(pretty=True) == outcome.get('pretty_name', '')
-+ assert self.distro.version() == outcome.get('version', '')
-+ assert self.distro.version(pretty=True) == \
-+ outcome.get('pretty_version', '')
-+ assert self.distro.version(best=True) == \
-+ outcome.get('best_version', '')
-+ assert self.distro.like() == outcome.get('like', '')
-+ assert self.distro.codename() == outcome.get('codename', '')
-+
-+ def test_linuxmint17_lsb_release(self):
-+ desired_outcome = {
-+ 'id': 'linuxmint',
-+ 'name': 'LinuxMint',
-+ 'pretty_name': 'Linux Mint 17.3 Rosa',
-+ 'version': '17.3',
-+ 'pretty_version': '17.3 (rosa)',
-+ 'best_version': '17.3',
-+ 'codename': 'rosa'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_manjaro1512_lsb_release(self):
-+ self._test_outcome({
-+ 'id': 'manjarolinux',
-+ 'name': 'ManjaroLinux',
-+ 'pretty_name': 'Manjaro Linux',
-+ 'version': '15.12',
-+ 'pretty_version': '15.12 (Capella)',
-+ 'best_version': '15.12',
-+ 'codename': 'Capella'
-+ })
-+
-+ # @pytest.mark.xfail
-+ # def test_openelec6_lsb_release(self):
-+ # # TODO: This should be fixed as part of #109 when dealing
-+ # # with distro inconsistencies
-+ # desired_outcome = {
-+ # 'id': 'openelec',
-+ # 'name': 'OpenELEC',
-+ # 'pretty_name': 'OpenELEC (official) - Version: 6.0.3',
-+ # 'version': '6.0.3',
-+ # 'pretty_version': '6.0.3',
-+ # 'best_version': '6.0.3',
-+ # }
-+ # self._test_outcome(desired_outcome)
-+
-+ def test_openbsd62_uname(self):
-+ self._test_outcome({
-+ 'id': 'openbsd',
-+ 'name': 'OpenBSD',
-+ 'version': '6.2',
-+ 'pretty_name': 'OpenBSD 6.2',
-+ 'pretty_version': '6.2',
-+ 'best_version': '6.2'
-+ })
-+
-+ def test_netbsd711_uname(self):
-+ self._test_outcome({
-+ 'id': 'netbsd',
-+ 'name': 'NetBSD',
-+ 'version': '7.1.1',
-+ 'pretty_name': 'NetBSD 7.1.1',
-+ 'pretty_version': '7.1.1',
-+ 'best_version': '7.1.1'
-+ })
-+
-+ def test_freebsd111_uname(self):
-+ self._test_outcome({
-+ 'id': 'freebsd',
-+ 'name': 'FreeBSD',
-+ 'version': '11.1',
-+ 'pretty_name': 'FreeBSD 11.1',
-+ 'pretty_version': '11.1',
-+ 'best_version': '11.1'
-+ })
-+
-+ def test_ubuntu14normal_lsb_release(self):
-+ self._setup_for_distro(os.path.join(TESTDISTROS, 'lsb',
-+ 'ubuntu14_normal'))
-+
-+ self.distro = distro.LinuxDistribution(True, 'non', 'non')
-+
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (trusty)',
-+ 'best_version': '14.04.3',
-+ 'codename': 'trusty'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_ubuntu14nomodules_lsb_release(self):
-+ self._setup_for_distro(os.path.join(TESTDISTROS, 'lsb',
-+ 'ubuntu14_nomodules'))
-+
-+ self.distro = distro.LinuxDistribution(True, 'non', 'non')
-+
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (trusty)',
-+ 'best_version': '14.04.3',
-+ 'codename': 'trusty'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_trailingblanks_lsb_release(self):
-+ self._setup_for_distro(os.path.join(TESTDISTROS, 'lsb',
-+ 'ubuntu14_trailingblanks'))
-+
-+ self.distro = distro.LinuxDistribution(True, 'non', 'non')
-+
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (trusty)',
-+ 'best_version': '14.04.3',
-+ 'codename': 'trusty'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ @pytest.mark.parametrize('errnum', ('001', '002', '126', '130', '255'))
-+ def test_lsb_release_error_level(self, errnum):
-+ self._setup_for_distro(os.path.join(
-+ TESTDISTROS, 'lsb', 'lsb_rc{0}'.format(errnum)))
-+ with pytest.raises(subprocess.CalledProcessError) as excinfo:
-+ distro.LinuxDistribution(True, 'non', 'non')._lsb_release_info
-+ assert excinfo.value.returncode == int(errnum)
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestSpecialRelease(DistroTestCase):
-+ def _test_outcome(self, outcome):
-+ assert self.distro.id() == outcome.get('id', '')
-+ assert self.distro.name() == outcome.get('name', '')
-+ assert self.distro.name(pretty=True) == outcome.get('pretty_name', '')
-+ assert self.distro.version() == outcome.get('version', '')
-+ assert self.distro.version(pretty=True) == \
-+ outcome.get('pretty_version', '')
-+ assert self.distro.version(best=True) == \
-+ outcome.get('best_version', '')
-+ assert self.distro.like() == outcome.get('like', '')
-+ assert self.distro.codename() == outcome.get('codename', '')
-+ assert self.distro.major_version() == outcome.get('major_version', '')
-+ assert self.distro.minor_version() == outcome.get('minor_version', '')
-+ assert self.distro.build_number() == outcome.get('build_number', '')
-+
-+ def test_empty_release(self):
-+ distro_release = os.path.join(SPECIAL, 'empty-release')
-+ self.distro = distro.LinuxDistribution(False, 'non', distro_release)
-+
-+ desired_outcome = {
-+ 'id': 'empty'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_unknowndistro_release(self):
-+ self._setup_for_distro(os.path.join(TESTDISTROS, 'distro',
-+ 'unknowndistro'))
-+
-+ self.distro = distro.LinuxDistribution()
-+
-+ desired_outcome = {
-+ 'id': 'unknowndistro',
-+ 'name': 'Unknown Distro',
-+ 'pretty_name': 'Unknown Distro 1.0 (Unknown Codename)',
-+ 'version': '1.0',
-+ 'pretty_version': '1.0 (Unknown Codename)',
-+ 'best_version': '1.0',
-+ 'codename': 'Unknown Codename',
-+ 'major_version': '1',
-+ 'minor_version': '0'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_bad_uname(self):
-+ self._setup_for_distro(os.path.join(TESTDISTROS, 'distro',
-+ 'baduname'))
-+ self.distro = distro.LinuxDistribution()
-+
-+ assert self.distro.uname_attr('id') == ''
-+ assert self.distro.uname_attr('name') == ''
-+ assert self.distro.uname_attr('release') == ''
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestDistroRelease:
-+
-+ def _test_outcome(self,
-+ outcome,
-+ distro_name='',
-+ version='',
-+ release_file_id='',
-+ release_file_suffix='release'):
-+ release_file_id = release_file_id or distro_name
-+ distro_release = os.path.join(
-+ DISTROS_DIR, distro_name + version, 'etc', '{0}-{1}'.format(
-+ release_file_id, release_file_suffix))
-+ self.distro = distro.LinuxDistribution(False, 'non', distro_release)
-+
-+ assert self.distro.id() == outcome.get('id', '')
-+ assert self.distro.name() == outcome.get('name', '')
-+ assert self.distro.name(pretty=True) == outcome.get('pretty_name', '')
-+ assert self.distro.version() == outcome.get('version', '')
-+ assert self.distro.version(pretty=True) == \
-+ outcome.get('pretty_version', '')
-+ assert self.distro.version(best=True) == \
-+ outcome.get('best_version', '')
-+ assert self.distro.like() == outcome.get('like', '')
-+ assert self.distro.codename() == outcome.get('codename', '')
-+ assert self.distro.major_version() == outcome.get('major_version', '')
-+ assert self.distro.minor_version() == outcome.get('minor_version', '')
-+ assert self.distro.build_number() == outcome.get('build_number', '')
-+
-+ def test_arch_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'arch'
-+ }
-+ self._test_outcome(desired_outcome, 'arch')
-+
-+ def test_centos5_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS',
-+ 'pretty_name': 'CentOS 5.11 (Final)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Final)',
-+ 'best_version': '5.11',
-+ 'codename': 'Final',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome, 'centos', '5')
-+
-+ def test_centos7_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS Linux',
-+ 'pretty_name': 'CentOS Linux 7.1.1503 (Core)',
-+ 'version': '7.1.1503',
-+ 'pretty_version': '7.1.1503 (Core)',
-+ 'best_version': '7.1.1503',
-+ 'codename': 'Core',
-+ 'major_version': '7',
-+ 'minor_version': '1',
-+ 'build_number': '1503'
-+ }
-+ self._test_outcome(desired_outcome, 'centos', '7')
-+
-+ def test_fedora19_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': u'Fedora 19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'version': '19',
-+ 'pretty_version': u'19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'best_version': '19',
-+ 'codename': u'Schr\u00F6dinger\u2019s Cat',
-+ 'major_version': '19'
-+ }
-+ self._test_outcome(desired_outcome, 'fedora', '19')
-+
-+ def test_fedora23_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 23 (Twenty Three)',
-+ 'version': '23',
-+ 'pretty_version': '23 (Twenty Three)',
-+ 'best_version': '23',
-+ 'codename': 'Twenty Three',
-+ 'major_version': '23'
-+ }
-+ self._test_outcome(desired_outcome, 'fedora', '23')
-+
-+ def test_fedora30_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 30 (Thirty)',
-+ 'version': '30',
-+ 'pretty_version': '30 (Thirty)',
-+ 'best_version': '30',
-+ 'codename': 'Thirty',
-+ 'major_version': '30'
-+ }
-+ self._test_outcome(desired_outcome, 'fedora', '30')
-+
-+ def test_gentoo_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'gentoo',
-+ 'name': 'Gentoo Base System',
-+ 'pretty_name': 'Gentoo Base System 2.2',
-+ 'version': '2.2',
-+ 'pretty_version': '2.2',
-+ 'best_version': '2.2',
-+ 'major_version': '2',
-+ 'minor_version': '2',
-+ }
-+ self._test_outcome(desired_outcome, 'gentoo')
-+
-+ def test_kvmibm1_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'base',
-+ 'name': 'KVM for IBM z Systems',
-+ 'pretty_name': 'KVM for IBM z Systems 1.1.1 (Z)',
-+ 'version': '1.1.1',
-+ 'pretty_version': '1.1.1 (Z)',
-+ 'best_version': '1.1.1',
-+ 'codename': 'Z',
-+ 'major_version': '1',
-+ 'minor_version': '1',
-+ 'build_number': '1'
-+ }
-+ self._test_outcome(desired_outcome, 'kvmibm', '1', 'base')
-+
-+ def test_mageia5_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'mageia',
-+ 'name': 'Mageia',
-+ 'pretty_name': 'Mageia 5 (Official)',
-+ 'version': '5',
-+ 'pretty_version': '5 (Official)',
-+ 'best_version': '5',
-+ 'codename': 'Official',
-+ 'major_version': '5'
-+ }
-+ self._test_outcome(desired_outcome, 'mageia', '5')
-+
-+ def test_manjaro1512_dist_release(self):
-+ self._test_outcome({
-+ 'id': 'manjaro',
-+ 'name': 'Manjaro Linux',
-+ 'pretty_name': 'Manjaro Linux',
-+ 'version': '',
-+ 'codename': ''
-+ }, 'manjaro', '1512')
-+
-+ def test_opensuse42_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'suse',
-+ 'name': 'openSUSE',
-+ 'pretty_name': 'openSUSE 42.1 (x86_64)',
-+ 'version': '42.1',
-+ 'pretty_version': '42.1 (x86_64)',
-+ 'best_version': '42.1',
-+ 'codename': 'x86_64',
-+ 'major_version': '42',
-+ 'minor_version': '1'
-+ }
-+ self._test_outcome(desired_outcome, 'opensuse', '42', 'SuSE')
-+
-+ def test_oracle7_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'oracle',
-+ 'name': 'Oracle Linux Server',
-+ 'pretty_name': 'Oracle Linux Server 7.5',
-+ 'version': '7.5',
-+ 'pretty_version': '7.5',
-+ 'best_version': '7.5',
-+ 'major_version': '7',
-+ 'minor_version': '5'
-+ }
-+ self._test_outcome(desired_outcome, 'oracle', '7')
-+
-+ def test_rhel6_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 6.5 (Santiago)',
-+ 'version': '6.5',
-+ 'pretty_version': '6.5 (Santiago)',
-+ 'best_version': '6.5',
-+ 'codename': 'Santiago',
-+ 'major_version': '6',
-+ 'minor_version': '5'
-+ }
-+ self._test_outcome(desired_outcome, 'rhel', '6', 'redhat')
-+
-+ def test_rhel7_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 7.0 (Maipo)',
-+ 'version': '7.0',
-+ 'pretty_version': '7.0 (Maipo)',
-+ 'best_version': '7.0',
-+ 'codename': 'Maipo',
-+ 'major_version': '7',
-+ 'minor_version': '0'
-+ }
-+ self._test_outcome(desired_outcome, 'rhel', '7', 'redhat')
-+
-+ def test_slackware14_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'slackware',
-+ 'name': 'Slackware',
-+ 'pretty_name': 'Slackware 14.1',
-+ 'version': '14.1',
-+ 'pretty_version': '14.1',
-+ 'best_version': '14.1',
-+ 'major_version': '14',
-+ 'minor_version': '1'
-+ }
-+ self._test_outcome(
-+ desired_outcome,
-+ 'slackware',
-+ '14',
-+ release_file_suffix='version')
-+
-+ def test_sles12_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'suse',
-+ 'name': 'SUSE Linux Enterprise Server',
-+ 'pretty_name': 'SUSE Linux Enterprise Server 12 (s390x)',
-+ 'version': '12',
-+ 'pretty_version': '12 (s390x)',
-+ 'best_version': '12',
-+ 'major_version': '12',
-+ 'codename': 's390x'
-+ }
-+ self._test_outcome(desired_outcome, 'sles', '12', 'SuSE')
-+
-+ def test_cloudlinux5_dist_release(self):
-+ # Uses redhat-release only to get information.
-+ # The id of 'rhel' can only be fixed with issue #109.
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Vladislav Volkov',
-+ 'name': 'CloudLinux Server',
-+ 'pretty_name': 'CloudLinux Server 5.11 (Vladislav Volkov)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Vladislav Volkov)',
-+ 'best_version': '5.11',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome, 'cloudlinux', '5', 'redhat')
-+
-+ def test_cloudlinux6_dist_release(self):
-+ # Same as above, only has redhat-release.
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Oleg Makarov',
-+ 'name': 'CloudLinux Server',
-+ 'pretty_name': 'CloudLinux Server 6.8 (Oleg Makarov)',
-+ 'version': '6.8',
-+ 'pretty_version': '6.8 (Oleg Makarov)',
-+ 'best_version': '6.8',
-+ 'major_version': '6',
-+ 'minor_version': '8'
-+ }
-+ self._test_outcome(desired_outcome, 'cloudlinux', '6', 'redhat')
-+
-+ def test_cloudlinux7_dist_release(self):
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Yury Malyshev',
-+ 'name': 'CloudLinux',
-+ 'pretty_name': 'CloudLinux 7.3 (Yury Malyshev)',
-+ 'version': '7.3',
-+ 'pretty_version': '7.3 (Yury Malyshev)',
-+ 'best_version': '7.3',
-+ 'major_version': '7',
-+ 'minor_version': '3'
-+ }
-+ self._test_outcome(desired_outcome, 'cloudlinux', '7', 'redhat')
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestOverall(DistroTestCase):
-+ """Test a LinuxDistribution object created with default arguments.
-+
-+ The direct accessor functions on that object are tested (e.g. `id()`); they
-+ implement the precedence between the different sources of information.
-+
-+ In addition, because the distro release file is searched when not
-+ specified, the information resulting from the distro release file is also
-+ tested. The LSB and os-release sources are not tested again, because their
-+ test is already done in TestLSBRelease and TestOSRelease, and their
-+ algorithm does not depend on whether or not the file is specified.
-+
-+ TODO: This class should have testcases for all distros that are claimed
-+ to be reliably maintained w.r.t. to their ID (see `id()`). Testcases for
-+ the following distros are still missing:
-+ * `amazon` - Amazon Linux
-+ * `gentoo` - GenToo Linux
-+ * `ibm_powerkvm` - IBM PowerKVM
-+ * `parallels` - Parallels
-+ * `pidora` - Pidora (Fedora remix for Raspberry Pi)
-+ * `raspbian` - Raspbian
-+ * `scientific` - Scientific Linux
-+ * `xenserver` - XenServer
-+ """
-+
-+ def setup_method(self, test_method):
-+ super(TestOverall, self).setup_method(test_method)
-+ dist = test_method.__name__.split('_')[1]
-+ self._setup_for_distro(os.path.join(DISTROS_DIR, dist))
-+ self.distro = distro.LinuxDistribution()
-+
-+ def _test_outcome(self, outcome):
-+ assert self.distro.id() == outcome.get('id', '')
-+ assert self.distro.name() == outcome.get('name', '')
-+ assert self.distro.name(pretty=True) == outcome.get('pretty_name', '')
-+ assert self.distro.version() == outcome.get('version', '')
-+ assert self.distro.version(pretty=True) == \
-+ outcome.get('pretty_version', '')
-+ assert self.distro.version(best=True) == \
-+ outcome.get('best_version', '')
-+ assert self.distro.like() == outcome.get('like', '')
-+ assert self.distro.codename() == outcome.get('codename', '')
-+ assert self.distro.major_version() == outcome.get('major_version', '')
-+ assert self.distro.minor_version() == outcome.get('minor_version', '')
-+ assert self.distro.build_number() == outcome.get('build_number', '')
-+
-+ def _test_non_existing_release_file(self):
-+ # Test the info from the searched distro release file
-+ # does not have one.
-+ assert self.distro.distro_release_file == ''
-+ assert len(self.distro.distro_release_info()) == 0
-+
-+ def _test_release_file_info(self, filename, outcome):
-+ # Test the info from the searched distro release file
-+ assert os.path.basename(self.distro.distro_release_file) == filename
-+ distro_info = self.distro.distro_release_info()
-+ for key, value in outcome.items():
-+ assert distro_info[key] == value
-+ return distro_info
-+
-+ def test_arch_release(self):
-+ desired_outcome = {
-+ 'id': 'arch',
-+ 'name': 'Arch Linux',
-+ 'pretty_name': 'Arch Linux',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ # Test the info from the searched distro release file
-+ # Does not have one; The empty /etc/arch-release file is not
-+ # considered a valid distro release file:
-+ self._test_non_existing_release_file()
-+
-+ def test_centos5_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS',
-+ 'pretty_name': 'CentOS 5.11 (Final)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Final)',
-+ 'best_version': '5.11',
-+ 'codename': 'Final',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'centos',
-+ 'name': 'CentOS',
-+ 'version_id': '5.11',
-+ 'codename': 'Final'
-+ }
-+ self._test_release_file_info('centos-release', desired_info)
-+
-+ def test_centos7_release(self):
-+ desired_outcome = {
-+ 'id': 'centos',
-+ 'name': 'CentOS Linux',
-+ 'pretty_name': 'CentOS Linux 7 (Core)',
-+ 'version': '7',
-+ 'pretty_version': '7 (Core)',
-+ 'best_version': '7.1.1503',
-+ 'like': 'rhel fedora',
-+ 'codename': 'Core',
-+ 'major_version': '7'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'centos',
-+ 'name': 'CentOS Linux',
-+ 'version_id': '7.1.1503',
-+ 'codename': 'Core'
-+ }
-+ self._test_release_file_info('centos-release', desired_info)
-+
-+ def test_coreos_release(self):
-+ desired_outcome = {
-+ 'id': 'coreos',
-+ 'name': 'CoreOS',
-+ 'pretty_name': 'CoreOS 899.15.0',
-+ 'version': '899.15.0',
-+ 'pretty_version': '899.15.0',
-+ 'best_version': '899.15.0',
-+ 'major_version': '899',
-+ 'minor_version': '15',
-+ 'build_number': '0'
-+ }
-+ self._test_outcome(desired_outcome)
-+ self._test_non_existing_release_file()
-+
-+ def test_debian8_release(self):
-+ desired_outcome = {
-+ 'id': 'debian',
-+ 'name': 'Debian GNU/Linux',
-+ 'pretty_name': 'Debian GNU/Linux 8 (jessie)',
-+ 'version': '8',
-+ 'pretty_version': '8 (jessie)',
-+ 'best_version': '8.2',
-+ 'codename': 'jessie',
-+ 'major_version': '8'
-+ }
-+ self._test_outcome(desired_outcome)
-+ self._test_non_existing_release_file()
-+
-+ def test_exherbo_release(self):
-+ desired_outcome = {
-+ 'id': 'exherbo',
-+ 'name': 'Exherbo',
-+ 'pretty_name': 'Exherbo Linux',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_fedora19_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': u'Fedora 19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'version': '19',
-+ 'pretty_version': u'19 (Schr\u00F6dinger\u2019s Cat)',
-+ 'best_version': '19',
-+ 'codename': u'Schr\u00F6dinger\u2019s Cat',
-+ 'major_version': '19'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'version_id': '19',
-+ 'codename': u'Schr\u00F6dinger\u2019s Cat'
-+ }
-+ self._test_release_file_info('fedora-release', desired_info)
-+
-+ def test_fedora23_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 23 (Twenty Three)',
-+ 'version': '23',
-+ 'pretty_version': '23 (Twenty Three)',
-+ 'best_version': '23',
-+ 'codename': 'Twenty Three',
-+ 'major_version': '23'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'version_id': '23',
-+ 'codename': 'Twenty Three'
-+ }
-+ self._test_release_file_info('fedora-release', desired_info)
-+
-+ def test_fedora30_release(self):
-+ desired_outcome = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'pretty_name': 'Fedora 30 (Thirty)',
-+ 'version': '30',
-+ 'pretty_version': '30',
-+ 'best_version': '30',
-+ 'codename': '',
-+ 'major_version': '30'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'fedora',
-+ 'name': 'Fedora',
-+ 'version_id': '30',
-+ 'codename': 'Thirty'
-+ }
-+ self._test_release_file_info('fedora-release', desired_info)
-+
-+ def test_kvmibm1_release(self):
-+ desired_outcome = {
-+ 'id': 'kvmibm',
-+ 'name': 'KVM for IBM z Systems',
-+ 'pretty_name': 'KVM for IBM z Systems 1.1.1 (Z)',
-+ 'version': '1.1.1',
-+ 'pretty_version': '1.1.1 (Z)',
-+ 'best_version': '1.1.1',
-+ 'like': 'rhel fedora',
-+ 'codename': 'Z',
-+ 'major_version': '1',
-+ 'minor_version': '1',
-+ 'build_number': '1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'base',
-+ 'name': 'KVM for IBM z Systems',
-+ 'version_id': '1.1.1',
-+ 'codename': 'Z'
-+ }
-+ self._test_release_file_info('base-release', desired_info)
-+
-+ def test_linuxmint17_release(self):
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (Trusty Tahr)',
-+ 'best_version': '14.04.3',
-+ 'like': 'debian',
-+ 'codename': 'Trusty Tahr',
-+ 'major_version': '14',
-+ 'minor_version': '04'
-+ }
-+ self._test_outcome(desired_outcome)
-+ self._test_non_existing_release_file()
-+
-+ def test_mageia5_release(self):
-+ desired_outcome = {
-+ 'id': 'mageia',
-+ 'name': 'Mageia',
-+ 'pretty_name': 'Mageia 5',
-+ 'version': '5',
-+ 'pretty_version': '5 (thornicroft)',
-+ 'best_version': '5',
-+ 'like': 'mandriva fedora',
-+ # TODO: Codename differs between distro release and lsb_release.
-+ 'codename': 'thornicroft',
-+ 'major_version': '5'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'mageia',
-+ 'name': 'Mageia',
-+ 'version_id': '5',
-+ 'codename': 'Official'
-+ }
-+ self._test_release_file_info('mageia-release', desired_info)
-+
-+ def test_manjaro1512_release(self):
-+ self._test_outcome({
-+ 'id': 'manjaro',
-+ 'name': 'Manjaro Linux',
-+ 'pretty_name': 'Manjaro Linux',
-+ 'version': '15.12',
-+ 'pretty_version': '15.12 (Capella)',
-+ 'best_version': '15.12',
-+ 'major_version': '15',
-+ 'minor_version': '12',
-+ 'codename': 'Capella'
-+ })
-+
-+ self._test_release_file_info(
-+ 'manjaro-release',
-+ {'id': 'manjaro',
-+ 'name': 'Manjaro Linux'})
-+
-+ def test_opensuse42_release(self):
-+ desired_outcome = {
-+ 'id': 'opensuse',
-+ 'name': 'openSUSE Leap',
-+ 'pretty_name': 'openSUSE Leap 42.1 (x86_64)',
-+ 'version': '42.1',
-+ 'pretty_version': '42.1 (x86_64)',
-+ 'best_version': '42.1',
-+ 'like': 'suse',
-+ 'codename': 'x86_64',
-+ 'major_version': '42',
-+ 'minor_version': '1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'SuSE',
-+ 'name': 'openSUSE',
-+ 'version_id': '42.1',
-+ 'codename': 'x86_64'
-+ }
-+ self._test_release_file_info('SuSE-release', desired_info)
-+
-+ def test_oracle7_release(self):
-+ desired_outcome = {
-+ 'id': 'oracle',
-+ 'name': 'Oracle Linux Server',
-+ 'pretty_name': 'Oracle Linux Server 7.5',
-+ 'version': '7.5',
-+ 'pretty_version': '7.5',
-+ 'best_version': '7.5',
-+ 'major_version': '7',
-+ 'minor_version': '5'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'oracle',
-+ 'name': 'Oracle Linux Server',
-+ 'version_id': '7.5',
-+ }
-+ distro_info = self._test_release_file_info(
-+ 'oracle-release', desired_info)
-+ assert 'codename' not in distro_info
-+
-+ def test_raspbian7_release(self):
-+ desired_outcome = {
-+ 'id': 'raspbian',
-+ 'name': 'Raspbian GNU/Linux',
-+ 'pretty_name': 'Raspbian GNU/Linux 7 (wheezy)',
-+ 'version': '7',
-+ 'pretty_version': '7 (wheezy)',
-+ 'best_version': '7',
-+ 'like': 'debian',
-+ 'codename': 'wheezy',
-+ 'major_version': '7',
-+ }
-+ self._test_outcome(desired_outcome)
-+ self._test_non_existing_release_file()
-+
-+ def test_raspbian8_release(self):
-+ desired_outcome = {
-+ 'id': 'raspbian',
-+ 'name': 'Raspbian GNU/Linux',
-+ 'pretty_name': 'Raspbian GNU/Linux 8 (jessie)',
-+ 'version': '8',
-+ 'pretty_version': '8 (jessie)',
-+ 'best_version': '8',
-+ 'like': 'debian',
-+ 'codename': 'jessie',
-+ 'major_version': '8',
-+ }
-+ self._test_outcome(desired_outcome)
-+ self._test_non_existing_release_file()
-+
-+ def test_rhel5_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 5.11 (Tikanga)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Tikanga)',
-+ 'best_version': '5.11',
-+ 'codename': 'Tikanga',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'redhat',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'version_id': '5.11',
-+ 'codename': 'Tikanga'
-+ }
-+ self._test_release_file_info('redhat-release', desired_info)
-+
-+ def test_rhel6_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 6.5 (Santiago)',
-+ 'version': '6.5',
-+ 'pretty_version': '6.5 (Santiago)',
-+ 'best_version': '6.5',
-+ 'codename': 'Santiago',
-+ 'major_version': '6',
-+ 'minor_version': '5'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'redhat',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'version_id': '6.5',
-+ 'codename': 'Santiago'
-+ }
-+ self._test_release_file_info('redhat-release', desired_info)
-+
-+ def test_rhel7_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'pretty_name': 'Red Hat Enterprise Linux Server 7.0 (Maipo)',
-+ 'version': '7.0',
-+ 'pretty_version': '7.0 (Maipo)',
-+ 'best_version': '7.0',
-+ 'like': 'fedora',
-+ 'codename': 'Maipo',
-+ 'major_version': '7',
-+ 'minor_version': '0'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'redhat',
-+ 'name': 'Red Hat Enterprise Linux Server',
-+ 'version_id': '7.0',
-+ 'codename': 'Maipo'
-+ }
-+ self._test_release_file_info('redhat-release', desired_info)
-+
-+ def test_slackware14_release(self):
-+ desired_outcome = {
-+ 'id': 'slackware',
-+ 'name': 'Slackware',
-+ 'pretty_name': 'Slackware 14.1',
-+ 'version': '14.1',
-+ 'pretty_version': '14.1',
-+ 'best_version': '14.1',
-+ 'major_version': '14',
-+ 'minor_version': '1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'slackware',
-+ 'name': 'Slackware',
-+ 'version_id': '14.1',
-+ }
-+ distro_info = self._test_release_file_info(
-+ 'slackware-version', desired_info)
-+ assert 'codename' not in distro_info
-+
-+ def test_sles12_release(self):
-+ desired_outcome = {
-+ 'id': 'sles',
-+ 'name': 'SLES',
-+ 'pretty_name': 'SUSE Linux Enterprise Server 12 SP1',
-+ 'version': '12.1',
-+ 'pretty_version': '12.1 (n/a)',
-+ 'best_version': '12.1',
-+ 'codename': 'n/a',
-+ 'major_version': '12',
-+ 'minor_version': '1'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'SuSE',
-+ 'name': 'SUSE Linux Enterprise Server',
-+ 'version_id': '12',
-+ 'codename': 's390x'
-+ }
-+ self._test_release_file_info('SuSE-release', desired_info)
-+
-+ def test_ubuntu14_release(self):
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 14.04.3 LTS',
-+ 'version': '14.04',
-+ 'pretty_version': '14.04 (Trusty Tahr)',
-+ 'best_version': '14.04.3',
-+ 'like': 'debian',
-+ 'codename': 'Trusty Tahr',
-+ 'major_version': '14',
-+ 'minor_version': '04'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ # Test the info from the searched distro release file
-+ # Does not have one; /etc/debian_version is not considered a distro
-+ # release file:
-+ self._test_non_existing_release_file()
-+
-+ def test_ubuntu16_release(self):
-+ desired_outcome = {
-+ 'id': 'ubuntu',
-+ 'name': 'Ubuntu',
-+ 'pretty_name': 'Ubuntu 16.04.1 LTS',
-+ 'version': '16.04',
-+ 'pretty_version': '16.04 (xenial)',
-+ 'best_version': '16.04.1',
-+ 'like': 'debian',
-+ 'codename': 'xenial',
-+ 'major_version': '16',
-+ 'minor_version': '04'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ # Test the info from the searched distro release file
-+ # Does not have one; /etc/debian_version is not considered a distro
-+ # release file:
-+ self._test_non_existing_release_file()
-+
-+ def test_amazon2016_release(self):
-+ desired_outcome = {
-+ 'id': 'amzn',
-+ 'name': 'Amazon Linux AMI',
-+ 'pretty_name': 'Amazon Linux AMI 2016.03',
-+ 'version': '2016.03',
-+ 'pretty_version': '2016.03',
-+ 'best_version': '2016.03',
-+ 'like': 'rhel fedora',
-+ 'major_version': '2016',
-+ 'minor_version': '03'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_amazon2014_release(self):
-+ # Amazon Linux 2014 only contains a system-release file.
-+ # distro doesn't currently handle it.
-+ desired_outcome = {}
-+ self._test_outcome(desired_outcome)
-+
-+ def test_scientific6_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Scientific Linux',
-+ 'pretty_name': 'Scientific Linux 6.4 (Carbon)',
-+ 'version': '6.4',
-+ 'pretty_version': '6.4 (Carbon)',
-+ 'best_version': '6.4',
-+ 'codename': 'Carbon',
-+ 'major_version': '6',
-+ 'minor_version': '4',
-+
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'redhat',
-+ 'name': 'Scientific Linux',
-+ 'version_id': '6.4',
-+ 'codename': 'Carbon'
-+ }
-+ self._test_release_file_info('redhat-release', desired_info)
-+
-+ def test_scientific7_release(self):
-+ desired_outcome = {
-+ 'id': 'rhel',
-+ 'name': 'Scientific Linux',
-+ 'pretty_name': 'Scientific Linux 7.2 (Nitrogen)',
-+ 'version': '7.2',
-+ 'pretty_version': '7.2 (Nitrogen)',
-+ 'best_version': '7.2',
-+ 'like': 'fedora',
-+ 'codename': 'Nitrogen',
-+ 'major_version': '7',
-+ 'minor_version': '2',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'redhat',
-+ 'name': 'Scientific Linux',
-+ 'version_id': '7.2',
-+ 'codename': 'Nitrogen'
-+ }
-+ self._test_release_file_info('redhat-release', desired_info)
-+
-+ def test_gentoo_release(self):
-+ desired_outcome = {
-+ 'id': 'gentoo',
-+ 'name': 'Gentoo',
-+ 'pretty_name': 'Gentoo/Linux',
-+ 'version': '2.2',
-+ 'pretty_version': '2.2',
-+ 'best_version': '2.2',
-+ 'major_version': '2',
-+ 'minor_version': '2',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'gentoo',
-+ 'name': 'Gentoo Base System',
-+ 'version_id': '2.2',
-+ }
-+ self._test_release_file_info('gentoo-release', desired_info)
-+
-+ def test_openelec6_release(self):
-+ desired_outcome = {
-+ 'id': 'openelec',
-+ 'name': 'OpenELEC',
-+ 'pretty_name': 'OpenELEC (official) - Version: 6.0.3',
-+ 'version': '6.0',
-+ 'pretty_version': '6.0',
-+ 'best_version': '6.0.3',
-+ 'major_version': '6',
-+ 'minor_version': '0',
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_mandriva2011_release(self):
-+ desired_outcome = {
-+ 'id': 'mandrivalinux',
-+ 'name': 'MandrivaLinux',
-+ 'pretty_name': 'Mandriva Linux 2011.0',
-+ 'version': '2011.0',
-+ 'pretty_version': '2011.0 (turtle)',
-+ 'best_version': '2011.0',
-+ 'major_version': '2011',
-+ 'minor_version': '0',
-+ 'codename': 'turtle'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ desired_info = {
-+ 'id': 'mandrake',
-+ 'name': 'Mandriva Linux',
-+ 'version_id': '2011.0',
-+ }
-+ self._test_release_file_info('mandrake-release', desired_info)
-+
-+ def test_cloudlinux5_release(self):
-+ # Uses redhat-release only to get information.
-+ # The id of 'rhel' can only be fixed with issue #109.
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Vladislav Volkov',
-+ 'name': 'CloudLinux Server',
-+ 'pretty_name': 'CloudLinux Server 5.11 (Vladislav Volkov)',
-+ 'version': '5.11',
-+ 'pretty_version': '5.11 (Vladislav Volkov)',
-+ 'best_version': '5.11',
-+ 'major_version': '5',
-+ 'minor_version': '11'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_cloudlinux6_release(self):
-+ # Same as above, only has redhat-release.
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Oleg Makarov',
-+ 'name': 'CloudLinux Server',
-+ 'pretty_name': 'CloudLinux Server 6.8 (Oleg Makarov)',
-+ 'version': '6.8',
-+ 'pretty_version': '6.8 (Oleg Makarov)',
-+ 'best_version': '6.8',
-+ 'major_version': '6',
-+ 'minor_version': '8'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+ def test_cloudlinux7_release(self):
-+ desired_outcome = {
-+ 'id': 'cloudlinux',
-+ 'codename': 'Yury Malyshev',
-+ 'name': 'CloudLinux',
-+ 'pretty_name': 'CloudLinux 7.3 (Yury Malyshev)',
-+ 'like': 'rhel fedora centos',
-+ 'version': '7.3',
-+ 'pretty_version': '7.3 (Yury Malyshev)',
-+ 'best_version': '7.3',
-+ 'major_version': '7',
-+ 'minor_version': '3'
-+ }
-+ self._test_outcome(desired_outcome)
-+
-+
-+def _bad_os_listdir(path='.'):
-+ """ This function is used by TestOverallWithEtcNotReadable to simulate
-+ a folder that cannot be called with os.listdir() but files are still
-+ readable. Forces distro to guess which *-release files are available. """
-+ raise OSError()
-+
-+
-+@pytest.mark.skipIf(not IS_LINUX, reason='Irrelevant on non-linx')
-+class TestOverallWithEtcNotReadable(TestOverall):
-+ def setup_method(self, test_method):
-+ self._old_listdir = os.listdir
-+ os.listdir = _bad_os_listdir
-+ super(TestOverallWithEtcNotReadable, self).setup_method(test_method)
-+
-+ def teardown_method(self, test_method):
-+ super(TestOverallWithEtcNotReadable, self).teardown_method(test_method)
-+ if os.listdir is _bad_os_listdir:
-+ os.listdir = self._old_listdir
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestGetAttr(DistroTestCase):
-+ """Test the consistency between the results of
-+ `{source}_release_attr()` and `{source}_release_info()` for all
-+ distros in `DISTROS`.
-+ """
-+
-+ def _test_attr(self, info_method, attr_method):
-+ for dist in DISTROS:
-+ self._setup_for_distro(os.path.join(DISTROS_DIR, dist))
-+ _distro = distro.LinuxDistribution()
-+ info = getattr(_distro, info_method)()
-+ for key in info.keys():
-+ try:
-+ assert info[key] == getattr(_distro, attr_method)(key)
-+ except AssertionError:
-+ print("distro: {0}, key: {1}".format(dist, key))
-+
-+ def test_os_release_attr(self):
-+ self._test_attr('os_release_info', 'os_release_attr')
-+
-+ def test_lsb_release_attr(self):
-+ self._test_attr('lsb_release_info', 'lsb_release_attr')
-+
-+ def test_distro_release_attr(self):
-+ self._test_attr('distro_release_info', 'distro_release_attr')
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestInfo(DistroTestCase):
-+
-+ def setup_method(self, test_method):
-+ super(TestInfo, self).setup_method(test_method)
-+ self.ubuntu14_os_release = os.path.join(
-+ DISTROS_DIR, 'ubuntu14', 'etc', 'os-release')
-+
-+ def test_info(self):
-+ _distro = distro.LinuxDistribution(
-+ False, self.ubuntu14_os_release, 'non')
-+
-+ desired_info = {
-+ 'id': 'ubuntu',
-+ 'version': '14.04',
-+ 'like': 'debian',
-+ 'version_parts': {
-+ 'major': '14',
-+ 'minor': '04',
-+ 'build_number': ''
-+ },
-+ 'codename': 'Trusty Tahr'
-+ }
-+
-+ info = _distro.info()
-+ assert info == desired_info
-+
-+ desired_info_diff = {
-+ 'version': '14.04 (Trusty Tahr)'
-+ }
-+ desired_info.update(desired_info_diff)
-+ info = _distro.info(pretty=True)
-+ assert info == desired_info
-+
-+ desired_info_diff = {
-+ 'version': '14.04.3',
-+ 'version_parts': {
-+ 'major': '14',
-+ 'minor': '04',
-+ 'build_number': '3'
-+ }
-+ }
-+ desired_info.update(desired_info_diff)
-+ info = _distro.info(best=True)
-+ assert info == desired_info
-+
-+ desired_info_diff = {
-+ 'version': '14.04.3 (Trusty Tahr)'
-+ }
-+ desired_info.update(desired_info_diff)
-+ info = _distro.info(pretty=True, best=True)
-+ assert info == desired_info
-+
-+ def test_none(self):
-+
-+ def _test_none(info):
-+ assert info['id'] == ''
-+ assert info['version'] == ''
-+ assert info['like'] == ''
-+ assert info['version_parts']['major'] == ''
-+ assert info['version_parts']['minor'] == ''
-+ assert info['version_parts']['build_number'] == ''
-+ assert info['codename'] == ''
-+
-+ _distro = distro.LinuxDistribution(False, 'non', 'non')
-+
-+ info = _distro.info()
-+ _test_none(info)
-+
-+ info = _distro.info(best=True)
-+ _test_none(info)
-+
-+ info = _distro.info(pretty=True)
-+ _test_none(info)
-+
-+ info = _distro.info(pretty=True, best=True)
-+ _test_none(info)
-+
-+ def test_linux_distribution(self):
-+ _distro = distro.LinuxDistribution(False, self.ubuntu14_os_release)
-+ i = _distro.linux_distribution()
-+ assert i == ('Ubuntu', '14.04', 'Trusty Tahr')
-+
-+ def test_linux_distribution_full_false(self):
-+ _distro = distro.LinuxDistribution(False, self.ubuntu14_os_release)
-+ i = _distro.linux_distribution(full_distribution_name=False)
-+ assert i == ('ubuntu', '14.04', 'Trusty Tahr')
-+
-+ def test_all(self):
-+ """Test info() by comparing its results with the results of specific
-+ consolidated accessor functions.
-+ """
-+ def _test_all(info, best=False, pretty=False):
-+ assert info['id'] == _distro.id()
-+ assert info['version'] == _distro.version(pretty=pretty, best=best)
-+ assert info['version_parts']['major'] == \
-+ _distro.major_version(best=best)
-+ assert info['version_parts']['minor'] == \
-+ _distro.minor_version(best=best)
-+ assert info['version_parts']['build_number'] == \
-+ _distro.build_number(best=best)
-+ assert info['like'] == _distro.like()
-+ assert info['codename'] == _distro.codename()
-+ assert len(info['version_parts']) == 3
-+ assert len(info) == 5
-+
-+ for dist in DISTROS:
-+ self._setup_for_distro(os.path.join(DISTROS_DIR, dist))
-+
-+ _distro = distro.LinuxDistribution()
-+
-+ info = _distro.info()
-+ _test_all(info)
-+
-+ info = _distro.info(best=True)
-+ _test_all(info, best=True)
-+
-+ info = _distro.info(pretty=True)
-+ _test_all(info, pretty=True)
-+
-+ info = _distro.info(pretty=True, best=True)
-+ _test_all(info, pretty=True, best=True)
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestOSReleaseParsing:
-+ """Test the parsing of os-release files.
-+ """
-+
-+ def setup_method(self, test_method):
-+ self.distro = distro.LinuxDistribution(False, None, None)
-+ self.distro.debug = True
-+
-+ def _get_props(self, input):
-+ return self.distro._parse_os_release_content(StringIO(
-+ input,
-+ ))
-+
-+ def _test_zero_length_props(self, input):
-+ props = self._get_props(input)
-+ assert len(props) == 0
-+
-+ def _test_empty_value(self, input):
-+ props = self._get_props(input)
-+ assert props.get('key', None) == ''
-+
-+ def _test_parsed_value(self, input):
-+ props = self._get_props(input)
-+ assert props.get('key', None) == 'value'
-+
-+ def test_kv_01_empty_file(self):
-+ self._test_zero_length_props('')
-+
-+ def test_kv_02_empty_line(self):
-+ self._test_zero_length_props('\n')
-+
-+ def test_kv_03_empty_line_with_crlf(self):
-+ self._test_zero_length_props('\r\n')
-+
-+ def test_kv_04_empty_line_with_just_cr(self):
-+ self._test_zero_length_props('\r')
-+
-+ def test_kv_05_comment(self):
-+ self._test_zero_length_props('# KEY=value\n')
-+
-+ def test_kv_06_empty_value(self):
-+ self._test_empty_value('KEY=\n')
-+
-+ def test_kv_07_empty_value_single_quoted(self):
-+ self._test_empty_value('KEY=\'\'\n')
-+
-+ def test_kv_08_empty_value_double_quoted(self):
-+ self._test_empty_value('KEY=""\n')
-+
-+ def test_kv_09_word(self):
-+ self._test_parsed_value('KEY=value\n')
-+
-+ def test_kv_10_word_no_newline(self):
-+ self._test_parsed_value('KEY=value')
-+
-+ def test_kv_11_word_with_crlf(self):
-+ self._test_parsed_value('KEY=value\r\n')
-+
-+ def test_kv_12_word_with_just_cr(self):
-+ self._test_parsed_value('KEY=value\r')
-+
-+ def test_kv_13_word_with_multi_blanks(self):
-+ self._test_empty_value('KEY= cmd \n')
-+ # Note: Without quotes, this assigns the empty string, and 'cmd' is
-+ # a separate token that is being ignored (it would be a command
-+ # in the shell).
-+
-+ def test_kv_14_unquoted_words(self):
-+ self._test_parsed_value('KEY=value cmd\n')
-+
-+ def test_kv_15_double_quoted_words(self):
-+ props = self._get_props('KEY="a simple value" cmd\n')
-+ assert props.get('key', None) == 'a simple value'
-+
-+ def test_kv_16_double_quoted_words_with_multi_blanks(self):
-+ props = self._get_props('KEY=" a simple value "\n')
-+ assert props.get('key', None) == ' a simple value '
-+
-+ def test_kv_17_double_quoted_word_with_single_quote(self):
-+ props = self._get_props('KEY="it\'s value"\n')
-+ assert props.get('key', None) == 'it\'s value'
-+
-+ def test_kv_18_double_quoted_word_with_double_quote(self):
-+ props = self._get_props('KEY="a \\"bold\\" move"\n')
-+ assert props.get('key', None) == 'a "bold" move'
-+
-+ def test_kv_19_single_quoted_words(self):
-+ props = self._get_props('KEY=\'a simple value\'\n')
-+ assert props.get('key', None) == 'a simple value'
-+
-+ def test_kv_20_single_quoted_words_with_multi_blanks(self):
-+ props = self._get_props('KEY=\' a simple value \'\n')
-+ assert props.get('key', None) == ' a simple value '
-+
-+ def test_kv_21_single_quoted_word_with_double_quote(self):
-+ props = self._get_props('KEY=\'a "bold" move\'\n')
-+ assert props.get('key', None) == 'a "bold" move'
-+
-+ def test_kv_22_quoted_unicode_wordchar(self):
-+ # "wordchar" means it is in the shlex.wordchars variable.
-+ props = self._get_props(u'KEY="wordchar: \u00CA (E accent grave)"\n')
-+ assert props.get('key', None) == u'wordchar: \u00CA (E accent grave)'
-+
-+ def test_kv_23_quoted_unicode_non_wordchar(self):
-+ # "non-wordchar" means it is not in the shlex.wordchars variable.
-+ props = self._get_props(
-+ u'KEY="non-wordchar: \u00A1 (inverted exclamation mark)"\n')
-+ assert (props.get('key', None) ==
-+ u'non-wordchar: \u00A1 (inverted exclamation mark)')
-+
-+ def test_kv_24_double_quoted_entire_single_quoted_word(self):
-+ props = self._get_props('KEY="\'value\'"\n')
-+ assert props.get('key', None) == "'value'"
-+
-+ def test_kv_25_single_quoted_entire_double_quoted_word(self):
-+ props = self._get_props('KEY=\'"value"\'\n')
-+ assert props.get('key', None) == '"value"'
-+
-+ def test_kv_26_double_quoted_multiline(self):
-+ props = self.distro._parse_os_release_content(StringIO(
-+ 'KEY="a multi\n'
-+ 'line value"\n'
-+ ))
-+ assert props.get('key', None) == 'a multi\nline value'
-+ # TODO: Find out why the result is not 'a multi line value'
-+
-+ def test_kv_27_double_quoted_multiline_2(self):
-+ props = self._get_props('KEY=\' a simple value \'\n')
-+ props = self.distro._parse_os_release_content(StringIO(
-+ 'KEY="a multi\n'
-+ 'line=value"\n'
-+ ))
-+ assert props.get('key', None) == 'a multi\nline=value'
-+ # TODO: Find out why the result is not 'a multi line=value'
-+
-+ def test_kv_28_double_quoted_word_with_equal(self):
-+ props = self._get_props('KEY="var=value"\n')
-+ assert props.get('key', None) == 'var=value'
-+
-+ def test_kv_29_single_quoted_word_with_equal(self):
-+ props = self._get_props('KEY=\'var=value\'\n')
-+ assert props.get('key', None) == 'var=value'
-+
-+ def test_kx_01(self):
-+ props = self.distro._parse_os_release_content(StringIO(
-+ 'KEY1=value1\n'
-+ 'KEY2="value 2"\n'
-+ ))
-+ assert props.get('key1', None) == 'value1'
-+ assert props.get('key2', None) == 'value 2'
-+
-+ def test_kx_02(self):
-+ props = self.distro._parse_os_release_content(StringIO(
-+ '# KEY1=value1\n'
-+ 'KEY2="value 2"\n'
-+ ))
-+ assert props.get('key1', None) is None
-+ assert props.get('key2', None) == 'value 2'
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestGlobal:
-+ """Test the global module-level functions, and default values of their
-+ arguments.
-+ """
-+
-+ def setup_method(self, test_method):
-+ pass
-+
-+ def test_global(self):
-+ # Because the module-level functions use the module-global
-+ # LinuxDistribution instance, it would influence the tested
-+ # code too much if we mocked that in order to use the distro
-+ # specific release files. Instead, we let the functions use
-+ # the release files of the distro this test runs on, and
-+ # compare the result of the global functions with the result
-+ # of the methods on the global LinuxDistribution object.
-+
-+ def _test_consistency(function, kwargs=None):
-+ kwargs = kwargs or {}
-+ method_result = getattr(MODULE_DISTRO, function)(**kwargs)
-+ function_result = getattr(distro, function)(**kwargs)
-+ assert method_result == function_result
-+
-+ kwargs = {'full_distribution_name': True}
-+ _test_consistency('linux_distribution', kwargs)
-+ kwargs = {'full_distribution_name': False}
-+ _test_consistency('linux_distribution', kwargs)
-+
-+ kwargs = {'pretty': False}
-+ _test_consistency('name', kwargs)
-+ _test_consistency('version', kwargs)
-+ _test_consistency('info', kwargs)
-+
-+ kwargs = {'pretty': True}
-+ _test_consistency('name', kwargs)
-+ _test_consistency('version', kwargs)
-+ _test_consistency('info', kwargs)
-+
-+ kwargs = {'best': False}
-+ _test_consistency('version', kwargs)
-+ _test_consistency('version_parts', kwargs)
-+ _test_consistency('major_version', kwargs)
-+ _test_consistency('minor_version', kwargs)
-+ _test_consistency('build_number', kwargs)
-+ _test_consistency('info', kwargs)
-+
-+ kwargs = {'best': True}
-+ _test_consistency('version', kwargs)
-+ _test_consistency('version_parts', kwargs)
-+ _test_consistency('major_version', kwargs)
-+ _test_consistency('minor_version', kwargs)
-+ _test_consistency('build_number', kwargs)
-+ _test_consistency('info', kwargs)
-+
-+ _test_consistency('id')
-+ _test_consistency('like')
-+ _test_consistency('codename')
-+ _test_consistency('info')
-+
-+ _test_consistency('os_release_info')
-+ _test_consistency('lsb_release_info')
-+ _test_consistency('distro_release_info')
-+ _test_consistency('uname_info')
-+
-+ os_release_keys = [
-+ 'name',
-+ 'version',
-+ 'id',
-+ 'id_like',
-+ 'pretty_name',
-+ 'version_id',
-+ 'codename',
-+ ]
-+ for key in os_release_keys:
-+ _test_consistency('os_release_attr', {'attribute': key})
-+
-+ lsb_release_keys = [
-+ 'distributor_id',
-+ 'description',
-+ 'release',
-+ 'codename',
-+ ]
-+ for key in lsb_release_keys:
-+ _test_consistency('lsb_release_attr', {'attribute': key})
-+
-+ distro_release_keys = [
-+ 'id',
-+ 'name',
-+ 'version_id',
-+ 'codename',
-+ ]
-+ for key in distro_release_keys:
-+ _test_consistency('distro_release_attr', {'attribute': key})
-+
-+ uname_keys = [
-+ 'id',
-+ 'name',
-+ 'release'
-+ ]
-+ for key in uname_keys:
-+ _test_consistency('uname_attr', {'attribute': key})
-+
-+
-+@pytest.mark.skipif(not IS_LINUX, reason='Irrelevant on non-linux')
-+class TestRepr:
-+ """Test the __repr__() method.
-+ """
-+
-+ def test_repr(self):
-+ # We test that the class name and the names of all instance attributes
-+ # show up in the repr() string.
-+ repr_str = repr(distro._distro)
-+ assert "LinuxDistribution" in repr_str
-+ for attr in MODULE_DISTRO.__dict__.keys():
-+ assert attr + '=' in repr_str
-diff --git a/third_party/python/enum34/enum/doc/enum.pdf b/third_party/python/enum34/enum/doc/enum.pdf
---- a/third_party/python/enum34/enum/doc/enum.pdf
-+++ b/third_party/python/enum34/enum/doc/enum.pdf
-@@ -1,10 +1,10 @@
- %PDF-1.4
--%東京 ReportLab Generated PDF document http://www.reportlab.com
-+% ReportLab Generated PDF document http://www.reportlab.com
- 1 0 obj
- << /F1 2 0 R /F2 3 0 R /F3 4 0 R /F4 5 0 R /F5 8 0 R /F6 15 0 R >>
- endobj
- 2 0 obj
- << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >>
- endobj
- 3 0 obj
- << /BaseFont /Courier-Bold /Encoding /WinAnsiEncoding /Name /F2 /Subtype /Type1 /Type /Font >>
-diff --git a/third_party/python/psutil/psutil/_pslinux.py b/third_party/python/psutil/psutil/_pslinux.py
---- a/third_party/python/psutil/psutil/_pslinux.py
-+++ b/third_party/python/psutil/psutil/_pslinux.py
-@@ -1046,30 +1046,28 @@ def disk_io_counters():
- # On Linux 2.4 each line has always 15 fields, e.g.:
- # "3 0 8 hda 8 8 8 8 8 8 8 8 8 8 8"
- # On Linux 2.6+ each line *usually* has 14 fields, and the disk
- # name is in another position, like this:
- # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8"
- # ...unless (Linux 2.6) the line refers to a partition instead
- # of a disk, in which case the line has less fields (7):
- # "3 1 hda1 8 8 8 8"
-- # 4.18+ has 4 fields added:
-- # "3 0 hda 8 8 8 8 8 8 8 8 8 8 8 0 0 0 0"
- # See:
- # https://www.kernel.org/doc/Documentation/iostats.txt
- # https://www.kernel.org/doc/Documentation/ABI/testing/procfs-diskstats
- fields = line.split()
- fields_len = len(fields)
- if fields_len == 15:
- # Linux 2.4
- name = fields[3]
- reads = int(fields[2])
- (reads_merged, rbytes, rtime, writes, writes_merged,
- wbytes, wtime, _, busy_time, _) = map(int, fields[4:14])
-- elif fields_len == 14 or fields_len == 18:
-+ elif fields_len == 14:
- # Linux 2.6+, line referring to a disk
- name = fields[2]
- (reads, reads_merged, rbytes, rtime, writes, writes_merged,
- wbytes, wtime, _, busy_time, _) = map(int, fields[3:14])
- elif fields_len == 7:
- # Linux 2.6+, line referring to a partition
- name = fields[2]
- reads, rbytes, writes, wbytes = map(int, fields[3:])
-diff --git a/third_party/python/requirements.in b/third_party/python/requirements.in
---- a/third_party/python/requirements.in
-+++ b/third_party/python/requirements.in
-@@ -1,11 +1,12 @@
- attrs==18.1.0
- biplist==1.0.3
- blessings==1.7
-+distro==1.4.0
- jsmin==2.1.0
- json-e==2.7.0
- mozilla-version==0.3.0
- pathlib2==2.3.2
- pip-tools==3.0.0
- pipenv==2018.5.18
- psutil==5.4.3
- pytest==3.6.2
-diff --git a/third_party/python/requirements.txt b/third_party/python/requirements.txt
---- a/third_party/python/requirements.txt
-+++ b/third_party/python/requirements.txt
-@@ -14,16 +14,19 @@ blessings==1.7 \
- certifi==2018.4.16 \
- --hash=sha256:13e698f54293db9f89122b0581843a782ad0934a4fe0172d2a980ba77fc61bb7 \
- --hash=sha256:9fa520c1bacfb634fa7af20a76bcbd3d5fb390481724c597da32c719a7dca4b0 \
- # via pipenv
- click==7.0 \
- --hash=sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13 \
- --hash=sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7 \
- # via pip-tools
-+distro==1.4.0 \
-+ --hash=sha256:362dde65d846d23baee4b5c058c8586f219b5a54be1cf5fc6ff55c4578392f57 \
-+ --hash=sha256:eedf82a470ebe7d010f1872c17237c79ab04097948800029994fa458e52fb4b4
- enum34==1.1.6 \
- --hash=sha256:2d81cbbe0e73112bdfe6ef8576f2238f2ba27dd0d55752a776c41d38b7da2850 \
- --hash=sha256:644837f692e5f550741432dd3f223bbb9852018674981b1664e5dc339387588a \
- --hash=sha256:6bd0f6ad48ec2aa117d3d141940d484deccda84d4fcd884f5c3d93c23ecd8c79 \
- --hash=sha256:8ad8c4783bf61ded74527bffb48ed9b54166685e4230386a9ed9b1279e2df5b1 \
- # via mozilla-version
- funcsigs==1.0.2 \
- --hash=sha256:330cc27ccbf7f1e992e69fef78261dc7c6569012cf397db8d3de0234e6c937ca \
-
diff --git a/libre/iceweasel/libre.patch b/libre/iceweasel/libre.patch
index 53abc78b2..018ab6e5d 100644
--- a/libre/iceweasel/libre.patch
+++ b/libre/iceweasel/libre.patch
@@ -1,5 +1,134 @@
+diff --git a/browser/app/permissions b/browser/app/permissions
+index ecb82a2..5d522ef 100644
+--- a/browser/app/permissions
++++ b/browser/app/permissions
+@@ -14,12 +14,6 @@ origin uitour 1 https://support.mozilla.org
+ origin uitour 1 about:home
+ origin uitour 1 about:newtab
+
+-# XPInstall
+-origin install 1 https://addons.mozilla.org
+-
+ # Remote troubleshooting
+ origin remote-troubleshooting 1 https://support.mozilla.org
+
+-# addon install
+-origin install 1 https://private-network.firefox.com
+-origin install 1 https://fpn.firefox.com
+diff --git a/browser/components/newtab/docs/index.rst b/browser/components/newtab/docs/index.rst
+index ea1e42a..855b245 100644
+--- a/browser/components/newtab/docs/index.rst
++++ b/browser/components/newtab/docs/index.rst
+@@ -1,8 +1,8 @@
+ ======================
+-Firefox Home (New Tab)
++Iceweasel Home (New Tab)
+ ======================
+
+-All files related to Firefox Home, which includes content that appears on `about:home`,
++All files related to Iceweasel Home, which includes content that appears on `about:home`,
+ `about:newtab`, and `about:welcome`, can we found in the `browser/components/newtab` directory.
+ Some of these source files (such as `.js`, `.jsx`, and `.sass`) require an additional build step.
+ We are working on migrating this to work with `mach`, but in the meantime, please
+diff --git a/browser/components/preferences/in-content/sync.inc.xhtml b/browser/components/preferences/in-content/sync.inc.xhtml
+index 7d37d26..4ebbc06 100644
+--- a/browser/components/preferences/in-content/sync.inc.xhtml
++++ b/browser/components/preferences/in-content/sync.inc.xhtml
+@@ -35,22 +35,6 @@
+ </hbox>
+ </vbox>
+ </hbox>
+- <label class="fxaMobilePromo" data-l10n-id="sync-mobile-promo">
+- <html:img
+- src="chrome://browser/skin/preferences/in-content/logo-android.svg"
+- data-l10n-name="android-icon"
+- class="androidIcon"/>
+- <html:a
+- data-l10n-name="android-link"
+- class="fxaMobilePromo-android text-link" target="_blank"/>
+- <html:img
+- src="chrome://browser/skin/preferences/in-content/logo-ios.svg"
+- data-l10n-name="ios-icon"
+- class="iOSIcon"/>
+- <html:a
+- data-l10n-name="ios-link"
+- class="fxaMobilePromo-ios text-link" target="_blank"/>
+- </label>
+ </groupbox>
+
+ <vbox id="hasFxaAccount">
+diff --git a/browser/locales/en-US/browser/newtab/newtab.ftl b/browser/locales/en-US/browser/newtab/newtab.ftl
+index 0737833..7cb90d6 100644
+--- a/browser/locales/en-US/browser/newtab/newtab.ftl
++++ b/browser/locales/en-US/browser/newtab/newtab.ftl
+@@ -2,7 +2,7 @@
+ # License, v. 2.0. If a copy of the MPL was not distributed with this
+ # file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+-### Firefox Home / New Tab strings for about:home / about:newtab.
++### Iceweasel Home / New Tab strings for about:home / about:newtab.
+
+ newtab-page-title = New Tab
+ newtab-settings-button =
+diff --git a/browser/locales/en-US/browser/policies/policies-descriptions.ftl b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
+index dabfadc..3ce732e 100644
+--- a/browser/locales/en-US/browser/policies/policies-descriptions.ftl
++++ b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
+@@ -96,7 +96,7 @@ policy-ExtensionSettings = Manage all aspects of extension installation.
+
+ policy-ExtensionUpdate = Enable or disable automatic extension updates.
+
+-policy-FirefoxHome = Configure Firefox Home.
++policy-FirefoxHome = Configure Iceweasel Home.
+
+ policy-FlashPlugin = Allow or deny usage of the Flash plugin.
+
+diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl
+index 1b29e8d..6f7566c 100644
+--- a/browser/locales/en-US/browser/preferences/preferences.ftl
++++ b/browser/locales/en-US/browser/preferences/preferences.ftl
+@@ -550,7 +550,7 @@ home-restore-defaults =
+ # "Firefox" should be treated as a brand and kept in English,
+ # while "Home" and "(Default)" can be localized.
+ home-mode-choice-default =
+- .label = Firefox Home (Default)
++ .label = Iceweasel Home (Default)
+
+ home-mode-choice-custom =
+ .label = Custom URLs…
+@@ -577,10 +577,10 @@ choose-bookmark =
+ .label = Use Bookmark…
+ .accesskey = B
+
+-## Home Section - Firefox Home Content Customization
++## Home Section - Iceweasel Home Content Customization
+
+-home-prefs-content-header = Firefox Home Content
+-home-prefs-content-description = Choose what content you want on your Firefox Home screen.
++home-prefs-content-header = Iceweasel Home Content
++home-prefs-content-description = Choose what content you want on your Iceweasel Home screen.
+
+ home-prefs-search-header =
+ .label = Web Search
+@@ -714,16 +714,6 @@ sync-signedout-account-signin2 =
+ .label = Sign in to { -sync-brand-short-name }…
+ .accesskey = i
+
+-# This message contains two links and two icon images.
+-# `<img data-l10n-name="android-icon"/>` - Android logo icon
+-# `<a data-l10n-name="android-link">` - Link to Android Download
+-# `<img data-l10n-name="ios-icon">` - iOS logo icon
+-# `<a data-l10n-name="ios-link">` - Link to iOS Download
+-#
+-# They can be moved within the sentence as needed to adapt
+-# to your language, but should not be changed or translated.
+-sync-mobile-promo = Download Firefox for <img data-l10n-name="android-icon"/> <a data-l10n-name="android-link">Android</a> or <img data-l10n-name="ios-icon"/> <a data-l10n-name="ios-link">iOS</a> to sync with your mobile device.
+-
+ ## Firefox Account - Signed in
+
+ sync-profile-picture =
diff --git a/browser/locales/generic/profile/bookmarks.html.in b/browser/locales/generic/profile/bookmarks.html.in
-index dc67747620..00221d37a1 100644
+index 2d3c7b4..00221d3 100644
--- a/browser/locales/generic/profile/bookmarks.html.in
+++ b/browser/locales/generic/profile/bookmarks.html.in
@@ -1,15 +1,15 @@
@@ -23,7 +152,7 @@ index dc67747620..00221d37a1 100644
<!-- This Source Code Form is subject to the terms of the Mozilla Public
- License, v. 2.0. If a copy of the MPL was not distributed with this
- file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
-@@ -21,30 +21,21 @@
+@@ -21,29 +21,21 @@
<dl><p>
<dt><h3 personal_toolbar_folder="true">@bookmarks_toolbarfolder@</h3></dt>
<dd>@bookmarks_toolbarfolder_description@
@@ -56,7 +185,6 @@ index dc67747620..00221d37a1 100644
- <dt><a href="https://developer.mozilla.org/" icon="@mdn_icon@" shortcuturl="mdn">@mdn@</a>
- <dt><a href="https://addons.mozilla.org/@AB_CD@/firefox/addon/nightly-tester-tools/" icon="@addon_icon@">@nightly_tester_tools@</a>
- <dt><a href="about:crashes" icon="@mozilla_icon@">@crashes@</a>
-- <dt><a href="https://mibbit.com/?server=irc.mozilla.org&channel=%23nightly" icon="@mozilla_icon@">@irc@</a>
- <dt><a href="https://planet.mozilla.org/" icon="@mozilla_icon@">@planet@</a>
+ <dt><a href="https://www.fsf.org/" icon="@fsf_icon@">Free Software Foundation</a>
+ <dt><a href="https://www.gnu.org/" icon="@gnu_icon@">The GNU Operating System and the Free Software Movement</a>
@@ -66,122 +194,62 @@ index dc67747620..00221d37a1 100644
-#endif
</dl>
diff --git a/devtools/client/locales/en-US/sourceeditor.properties b/devtools/client/locales/en-US/sourceeditor.properties
-index 842d549f04..31dcb82e5a 100644
+index 9427244..c17d490 100644
--- a/devtools/client/locales/en-US/sourceeditor.properties
+++ b/devtools/client/locales/en-US/sourceeditor.properties
@@ -4,7 +4,7 @@
# LOCALIZATION NOTE These strings are used inside the Source Editor component.
# This component is used whenever source code is displayed for the purpose of
--# being edited, inside the Firefox developer tools - current examples are the
-+# being edited, inside the Iceweasel developer tools - current examples are the
- # Scratchpad and the Style Editor tools.
+-# being edited, inside the Firefox developer tools (like Style Editor).
++# being edited, inside the Iceweasel developer tools (like Style Editor).
# LOCALIZATION NOTE The correct localization of this file might be to keep it
-diff --git a/browser/app/permissions b/browser/app/permissions
-index f40a60e..c23fa76 100644
---- a/browser/app/permissions
-+++ b/browser/app/permissions
-@@ -14,16 +14,9 @@ origin uitour 1 https://support.mozilla.org
- origin uitour 1 about:home
- origin uitour 1 about:newtab
-
--# XPInstall
--origin install 1 https://addons.mozilla.org
--
- # Remote troubleshooting
- origin remote-troubleshooting 1 https://support.mozilla.org
-
- # Hybrid Content Telemetry - https://firefox-source-docs.mozilla.org/toolkit/components/telemetry/telemetry/collection/hybrid-content.html
- # Adding hc_telemetry permission to a new domain requires Data Collection Review: https://wiki.mozilla.org/Firefox/Data_Collection
- origin hc_telemetry 1 https://discovery.addons.mozilla.org
--
--# addon install
--origin install 1 https://private-network.firefox.com
--origin install 1 https://fpn.firefox.com
-diff --git a/browser/components/preferences/in-content/sync.inc.xul b/browser/components/preferences/in-content/sync.inc.xul
-index e444bf3..05e9824 100644
---- a/browser/components/preferences/in-content/sync.inc.xul
-+++ b/browser/components/preferences/in-content/sync.inc.xul
-@@ -46,22 +46,6 @@
- </hbox>
- </vbox>
- </hbox>
-- <label class="fxaMobilePromo" data-l10n-id="sync-mobile-promo">
-- <html:img
-- src="chrome://browser/skin/preferences/in-content/logo-android.svg"
-- data-l10n-name="android-icon"
-- class="androidIcon"/>
-- <html:a
-- data-l10n-name="android-link"
-- class="fxaMobilePromo-android text-link" target="_blank"/>
-- <html:img
-- src="chrome://browser/skin/preferences/in-content/logo-ios.svg"
-- data-l10n-name="ios-icon"
-- class="iOSIcon"/>
-- <html:a
-- data-l10n-name="ios-link"
-- class="fxaMobilePromo-ios text-link" target="_blank"/>
-- </label>
- </groupbox>
-
- <vbox id="hasFxaAccount">
-diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl
-index 8e0602d..cde6252 100644
---- a/browser/locales/en-US/browser/preferences/preferences.ftl
-+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
-@@ -719,16 +719,6 @@ sync-signedout-account-signin =
- .label = Sign In…
- .accesskey = I
-
--# This message contains two links and two icon images.
--# `<img data-l10n-name="android-icon"/>` - Android logo icon
--# `<a data-l10n-name="android-link">` - Link to Android Download
--# `<img data-l10n-name="ios-icon">` - iOS logo icon
--# `<a data-l10n-name="ios-link">` - Link to iOS Download
--#
--# They can be moved within the sentence as needed to adapt
--# to your language, but should not be changed or translated.
--sync-mobile-promo = Download Firefox for <img data-l10n-name="android-icon"/> <a data-l10n-name="android-link">Android</a> or <img data-l10n-name="ios-icon"/> <a data-l10n-name="ios-link">iOS</a> to sync with your mobile device.
--
- ## Firefox Account - Signed in
-
- sync-profile-picture =
+ # in English, or another language commonly spoken among web developers.
diff --git a/devtools/client/whats-new/src/main.js b/devtools/client/whats-new/src/main.js
-index ad34ff9..3e937c6 100644
+index 0a31843..c01e488 100644
--- a/devtools/client/whats-new/src/main.js
+++ b/devtools/client/whats-new/src/main.js
-@@ -23,7 +23,7 @@ const aside = {
+@@ -29,7 +29,7 @@ const aside = {
};
const release = {
-- title: "What’s New in DevTools (Firefox 70 & 71)",
-+ title: "What’s New in DevTools (Iceweasel 70 & 71)",
+- title: "What’s New in DevTools (Firefox 72 & 71)",
++ title: "What’s New in DevTools (Iceweasel 72 & 71)",
linkText: "Read more",
- linkUrl:
- "https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/71?utm_source=devtools&utm_medium=devtools_whatsnew",
-@@ -83,20 +83,6 @@ const release = {
+ linkUrl: `https://developer.mozilla.org/docs/Mozilla/Firefox/Releases/72?${utmParams}`,
+ features: [
+@@ -66,29 +66,6 @@ const release = {
],
};
-const dev = {
- title: "Experimental Features in Firefox Developer Edition",
-- linkUrl:
-- "https://www.mozilla.org/firefox/developer/?utm_medium=devtools_whatsnew&utm_source=devtools",
+- linkUrl: `https://www.mozilla.org/firefox/developer/?${utmParams}`,
- linkText: "Get DevEdition",
- features: [
- {
-- header: `Debug Variables with Watchpoints`,
-- description: `Debugger’s new Watchpoints feature lets you pause when properties get read or written. Right-click object properties in the Scopes pane when paused to use the new “Break on…” menu.`,
-- href: `https://developer.mozilla.org/docs/Tools/Debugger/How_to/Set_a_watchpoint_on_a_property?utm_source=devtools&utm_medium=devtools_whatsnew`,
+- header: `Asynchronous Stacks in Debugger`,
+- description: `Asynchronous call stacks in the Debugger let you examine the event-driven function calls at previous points in time.`,
+- href: `https://developer.mozilla.org/en-US/docs/Tools/Debugger/UI_Tour?${utmParams}`,
+- },
+- {
+- header: `Correct Meta Viewport in Responsive Design Mode`,
+- description: `RDM with touch simulation enabled will now correctly simulate the meta viewport rendering of a mobile device.`,
+- href: `https://developer.mozilla.org/docs/Tools/Responsive_Design_Mode?${utmParams}`,
+- },
+- {
+- header: `CSP Style Directives No Longer Prevent CSS Edits`,
+- description: `Editing an element’s inline style from Inspector’s rule-view now works even if style-src is blocked by CSP.`,
+- href: `https://developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Examine_and_edit_CSS?${utmParams}`,
- },
- ],
-};
-
- class Aside extends Component {
- render() {
- return dom.aside(
-@@ -183,11 +169,6 @@ class App extends Component {
+ function openLink(href, e) {
+ return openDocLink(href, {
+ relatedToCurrent: true,
+@@ -182,11 +159,6 @@ class App extends Component {
...release.features
.filter(feature => !feature.hidden)
.map(feature => createFactory(Feature)(feature))
@@ -239,6 +307,7 @@ index db2146d..e02ab58 100644
enable-learn-more-link = Learn more about Developer Tools
enable-enable-button = Enable Developer Tools
enable-close-button = Close this Tab
+
-welcome-title = Welcome to Firefox Developer Tools!
+welcome-title = Welcome to Iceweasel Developer Tools!
newsletter-title = Mozilla Developer Newsletter
@@ -254,11 +323,11 @@ index db2146d..e02ab58 100644
features-learn-more = Learn more
diff --git a/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl b/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
-index 0066077..801f2fb 100644
+index edd871b..77870fe 100644
--- a/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
+++ b/toolkit/locales/en-US/toolkit/about/aboutAddons.ftl
-@@ -6,7 +6,7 @@ addons-window =
- .title = Add-ons Manager
+@@ -7,7 +7,7 @@ addons-window =
+ addons-page-title = Add-ons Manager
search-header =
- .placeholder = Search addons.mozilla.org
@@ -266,72 +335,3 @@ index 0066077..801f2fb 100644
.searchbuttonlabel = Search
search-header-shortcut =
-diff --git a/browser/components/newtab/docs/index.rst b/browser/components/newtab/docs/index.rst
-index ea1e42ae8..855b245a1 100644
---- a/browser/components/newtab/docs/index.rst
-+++ b/browser/components/newtab/docs/index.rst
-@@ -1,8 +1,8 @@
- ======================
--Firefox Home (New Tab)
-+Iceweasel Home (New Tab)
- ======================
-
--All files related to Firefox Home, which includes content that appears on `about:home`,
-+All files related to Iceweasel Home, which includes content that appears on `about:home`,
- `about:newtab`, and `about:welcome`, can we found in the `browser/components/newtab` directory.
- Some of these source files (such as `.js`, `.jsx`, and `.sass`) require an additional build step.
- We are working on migrating this to work with `mach`, but in the meantime, please
-diff --git a/browser/locales/en-US/browser/newtab/newtab.ftl b/browser/locales/en-US/browser/newtab/newtab.ftl
-index d0f0fe0af..360e04b61 100644
---- a/browser/locales/en-US/browser/newtab/newtab.ftl
-+++ b/browser/locales/en-US/browser/newtab/newtab.ftl
-@@ -2,7 +2,7 @@
- # License, v. 2.0. If a copy of the MPL was not distributed with this
- # file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
--### Firefox Home / New Tab strings for about:home / about:newtab.
-+### Iceweasel Home / New Tab strings for about:home / about:newtab.
-
- newtab-page-title = New Tab
- newtab-settings-button =
-diff --git a/browser/locales/en-US/browser/policies/policies-descriptions.ftl b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
-index dfee10e51..6402f5c85 100644
---- a/browser/locales/en-US/browser/policies/policies-descriptions.ftl
-+++ b/browser/locales/en-US/browser/policies/policies-descriptions.ftl
-@@ -96,7 +96,7 @@ policy-ExtensionSettings = Manage all aspects of extension installation.
-
- policy-ExtensionUpdate = Enable or disable automatic extension updates.
-
--policy-FirefoxHome = Configure Firefox Home.
-+policy-FirefoxHome = Configure Iceweasel Home.
-
- policy-FlashPlugin = Allow or deny usage of the Flash plugin.
-
-diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl
-index cde625248..662c15736 100644
---- a/browser/locales/en-US/browser/preferences/preferences.ftl
-+++ b/browser/locales/en-US/browser/preferences/preferences.ftl
-@@ -551,7 +551,7 @@ home-restore-defaults =
- # "Firefox" should be treated as a brand and kept in English,
- # while "Home" and "(Default)" can be localized.
- home-mode-choice-default =
-- .label = Firefox Home (Default)
-+ .label = Iceweasel Home (Default)
-
- home-mode-choice-custom =
- .label = Custom URLs…
-@@ -578,10 +578,10 @@ choose-bookmark =
- .label = Use Bookmark…
- .accesskey = B
-
--## Home Section - Firefox Home Content Customization
-+## Home Section - Iceweasel Home Content Customization
-
--home-prefs-content-header = Firefox Home Content
--home-prefs-content-description = Choose what content you want on your Firefox Home screen.
-+home-prefs-content-header = Iceweasel Home Content
-+home-prefs-content-description = Choose what content you want on your Iceweasel Home screen.
-
- home-prefs-search-header =
- .label = Web Search
-
diff --git a/libre/iceweasel/vendor.js.in b/libre/iceweasel/vendor.js.in
new file mode 100644
index 000000000..f530b75e2
--- /dev/null
+++ b/libre/iceweasel/vendor.js.in
@@ -0,0 +1,317 @@
+
+
+/*\
+|*| Parabola additions to vendor.js
+|*|
+|*| TODO: Go through this and figure out what's nescessary, remove
+|*| most of it. This is mostly cargo-cult BS. For example, disabling
+|*| all the EME stuff... that's already off because of `--disable-eme`
+|*| in `.mozconfig`. Some of these settings no longer exist. Some of
+|*| these settings don't do anything on GNU/Linux.
+|*|
+|*| However, they don't seem to be causing any of the critical issues.
+\*/
+
+// Disable "alt" as a shortcut key to open full menu bar. Conflicts with "alt" as a modifier
+pref("ui.key.menuAccessKeyFocuses", false);
+
+// Disable the GeoLocation API for content
+pref("geo.enabled", false);
+
+// Make sure that the request URL of the GeoLocation backend is empty
+pref("geo.wifi.uri", "");
+
+// Google Widevine DRM
+// https://blog.mozilla.org/futurereleases/2016/04/08/mozilla-to-test-widevine-cdm-in-firefox-nightly/
+// https://wiki.mozilla.org/QA/Widevine_CDM
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1288580
+pref("media.gmp-widevinecdm.visible", false);
+pref("media.gmp-widevinecdm.enabled", false);
+pref("media.gmp-widevinecdm.autoupdate", false);
+
+// Default sites for about:newtab
+pref("browser.newtabpage.activity-stream.default.sites", "https://wiki.parabola.nu/,https://labs.parabola.nu/,https://www.gnu.org/,https://libreplanet.org/,https://www.wikipedia.org/");
+
+// Poodle attack
+pref("security.tls.version.min", 1);
+
+// Don't call home for blacklisting
+pref("extensions.blocklist.enabled", false);
+
+// Disable plugin installer
+pref("plugins.hide_infobar_for_missing_plugin", true);
+pref("plugins.hide_infobar_for_outdated_plugin", true);
+pref("plugins.notifyMissingFlash", false);
+
+//https://developer.mozilla.org/en-US/docs/Web/API/MediaSource
+//pref("media.mediasource.enabled",true);
+
+// Speeding it up
+pref("network.http.pipelining", true);
+pref("network.http.proxy.pipelining", true);
+pref("network.http.pipelining.maxrequests", 10);
+pref("nglayout.initialpaint.delay", 0);
+
+// Disable third party cookies
+pref("network.cookie.cookieBehavior", 1);
+
+// Prevent EULA dialog to popup on first run
+pref("browser.EULA.override", true);
+
+// Set useragent to Firefox compatible
+//pref("general.useragent.compatMode.firefox", true);
+// Spoof the useragent to a generic one
+pref("general.useragent.compatMode.firefox", true);
+// Spoof the useragent to a generic one
+pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:@_SHORTVER_@) Gecko/20100101 Firefox/@_SHORTVER_@");
+pref("general.appname.override", "Netscape");
+pref("general.appversion.override", "@_SHORTVER_@");
+pref("general.buildID.override", "Gecko/20100101");
+pref("general.oscpu.override", "Windows NT 6.1");
+pref("general.platform.override", "Win32");
+
+// Privacy & Freedom Issues
+// https://webdevelopmentaid.wordpress.com/2013/10/21/customize-privacy-settings-in-mozilla-firefox-part-1-aboutconfig/
+// https://panopticlick.eff.org
+// http://ip-check.info
+// http://browserspy.dk
+// https://wiki.mozilla.org/Fingerprinting
+// http://www.browserleaks.com
+// http://fingerprint.pet-portal.eu
+pref("privacy.donottrackheader.enabled", true);
+pref("privacy.donottrackheader.value", 1);
+pref("dom.ipc.plugins.flash.subprocess.crashreporter.enabled", false);
+
+// CIS 2.1.1 Disable Auto Update / Balrog
+pref("app.update.auto", false);
+pref("app.update.checkInstallTime", false);
+pref("app.update.enabled", false);
+pref("app.update.staging.enabled", false);
+pref("app.update.url", "about:blank");
+pref("media.gmp-manager.certs.1.commonName", "");
+pref("media.gmp-manager.certs.2.commonName", "");
+// Disable Gecko media plugins: https://wiki.mozilla.org/GeckoMediaPlugins
+pref("media.gmp-manager.url", "http://127.0.0.1/");
+pref("media.gmp-manager.url.override", "data:text/plain,");
+pref("media.gmp-provider.enabled", false);
+// Don't install openh264 codec
+pref("media.gmp-gmpopenh264.enabled", false);
+pref("media.gmp-eme-adobe.enabled", false);
+pref("media.peerconnection.video.h264_enabled", false);
+
+// CIS 2.3.4 Block Reported Web Forgeries
+// http://kb.mozillazine.org/Browser.safebrowsing.enabled
+// http://kb.mozillazine.org/Safe_browsing
+// https://support.mozilla.org/en-US/kb/how-does-phishing-and-malware-protection-work
+// http://forums.mozillazine.org/viewtopic.php?f=39&t=2711237&p=12896849#p12896849
+pref("browser.safebrowsing.enabled", false);
+
+// CIS 2.3.5 Block Reported Attack Sites
+// http://kb.mozillazine.org/Browser.safebrowsing.malware.enabled
+pref("browser.safebrowsing.malware.enabled", false);
+
+// Disable safe browsing remote lookups for downloaded files.
+// This leaks information to google.
+// https://www.mozilla.org/en-US/firefox/39.0/releasenotes/
+// https://wiki.mozilla.org/Security/Application_Reputation
+pref("browser.safebrowsing.downloads.remote.enabled", false);
+pref("browser.safebrowsing.appRepURL", "about:blank");
+pref("browser.safebrowsing.provider.mozilla.gethashURL", "about:blank");
+pref("browser.safebrowsing.provider.mozilla.updateURL", "about:blank");
+pref("browser.safebrowsing.downloads.remote.block_dangerous", false);
+pref("browser.safebrowsing.downloads.remote.block_dangerous_host", false);
+pref("browser.safebrowsing.downloads.remote.block_potentially_unwanted", false);
+pref("browser.safebrowsing.downloads.remote.block_uncommon", false);
+pref("browser.safebrowsing.downloads.remote.enabled", false);
+pref("browser.safebrowsing.downloads.remote.url", "about:blank");
+pref("browser.safebrowsing.provider.google.gethashURL", "about:blank");
+pref("browser.safebrowsing.provider.google.updateURL", "about:blank");
+pref("browser.safebrowsing.provider.google.lists", "about:blank");
+
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1025965
+pref("browser.safebrowsing.phishing.enabled", false);
+pref("browser.safebrowsing.provider.google4.lists", "about:blank");
+pref("browser.safebrowsing.provider.google4.updateURL", "about:blank");
+pref("browser.safebrowsing.provider.google4.gethashURL", "about:blank");
+pref("browser.safebrowsing.provider.google4.reportURL", "about:blank");
+pref("browser.safebrowsing.provider.mozilla.lists", "about:blank");
+
+// Disable Microsoft Family Safety MiTM support
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1239166
+// https://wiki.mozilla.org/SecurityEngineering/Untrusted_Certificates_in_Windows_Child_Mode
+// https://hg.mozilla.org/releases/mozilla-release/file/ddb37c386bb2ffa180117b4d30ca3b41a8af233c/security/manager/ssl/nsNSSComponent.cpp#l782
+pref("security.family_safety.mode", 0);
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1265113
+// https://hg.mozilla.org/releases/mozilla-release/rev/d9659c22b3c5
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1298883
+pref("security.enterprise_roots.enabled", false);
+
+//pref("services.sync.privacyURL", "https://www.gnu.org/software/gnuzilla/");
+pref("social.enabled", false);
+pref("social.remote-install.enabled", false);
+pref("datareporting.healthreport.uploadEnabled", false);
+pref("datareporting.healthreport.about.reportUrl", "127.0.0.1");
+pref("datareporting.healthreport.documentServerURI", "127.0.0.1");
+pref("healthreport.uploadEnabled", false);
+pref("social.toast-notifications.enabled", false);
+pref("datareporting.policy.dataSubmissionEnabled", false);
+pref("datareporting.healthreport.service.enabled", false);
+pref("browser.slowStartup.notificationDisabled", true);
+pref("network.http.sendRefererHeader", 2);
+//pref("network.http.referer.spoofSource", true);
+//http://grack.com/blog/2010/01/06/3rd-party-cookies-dom-storage-and-privacy/
+//pref("dom.storage.enabled", false);
+pref("dom.event.clipboardevents.enabled",false);
+pref("network.prefetch-next", false);
+pref("network.dns.disablePrefetch", true);
+pref("network.http.sendSecureXSiteReferrer", false);
+pref("toolkit.telemetry.archive.enabled", false);
+pref("toolkit.telemetry.bhrPing.enabled", false);
+pref("toolkit.telemetry.enabled", false);
+pref("toolkit.telemetry.unified", false);
+pref("toolkit.telemetry.newProfilePing.enabled", false);
+pref("toolkit.telemetry.firstShutdownPing.enabled", false);
+pref("toolkit.telemetry.server", "127.0.0.1");
+pref("app.shield.optoutstudies.enabled", false);
+pref("experiments.enabled", false);
+pref("experiments.manifest.uri", "127.0.0.1");
+pref("extensions.pocket.enabled", false);
+pref("extensions.pocket.api", "127.0.0.1");
+// Do not tell what plugins do we have enabled: https://mail.mozilla.org/pipermail/firefox-dev/2013-November/001186.html
+pref("plugins.enumerable_names", "");
+pref("plugin.state.flash", 0);
+// Do not autoupdate search engines
+pref("browser.search.update", false);
+// Warn when the page tries to redirect or refresh
+//pref("accessibility.blockautorefresh", true);
+pref("dom.battery.enabled", false);
+pref("device.sensors.enabled", false);
+pref("camera.control.face_detection.enabled", false);
+pref("camera.control.autofocus_moving_callback.enabled", false);
+pref("network.http.speculative-parallel-limit", 0);
+// No search suggestions
+pref("browser.urlbar.userMadeSearchSuggestionsChoice", true);
+pref("browser.search.suggest.enabled", false);
+
+// Crypto hardening
+// https://gist.github.com/haasn/69e19fc2fe0e25f3cff5
+// General settings
+//pref("security.tls.unrestricted_rc4_fallback", false);
+//pref("security.tls.insecure_fallback_hosts.use_static_list", false);
+//pref("security.tls.version.min", 1);
+//pref("security.ssl.require_safe_negotiation", true);
+//pref("security.ssl.treat_unsafe_negotiation_as_broken", true);
+//pref("security.ssl3.rsa_seed_sha", true);
+//pref("security.OCSP.enabled", 1);
+//pref("security.OCSP.require", true);
+
+
+// WebRTC
+pref("media.peerconnection.enabled", false);
+pref("media.peerconnection.ice.default_address_only", true);
+
+pref("font.default.x-western", "sans-serif");
+
+// Preferences for the Get Add-ons panel and search engines
+pref("extensions.webservice.discoverURL", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("extensions.getAddons.search.url", "https://directory.fsf.org/wiki/GNU_IceCat");
+pref("browser.search.searchEnginesURL", "https://directory.fsf.org/wiki/GNU_IceCat");
+
+// Mobile
+pref("privacy.announcements.enabled", false);
+pref("browser.snippets.enabled", false);
+pref("browser.snippets.syncPromo.enabled", false);
+pref("identity.mobilepromo.android", "https://f-droid.org/repository/browse/?fdid=org.gnu.icecat&");
+pref("browser.snippets.geoUrl", "http://127.0.0.1/");
+pref("browser.snippets.updateUrl", "http://127.0.0.1/");
+pref("browser.snippets.statsUrl", "http://127.0.0.1/");
+pref("datareporting.policy.firstRunTime", 0);
+pref("datareporting.policy.dataSubmissionPolicyVersion", 2);
+pref("browser.webapps.checkForUpdates", 0);
+pref("browser.webapps.updateCheckUrl", "http://127.0.0.1/");
+pref("app.faqURL", "http://libreplanet.org/wiki/Group:IceCat/FAQ");
+
+// PFS url
+pref("pfs.datasource.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
+pref("pfs.filehint.url", "http://gnuzilla.gnu.org/plugins/PluginFinderService.php?mimetype=%PLUGIN_MIMETYPE%");
+
+// Geolocation depends on third party services
+pref("geo.enabled", false);
+pref("geo.wifi.uri", "");
+
+// Disable heartbeat
+pref("browser.selfsupport.url", "");
+
+// Disable Link to FireFox Marketplace, currently loaded with non-free "apps"
+pref("browser.apps.URL", "");
+
+// Use old style preferences, that allow javascript to be disabled
+pref("browser.preferences.inContent",false);
+
+// Don't download ads for the newtab page
+pref("browser.newtabpage.directory.source", "");
+pref("browser.newtabpage.directory.ping", "");
+pref("browser.newtabpage.introShown", true);
+
+// Disable home snippets
+pref("browser.aboutHomeSnippets.updateUrl", "data:text/html");
+
+// Disable hardware acceleration and WebGL
+//pref("layers.acceleration.disabled", false);
+pref("webgl.disabled", false);
+
+// Disable SSDP
+pref("browser.casting.enabled", false);
+
+// Disable directory service
+pref("social.directories", "");
+pref("social.whitelist", "");
+pref("social.shareDirectory", "");
+
+// Disable Pocket integration
+pref("browser.pocket.api", "about:blank");
+pref("browser.pocket.enabled", false);
+pref("browser.pocket.enabledLocales", "about:blank");
+pref("browser.pocket.oAuthConsumerKey", "about:blank");
+pref("browser.pocket.site", "about:blank");
+pref("browser.pocket.useLocaleList", false);
+pref("extensions.pocket.enabled", false);
+
+// Do not require xpi extensions to be signed by Mozilla
+pref("xpinstall.signatures.required", false);
+
+// Disable File and Directory Entries API (Imported from Edge/Chromium)
+// https://developer.mozilla.org/en-US/Firefox/Releases/50#Files_and_directories
+// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API
+// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Introduction
+// https://developer.mozilla.org/en-US/docs/Web/API/File_and_Directory_Entries_API/Firefox_support
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1265767
+pref("dom.webkitBlink.filesystem.enabled", false);
+// https://developer.mozilla.org/en-US/docs/Web/API/HTMLInputElement/webkitdirectory
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1258489
+// https://hg.mozilla.org/releases/mozilla-release/rev/133af19777be
+pref("dom.webkitBlink.dirPicker.enabled", false);
+
+// Directory Upload API, webkitdirectory
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1188880
+// https://bugzilla.mozilla.org/show_bug.cgi?id=907707
+// https://wicg.github.io/directory-upload/proposal.html
+pref("dom.input.dirpicker", false);
+
+// fix alsa sound sandbox issue for iceweasel-58
+// https://labs.parabola.nu/issues/1628
+pref("security.sandbox.content.syscall_whitelist", "16");
+
+// Disable recommendations of extensions and themes on about:addons page
+// https://labs.parabola.nu/issues/2409
+pref("extensions.htmlaboutaddons.discover.enabled", false);
+pref("extensions.htmlaboutaddons.recommendations.enabled", false);
+
+// Disable "Recommend extensions as you browse" in about:preferences#general
+pref("browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons", false);
+
+// URL for 'Find more extensions / themes' in about:addons page
+pref("extensions.getAddons.search.browseURL", "https://www.parabola.nu/packages/?q=%TERMS%");
+
+// Make extensions work on Mozilla domains
+pref("extensions.webextensions.restrictedDomains", "");