| #!/usr/bin/env python3 |
| # Copyright 2015 The ChromiumOS Authors |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Authoritative source for Chromium OS region/locale configuration. |
| |
| Run this module to display all known regions (use --help to see options). |
| """ |
| |
| import argparse |
| import collections.abc |
| import json |
| import re |
| import sys |
| |
| import yaml # pylint: disable=import-error |
| |
| |
| # TBR means you have to get reviewed through go/vpdsettings. |
| TBR = "To be reviewed" |
| |
| # Standard keyboard layout for LATAM-es-419 countries. |
| XKB_LATAM = "xkb:latam::spa" |
| |
| # The regular expression to check values in Region.keyboards and Region.locales. |
| # Keyboards should come with xkb: protocol, or the input methods (ime:, m17n:). |
| # Examples: xkb:us:intl:eng, ime:ime:zh-t:cangjie, xkb:us:altgr-intl:eng |
| KEYBOARD_PATTERN = re.compile( |
| r"^xkb:\w+:[\w-]*:\w+$|" r"^(ime|m17n|t13n):[\w:-]+$" |
| ) |
| # Locale should be a combination of language and location. |
| # Examples: en-US, ja. |
| LOCALE_PATTERN = re.compile(r"^(\w+)(-[A-Z0-9]+)?$") |
| |
| |
| class Enum(frozenset): |
| """An enumeration type. |
| |
| Examples: |
| |
| To create a enum object: |
| dummy_enum = Enum(['A', 'B', 'C']) |
| |
| To access a enum object, use: |
| dummy_enum.A |
| dummy_enum.B |
| """ |
| |
| def __getattr__(self, name): |
| if name in self: |
| return name |
| raise AttributeError |
| |
| |
| class RegionException(Exception): |
| """Exception in Region handling.""" |
| |
| |
| def MakeList(value): |
| """Converts the given value to a list. |
| |
| Returns: |
| A list of elements from "value" if it is iterable (except string); |
| otherwise, a list contains only one element. |
| """ |
| if isinstance(value, collections.abc.Iterable) and not isinstance( |
| value, str |
| ): |
| return list(value) |
| return [value] |
| |
| |
| class Region: |
| """Comprehensive, standard locale configuration per country/region. |
| |
| See :ref:`regions-values` for detailed information on how to set |
| these values. |
| """ |
| |
| # pylint gets confused by some of the docstrings. |
| |
| # ANSI = US-like |
| # ISO = UK-like |
| # JIS = Japanese |
| # KS = Korean (see http://crosbug.com/p/50753 for why this is not used yet) |
| # ABNT2 = Brazilian (like ISO but with an extra key to the left of the |
| # right shift key) |
| KeyboardMechanicalLayout = Enum(["ANSI", "ISO", "JIS", "KS", "ABNT2"]) |
| |
| region_code = None |
| """A unique identifier for the region. This may be a lower-case |
| `ISO 3166-1 alpha-2 code |
| <http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2>`_ (e.g., ``us``), |
| a variant within an alpha-2 entity (e.g., ``ca.fr``), or an |
| identifier for a collection of countries or entities (e.g., |
| ``latam-es-419`` or ``nordic``). See :ref:`region-codes`. |
| |
| Note that ``uk`` is not a valid identifier; ``gb`` is used as it is |
| the real alpha-2 code for the UK.""" |
| |
| keyboards = None |
| """A list of keyboard layout identifiers (e.g., ``xkb:us:intl:eng`` |
| or ``m17n:ar``). This field was designed to be the physical keyboard layout |
| in the beginning, and then becomes a list of OOBE keyboard selection, which |
| then includes non-physical layout elements like input methods (``ime:``). |
| To avoid confusion, physical layout is now defined by |
| :py:attr:`keyboard_mechanical_layout`, and this is reserved for logical |
| layouts. |
| |
| This is identical to the legacy VPD ``keyboard_layout`` value.""" |
| |
| time_zones = None |
| """A list of default `tz database time zone |
| <http://en.wikipedia.org/wiki/List_of_tz_database_time_zones>`_ |
| identifiers (e.g., ``America/Los_Angeles``). See |
| `timezone_settings.cc <http://goo.gl/WSVUeE>`_ for supported time |
| zones. |
| |
| This is identical to the legacy VPD ``initial_timezone`` value.""" |
| |
| locales = None |
| """A list of default locale codes (e.g., ``en-US``); see |
| `l10n_util.cc <http://goo.gl/kVkht>`_ for supported locales. |
| |
| This is identital to the legacy VPD ``initial_locale`` field.""" |
| |
| keyboard_mechanical_layout = None |
| """The keyboard's mechanical layout (``ANSI`` [US-like], ``ISO`` |
| [UK-like], ``JIS`` [Japanese], ``ABNT2`` [Brazilian] or ``KS`` [Korean]).""" |
| |
| description = None |
| """A human-readable description of the region. |
| This defaults to :py:attr:`region_code` if not set.""" |
| |
| notes = None |
| """Implementation notes about the region. This may be None.""" |
| |
| regulatory_domain = None |
| """An ISO 3166-1 alpha 2 upper-cased two-letter region code for setting |
| Wireless regulatory. See crosbug.com/p/38745 for more details. |
| |
| When omitted, this will derive from region_code.""" |
| |
| confirmed = None |
| """An optional boolean flag to indicate if the region data is confirmed.""" |
| |
| FIELDS = [ |
| "region_code", |
| "description", |
| "keyboards", |
| "time_zones", |
| "locales", |
| "keyboard_mechanical_layout", |
| "regulatory_domain", |
| ] |
| """Names of fields that define the region.""" |
| |
| def __init__( |
| self, |
| region_code, |
| keyboards, |
| time_zones, |
| locales, |
| keyboard_mechanical_layout, |
| description=None, |
| notes=None, |
| regdomain=None, |
| ): |
| """Constructor. |
| |
| Args: |
| region_code: See :py:attr:`region_code`. |
| keyboards: See :py:attr:`keyboards`. A single string is accepted for |
| backward compatibility. |
| time_zones: See :py:attr:`time_zones`. |
| locales: See :py:attr:`locales`. A single string is accepted |
| for backward compatibility. |
| keyboard_mechanical_layout: See :py:attr:`keyboard_mechanical_layout`. |
| description: See :py:attr:`description`. |
| notes: See :py:attr:`notes`. |
| regdomain: See :py:attr:`regulatory_domain`. |
| """ |
| |
| def regdomain_from_region(region): |
| if region.find(".") >= 0: |
| region = region[: region.index(".")] |
| if len(region) == 2: |
| return region.upper() |
| return None |
| |
| # Quick check: should be 'gb', not 'uk' |
| if region_code == "uk": |
| raise RegionException("'uk' is not a valid region code (use 'gb')") |
| |
| self.region_code = region_code |
| self.keyboards = MakeList(keyboards) |
| self.time_zones = MakeList(time_zones) |
| self.locales = MakeList(locales) |
| self.keyboard_mechanical_layout = keyboard_mechanical_layout |
| self.description = description or region_code |
| self.notes = notes |
| self.regulatory_domain = regdomain or regdomain_from_region(region_code) |
| self.confirmed = None |
| |
| for f in (self.keyboards, self.locales): |
| assert all(isinstance(x, str) for x in f), ( |
| "Expected a list of strings, not %r" % f |
| ) |
| for f in self.keyboards: |
| assert f is TBR or KEYBOARD_PATTERN.match( |
| f |
| ), "Keyboard pattern %r does not match %r" % ( |
| f, |
| KEYBOARD_PATTERN.pattern, |
| ) |
| for f in self.locales: |
| assert f is TBR or LOCALE_PATTERN.match( |
| f |
| ), "Locale %r does not match %r" % ( |
| f, |
| LOCALE_PATTERN.pattern, |
| ) |
| assert ( |
| self.regulatory_domain |
| and len(self.regulatory_domain) == 2 |
| and self.regulatory_domain.upper() == self.regulatory_domain |
| ), ("Regulatory domain settings error for region %s" % region_code) |
| |
| def __repr__(self): |
| return "Region(%s)" % ( |
| ", ".join([getattr(self, x) for x in self.FIELDS]) |
| ) |
| |
| def GetFieldsDict(self): |
| """Returns a dict of all substantive fields. |
| |
| notes and description are excluded. |
| """ |
| return dict((k, getattr(self, k)) for k in self.FIELDS) |
| |
| |
| KML = Region.KeyboardMechanicalLayout |
| PSEUDOLOCALE_REGIONS_LIST = [ |
| Region( |
| "ar.xb", |
| "xkb:us::eng", |
| "America/Los_Angeles", |
| "ar-XB", |
| KML.ANSI, |
| "Pseudolocale (RTL)", |
| ), |
| Region( |
| "en.xa", |
| "xkb:us::eng", |
| "America/Los_Angeles", |
| "en-XA", |
| KML.ANSI, |
| "Pseudolocale (long strings)", |
| ), |
| ] |
| REGIONS_LIST = [ |
| Region( |
| "au", "xkb:us::eng", "Australia/Sydney", "en-AU", KML.ANSI, "Australia" |
| ), |
| Region( |
| "be", |
| "xkb:be::nld", |
| "Europe/Brussels", |
| "en-GB", |
| KML.ISO, |
| "Belgium", |
| ( |
| "Flemish (Belgian Dutch) keyboard; British English language for " |
| "neutrality" |
| ), |
| ), |
| Region( |
| "br", |
| "xkb:br::por", |
| "America/Sao_Paulo", |
| "pt-BR", |
| KML.ABNT2, |
| "Brazil (ABNT2)", |
| ( |
| "ABNT2 = ABNT NBR 10346 variant 2. This is the preferred layout " |
| "for Brazil. ABNT2 is mostly an ISO layout, but it 12 keys between " |
| "the shift keys; see http://goo.gl/twA5tq" |
| ), |
| ), |
| Region( |
| "br.abnt", |
| "xkb:br::por", |
| "America/Sao_Paulo", |
| "pt-BR", |
| KML.ISO, |
| "Brazil (ABNT)", |
| ( |
| "Like ABNT2, but lacking the extra key to the left of the right " |
| 'shift key found in that layout. ABNT2 (the "br" region) is ' |
| "preferred to this layout" |
| ), |
| ), |
| Region( |
| "br.usintl", |
| "xkb:us:intl:eng", |
| "America/Sao_Paulo", |
| "pt-BR", |
| KML.ANSI, |
| "Brazil (US Intl)", |
| ( |
| 'Brazil with US International keyboard layout. ABNT2 ("br") and ' |
| 'ABNT1 ("br.abnt1 ") are both preferred to this.' |
| ), |
| ), |
| Region( |
| "ca.ansi", |
| "xkb:us::eng", |
| "America/Toronto", |
| "en-CA", |
| KML.ANSI, |
| "Canada (US keyboard)", |
| ( |
| "Canada with US (ANSI) keyboard. Only allowed if there are " |
| "separate US English, Canadian English, and French SKUs. " |
| "Not for en/fr hybrid ANSI keyboards; for that you would want " |
| "ca.hybridansi. See http://goto/cros-canada" |
| ), |
| ), |
| Region( |
| "ca.fr", |
| "xkb:ca::fra", |
| "America/Toronto", |
| "fr-CA", |
| KML.ISO, |
| "Canada (French keyboard)", |
| ( |
| "Canadian French (ISO) keyboard. The most common configuration for " |
| "Canadian French SKUs. See http://goto/cros-canada" |
| ), |
| ), |
| Region( |
| "ca.hybrid", |
| "xkb:ca:eng:eng", |
| "America/Toronto", |
| "en-CA", |
| KML.ISO, |
| "Canada (hybrid ISO)", |
| ( |
| "Canada with hybrid (ISO) xkb:ca:eng:eng + xkb:ca::fra keyboard, " |
| "defaulting to English language and keyboard. Used only if there " |
| "needs to be a single SKU for all of Canada. See " |
| "http://goto/cros-canada" |
| ), |
| ), |
| Region( |
| "ca.hybridansi", |
| "xkb:ca:eng:eng", |
| "America/Toronto", |
| "en-CA", |
| KML.ANSI, |
| "Canada (hybrid ANSI)", |
| ( |
| "Canada with hybrid (ANSI) xkb:ca:eng:eng + xkb:ca::fra keyboard, " |
| "defaulting to English language and keyboard. Used only if there " |
| "needs to be a single SKU for all of Canada. See " |
| "http://goto/cros-canada" |
| ), |
| ), |
| Region( |
| "ca.multix", |
| "xkb:ca:multix:fra", |
| "America/Toronto", |
| "fr-CA", |
| KML.ISO, |
| "Canada (multilingual)", |
| ( |
| "Canadian Multilingual keyboard; you probably don't want this. See " |
| "http://goto/cros-canada" |
| ), |
| ), |
| Region( |
| "ch", |
| "xkb:ch::ger", |
| "Europe/Zurich", |
| "de-CH", |
| KML.ISO, |
| "Switzerland", |
| ("German keyboard"), |
| ), |
| Region("de", "xkb:de::ger", "Europe/Berlin", "de", KML.ISO, "Germany"), |
| Region("es", "xkb:es::spa", "Europe/Madrid", "es", KML.ISO, "Spain"), |
| Region("fi", "xkb:fi::fin", "Europe/Helsinki", "fi", KML.ISO, "Finland"), |
| Region("fr", "xkb:fr::fra", "Europe/Paris", "fr", KML.ISO, "France"), |
| Region("gb", "xkb:gb:extd:eng", "Europe/London", "en-GB", KML.ISO, "UK"), |
| Region( |
| "ie", "xkb:gb:extd:eng", "Europe/Dublin", "en-GB", KML.ISO, "Ireland" |
| ), |
| Region("in", "xkb:us::eng", "Asia/Calcutta", "en-US", KML.ANSI, "India"), |
| Region("it", "xkb:it::ita", "Europe/Rome", "it", KML.ISO, "Italy"), |
| Region( |
| "latam-es-419", |
| "xkb:latam::spa", |
| "America/Mexico_City", |
| "es-419", |
| KML.ISO, |
| "Hispanophone Latin America", |
| ( |
| "Spanish-speaking countries in Latin America, using the Iberian " |
| "(Spain) Spanish keyboard, which is increasingly dominant in " |
| "Latin America. Known to be correct for at least Chile, Colombia, " |
| "Mexico, Peru; other es-419 countries may need to be reviewed " |
| "through http://goto/vpdsettings. See also http://goo.gl/Iffuqh . " |
| "Note that 419 is the UN M.49 region code for Latin America." |
| ), |
| "MX", |
| ), |
| Region( |
| "my", "xkb:us::eng", "Asia/Kuala_Lumpur", "ms", KML.ANSI, "Malaysia" |
| ), |
| Region( |
| "nl", |
| "xkb:us:intl:eng", |
| "Europe/Amsterdam", |
| "nl", |
| KML.ANSI, |
| "Netherlands", |
| ), |
| Region( |
| "nordic", |
| "xkb:se::swe", |
| "Europe/Stockholm", |
| "en-US", |
| KML.ISO, |
| "Nordics", |
| ( |
| "Unified SKU for Sweden, Norway, and Denmark. This defaults " |
| "to Swedish keyboard layout, but starts with US English language " |
| "for neutrality. Use if there is a single combined SKU for Nordic " |
| "countries." |
| ), |
| "SE", |
| ), |
| Region( |
| "nz", |
| "xkb:us::eng", |
| "Pacific/Auckland", |
| "en-NZ", |
| KML.ANSI, |
| "New Zealand", |
| ), |
| Region( |
| "ph", "xkb:us::eng", "Asia/Manila", "en-US", KML.ANSI, "Philippines" |
| ), |
| Region( |
| "ru", |
| ["xkb:us::eng", "xkb:ru::rus"], |
| "Europe/Moscow", |
| "ru", |
| KML.ANSI, |
| "Russia", |
| ("For R31+ only; R30 and earlier must use US keyboard for login"), |
| ), |
| Region( |
| "se", |
| "xkb:se::swe", |
| "Europe/Stockholm", |
| "sv", |
| KML.ISO, |
| "Sweden", |
| ( |
| "Use this if there separate SKUs for Nordic countries (Sweden, " |
| "Norway, and Denmark), or the device is only shipping to Sweden. " |
| "If there is a single unified SKU, use 'nordic' instead." |
| ), |
| ), |
| Region( |
| "sg", "xkb:us::eng", "Asia/Singapore", "en-GB", KML.ANSI, "Singapore" |
| ), |
| Region( |
| "us", |
| "xkb:us::eng", |
| "America/Los_Angeles", |
| "en-US", |
| KML.ANSI, |
| "United States", |
| ), |
| Region( |
| "jp", |
| ["xkb:jp::jpn", "ime:jp:mozc_jp"], |
| "Asia/Tokyo", |
| "ja", |
| KML.JIS, |
| "Japan", |
| ), |
| Region( |
| "za", |
| "xkb:za:gb:eng", |
| "Africa/Johannesburg", |
| "en-ZA", |
| KML.ISO, |
| "South Africa", |
| ), |
| Region( |
| "ng", "xkb:us:intl:eng", "Africa/Lagos", "en-GB", KML.ANSI, "Nigeria" |
| ), |
| Region( |
| "hk", |
| [ |
| "xkb:us::eng", |
| "ime:zh-t:cangjie", |
| "ime:zh-t:quick", |
| "ime:zh-t:array", |
| "ime:zh-t:dayi", |
| "ime:zh-t:zhuyin", |
| "ime:zh-t:pinyin", |
| ], |
| "Asia/Hong_Kong", |
| ["zh-TW", "en-GB", "zh-CN"], |
| KML.ANSI, |
| "Hong Kong", |
| ), |
| Region( |
| "gcc", |
| ["xkb:us::eng", "m17n:ar", "t13n:ar"], |
| "Asia/Riyadh", |
| ["ar", "en-GB"], |
| KML.ANSI, |
| "Gulf Cooperation Council (GCC)", |
| ( |
| "GCC is a regional intergovernmental political and economic " |
| "union consisting of all Arab states of the Persian Gulf except " |
| "for Iraq. Its member states are the Islamic monarchies of " |
| "Bahrain, Kuwait, Oman, Qatar, Saudi Arabia, and the United Arab " |
| "Emirates." |
| ), |
| "SA", |
| ), |
| Region( |
| "cz", |
| ["xkb:cz::cze", "xkb:cz:qwerty:cze"], |
| "Europe/Prague", |
| ["cs", "en-GB"], |
| KML.ISO, |
| "Czech Republic", |
| ), |
| Region( |
| "th", |
| ["xkb:us::eng", "m17n:th", "m17n:th_pattajoti", "m17n:th_tis"], |
| "Asia/Bangkok", |
| ["th", "en-GB"], |
| KML.ANSI, |
| "Thailand", |
| ), |
| Region( |
| "id", |
| "xkb:us::ind", |
| "Asia/Jakarta", |
| ["id", "en-GB"], |
| KML.ANSI, |
| "Indonesia", |
| ), |
| Region( |
| "tw", |
| [ |
| "xkb:us::eng", |
| "ime:zh-t:zhuyin", |
| "ime:zh-t:array", |
| "ime:zh-t:dayi", |
| "ime:zh-t:cangjie", |
| "ime:zh-t:quick", |
| "ime:zh-t:pinyin", |
| ], |
| "Asia/Taipei", |
| ["zh-TW", "en-US"], |
| KML.ANSI, |
| "Taiwan", |
| ), |
| Region( |
| "pl", |
| "xkb:pl::pol", |
| "Europe/Warsaw", |
| ["pl", "en-GB"], |
| KML.ANSI, |
| "Poland", |
| ), |
| Region( |
| "gr", |
| ["xkb:us::eng", "xkb:gr::gre", "t13n:el"], |
| "Europe/Athens", |
| ["el", "en-GB"], |
| KML.ANSI, |
| "Greece", |
| ), |
| Region( |
| "il", |
| ["xkb:us::eng", "xkb:il::heb", "t13n:he"], |
| "Asia/Jerusalem", |
| ["he", "en-US", "ar"], |
| KML.ANSI, |
| "Israel", |
| ), |
| Region( |
| "pt", |
| "xkb:pt::por", |
| "Europe/Lisbon", |
| ["pt-PT", "en-GB"], |
| KML.ISO, |
| "Portugal", |
| ), |
| Region( |
| "ro", |
| ["xkb:us::eng", "xkb:ro::rum"], |
| "Europe/Bucharest", |
| ["ro", "hu", "de", "en-GB"], |
| KML.ISO, |
| "Romania", |
| ), |
| Region( |
| "kr", |
| ["xkb:us::eng", "ime:ko:hangul"], |
| "Asia/Seoul", |
| ["ko", "en-US"], |
| KML.ANSI, |
| "South Korea", |
| ), |
| Region("ae", "xkb:us::eng", "Asia/Dubai", "ar", KML.ANSI, "UAE"), |
| Region( |
| "za.us", |
| "xkb:us::eng", |
| "Africa/Johannesburg", |
| "en-ZA", |
| KML.ANSI, |
| "South Africa", |
| ), |
| Region( |
| "vn", |
| [ |
| "xkb:us::eng", |
| "m17n:vi_telex", |
| "m17n:vi_vni", |
| "m17n:vi_viqr", |
| "m17n:vi_tcvn", |
| ], |
| "Asia/Ho_Chi_Minh", |
| ["vi", "en-GB", "en-US", "fr", "zh-TW"], |
| KML.ANSI, |
| "Vietnam", |
| ), |
| Region( |
| "at", |
| ["xkb:de::ger", "xkb:de:neo:ger"], |
| "Europe/Vienna", |
| ["de", "en-GB"], |
| KML.ISO, |
| "Austria", |
| ), |
| Region( |
| "sk", |
| ["xkb:us::eng", "xkb:sk::slo"], |
| "Europe/Bratislava", |
| ["sk", "hu", "cs", "en-GB"], |
| KML.ISO, |
| "Slovakia", |
| ), |
| Region( |
| "ch.usintl", |
| "xkb:us:intl:eng", |
| "Europe/Zurich", |
| "en-US", |
| KML.ANSI, |
| "Switzerland (US Intl)", |
| ("Switzerland with US International keyboard layout."), |
| ), |
| Region("pe", "xkb:latam::spa", "America/Lima", "es-419", KML.ANSI, "Peru"), |
| Region( |
| "sa", |
| "xkb:us::eng", |
| "Asia/Riyadh", |
| ["ar", "en"], |
| KML.ANSI, |
| "Saudi Arabia", |
| ), |
| Region( |
| "mx", |
| "xkb:latam::spa", |
| "America/Mexico_City", |
| "es-MX", |
| KML.ANSI, |
| "Mexico", |
| ), |
| Region( |
| "cl", "xkb:latam::spa", "America/Santiago", "es-419", KML.ANSI, "Chile" |
| ), |
| Region( |
| "kw", |
| ["xkb:us::eng", "m17n:ar", "t13n:ar"], |
| "Asia/Kuwait", |
| ["ar", "en"], |
| KML.ANSI, |
| "Kuwait", |
| ), |
| Region( |
| "uy", |
| "xkb:latam::spa", |
| "America/Montevideo", |
| "es-419", |
| KML.ANSI, |
| "Uruguay", |
| ), |
| Region( |
| "tr", |
| ["xkb:tr::tur", "xkb:tr:f:tur"], |
| "Europe/Istanbul", |
| ["tr", "en-GB"], |
| KML.ISO, |
| "Turkey", |
| ), |
| Region( |
| "ar", |
| "xkb:latam::spa", |
| "America/Argentina/Buenos_Aires", |
| [ |
| "es-AR", |
| ], |
| KML.ISO, |
| "Argentina", |
| ), |
| Region( |
| "gb.usext", |
| "xkb:us:altgr-intl:eng", |
| "Europe/London", |
| "en-GB", |
| KML.ISO, |
| "UK (US extended keyboard)", |
| ("GB with US extended keyboard"), |
| ), |
| Region( |
| "bg", |
| ["xkb:bg::bul", "xkb:bg:phonetic:bul"], |
| "Europe/Sofia", |
| ["bg", "tr", "en-US"], |
| KML.ANSI, |
| "Bulgaria", |
| ), |
| Region( |
| "jp.us", |
| ["xkb:us::eng", "ime:jp:mozc_us"], |
| "Asia/Tokyo", |
| "ja", |
| KML.ANSI, |
| "Japan with US keyboard", |
| ), |
| Region( |
| "is", |
| "xkb:is::ice", |
| "Atlantic/Reykjavik", |
| ["is", "en-GB"], |
| KML.ISO, |
| "Iceland", |
| ), |
| Region( |
| "us.intl", |
| "xkb:us:intl:eng", |
| "America/Los_Angeles", |
| "en-US", |
| KML.ANSI, |
| "US (English Intl)", |
| ), |
| Region( |
| "co", "xkb:latam::spa", "America/Bogota", "es-CO", KML.ANSI, "Colombia" |
| ), |
| Region( |
| "hr", |
| "xkb:hr::scr", |
| "Europe/Zagreb", |
| ["hr", "en-GB"], |
| KML.ISO, |
| "Croatia", |
| ), |
| Region( |
| "kz", |
| ["xkb:us::eng", "xkb:kz::kaz", "xkb:ru::rus"], |
| ["Asia/Almaty", "Asia/Aqtobe"], |
| ["kk", "ru"], |
| KML.ANSI, |
| "Kazakhstan", |
| ), |
| Region( |
| "ee", |
| "xkb:ee::est", |
| "Europe/Tallinn", |
| ["et", "ru", "en-GB"], |
| KML.ISO, |
| "Estonia", |
| ), |
| Region( |
| "ro.us", |
| ["xkb:us::eng", "xkb:ro::rum"], |
| "Europe/Bucharest", |
| ["ro", "hu", "de", "en-GB"], |
| KML.ANSI, |
| "Romania with US keyboard", |
| ), |
| Region( |
| "ua", |
| ["xkb:us::eng", "xkb:ua::ukr"], |
| ["Europe/Kiev"], |
| # "uk" is Ukraine, not United Kingdom. |
| ["uk", "en-US"], |
| KML.ANSI, |
| "Ukraine", |
| ), |
| Region( |
| "ro.usintl", |
| ["xkb:us:intl:eng"], |
| ["Europe/Bucharest"], |
| ["ro", "hu", "de", "en-GB"], |
| KML.ANSI, |
| "Romania with US International keyboard layout", |
| ), |
| Region( |
| "in.hybrid", |
| ["xkb:in::eng", "xkb:us::eng"], |
| "Asia/Calcutta", |
| ["en-IN", "en-US"], |
| KML.ANSI, |
| "India with Indian keyboard", |
| ), |
| ] |
| |
| """A list of :py:class:`regions.Region` objects for |
| all **confirmed** regions. A confirmed region is a region whose |
| properties are known to be correct and valid: all contents (locale / timezone / |
| keyboards) are supported by Chrome. |
| |
| NOTE: This list is NOT alpha-sorted. New entries MUST be appended to the end of |
| the list to retain relative order of existing entries. For backward |
| compatibility, legacy entries need to stay in the same order because they used |
| to have numeric mappings. |
| """ |
| |
| NOTES_USE_419 = ( |
| "Use this if there are separate SKUs for Spanish-speaking countries " |
| "in Latin America countries, or the device is only shipping to this " |
| "region. Otherwise (or if there is a single unified SKU), use " |
| "'latam-es-419' region code instead." |
| ) |
| NOTES_USE_NORDIC = ( |
| "Use this if there are separate SKUs for Nordic countries (Sweden, " |
| "Norway, and Denmark), or the device is only shipping to this region. " |
| "Otherwise (or if there is a single unified SKU), use 'nordic' instead." |
| ) |
| |
| UNCONFIRMED_REGIONS_LIST = [ |
| Region("ad", TBR, TBR, TBR, TBR, "Andorra"), |
| Region("af", TBR, TBR, TBR, TBR, "Afghanistan"), |
| Region("ag", TBR, TBR, TBR, TBR, "Antigua and Barbuda"), |
| Region("ai", TBR, TBR, TBR, TBR, "Anguilla"), |
| Region("al", TBR, TBR, TBR, TBR, "Albania"), |
| Region("am", TBR, TBR, TBR, TBR, "Armenia"), |
| Region("ao", TBR, TBR, TBR, TBR, "Angola"), |
| Region("as", TBR, TBR, TBR, TBR, "American Samoa"), |
| Region("aw", TBR, TBR, TBR, TBR, "Aruba"), |
| Region("ax", TBR, TBR, TBR, TBR, "Aland Islands"), |
| Region("az", TBR, TBR, TBR, TBR, "Azerbaijan"), |
| Region("ba", TBR, TBR, TBR, TBR, "Bosnia and Herzegovina"), |
| Region("bb", TBR, TBR, TBR, TBR, "Barbados"), |
| Region("bd", TBR, TBR, TBR, TBR, "Bangladesh"), |
| Region("bf", TBR, TBR, TBR, TBR, "Burkina Faso"), |
| Region("bh", TBR, TBR, TBR, TBR, "Bahrain"), |
| Region("bi", TBR, TBR, TBR, TBR, "Burundi"), |
| Region("bj", TBR, TBR, TBR, TBR, "Benin"), |
| Region("bl", TBR, TBR, TBR, TBR, "Saint Barthelemy"), |
| Region("bm", TBR, TBR, TBR, TBR, "Bermuda"), |
| Region("bn", TBR, TBR, TBR, TBR, "Brunei"), |
| Region("bq", TBR, TBR, TBR, TBR, "Bonaire, Saint Eustatius and Saba "), |
| Region("bs", TBR, TBR, TBR, TBR, "Bahamas"), |
| Region("bt", TBR, TBR, TBR, TBR, "Bhutan"), |
| Region("bw", TBR, TBR, TBR, TBR, "Botswana"), |
| Region("by", TBR, TBR, TBR, TBR, "Belarus"), |
| Region("bz", TBR, TBR, TBR, TBR, "Belize"), |
| Region("cc", TBR, TBR, TBR, TBR, "Cocos Islands"), |
| Region("cd", TBR, TBR, TBR, TBR, "Democratic Republic of the Congo"), |
| Region("cf", TBR, TBR, TBR, TBR, "Central African Republic"), |
| Region("cg", TBR, TBR, TBR, TBR, "Republic of the Congo"), |
| Region("ci", TBR, TBR, TBR, TBR, "Ivory Coast"), |
| Region("ck", TBR, TBR, TBR, TBR, "Cook Islands"), |
| Region("cm", TBR, TBR, TBR, TBR, "Cameroon"), |
| Region("cn", TBR, TBR, TBR, TBR, "China"), |
| Region("cv", TBR, TBR, TBR, TBR, "Cape Verde"), |
| Region("cw", TBR, TBR, TBR, TBR, "Curacao"), |
| Region("cx", TBR, TBR, TBR, TBR, "Christmas Island"), |
| Region("cy", TBR, TBR, TBR, TBR, "Cyprus"), |
| Region("dj", TBR, TBR, TBR, TBR, "Djibouti"), |
| Region("dm", TBR, TBR, TBR, TBR, "Dominica"), |
| Region("dz", TBR, TBR, TBR, TBR, "Algeria"), |
| Region("eg", TBR, TBR, TBR, TBR, "Egypt"), |
| Region("eh", TBR, TBR, TBR, TBR, "Western Sahara"), |
| Region("er", TBR, TBR, TBR, TBR, "Eritrea"), |
| Region("et", TBR, TBR, TBR, TBR, "Ethiopia"), |
| Region("fj", TBR, TBR, TBR, TBR, "Fiji"), |
| Region("fk", TBR, TBR, TBR, TBR, "Falkland Islands"), |
| Region("fm", TBR, TBR, TBR, TBR, "Micronesia"), |
| Region("fo", TBR, TBR, TBR, TBR, "Faroe Islands"), |
| Region("ga", TBR, TBR, TBR, TBR, "Gabon"), |
| Region("gd", TBR, TBR, TBR, TBR, "Grenada"), |
| Region("ge", TBR, TBR, TBR, TBR, "Georgia"), |
| Region("gf", TBR, TBR, TBR, TBR, "French Guiana"), |
| Region("gg", TBR, TBR, TBR, TBR, "Guernsey"), |
| Region("gh", TBR, TBR, TBR, TBR, "Ghana"), |
| Region("gi", TBR, TBR, TBR, TBR, "Gibraltar"), |
| Region("gl", TBR, TBR, TBR, TBR, "Greenland"), |
| Region("gm", TBR, TBR, TBR, TBR, "Gambia"), |
| Region("gn", TBR, TBR, TBR, TBR, "Guinea"), |
| Region("gp", TBR, TBR, TBR, TBR, "Guadeloupe"), |
| Region("gq", TBR, TBR, TBR, TBR, "Equatorial Guinea"), |
| Region( |
| "gs", TBR, TBR, TBR, TBR, "South Georgia and the South Sandwich Islands" |
| ), |
| Region("gu", TBR, TBR, TBR, TBR, "Guam"), |
| Region("gw", TBR, TBR, TBR, TBR, "Guinea-Bissau"), |
| Region("gy", TBR, TBR, TBR, TBR, "Guyana"), |
| Region("ht", TBR, TBR, TBR, TBR, "Haiti"), |
| Region("hu", TBR, TBR, TBR, TBR, "Hungary"), |
| Region("im", TBR, TBR, TBR, TBR, "Isle of Man"), |
| Region("io", TBR, TBR, TBR, TBR, "British Indian Ocean Territory"), |
| Region("iq", TBR, TBR, TBR, TBR, "Iraq"), |
| Region("ir", TBR, TBR, TBR, TBR, "Iran"), |
| Region("je", TBR, TBR, TBR, TBR, "Jersey"), |
| Region("jm", TBR, TBR, TBR, TBR, "Jamaica"), |
| Region("jo", TBR, TBR, TBR, TBR, "Jordan"), |
| Region("ke", TBR, TBR, TBR, TBR, "Kenya"), |
| Region("kg", TBR, TBR, TBR, TBR, "Kyrgyzstan"), |
| Region("kh", TBR, TBR, TBR, TBR, "Cambodia"), |
| Region("ki", TBR, TBR, TBR, TBR, "Kiribati"), |
| Region("km", TBR, TBR, TBR, TBR, "Comoros"), |
| Region("kn", TBR, TBR, TBR, TBR, "Saint Kitts and Nevis"), |
| Region("kp", TBR, TBR, TBR, TBR, "North Korea"), |
| Region("ky", TBR, TBR, TBR, TBR, "Cayman Islands"), |
| Region("la", TBR, TBR, TBR, TBR, "Laos"), |
| Region("lb", TBR, TBR, TBR, TBR, "Lebanon"), |
| Region("lc", TBR, TBR, TBR, TBR, "Saint Lucia"), |
| Region("li", TBR, TBR, TBR, TBR, "Liechtenstein"), |
| Region("lk", TBR, TBR, TBR, TBR, "Sri Lanka"), |
| Region("lr", TBR, TBR, TBR, TBR, "Liberia"), |
| Region("ls", TBR, TBR, TBR, TBR, "Lesotho"), |
| Region("lt", TBR, TBR, TBR, TBR, "Lithuania"), |
| Region("lu", TBR, TBR, TBR, TBR, "Luxembourg"), |
| Region("lv", TBR, TBR, TBR, TBR, "Latvia"), |
| Region("ly", TBR, TBR, TBR, TBR, "Libya"), |
| Region("ma", TBR, TBR, TBR, TBR, "Morocco"), |
| Region("mc", TBR, TBR, TBR, TBR, "Monaco"), |
| Region("md", TBR, TBR, TBR, TBR, "Moldova"), |
| Region("me", TBR, TBR, TBR, TBR, "Montenegro"), |
| Region("mf", TBR, TBR, TBR, TBR, "Saint Martin"), |
| Region("mg", TBR, TBR, TBR, TBR, "Madagascar"), |
| Region("mh", TBR, TBR, TBR, TBR, "Marshall Islands"), |
| Region("mk", TBR, TBR, TBR, TBR, "Macedonia"), |
| Region("ml", TBR, TBR, TBR, TBR, "Mali"), |
| Region("mm", TBR, TBR, TBR, TBR, "Myanmar"), |
| Region("mn", TBR, TBR, TBR, TBR, "Mongolia"), |
| Region("mo", TBR, TBR, TBR, TBR, "Macao"), |
| Region("mp", TBR, TBR, TBR, TBR, "Northern Mariana Islands"), |
| Region("mq", TBR, TBR, TBR, TBR, "Martinique"), |
| Region("mr", TBR, TBR, TBR, TBR, "Mauritania"), |
| Region("ms", TBR, TBR, TBR, TBR, "Montserrat"), |
| Region("mt", TBR, TBR, TBR, TBR, "Malta"), |
| Region("mu", TBR, TBR, TBR, TBR, "Mauritius"), |
| Region("mv", TBR, TBR, TBR, TBR, "Maldives"), |
| Region("mw", TBR, TBR, TBR, TBR, "Malawi"), |
| Region("mz", TBR, TBR, TBR, TBR, "Mozambique"), |
| Region("na", TBR, TBR, TBR, TBR, "Namibia"), |
| Region("nc", TBR, TBR, TBR, TBR, "New Caledonia"), |
| Region("ne", TBR, TBR, TBR, TBR, "Niger"), |
| Region("nf", TBR, TBR, TBR, TBR, "Norfolk Island"), |
| Region("np", TBR, TBR, TBR, TBR, "Nepal"), |
| Region("nr", TBR, TBR, TBR, TBR, "Nauru"), |
| Region("nu", TBR, TBR, TBR, TBR, "Niue"), |
| Region("om", TBR, TBR, TBR, TBR, "Oman"), |
| Region("pf", TBR, TBR, TBR, TBR, "French Polynesia"), |
| Region("pg", TBR, TBR, TBR, TBR, "Papua New Guinea"), |
| Region("pk", TBR, TBR, TBR, TBR, "Pakistan"), |
| Region("pm", TBR, TBR, TBR, TBR, "Saint Pierre and Miquelon"), |
| Region("pn", TBR, TBR, TBR, TBR, "Pitcairn"), |
| Region("pr", TBR, TBR, TBR, TBR, "Puerto Rico"), |
| Region("ps", TBR, TBR, TBR, TBR, "Palestinian Territory"), |
| Region("pw", TBR, TBR, TBR, TBR, "Palau"), |
| Region("qa", TBR, TBR, TBR, TBR, "Qatar"), |
| Region("re", TBR, TBR, TBR, TBR, "Reunion"), |
| Region("rs", TBR, TBR, TBR, TBR, "Serbia"), |
| Region("rw", TBR, TBR, TBR, TBR, "Rwanda"), |
| Region("sb", TBR, TBR, TBR, TBR, "Solomon Islands"), |
| Region("sc", TBR, TBR, TBR, TBR, "Seychelles"), |
| Region("sd", TBR, TBR, TBR, TBR, "Sudan"), |
| Region("sh", TBR, TBR, TBR, TBR, "Saint Helena"), |
| Region("si", TBR, TBR, TBR, TBR, "Slovenia"), |
| Region("sj", TBR, TBR, TBR, TBR, "Svalbard and Jan Mayen"), |
| Region("sl", TBR, TBR, TBR, TBR, "Sierra Leone"), |
| Region("sm", TBR, TBR, TBR, TBR, "San Marino"), |
| Region("sn", TBR, TBR, TBR, TBR, "Senegal"), |
| Region("so", TBR, TBR, TBR, TBR, "Somalia"), |
| Region("sr", TBR, TBR, TBR, TBR, "Suriname"), |
| Region("ss", TBR, TBR, TBR, TBR, "South Sudan"), |
| Region("st", TBR, TBR, TBR, TBR, "Sao Tome and Principe"), |
| Region("sx", TBR, TBR, TBR, TBR, "Sint Maarten"), |
| Region("sy", TBR, TBR, TBR, TBR, "Syria"), |
| Region("sz", TBR, TBR, TBR, TBR, "Swaziland"), |
| Region("tc", TBR, TBR, TBR, TBR, "Turks and Caicos Islands"), |
| Region("td", TBR, TBR, TBR, TBR, "Chad"), |
| Region("tf", TBR, TBR, TBR, TBR, "French Southern Territories"), |
| Region("tg", TBR, TBR, TBR, TBR, "Togo"), |
| Region("tj", TBR, TBR, TBR, TBR, "Tajikistan"), |
| Region("tk", TBR, TBR, TBR, TBR, "Tokelau"), |
| Region("tl", TBR, TBR, TBR, TBR, "East Timor"), |
| Region("tm", TBR, TBR, TBR, TBR, "Turkmenistan"), |
| Region("tn", TBR, TBR, TBR, TBR, "Tunisia"), |
| Region("to", TBR, TBR, TBR, TBR, "Tonga"), |
| Region("tt", TBR, TBR, TBR, TBR, "Trinidad and Tobago"), |
| Region("tv", TBR, TBR, TBR, TBR, "Tuvalu"), |
| Region("tz", TBR, TBR, TBR, TBR, "Tanzania"), |
| Region("ug", TBR, TBR, TBR, TBR, "Uganda"), |
| Region("um", TBR, TBR, TBR, TBR, "United States Minor Outlying Islands"), |
| Region("uz", TBR, TBR, TBR, TBR, "Uzbekistan"), |
| Region("va", TBR, TBR, TBR, TBR, "Vatican"), |
| Region("vc", TBR, TBR, TBR, TBR, "Saint Vincent and the Grenadines"), |
| Region("vg", TBR, TBR, TBR, TBR, "British Virgin Islands"), |
| Region("vi", TBR, TBR, TBR, TBR, "U.S. Virgin Islands"), |
| Region("vu", TBR, TBR, TBR, TBR, "Vanuatu"), |
| Region("wf", TBR, TBR, TBR, TBR, "Wallis and Futuna"), |
| Region("ws", TBR, TBR, TBR, TBR, "Samoa"), |
| Region("ye", TBR, TBR, TBR, TBR, "Yemen"), |
| Region("yt", TBR, TBR, TBR, TBR, "Mayotte"), |
| Region("zm", TBR, TBR, TBR, TBR, "Zambia"), |
| Region("zw", TBR, TBR, TBR, TBR, "Zimbabwe"), |
| # Please consider using 'nordic' instead before trying to review 'dk'. |
| Region("dk", TBR, TBR, TBR, TBR, "Denmark", NOTES_USE_NORDIC), |
| # Please consider using 'nordic' instead before trying to review 'no'. |
| Region("no", TBR, TBR, TBR, TBR, "Norway", NOTES_USE_NORDIC), |
| # Below are regions already covered by 'latam-es-419' region code. |
| # Please consider using 'latam-es-419' before trying to confirm/review them. |
| Region("bo", XKB_LATAM, TBR, "es-419", TBR, "Bolivia", NOTES_USE_419), |
| Region("cu", XKB_LATAM, TBR, "es-419", TBR, "Cuba", NOTES_USE_419), |
| Region("do", XKB_LATAM, TBR, "es-419", TBR, "Dominican Republic", |
| NOTES_USE_419), |
| Region("ec", XKB_LATAM, TBR, "es-419", TBR, "Ecuador", NOTES_USE_419), |
| Region("gt", XKB_LATAM, TBR, "es-419", TBR, "Guatemala", NOTES_USE_419), |
| Region("ni", XKB_LATAM, TBR, "es-419", TBR, "Nicaragua", NOTES_USE_419), |
| Region("pa", XKB_LATAM, TBR, "es-419", TBR, "Panama", NOTES_USE_419), |
| Region("py", XKB_LATAM, TBR, "es-419", TBR, "Paraguay", NOTES_USE_419), |
| Region("sv", XKB_LATAM, TBR, "es-419", TBR, "El Salvador", NOTES_USE_419), |
| Region("ve", XKB_LATAM, TBR, "es-419", TBR, "Venezuela", NOTES_USE_419), |
| Region("hn", XKB_LATAM, TBR, "es-419", TBR, "Honduras", NOTES_USE_419), |
| Region("cr", XKB_LATAM, TBR, "es-419", TBR, "Costa Rica", NOTES_USE_419), |
| ] |
| |
| """A list of :py:class:`regions.Region` objects for |
| **unconfirmed** regions. These may contain incorrect information (or not |
| supported by Chrome browser yet), and all fields must be reviewed before launch. |
| See http://goto/vpdsettings. |
| |
| Currently, non-Latin keyboards must use an underlying Latin keyboard |
| for VPD. (This assumption should be revisited when moving items to |
| :py:data:`regions.Region.REGIONS_LIST`.) This is |
| currently being discussed on <http://crbug.com/325389>. |
| |
| Some timezones or locales may be missing from ``timezone_settings.cc`` (see |
| http://crosbug.com/p/23902). This must be rectified before moving |
| items to :py:data:`regions.Region.REGIONS_LIST`. |
| """ |
| |
| |
| def ConsolidateRegions(regions): |
| """Consolidates a list of regions into a dict. |
| |
| Args: |
| regions: A list of Region objects. All objects for any given |
| region code must be identical or we will throw an exception. |
| (We allow duplicates in case identical region objects are |
| defined in both regions.py and the overlay, e.g., when moving |
| items to the public overlay.) |
| |
| Returns: |
| A dict from region code to Region. |
| |
| Raises: |
| RegionException: If there are multiple regions defined for a given |
| region, and the values for those regions differ. |
| """ |
| # Build a dict from region_code to the first Region with that code. |
| region_dict = {} |
| for r in regions: |
| existing_region = region_dict.get(r.region_code) |
| if existing_region: |
| if existing_region.GetFieldsDict() != r.GetFieldsDict(): |
| raise RegionException( |
| "Conflicting definitions for region %r: %r, %r" |
| % ( |
| r.region_code, |
| existing_region.GetFieldsDict(), |
| r.GetFieldsDict(), |
| ) |
| ) |
| else: |
| region_dict[r.region_code] = r |
| |
| return region_dict |
| |
| |
| def BuildRegionsDict(include_all=False, include_pseudolocales=False): |
| """Builds a mapping from code to :py:class:`regions.Region` object. |
| |
| ``include_pseudolocales`` should never be true for production builds. |
| |
| The regions include: |
| |
| * :py:data:`regions.REGIONS_LIST` |
| * :py:data:`regions_overlay.REGIONS_LIST` |
| * Only if ``include_all`` is true: |
| * :py:data:`regions.UNCONFIRMED_REGIONS_LIST` |
| * :py:data:`regions.INCOMPLETE_REGIONS_LIST` |
| * Only if ``include_pseudolocales`` is true: |
| * :py:data:`regions.PSEUDOLOCALE_REGIONS_LIST` |
| |
| A region may only appear in one of the above lists, or this function |
| will (deliberately) fail. |
| """ |
| regions = list(REGIONS_LIST) |
| if include_all: |
| known_codes = [r.region_code for r in regions] |
| regions += [ |
| r |
| for r in UNCONFIRMED_REGIONS_LIST |
| if r.region_code not in known_codes |
| ] |
| if include_pseudolocales: |
| regions += PSEUDOLOCALE_REGIONS_LIST |
| |
| # Build dictionary of region code to list of regions with that |
| # region code. Check manually for duplicates, since the region may |
| # be present both in the overlay and the public repo. |
| return ConsolidateRegions(regions) |
| |
| |
| REGIONS = BuildRegionsDict() |
| |
| |
| def main(args=None, out=None): |
| if args is None: |
| args = sys.argv[1:] |
| |
| parser = argparse.ArgumentParser( |
| description=("Display all known regions and their parameters. ") |
| ) |
| parser.add_argument( |
| "--format", |
| choices=("human-readable", "csv", "json", "yaml"), |
| default="human-readable", |
| help="Output format (default=%(default)s)", |
| ) |
| parser.add_argument( |
| "--all", |
| action="store_true", |
| help="Include unconfirmed and incomplete regions", |
| ) |
| parser.add_argument( |
| "--notes", action="store_true", help="Include notes in output" |
| ) |
| parser.add_argument( |
| "--include_pseudolocales", |
| action="store_true", |
| help="Include pseudolocales in output", |
| ) |
| parser.add_argument("--output", default=None, help="Specify output file") |
| parser.add_argument( |
| "--overlay", |
| default=None, |
| help="Specify a Python file to overlay extra data", |
| ) |
| args = parser.parse_args(args) |
| |
| if args.overlay is not None: |
| with open(args.overlay, encoding="utf-8") as f: |
| exec(f.read()) # pylint: disable=exec-used |
| |
| if args.all: |
| # Add an additional 'confirmed' property to help identifying region |
| # status for autotests, unit tests and factory module. |
| Region.FIELDS.insert(1, "confirmed") |
| for r in REGIONS_LIST: |
| r.confirmed = True |
| for r in UNCONFIRMED_REGIONS_LIST: |
| r.confirmed = False |
| |
| regions_dict = BuildRegionsDict(args.all, args.include_pseudolocales) |
| |
| if out is None: |
| if args.output is None: |
| out = sys.stdout |
| else: |
| out = open( |
| args.output, "w", encoding="utf-8" |
| ) # pylint: disable=consider-using-with |
| |
| if args.notes or args.format == "csv": |
| Region.FIELDS += ["notes"] |
| |
| # Handle YAML and JSON output. |
| if args.format in ("yaml", "json"): |
| data = {} |
| for region in regions_dict.values(): |
| item = {} |
| for field in Region.FIELDS: |
| item[field] = getattr(region, field) |
| data[region.region_code] = item |
| if args.format == "yaml": |
| yaml.dump(data, out) |
| else: |
| json.dump(data, out) |
| return |
| |
| # Handle CSV or plain-text output: build a list of lines to print. |
| lines = [Region.FIELDS] |
| |
| def CoerceToString(value): |
| """Returns the arguments in simple string type. |
| |
| If value is a list, concatenate its values with commas. Otherwise, just |
| return value. |
| """ |
| if isinstance(value, list): |
| return ",".join(value) |
| else: |
| return str(value) |
| |
| for region in sorted(regions_dict.values(), key=lambda v: v.region_code): |
| lines.append( |
| [CoerceToString(getattr(region, field)) for field in Region.FIELDS] |
| ) |
| |
| if args.format == "csv": |
| # Just print the lines in CSV format. Note the values may |
| # include ',' so the separator must be tab. |
| for l in lines: |
| print("\t".join(l)) |
| elif args.format == "human-readable": |
| num_columns = len(lines[0]) |
| |
| # Calculate maximum length of each column. |
| max_lengths = [] |
| for column_no in range(num_columns): |
| max_lengths.append(max(len(line[column_no]) for line in lines)) |
| |
| # Print each line, padding as necessary to the max column length. |
| for line in lines: |
| for column_no in range(num_columns): |
| out.write(line[column_no].ljust(max_lengths[column_no] + 2)) |
| out.write("\n") |
| else: |
| sys.exit("Sorry, unknown format specified: %s" % args.format) |
| |
| |
| if __name__ == "__main__": |
| main() |