Skip to content

Commit 44c083c

Browse files
authored
Merge pull request #63 from berislavlopac/28-builder-from-uri
implement from_uri to create builder
2 parents 76e8ffb + 6455dfc commit 44c083c

File tree

4 files changed

+58
-1
lines changed

4 files changed

+58
-1
lines changed

docs/source/api-ref/builder.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
.. autoclass:: rfc3986.builder.URIBuilder
66

7+
.. automethod:: rfc3986.builder.URIBuilder.from_uri
8+
79
.. automethod:: rfc3986.builder.URIBuilder.add_scheme
810

911
.. automethod:: rfc3986.builder.URIBuilder.add_credentials

docs/source/user/building.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,17 @@ a :class:`~rfc3986.uri.URIReference` and call
4242
... ).finalize().unsplit())
4343
https://github.com
4444

45+
It is possible to update an existing URI by constructing a builder from an
46+
instance of :class:`~rfc3986.uri.URIReference` or a textual representation:
47+
48+
.. doctest::
49+
50+
>>> from rfc3986 import builder
51+
>>> print(builder.URIBuilder.from_uri("http://github.com").add_scheme(
52+
... 'https'
53+
... ).finalize().unsplit())
54+
https://github.com
55+
4556
Each time you invoke a method, you get a new instance of a
4657
:class:`~rfc3986.builder.URIBuilder` class so you can build several different
4758
URLs from one base instance.

src/rfc3986/builder.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from . import compat
1717
from . import normalizers
1818
from . import uri
19+
from . import uri_reference
1920

2021

2122
class URIBuilder(object):
@@ -63,6 +64,26 @@ def __repr__(self):
6364
'query={b.query}, fragment={b.fragment})')
6465
return formatstr.format(b=self)
6566

67+
@classmethod
68+
def from_uri(cls, reference):
69+
"""Initialize the URI builder from another URI.
70+
71+
Takes the given URI reference and creates a new URI builder instance
72+
populated with the values from the reference. If given a string it will
73+
try to convert it to a reference before constructing the builder.
74+
"""
75+
if not isinstance(reference, uri.URIReference):
76+
reference = uri_reference(reference)
77+
return cls(
78+
scheme=reference.scheme,
79+
userinfo=reference.userinfo,
80+
host=reference.host,
81+
port=reference.port,
82+
path=reference.path,
83+
query=reference.query,
84+
fragment=reference.fragment
85+
)
86+
6687
def add_scheme(self, scheme):
6788
"""Add a scheme to our builder object.
6889

tests/test_builder.py

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"""Module containing the tests for the URIBuilder object."""
1616
import pytest
1717

18-
from rfc3986 import builder
18+
from rfc3986 import builder, uri_reference
1919

2020

2121
def test_builder_default():
@@ -30,6 +30,29 @@ def test_builder_default():
3030
assert uribuilder.fragment is None
3131

3232

33+
def test_from_uri_reference():
34+
uri = uri_reference("http://foo.bar:1234/baz")
35+
uribuilder = builder.URIBuilder().from_uri(uri)
36+
assert uribuilder.scheme == 'http'
37+
assert uribuilder.userinfo is None
38+
assert uribuilder.host == 'foo.bar'
39+
assert uribuilder.port == '1234'
40+
assert uribuilder.path == '/baz'
41+
assert uribuilder.query is None
42+
assert uribuilder.fragment is None
43+
44+
45+
def test_from_uri_string():
46+
uribuilder = builder.URIBuilder().from_uri("https://bar.foo:4321/boom")
47+
assert uribuilder.scheme == 'https'
48+
assert uribuilder.userinfo is None
49+
assert uribuilder.host == 'bar.foo'
50+
assert uribuilder.port == '4321'
51+
assert uribuilder.path == '/boom'
52+
assert uribuilder.query is None
53+
assert uribuilder.fragment is None
54+
55+
3356
def test_repr():
3457
"""Verify our repr looks like our class."""
3558
uribuilder = builder.URIBuilder()

0 commit comments

Comments
 (0)