Repository: oasis-open/cti-python-stix2

Issue:
Location Object can't have 0 for Longitude/Latitude
When attempting to create Location objects with '0' as a value for either the latitude or longitude, the library raises a DependentPropertiesError when it should not. See relevant portion of the StackTrace below:  

`country = stix2.Location( File "/usr/local/lib/python3.9/site-packages/stix2/base.py", line 232, in __init__ self._check_object_constraints() File "/usr/local/lib/python3.9/site-packages/stix2/v21/sdo.py", line 398, in _check_object_constraints self._check_properties_dependency(['longitude'], ['latitude']) File "/usr/local/lib/python3.9/site-packages/stix2/base.py", line 109, in _check_properties_dependency raise DependentPropertiesError(self.__class__, failed_dependency_pairs) stix2.exceptions.DependentPropertiesError: The property dependencies for Location: (longitude, latitude) are not met.`

I've traced the issue to the stix2\base.py _check_properties_dependency method where the function uses the "not" operator to check if a property is a valid value. In this scenario, '0' is a valid Longitude and Latitude and an additional layer of checking needs to occur for Number values. **Note: Issue arises at ```if not self.get(p)```**

```
    def _check_properties_dependency(self, list_of_properties, list_of_dependent_properties):
        failed_dependency_pairs = []
        for p in list_of_properties:
            for dp in list_of_dependent_properties:
                if not self.get(p) and self.get(dp):
                    failed_dependency_pairs.append((p, dp))
        if failed_dependency_pairs:
            raise DependentPropertiesError(self.__class__, failed_dependency_pairs)
```

Hints from issue comments:
@ejratl: Thanks for the bug report and for tracking down the exact location in the code where this occurs! TIL: 0°N 0°E is known as "Null Island". @rpiazza: _check_properties_dependency mentioned above can be found at 

https://github.com/oasis-open/cti-python-stix2/blob/master/stix2/base.py#L102 

I think the problem is that the get method doesn't take into consideration that a value of 0 will be interpreted as None.  If the property has a value of 0, then it exists, and shouldn't cause this error.

Solution patch:
diff --git a/stix2/base.py b/stix2/base.py
index 3ff01d98..a4f3f03b 100644
--- a/stix2/base.py
+++ b/stix2/base.py
@@ -103,7 +103,9 @@ def _check_properties_dependency(self, list_of_properties, list_of_dependent_pro
         failed_dependency_pairs = []
         for p in list_of_properties:
             for dp in list_of_dependent_properties:
-                if not self.get(p) and self.get(dp):
+                if p not in self and dp in self:
+                    failed_dependency_pairs.append((p, dp))
+                elif p in self and (self[p] is None or self[p] is False) and dp in self and self[dp] is not None:
                     failed_dependency_pairs.append((p, dp))
         if failed_dependency_pairs:
             raise DependentPropertiesError(self.__class__, failed_dependency_pairs)


Test patch:
diff --git a/stix2/test/v21/test_location.py b/stix2/test/v21/test_location.py
index 5d3eab8a..e5d3f862 100644
--- a/stix2/test/v21/test_location.py
+++ b/stix2/test/v21/test_location.py
@@ -377,3 +377,48 @@ def test_bing_map_url_multiple_props_and_long_lat_provided():
 
     loc_url = loc.to_maps_url("Bing Maps")
     assert loc_url == expected_url
+
+
+def test_bing_map_url_for_0_long_lat():
+    expected_url = "https://bing.com/maps/default.aspx?where1=0.0%2C0.0&lvl=16"
+
+    loc = stix2.v21.Location(
+        region="Gulf of Guinea",
+        country="International waters",
+        street_address="0°N, 0°E – Null Island",
+        latitude=0.0,
+        longitude=0.0,
+    )
+
+    loc_url = loc.to_maps_url("Bing Maps")
+    assert loc_url == expected_url
+
+
+def test_bing_map_url_for_0_long():
+    expected_url = "https://bing.com/maps/default.aspx?where1=0.0%2C39.668&lvl=16"
+
+    loc = stix2.v21.Location(
+        region="Eastern Africa",
+        country="Kenya",
+        street_address="0°N, 39.668°E",
+        latitude=0.0,
+        longitude=39.668,
+    )
+
+    loc_url = loc.to_maps_url("Bing Maps")
+    assert loc_url == expected_url
+
+
+def test_bing_map_url_for_0_lat():
+    expected_url = "https://bing.com/maps/default.aspx?where1=51.477%2C0.0&lvl=16"
+
+    loc = stix2.v21.Location(
+        region="Western Europe",
+        country="United Kingdom",
+        street_address="Royal Observatory, Blackheath Ave, Greenwich, London SE10 8XJ, United Kingdom",
+        latitude=51.477,
+        longitude=0.0,
+    )
+
+    loc_url = loc.to_maps_url("Bing Maps")
+    assert loc_url == expected_url