1- from time import time
21import pytest
3- from openml .testing import TestBase , TestAPIBase
4- from openml ._api import ResourceV1API , ResourceV2API , FallbackProxy , ResourceAPI
2+ from requests import Session , Response
3+ from unittest .mock import patch
4+ from openml .testing import TestAPIBase
5+ from openml ._api import FallbackProxy , ResourceAPI
56from openml .enums import ResourceType , APIVersion
67from openml .exceptions import OpenMLNotSupportedError
78
89
9- @pytest .mark .uses_test_server ()
1010class TestResourceAPIBase (TestAPIBase ):
1111 resource : ResourceAPI | FallbackProxy
1212
13- def _publish_and_delete (self ):
14- task_xml = """
15- <oml:task_inputs xmlns:oml="http://openml.org/openml">
16- <oml:task_type_id>5</oml:task_type_id>
17- <oml:input name="source_data">193</oml:input>
18- <oml:input name="estimation_procedure">17</oml:input>
19- </oml:task_inputs>
20- """
21- # publish
22- task_id = self .resource .publish (
23- "task" ,
24- files = {"description" : task_xml },
25- )
26- self .assertIsNotNone (task_id )
27-
28- # cleanup incase of failure
29- TestBase ._mark_entity_for_removal ("task" , task_id )
30- TestBase .logger .info (f"collected from { __file__ } : { task_id } " )
31-
32- # delete
33- success = self .resource .delete (task_id )
34- self .assertTrue (success )
35-
36- def _tag_and_untag (self ):
37- resource_id = 1
38- unique_indicator = str (time ()).replace ("." , "" )
39- tag = f"{ self .__class__ .__name__ } _test_tag_and_untag_{ unique_indicator } "
40-
41- tags = self .resource .tag (resource_id , tag )
42- self .assertIn (tag , tags )
43-
44- tags = self .resource .untag (resource_id , tag )
45- self .assertNotIn (tag , tags )
46-
13+ @property
14+ def http_client (self ):
15+ return self .resource ._http
16+
17+ def _publish (self ):
18+ resource_name = "task"
19+ resource_files = {"description" : """Resource Description File""" }
20+ resource_id = 123
21+
22+ with patch .object (Session , "request" ) as mock_request :
23+ mock_request .return_value = Response ()
24+ mock_request .return_value .status_code = 200
25+ mock_request .return_value ._content = f'<oml:upload_task xmlns:oml="http://openml.org/openml">\n \t <oml:id>{ resource_id } </oml:id>\n </oml:upload_task>\n ' .encode ("utf-8" )
26+
27+ published_resource_id = self .resource .publish (
28+ resource_name ,
29+ files = resource_files ,
30+ )
31+
32+ self .assertEqual (resource_id , published_resource_id )
33+
34+ mock_request .assert_called_once_with (
35+ method = "POST" ,
36+ url = self .http_client .server + self .http_client .base_url + resource_name ,
37+ params = {},
38+ data = {'api_key' : self .http_client .api_key },
39+ headers = self .http_client .headers ,
40+ files = resource_files ,
41+ )
42+
43+ def _delete (self ):
44+ resource_name = "task"
45+ resource_id = 123
46+
47+ with patch .object (Session , "request" ) as mock_request :
48+ mock_request .return_value = Response ()
49+ mock_request .return_value .status_code = 200
50+ mock_request .return_value ._content = f'<oml:task_delete xmlns:oml="http://openml.org/openml">\n <oml:id>{ resource_id } </oml:id>\n </oml:task_delete>\n ' .encode ("utf-8" )
51+
52+ self .resource .delete (resource_id )
53+
54+ mock_request .assert_called_once_with (
55+ method = "DELETE" ,
56+ url = self .http_client .server + self .http_client .base_url + resource_name + "/" + str (resource_id ),
57+ params = {'api_key' : self .http_client .api_key },
58+ data = {},
59+ headers = self .http_client .headers ,
60+ files = None ,
61+ )
62+
63+ def _tag (self ):
64+ resource_id = 123
65+ resource_tag = "TAG"
66+
67+ with patch .object (Session , "request" ) as mock_request :
68+ mock_request .return_value = Response ()
69+ mock_request .return_value .status_code = 200
70+ mock_request .return_value ._content = f'<oml:task_tag xmlns:oml="http://openml.org/openml"><oml:id>{ resource_id } </oml:id><oml:tag>{ resource_tag } </oml:tag></oml:task_tag>' .encode ("utf-8" )
71+
72+ tags = self .resource .tag (resource_id , resource_tag )
73+ self .assertIn (resource_tag , tags )
74+
75+ mock_request .assert_called_once_with (
76+ method = "POST" ,
77+ url = self .http_client .server + self .http_client .base_url + self .resource .resource_type + "/tag" ,
78+ params = {},
79+ data = {'api_key' : self .http_client .api_key , 'task_id' : resource_id , 'tag' : resource_tag },
80+ headers = self .http_client .headers ,
81+ files = None ,
82+ )
83+
84+ def _untag (self ):
85+ resource_id = 123
86+ resource_tag = "TAG"
87+
88+ with patch .object (Session , "request" ) as mock_request :
89+ mock_request .return_value = Response ()
90+ mock_request .return_value .status_code = 200
91+ mock_request .return_value ._content = f'<oml:task_untag xmlns:oml="http://openml.org/openml"><oml:id>{ resource_id } </oml:id></oml:task_untag>' .encode ("utf-8" )
92+
93+ tags = self .resource .untag (resource_id , resource_tag )
94+ self .assertNotIn (resource_tag , tags )
95+
96+ mock_request .assert_called_once_with (
97+ method = "POST" ,
98+ url = self .http_client .server + self .http_client .base_url + self .resource .resource_type + "/untag" ,
99+ params = {},
100+ data = {'api_key' : self .http_client .api_key , 'task_id' : resource_id , 'tag' : resource_tag },
101+ headers = self .http_client .headers ,
102+ files = None ,
103+ )
47104
48105class TestResourceV1API (TestResourceAPIBase ):
49106 def setUp (self ):
@@ -53,11 +110,17 @@ def setUp(self):
53110 resource_type = ResourceType .TASK ,
54111 )
55112
56- def test_publish_and_delete (self ):
57- self ._publish_and_delete ()
113+ def test_publish (self ):
114+ self ._publish ()
115+
116+ def test_delete (self ):
117+ self ._delete ()
58118
59- def test_tag_and_untag (self ):
60- self ._tag_and_untag ()
119+ def test_tag (self ):
120+ self ._tag ()
121+
122+ def test_untag (self ):
123+ self ._untag ()
61124
62125
63126class TestResourceV2API (TestResourceAPIBase ):
@@ -68,16 +131,29 @@ def setUp(self):
68131 resource_type = ResourceType .TASK ,
69132 )
70133
71- def test_publish_and_delete (self ):
134+ def test_publish (self ):
135+ with pytest .raises (OpenMLNotSupportedError ):
136+ self ._publish ()
137+
138+ def test_delete (self ):
139+ with pytest .raises (OpenMLNotSupportedError ):
140+ self ._delete ()
141+
142+ def test_tag (self ):
72143 with pytest .raises (OpenMLNotSupportedError ):
73- self ._tag_and_untag ()
144+ self ._tag ()
74145
75- def test_tag_and_untag (self ):
146+ def test_untag (self ):
76147 with pytest .raises (OpenMLNotSupportedError ):
77- self ._tag_and_untag ()
148+ self ._untag ()
78149
79150
80151class TestResourceFallbackAPI (TestResourceAPIBase ):
152+ @property
153+ def http_client (self ):
154+ # since these methods are not implemented for v2, they will fallback to v1 api
155+ return self .http_clients [APIVersion .V1 ]
156+
81157 def setUp (self ):
82158 super ().setUp ()
83159 resource_v1 = self ._create_resource (
@@ -90,8 +166,14 @@ def setUp(self):
90166 )
91167 self .resource = FallbackProxy (resource_v2 , resource_v1 )
92168
93- def test_publish_and_delete (self ):
94- self ._publish_and_delete ()
169+ def test_publish (self ):
170+ self ._publish ()
171+
172+ def test_delete (self ):
173+ self ._delete ()
174+
175+ def test_tag (self ):
176+ self ._tag ()
95177
96- def test_tag_and_untag (self ):
97- self ._tag_and_untag ()
178+ def test_untag (self ):
179+ self ._untag ()
0 commit comments