Skip to content

Commit

Permalink
Merge pull request #100 from nasa/harmony-1936
Browse files Browse the repository at this point in the history
Harmony 1936: Add default job label to harmony-py jobs
  • Loading branch information
indiejames authored Jan 23, 2025
2 parents d70e3a8 + 08d2287 commit c2c1737
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 16 deletions.
4 changes: 3 additions & 1 deletion examples/basic.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,9 @@
"id": "tracked-distributor",
"metadata": {},
"source": [
"Now that we have a request, we can submit it to Harmony using the Harmony Client object we created earlier. We'll get back a job id belonging to our Harmony request."
"Now that we have a request, we can submit it to Harmony using the Harmony Client object we created earlier. We'll get back a job id belonging to our Harmony request.\n",
"\n",
"By default the job will have a 'harmony_py' label. This can be disabled by setting the `EXCLUDE_DEFAULT_LABEL` environment variable to \"true\" before making the request."
]
},
{
Expand Down
13 changes: 5 additions & 8 deletions examples/intro_tutorial.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@
"source": [
"### Submit Request\n",
"\n",
"Once you have created your request, you can now submit it to Harmony using the Harmony Client object. A job id is returned, which is a unique identifier that represents your submitted request. "
"Once you have created your request, you can now submit it to Harmony using the Harmony Client object. A job id is returned, which is a unique identifier that represents your submitted request.\n",
"\n",
"By default the job will have a 'harmony_py' label. This can be disabled by setting the `EXCLUDE_DEFAULT_LABEL` environment variable to \"true\" before making the request."
]
},
{
Expand Down Expand Up @@ -625,7 +627,7 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"display_name": "harmony-py-notebooks",
"language": "python",
"name": "python3"
},
Expand All @@ -639,12 +641,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.9"
},
"vscode": {
"interpreter": {
"hash": "d0b323d74a2eccdefaacaf33c041ca03218ebb6c9aa84851ec587afd8a56d428"
}
"version": "3.10.14"
}
},
"nbformat": 4,
Expand Down
18 changes: 14 additions & 4 deletions harmony/harmony.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
from harmony.config import Config, Environment
from harmony import __version__ as harmony_version

DEFAULT_JOB_LABEL = "harmony-py"

progressbar_widgets = [
' [ Processing: ', progressbar.Percentage(), ' ] ',
progressbar.Bar(),
Expand Down Expand Up @@ -352,7 +354,8 @@ def __init__(self,
concatenate: bool = None,
skip_preview: bool = None,
ignore_errors: bool = None,
grid: str = None):
grid: str = None,
labels: List[str] = None):
"""Creates a new Request instance from all specified criteria.'
"""
super().__init__(collection=collection)
Expand All @@ -377,6 +380,7 @@ def __init__(self,
self.skip_preview = skip_preview
self.ignore_errors = ignore_errors
self.grid = grid
self.labels = labels

if self.is_edr_request():
self.variable_name_to_query_param = {
Expand All @@ -397,7 +401,8 @@ def __init__(self,
'ignore_errors': 'ignoreErrors',
'grid': 'grid',
'extend': 'extend',
'variables': 'parameter-name'
'variables': 'parameter-name',
'labels': 'label',
}
self.spatial_validations = [
(lambda s: is_wkt_valid(s.wkt), f'WKT {spatial.wkt} is invalid'),
Expand All @@ -421,7 +426,8 @@ def __init__(self,
'ignore_errors': 'ignoreErrors',
'grid': 'grid',
'extend': 'extend',
'variables': 'variable'
'variables': 'variable',
'labels': 'label',
}

self.spatial_validations = [
Expand Down Expand Up @@ -694,6 +700,10 @@ def _params(self, request: BaseRequest) -> dict:

if len(subset) > 0:
params['subset'] = subset
if (os.getenv('EXCLUDE_DEFAULT_LABEL') != 'true'):
labels = getattr(params, 'labels', [])
labels.append(DEFAULT_JOB_LABEL)
params['label'] = labels

skipped_params = ['shapefile']
query_params = [pv for pv in request.parameter_values() if pv[0] not in skipped_params]
Expand Down Expand Up @@ -1235,7 +1245,7 @@ def result_urls(self,

def _is_staged_result(self, url: str) -> str:
"""Check if the URL indicates that the data is associated with actual
service ouputs (as opposed to a download link for example).
service outputs (as opposed to a download link for example).
Args:
url: The location (URL) of the file to be downloaded
Expand Down
53 changes: 50 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import responses

from harmony.harmony import BBox, Client, Collection, LinkType, ProcessingFailedException, Dimension
from harmony.harmony import Request, CapabilitiesRequest
from harmony.harmony import Request, CapabilitiesRequest, DEFAULT_JOB_LABEL


@pytest.fixture()
Expand Down Expand Up @@ -94,6 +94,8 @@ def construct_expected_params(query_string):
else:
# Add the key-value pair to the dictionary
expected_params[key] = value
if (os.getenv('EXCLUDE_DEFAULT_LABEL') != 'true'):
expected_params['label'] = DEFAULT_JOB_LABEL
return expected_params

def is_expected_url_and_form_encoded_body(harmony_request, http_request):
Expand Down Expand Up @@ -521,6 +523,52 @@ def test_post_request_has_user_agent_headers(examples_dir):
expected_user_agent_header_regex(), user_agent_header
)

@responses.activate
def test_post_request_has_default_label(examples_dir):
collection = Collection('foobar')
request = Request(
collection=collection,
shape=os.path.join(examples_dir, 'asf_example.json'),
spatial=BBox(-107, 40, -105, 42),
)
responses.add(
responses.POST,
expected_submit_url(collection.id),
status=200,
json=expected_job(collection.id, 'abcd-1234'),
)

Client(should_validate_auth=False).submit(request)
form_data_params = parse_multipart_data(responses.calls[0].request)
label = form_data_params['label']
assert label == DEFAULT_JOB_LABEL

@responses.activate
def test_post_request_can_skip_default_label(examples_dir):
collection = Collection('foobar')
request = Request(
collection=collection,
shape=os.path.join(examples_dir, 'asf_example.json'),
spatial=BBox(-107, 40, -105, 42),
)
responses.add(
responses.POST,
expected_submit_url(collection.id),
status=200,
json=expected_job(collection.id, 'abcd-1234'),
)

origninal_exclude_label = os.getenv('EXCLUDE_DEFAULT_LABEL')

os.environ['EXCLUDE_DEFAULT_LABEL'] = 'true'

Client(should_validate_auth=False).submit(request)
form_data_params = parse_multipart_data(responses.calls[0].request)
assert 'label' not in form_data_params

os.environ['EXCLUDE_DEFAULT_LABEL'] = origninal_exclude_label or ''


@pytest.mark.parametrize('param,expected', [
({'crs': 'epsg:3141'}, 'outputcrs=epsg:3141'),
({'destination_url': 's3://bucket'}, 'destinationUrl=s3://bucket'),
Expand Down Expand Up @@ -1024,7 +1072,6 @@ def test_download_opendap_file():
match=[responses.matchers.urlencoded_params_matcher({"dap4.ce": "/ds_surf_type[0:1:4]"})])
client = Client(should_validate_auth=False)
actual_output = client._download_file(url, overwrite=False)

assert actual_output == expected_filename
with open(expected_filename, 'rb') as temp_file:
data = temp_file.read()
Expand Down Expand Up @@ -1537,7 +1584,7 @@ def test_request_as_url():
)

url = Client(should_validate_auth=False).request_as_url(request)
assert url == 'https://harmony.earthdata.nasa.gov/C1940468263-POCLOUD/ogc-api-coverages/1.0.0/collections/parameter_vars/coverage/rangeset?forceAsync=true&subset=lat%2840%3A42%29&subset=lon%28-107%3A-105%29&variable=all'
assert url == f'https://harmony.earthdata.nasa.gov/C1940468263-POCLOUD/ogc-api-coverages/1.0.0/collections/parameter_vars/coverage/rangeset?forceAsync=true&subset=lat%2840%3A42%29&subset=lon%28-107%3A-105%29&label={DEFAULT_JOB_LABEL}&variable=all'

def test_request_with_shapefile_as_url(examples_dir):
collection = Collection(id='C1940468263-POCLOUD')
Expand Down

0 comments on commit c2c1737

Please sign in to comment.