diff --git a/.hgignore b/.hgignore index ffd82f1..d95b5a7 100644 --- a/.hgignore +++ b/.hgignore @@ -8,3 +8,4 @@ syntax: glob *.gz build/* .cache/* +.pytest_cache/* diff --git a/README.rst b/README.rst index 69c6fd8..67f66f0 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,8 @@ miniuri miniuri is a universal URI parser class. -It is written in 128 lines of Python. +Only 145 lines of Python (400 lines if you count unit tests). + Installation ============ @@ -12,6 +13,7 @@ Installation pip install miniuri + What does it do? ================ @@ -29,6 +31,7 @@ The parser grants access to the following attributes: | | port filename + Tutorial ======== @@ -51,6 +54,7 @@ This example shows how you can set and get any of the URI attributes: >>> print(u.relative_uri) '/path/filename.jpg?p=2#5' + How do I thank you? =================== @@ -67,4 +71,3 @@ Public Revision Control ======================= https://bitbucket.org/russellballestrini/miniuri/overview - diff --git a/miniuri/miniuri.py b/miniuri/miniuri.py index e61588b..b5eaa6a 100644 --- a/miniuri/miniuri.py +++ b/miniuri/miniuri.py @@ -14,7 +14,14 @@ class Uri(object): port filename """ + def _reset_attrs(self): + self.scheme = self.username = self.password = None + self.hostname = self.port = self.path = None + self.filename = self.query = self.fragment = None + self.extension = None + def __init__(self, uri=None): + self._reset_attrs() if uri: self.uri = uri # invoke uri.setter @@ -25,14 +32,16 @@ class Uri(object): def uri(self): """build and return uri from attributes""" scheme = self.scheme + "://" if self.scheme else "" - return "".join([scheme, self.authority, self.relative_uri]) + authority = self.authority if self.authority else "" + return "".join([scheme, authority, self.relative_uri]) @uri.setter def uri(self, uri): """parse and set all uri attributes""" - self.scheme = self.username = self.password = None - self.hostname = self.port = self.path = None - self.filename = self.query = self.fragment = None + self._reset_attrs() + + if uri == "" or uri is None: + return None if "://" in uri: self.scheme, uri = uri.split("://") @@ -52,16 +61,17 @@ class Uri(object): @property def authority(self): """return a authority string from attributes""" - a = "" - if self.username: - a += self.username - if self.password: - a += ":" + self.password - a += "@" - a += self.hostname - if self.port: - a += ":" + self.port - return a + if self.hostname: + a = "" + if self.username: + a += self.username + if self.password: + a += ":" + self.password + a += "@" + a += self.hostname + if self.port: + a += ":" + self.port + return a @authority.setter def authority(self, a): @@ -105,7 +115,8 @@ class Uri(object): """return path""" p = self._path if self._path is not None else "" f = self.filename if self.filename is not None else "" - return p + f + if p or f: + return p + f @path.setter def path(self, new_path): @@ -123,11 +134,9 @@ class Uri(object): if self.extension: return "{}.{}".format(self._filename, self.extension) return self._filename - return "" @filename.setter def filename(self, new_filename): - self.extension = "" if new_filename: self._filename = new_filename.split(".")[0] if "." in new_filename: diff --git a/setup.py b/setup.py index aaa0476..a63ee18 100644 --- a/setup.py +++ b/setup.py @@ -4,7 +4,7 @@ from setuptools import setup, find_packages setup( name="miniuri", - version="1.0.5", + version="1.0.6", long_description=open("README.rst").read(), description="miniuri: The Universal URI Parser", keywords="miniuri uri url parser", diff --git a/test_miniuri.py b/test_miniuri.py index 5bc4831..ae79a87 100644 --- a/test_miniuri.py +++ b/test_miniuri.py @@ -59,9 +59,9 @@ class TestMiniUri(TestCase): self.assertEqual(self.u.password, "pass") self.assertEqual(self.u.hostname, "www.foxhop.net") self.assertEqual(self.u.port, "81") - self.assertEqual(self.u.path, "") - self.assertEqual(self.u.filename, "") - self.assertEqual(self.u.extension, "") + self.assertEqual(self.u.path, None) + self.assertEqual(self.u.filename, None) + self.assertEqual(self.u.extension, None) def test_uri_filename_only_path(self): self.u = Uri("https://fox:pass@www.foxhop.net:81/filename.jpg?p=2#5") @@ -184,3 +184,65 @@ class TestMiniUri(TestCase): def test_relative_uri(self): self.assertEqual(self.u.relative_uri, "/path/filename.jpg?p=2#5") + + def test_empty_uri_sets_attrs_to_none(self): + self.u.uri = "" + self.assertEqual(self.u.uri, "") + self.assertIsNone(self.u.scheme) + self.assertIsNone(self.u.username) + self.assertIsNone(self.u.password) + self.assertIsNone(self.u.hostname) + self.assertIsNone(self.u.port) + self.assertIsNone(self.u.path) + self.assertIsNone(self.u.filename) + self.assertIsNone(self.u.query) + self.assertIsNone(self.u.fragment) + self.assertIsNone(self.u.extension) + self.assertIsNone(self.u.authority) + + def test_empty_uri_sets_attrs_to_none2(self): + # same as above but tests the constructor. + self.u = Uri("") + self.assertEqual(self.u.uri, "") + self.assertIsNone(self.u.scheme) + self.assertIsNone(self.u.username) + self.assertIsNone(self.u.password) + self.assertIsNone(self.u.hostname) + self.assertIsNone(self.u.port) + self.assertIsNone(self.u.path) + self.assertIsNone(self.u.filename) + self.assertIsNone(self.u.query) + self.assertIsNone(self.u.fragment) + self.assertIsNone(self.u.extension) + self.assertIsNone(self.u.authority) + + def test_none_uri_sets_attrs_to_none(self): + self.u.uri = None + self.assertEqual(self.u.uri, "") + self.assertIsNone(self.u.scheme) + self.assertIsNone(self.u.username) + self.assertIsNone(self.u.password) + self.assertIsNone(self.u.hostname) + self.assertIsNone(self.u.port) + self.assertIsNone(self.u.path) + self.assertIsNone(self.u.filename) + self.assertIsNone(self.u.query) + self.assertIsNone(self.u.fragment) + self.assertIsNone(self.u.extension) + self.assertIsNone(self.u.authority) + + def test_none_uri_sets_attrs_to_none2(self): + # same as above but tests the constructor. + self.u = Uri(None) + self.assertEqual(self.u.uri, "") + self.assertIsNone(self.u.scheme) + self.assertIsNone(self.u.username) + self.assertIsNone(self.u.password) + self.assertIsNone(self.u.hostname) + self.assertIsNone(self.u.port) + self.assertIsNone(self.u.path) + self.assertIsNone(self.u.filename) + self.assertIsNone(self.u.query) + self.assertIsNone(self.u.fragment) + self.assertIsNone(self.u.extension) + self.assertIsNone(self.u.authority)