Skip to content

Commit a78de8f

Browse files
committed
#645: fix for addressing file/folder by path
1 parent d8addbf commit a78de8f

File tree

7 files changed

+80
-47
lines changed

7 files changed

+80
-47
lines changed

examples/sharepoint/folders/get_by_path.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33

44
ctx = ClientContext(test_team_site_url).with_credentials(test_client_credentials)
55
folder = ctx.web.folders.get_by_path('Shared Documents')
6-
ctx.load(folder, ["Folders"]).execute_query()
6+
ctx.load(folder, ["ServerRelativeUrl", "Folders"]).execute_query()
77
print(folder.serverRelativeUrl)
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""
2+
Resolves web from absolute resource (e.g. page) url
3+
"""
4+
5+
from office365.sharepoint.client_context import ClientContext
6+
from tests import test_team_site_url, test_user_credentials
7+
8+
page_abs_url = "{site_url}/SitePages/Home.aspx".format(site_url=test_team_site_url)
9+
ctx = ClientContext.from_url(page_abs_url).with_credentials(test_user_credentials)
10+
web = ctx.web.get().execute_query()
11+
print(web.url)

office365/runtime/odata/path_builder.py

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -22,45 +22,3 @@ def parse(path_str):
2222
for segment in segments:
2323
path = ResourcePath(segment, path)
2424
return path
25-
26-
@staticmethod
27-
def build(name, parameters=None):
28-
"""
29-
Constructs path segment from operation name and parameters
30-
31-
:type parameters: list or dict or ClientValue
32-
:type name: str
33-
"""
34-
url = name or ""
35-
if isinstance(parameters, ClientValue):
36-
url += "(@v)?@v={0}".format(json.dumps(parameters.to_json()))
37-
elif parameters is not None:
38-
url += "("
39-
if isinstance(parameters, dict):
40-
url += ','.join(['%s=%s' % (key, ODataPathBuilder.encode_method_value(value)) for (key, value) in
41-
parameters.items() if value is not None])
42-
else:
43-
url += ','.join(['%s' % (ODataPathBuilder.encode_method_value(value)) for (i, value) in
44-
enumerate(parameters) if value is not None])
45-
url += ")"
46-
return url
47-
48-
@staticmethod
49-
def encode_method_value(value):
50-
if is_string_type(value):
51-
value = value.replace("'", "''")
52-
53-
# Same replacements as SQL Server
54-
# https://web.archive.org/web/20150101222238/http://msdn.microsoft.com/en-us/library/aa226544(SQL.80).aspx
55-
# https://stackoverflow.com/questions/4229054/how-are-special-characters-handled-in-an-odata-query#answer-45883747
56-
value = value.replace('%', '%25')
57-
value = value.replace('+', '%2B')
58-
value = value.replace('/', '%2F')
59-
value = value.replace('?', '%3F')
60-
value = value.replace('#', '%23')
61-
value = value.replace('&', '%26')
62-
63-
value = "'{0}'".format(value)
64-
elif isinstance(value, bool):
65-
value = str(value).lower()
66-
return value
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import json
2+
3+
from office365.runtime.client_value import ClientValue
4+
from office365.runtime.compat import is_string_type
5+
6+
7+
class ODataUrlBuilder(object):
8+
9+
@staticmethod
10+
def build_segment(path):
11+
"""
12+
Constructs url for path segment
13+
14+
:type path: office365.runtime.paths.service_operation.ServiceOperationPath
15+
"""
16+
url = path.key or ""
17+
if isinstance(path.parameters, ClientValue):
18+
url += "(@v)?@v={0}".format(json.dumps(path.parameters.to_json()))
19+
elif path.parameters is not None:
20+
url += "("
21+
if isinstance(path.parameters, dict):
22+
url += ','.join(['%s=%s' % (key, ODataUrlBuilder._encode_method_value(value)) for (key, value) in
23+
path.parameters.items() if value is not None])
24+
else:
25+
url += ','.join(['%s' % (ODataUrlBuilder._encode_method_value(value)) for (i, value) in
26+
enumerate(path.parameters) if value is not None])
27+
url += ")"
28+
return url
29+
30+
@staticmethod
31+
def _encode_method_value(value):
32+
if is_string_type(value):
33+
value = value.replace("'", "''")
34+
35+
# Same replacements as SQL Server
36+
# https://web.archive.org/web/20150101222238/http://msdn.microsoft.com/en-us/library/aa226544(SQL.80).aspx
37+
# https://stackoverflow.com/questions/4229054/how-are-special-characters-handled-in-an-odata-query#answer-45883747
38+
value = value.replace('%', '%25')
39+
value = value.replace('+', '%2B')
40+
value = value.replace('/', '%2F')
41+
value = value.replace('?', '%3F')
42+
value = value.replace('#', '%23')
43+
value = value.replace('&', '%26')
44+
45+
value = "'{0}'".format(value)
46+
elif isinstance(value, bool):
47+
value = str(value).lower()
48+
return value

office365/runtime/paths/service_operation.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1+
from office365.runtime.odata.url_builder import ODataUrlBuilder
12
from office365.runtime.paths.resource_path import ResourcePath
2-
from office365.runtime.odata.path_builder import ODataPathBuilder
33

44

55
class ServiceOperationPath(ResourcePath):
@@ -16,4 +16,8 @@ def __init__(self, name, parameters=None, parent=None):
1616

1717
@property
1818
def segment(self):
19-
return ODataPathBuilder.build(self._key, self._parameters)
19+
return ODataUrlBuilder.build_segment(self)
20+
21+
@property
22+
def parameters(self):
23+
return self._parameters

office365/runtime/queries/client_query.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ def url(self):
3636
else:
3737
return self.context.service_root_url()
3838

39+
@property
40+
def query_options(self):
41+
return self.binding_type.query_options
42+
3943
@property
4044
def path(self):
4145
if self.binding_type is not None:

office365/runtime/queries/read_entity.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,13 @@ def query_options(self):
1919

2020
@property
2121
def url(self):
22-
orig_url = super(ReadEntityQuery, self).url
23-
return orig_url if self._query_options.is_empty else orig_url + "?" + str(self._query_options)
22+
if not self.query_options.is_empty:
23+
delimiter = "?"
24+
from office365.runtime.paths.service_operation import ServiceOperationPath
25+
from office365.runtime.client_value import ClientValue
26+
if isinstance(self.path, ServiceOperationPath) and isinstance(self.path.parameters, ClientValue):
27+
delimiter = "&"
28+
return self.binding_type.resource_url + delimiter + str(self.query_options)
29+
else:
30+
return self.binding_type.resource_url
31+

0 commit comments

Comments
 (0)