Skip to content

Commit 6099e6f

Browse files
authored
[V0/V1 Migration] Migrate /v1/bulk/properties/{direction} to /v2/node (#280)
Based on a [github search](https://github.com/search?q=org%3Adatacommonsorg+BulkProperties&type=code) it looks like this endpoint is only used by the old Python client (except some legacy docsite references), so this PR migrates the Python client usage. This is a pretty straightforward migration to /v2/node, which has a very similar structure for fetching properties, so there was little change in response processing. I also updated tests and added an additional test case. Based on Apigee, in the past month there's been 480 requests to this endpoint: * 440 (not set) * 39 datcom-core * 1 me (for testing) This PR also bumps the version for typing_extensions for compatibility
1 parent 230bf7f commit 6099e6f

4 files changed

Lines changed: 80 additions & 13 deletions

File tree

datacommons/node.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from typing import Dict, List
1818

1919
from datacommons.requests import _post
20+
from datacommons.utils import _get_arrow
2021
from datacommons.utils import _get_direction
2122

2223

@@ -31,12 +32,10 @@ def properties(nodes: List[str], is_out: bool = True) -> Dict[str, List[str]]:
3132
A dict keyed by node DCID, with the values being a list of properties
3233
for the queried node.
3334
"""
34-
resp = _post(f'/v1/bulk/properties/{_get_direction(is_out)}', {
35-
'nodes': nodes,
36-
})
35+
resp = _post('/v2/node', {'nodes': nodes, 'property': _get_arrow(is_out)})
3736
result = {}
38-
for item in resp.get('data', []):
39-
node, properties = item['node'], item.get('properties', [])
37+
for node, item in resp.get('data', {}).items():
38+
properties = item.get('properties', [])
4039
result[node] = properties
4140
return result
4241

datacommons/test/node_test.py

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,17 +24,74 @@ class TestProperties(unittest.TestCase):
2424
def test_with_data(self, _post):
2525

2626
def side_effect(path, data):
27-
if path == "/v1/bulk/properties/out" and data == {"nodes": ["City"]}:
27+
if path == "/v2/node" and data == {
28+
"nodes": ["City", "Count_Person", "foo"],
29+
"property": "->"
30+
}:
2831
return {
29-
"data": [{
30-
"node": "City",
31-
"properties": ["name", "provenance", "subClassOf", "typeOf"]
32-
}]
32+
"data": {
33+
"City": {
34+
"properties": [
35+
"name", "provenance", "subClassOf", "typeOf"
36+
]
37+
},
38+
"Count_Person": {
39+
"properties": [
40+
"description", "measuredProperty", "memberOf", "name",
41+
"populationType", "provenance", "statType", "typeOf"
42+
]
43+
},
44+
"foo": {}
45+
}
46+
}
47+
48+
_post.side_effect = side_effect
49+
response = datacommons.properties(["City", "Count_Person", "foo"])
50+
assert response == {
51+
"City": ["name", "provenance", "subClassOf", "typeOf"],
52+
"Count_Person": [
53+
"description", "measuredProperty", "memberOf", "name",
54+
"populationType", "provenance", "statType", "typeOf"
55+
],
56+
"foo": []
57+
}
58+
59+
@patch("datacommons.node._post")
60+
def test_with_direction(self, _post):
61+
62+
def side_effect(path, data):
63+
if path == "/v2/node" and data == {
64+
"nodes": ["City", "Count_Person", "foo"],
65+
"property": "<-"
66+
}:
67+
return {
68+
"data": {
69+
"City": {
70+
"properties": [
71+
"placeType", "rangeIncludes", "schoolLocationType",
72+
"typeOf"
73+
]
74+
},
75+
"Count_Person": {
76+
"properties": [
77+
"measurementDenominator", "outputProperty",
78+
"relevantVariable"
79+
]
80+
},
81+
"foo": {}
82+
}
3383
}
3484

3585
_post.side_effect = side_effect
36-
response = datacommons.properties(["City"])
37-
assert response == {"City": ["name", "provenance", "subClassOf", "typeOf"]}
86+
response = datacommons.properties(["City", "Count_Person", "foo"],
87+
is_out=False)
88+
assert response == {
89+
"City": ["placeType", "rangeIncludes", "schoolLocationType", "typeOf"],
90+
"Count_Person": [
91+
"measurementDenominator", "outputProperty", "relevantVariable"
92+
],
93+
"foo": []
94+
}
3895

3996

4097
class TestPropertyValues(unittest.TestCase):

datacommons/utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,14 @@ def _format_expand_payload(payload, new_key, must_exist=[]):
124124

125125
def _get_direction(out: bool):
126126
return "out" if out else "in"
127+
128+
129+
def _get_arrow(out: bool):
130+
"""Returns the arrow syntax for an arc direction.
131+
132+
Args:
133+
out: Whether the arc direction is out.
134+
Returns:
135+
The corresponding arrow syntax.
136+
"""
137+
return "->" if out else "<-"

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ mock
33
pandas
44
pytest
55
requests==2.32.0
6-
typing_extensions==4.7.1
6+
typing_extensions==4.12.2
77
yapf==0.40.2
88
pydantic>=2.11

0 commit comments

Comments
 (0)