Coverage for pyguymer3/geo/getRecordAttribute.py: 3%
31 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-08 18:47 +0000
1#!/usr/bin/env python3
3# Define function ...
4def getRecordAttribute(
5 record,
6 attribute,
7 /,
8 *,
9 strict = False,
10):
11 """Get an attribute of a Shapefile record
13 This function gets an attribute of a Shapefile record, falling back on
14 different attributes to work around inconsistencies in records in Shapefiles
15 obtained from `Natural Earth <https://www.naturalearthdata.com>`_.
17 For example, if the user wants the "ISO_A2" attribute then this function
18 (with ``strict = False``) will return the first value it finds (which does
19 *not* equal "-99") from:
21 * ``record.attributes["ISO_A2"]``
22 * ``record.attributes["iso_a2"]``
23 * ``record.attributes["ISO_A2_EH"]``
24 * ``record.attributes["iso_a2_eh"]``
26 Parameters
27 ----------
28 record : cartopy.io.shapereader.Record
29 the record
30 attribute : str
31 the attribute
32 debug : bool, optional
33 if ``True`` then return "-99" if that is what the value is; if ``False``
34 then continue looping through the possibilities
36 Returns
37 -------
38 value : str
39 the value
41 Notes
42 -----
43 According to the developer of Natural Earth [1]_ :
45 "Because Natural Earth has a more fidelity than ISO, and tracks
46 countries that ISO doesn't, Natural Earth maintains it's own set of
47 3-character codes for each admin-0 related feature."
49 Therefore, when "ISO_A2" or "ISO_A3" are not populated I must fall back on
50 "ISO_A2_EH" and "ISO_A3_EH" instead.
52 Copyright 2017 Thomas Guymer [2]_
54 References
55 ----------
56 .. [1] developer comment on issue #268 of Natural Earth, https://github.com/nvkelso/natural-earth-vector/issues/268#issuecomment-778832542
57 .. [2] PyGuymer3, https://github.com/Guymer/PyGuymer3
58 """
60 # Import standard modules ...
61 import os
63 # Import special modules ...
64 try:
65 import cartopy
66 cartopy.config.update(
67 {
68 "cache_dir" : os.path.expanduser("~/.local/share/cartopy_cache"),
69 }
70 )
71 except:
72 raise Exception("\"cartopy\" is not installed; run \"pip install --user Cartopy\"") from None
74 # **************************************************************************
76 # Check argument ...
77 assert isinstance(record, cartopy.io.shapereader.Record), "\"record\" is not a Record"
79 # Loop over possible attribute names ...
80 for posAttribute in [attribute.upper(), attribute.lower()]:
81 # Skip if it is not present ...
82 if posAttribute not in record.attributes:
83 continue
85 # Extract the value (whilst handling Natural Earth's foibles) ...
86 value = record.attributes[posAttribute]
87 if isinstance(value, str):
88 value = value.replace("\x00", " ").strip()
90 # Check if the user wants to be strict ...
91 if strict:
92 # Return answer ...
93 return value
95 # Skip if it is bad and we want to try more possible attribute names ...
96 if value == "-99":
97 continue
99 # Return answer ...
100 return value
102 # Loop over possible attribute names ...
103 for posAttribute in [f"{attribute.upper()}_EH", f"{attribute.lower()}_eh"]:
104 # Skip if it is not present ...
105 if posAttribute not in record.attributes:
106 continue
108 # Extract the value (whilst handling Natural Earth's foibles) ...
109 value = record.attributes[posAttribute]
110 if isinstance(value, str):
111 value = value.replace("\x00", " ").strip()
113 # Check if the user wants to be strict ...
114 if strict:
115 # Return answer ...
116 return value
118 # Skip if it is bad and we want to try more possible attribute names ...
119 if value == "-99":
120 continue
122 # Return answer ...
123 return value
125 # Return answer ...
126 return "ERROR"