1818SET_ATTRIBUTES = frozenset (URL_ATTRIBUTES )
1919
2020
21+ def _get_urlobj (constructor , * args ):
22+ urlobj = constructor (* args )
23+
24+ return ffi .gc (urlobj , lib .ada_free )
25+
26+
2127def _get_str (x ):
2228 ret = ffi .string (x .data , x .length ).decode ('utf-8' ) if x .length else ''
2329 return ret
@@ -32,19 +38,14 @@ class URL:
3238
3339 >>> from ada_url import URL
3440 >>> 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
4043 'example.org'
44+ >>> urlobj.host = 'example.com'
45+ >>> new_url = urlobj.href
4146 >>> new_url
4247 'https://example.com:443/file.txt?q=1'
4348
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-
4849 You can read and write the following attributes:
4950
5051 * ``href``
@@ -78,11 +79,15 @@ def __init__(self, url, base=None):
7879 url_bytes = url .encode ('utf-8' )
7980
8081 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 ))
8283 else :
8384 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 ),
8691 )
8792
8893 if not lib .ada_is_valid (self .urlobj ):
@@ -119,15 +124,6 @@ def __setattr__(self, attr, value):
119124
120125 return super ().__setattr__ (attr , value )
121126
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-
131127 @staticmethod
132128 def can_parse (url , base = None ):
133129 try :
@@ -166,11 +162,8 @@ def check_url(s):
166162 except Exception :
167163 return False
168164
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 )
174167
175168
176169def join_url (base_url , s ):
@@ -192,14 +185,13 @@ def join_url(base_url, s):
192185 except Exception :
193186 raise ValueError ('Invalid URL' ) from None
194187
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
199193
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 ))
203195
204196
205197def normalize_url (s ):
@@ -260,19 +252,16 @@ def parse_url(s, attributes=PARSE_ATTRIBUTES):
260252 raise ValueError ('Invalid URL' ) from None
261253
262254 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
267258
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 )
276265
277266 return ret
278267
@@ -300,26 +289,23 @@ def replace_url(s, **kwargs):
300289 except Exception :
301290 raise ValueError ('Invalid URL' ) from None
302291
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
307295
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
312300
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
317305
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
322310
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