18
18
SET_ATTRIBUTES = frozenset (URL_ATTRIBUTES )
19
19
20
20
21
+ def _get_urlobj (constructor , * args ):
22
+ urlobj = constructor (* args )
23
+
24
+ return ffi .gc (urlobj , lib .ada_free )
25
+
26
+
21
27
def _get_str (x ):
22
28
ret = ffi .string (x .data , x .length ).decode ('utf-8' ) if x .length else ''
23
29
return ret
@@ -32,19 +38,14 @@ class URL:
32
38
33
39
>>> from ada_url import URL
34
40
>>> old_url = 'https://example.org:443/file.txt?q=1'
35
- >>> with URL(old_url) as urlobj:
36
- ... old_host = urlobj.host
37
- ... urlobj.host = 'example.com'
38
- ... new_url = urlobj.href
39
- >>> old_host
41
+ >>> urlobj = URL(old_url)
42
+ >>> urlobj.host
40
43
'example.org'
44
+ >>> urlobj.host = 'example.com'
45
+ >>> new_url = urlobj.href
41
46
>>> new_url
42
47
'https://example.com:443/file.txt?q=1'
43
48
44
- Note that you should use this class as a context manager to ensure
45
- that resources are freed. If you use it without a ``with``
46
- statement, call the ``close()`` method manually.
47
-
48
49
You can read and write the following attributes:
49
50
50
51
* ``href``
@@ -78,11 +79,15 @@ def __init__(self, url, base=None):
78
79
url_bytes = url .encode ('utf-8' )
79
80
80
81
if base is None :
81
- self .urlobj = lib .ada_parse ( url_bytes , len (url_bytes ))
82
+ self .urlobj = _get_urlobj ( lib .ada_parse , url_bytes , len (url_bytes ))
82
83
else :
83
84
base_bytes = base .encode ('utf-8' )
84
- self .urlobj = lib .ada_parse_with_base (
85
- url_bytes , len (url_bytes ), base_bytes , len (base_bytes )
85
+ self .urlobj = _get_urlobj (
86
+ lib .ada_parse_with_base ,
87
+ url_bytes ,
88
+ len (url_bytes ),
89
+ base_bytes ,
90
+ len (base_bytes ),
86
91
)
87
92
88
93
if not lib .ada_is_valid (self .urlobj ):
@@ -119,15 +124,6 @@ def __setattr__(self, attr, value):
119
124
120
125
return super ().__setattr__ (attr , value )
121
126
122
- def close (self ):
123
- lib .ada_free (self .urlobj )
124
-
125
- def __enter__ (self , * args , ** kwargs ):
126
- return self
127
-
128
- def __exit__ (self , * args , ** kwargs ):
129
- self .close ()
130
-
131
127
@staticmethod
132
128
def can_parse (url , base = None ):
133
129
try :
@@ -166,11 +162,8 @@ def check_url(s):
166
162
except Exception :
167
163
return False
168
164
169
- urlobj = lib .ada_parse (s_bytes , len (s_bytes ))
170
- try :
171
- return lib .ada_is_valid (urlobj )
172
- finally :
173
- lib .ada_free (urlobj )
165
+ urlobj = _get_urlobj (lib .ada_parse , s_bytes , len (s_bytes ))
166
+ return lib .ada_is_valid (urlobj )
174
167
175
168
176
169
def join_url (base_url , s ):
@@ -192,14 +185,13 @@ def join_url(base_url, s):
192
185
except Exception :
193
186
raise ValueError ('Invalid URL' ) from None
194
187
195
- urlobj = lib .ada_parse_with_base (s_bytes , len (s_bytes ), base_bytes , len (base_bytes ))
196
- try :
197
- if not lib .ada_is_valid (urlobj ):
198
- raise ValueError ('Invalid URL' ) from None
188
+ urlobj = _get_urlobj (
189
+ lib .ada_parse_with_base , s_bytes , len (s_bytes ), base_bytes , len (base_bytes )
190
+ )
191
+ if not lib .ada_is_valid (urlobj ):
192
+ raise ValueError ('Invalid URL' ) from None
199
193
200
- return _get_str (lib .ada_get_href (urlobj ))
201
- finally :
202
- lib .ada_free (urlobj )
194
+ return _get_str (lib .ada_get_href (urlobj ))
203
195
204
196
205
197
def normalize_url (s ):
@@ -260,19 +252,16 @@ def parse_url(s, attributes=PARSE_ATTRIBUTES):
260
252
raise ValueError ('Invalid URL' ) from None
261
253
262
254
ret = {}
263
- urlobj = lib .ada_parse (s_bytes , len (s_bytes ))
264
- try :
265
- if not lib .ada_is_valid (urlobj ):
266
- raise ValueError ('Invalid URL' ) from None
255
+ urlobj = _get_urlobj (lib .ada_parse , s_bytes , len (s_bytes ))
256
+ if not lib .ada_is_valid (urlobj ):
257
+ raise ValueError ('Invalid URL' ) from None
267
258
268
- for attr in attributes :
269
- get_func = getattr (lib , f'ada_get_{ attr } ' )
270
- data = get_func (urlobj )
271
- ret [attr ] = _get_str (data )
272
- if attr == 'origin' :
273
- lib .ada_free_owned_string (data )
274
- finally :
275
- lib .ada_free (urlobj )
259
+ for attr in attributes :
260
+ get_func = getattr (lib , f'ada_get_{ attr } ' )
261
+ data = get_func (urlobj )
262
+ ret [attr ] = _get_str (data )
263
+ if attr == 'origin' :
264
+ lib .ada_free_owned_string (data )
276
265
277
266
return ret
278
267
@@ -300,26 +289,23 @@ def replace_url(s, **kwargs):
300
289
except Exception :
301
290
raise ValueError ('Invalid URL' ) from None
302
291
303
- urlobj = lib .ada_parse (s_bytes , len (s_bytes ))
304
- try :
305
- if not lib .ada_is_valid (urlobj ):
306
- raise ValueError ('Invalid URL' ) from None
292
+ urlobj = _get_urlobj (lib .ada_parse , s_bytes , len (s_bytes ))
293
+ if not lib .ada_is_valid (urlobj ):
294
+ raise ValueError ('Invalid URL' ) from None
307
295
308
- for attr in URL_ATTRIBUTES :
309
- value = kwargs .get (attr )
310
- if value is None :
311
- continue
296
+ for attr in URL_ATTRIBUTES :
297
+ value = kwargs .get (attr )
298
+ if value is None :
299
+ continue
312
300
313
- try :
314
- value_bytes = value .encode ()
315
- except Exception :
316
- raise ValueError (f'Invalid value for { attr } ' ) from None
301
+ try :
302
+ value_bytes = value .encode ()
303
+ except Exception :
304
+ raise ValueError (f'Invalid value for { attr } ' ) from None
317
305
318
- set_func = getattr (lib , f'ada_set_{ attr } ' )
319
- set_result = set_func (urlobj , value_bytes , len (value_bytes ))
320
- if (set_result is not None ) and (not set_result ):
321
- raise ValueError (f'Invalid value for { attr } ' ) from None
306
+ set_func = getattr (lib , f'ada_set_{ attr } ' )
307
+ set_result = set_func (urlobj , value_bytes , len (value_bytes ))
308
+ if (set_result is not None ) and (not set_result ):
309
+ raise ValueError (f'Invalid value for { attr } ' ) from None
322
310
323
- return _get_str (lib .ada_get_href (urlobj ))
324
- finally :
325
- lib .ada_free (urlobj )
311
+ return _get_str (lib .ada_get_href (urlobj ))
0 commit comments