Skip to content

Commit b666c10

Browse files
vvgrem@gmail.comvvgrem@gmail.com
authored andcommitted
SharePoint API: create taxonomy field
1 parent 4da5d3f commit b666c10

File tree

8 files changed

+129
-42
lines changed

8 files changed

+129
-42
lines changed

examples/onedrive/upload_file.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import os
2+
3+
import msal
4+
5+
from office365.graph_client import GraphClient
6+
from settings import settings
7+
8+
9+
def acquire_token():
10+
"""
11+
Acquire token (MSAL)
12+
"""
13+
authority_url = 'https://login.microsoftonline.com/{0}'.format(settings.get('tenant'))
14+
app = msal.ConfidentialClientApplication(
15+
authority=authority_url,
16+
client_id=settings.get('client_credentials').get('client_id'),
17+
client_credential=settings.get('client_credentials').get('client_secret')
18+
)
19+
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])
20+
return result
21+
22+
23+
client = GraphClient(acquire_token)
24+
target_drive = client.users["jdoe@mediadev8.onmicrosoft.com"].drive
25+
26+
local_path = "../../tests/data/SharePoint User Guide.docx"
27+
with open(local_path, 'rb') as f:
28+
file_content = f.read()
29+
file_name = os.path.basename(local_path)
30+
target_file = target_drive.root.upload(file_name, file_content).execute_query()
31+
print(f"File {target_file.web_url} has been uploaded")

examples/sharepoint/files/upload_file.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
from office365.runtime.auth.user_credential import UserCredential
66
from office365.sharepoint.client_context import ClientContext
77

8-
ctx = ClientContext.connect_with_credentials(settings['url'],
9-
UserCredential(settings['user_credentials']['username'],
10-
settings['user_credentials']['password']))
8+
credentials = UserCredential(settings.get('user_credentials').get('username'),
9+
settings.get('user_credentials').get('password'))
10+
ctx = ClientContext(settings.get('url')).with_credentials(credentials)
1111

1212
path = "../../../tests/data/SharePoint User Guide.docx"
1313
with open(path, 'rb') as content_file:
Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import os
2+
13
from settings import settings
24

35
from office365.runtime.auth.user_credential import UserCredential
@@ -8,15 +10,23 @@ def print_upload_progress(offset):
810
print("Uploaded '{0}' bytes...".format(offset))
911

1012

11-
if __name__ == '__main__':
12-
credentials = UserCredential(settings['user_credentials']['username'],
13-
settings['user_credentials']['password'])
14-
ctx = ClientContext(settings['url']).with_credentials(credentials)
13+
credentials = UserCredential(settings['user_credentials']['username'],
14+
settings['user_credentials']['password'])
15+
ctx = ClientContext(settings['url']).with_credentials(credentials)
16+
17+
target_url = "/Shared Documents"
18+
target_folder = ctx.web.get_folder_by_server_relative_url(target_url)
19+
size_chunk = 1000000
20+
local_path = "../../../tests/data/big_buck_bunny.mp4"
21+
# local_path = "../../../tests/data/SharePoint User Guide.docx"
22+
file_size = os.path.getsize(local_path)
1523

16-
size_1Mb = 1000000
17-
local_path = "../../../tests/data/big_buck_bunny.mp4"
18-
target_url = "/Shared Documents"
19-
result_file = ctx.web.get_folder_by_server_relative_url(target_url) \
20-
.files.create_upload_session(local_path, size_1Mb, print_upload_progress)
21-
ctx.execute_query()
22-
print('File {0} has been uploaded successfully'.format(result_file.serverRelativeUrl))
24+
if file_size > size_chunk:
25+
result_file = target_folder.files.create_upload_session(local_path, size_chunk, print_upload_progress)
26+
else:
27+
with open(local_path, 'rb') as content_file:
28+
file_content = content_file.read()
29+
name = os.path.basename(local_path)
30+
result_file = target_folder.upload_file(name, file_content)
31+
ctx.execute_query()
32+
print('File {0} has been uploaded successfully'.format(result_file.serverRelativeUrl))

office365/sharepoint/fields/field.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ def __init__(self, context, resource_path=None):
1212
super().__init__(context, resource_path)
1313

1414
@staticmethod
15-
def resolve_field_type(type_id):
15+
def resolve_field_type(type_id_or_name):
1616
from office365.sharepoint.fields.field_calculated import FieldCalculated
1717
from office365.sharepoint.fields.field_choice import FieldChoice
1818
from office365.sharepoint.fields.field_computed import FieldComputed
@@ -24,7 +24,8 @@ def resolve_field_type(type_id):
2424
from office365.sharepoint.fields.field_text import FieldText
2525
from office365.sharepoint.fields.field_url import FieldUrl
2626
from office365.sharepoint.fields.field_user import FieldUser
27-
field_types = {
27+
from office365.sharepoint.taxonomy.taxonomyField import TaxonomyField
28+
field_known_types = {
2829
FieldType.Text: FieldText,
2930
FieldType.Calculated: FieldCalculated,
3031
FieldType.Choice: FieldChoice,
@@ -37,7 +38,10 @@ def resolve_field_type(type_id):
3738
FieldType.Currency: FieldCurrency,
3839
FieldType.Note: FieldMultiLineText
3940
}
40-
return field_types.get(type_id, Field)
41+
if isinstance(type_id_or_name, int):
42+
return field_known_types.get(type_id_or_name, Field)
43+
else:
44+
return TaxonomyField if type_id_or_name == "TaxonomyFieldType" else Field
4145

4246
@staticmethod
4347
def create_field_from_type(context, field_type):
@@ -51,6 +55,7 @@ def set_show_in_display_form(self, flag):
5155
"""
5256
qry = ServiceOperationQuery(self, "setShowInDisplayForm", [flag])
5357
self.context.add_query(qry)
58+
return self
5459

5560
def set_show_in_edit_form(self, flag):
5661
"""Sets the value of the ShowInEditForm property for this fields.
@@ -88,4 +93,6 @@ def set_property(self, name, value, persist_changes=True):
8893
"getById", [value], self._parent_collection.resource_path)
8994
if name == "FieldTypeKind":
9095
self.__class__ = self.resolve_field_type(value)
96+
elif name == "TypeAsString" and self.properties.get('FieldTypeKind', 0) == 0:
97+
self.__class__ = self.resolve_field_type(value)
9198
return self

office365/sharepoint/fields/field_collection.py

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -44,29 +44,47 @@ def create_taxonomy_field(self, name, ssp_id, term_set_id, anchor_id="00000000-0
4444
"web_id": web_id,
4545
"target_field": target_field
4646
}
47-
4847
if field_id is None:
4948
field_params["field_id"] = str(uuid.uuid1())
5049

51-
from office365.sharepoint.lists.list import List
52-
if isinstance(self._parent, List):
53-
parent_list = self._parent
54-
55-
def _list_loaded():
56-
field_params["web_id"] = parent_list.parentWeb.properties["Id"]
57-
field_params["list_id"] = parent_list.properties["Id"]
58-
self._create_taxonomy_field_query(**field_params)
59-
self._parent.ensure_properties(["Id", "ParentWeb"], _list_loaded)
50+
def _create_taxonomy_field_inner():
51+
from office365.sharepoint.lists.list import List
52+
if isinstance(self._parent, List):
53+
parent_list = self._parent
54+
55+
def _list_loaded():
56+
field_params["web_id"] = parent_list.parentWeb.properties["Id"]
57+
field_params["list_id"] = parent_list.properties["Id"]
58+
self._build_taxonomy_field_query(**field_params)
59+
self._parent.ensure_properties(["Id", "ParentWeb"], _list_loaded)
60+
else:
61+
62+
def _web_loaded():
63+
field_params["web_id"] = self.context.web.properties["Id"]
64+
self._build_taxonomy_field_query(**field_params)
65+
self.context.web.ensure_property("Id", _web_loaded)
66+
67+
if text_field_id is None:
68+
text_field_name = f"{uuid.uuid4().hex}"
69+
text_field_schema = f'''
70+
<Field Type="Note" DisplayName="{name}_0" Hidden="TRUE" CanBeDeleted="TRUE" ShowInViewForms="FALSE"
71+
StaticName="{text_field_name}" Name="{text_field_name}">
72+
</Field>
73+
'''
74+
text_field = self.create_field_as_xml(text_field_schema)
75+
76+
def _after_text_field_created(resp):
77+
field_params["text_field_id"] = text_field.properties["Id"]
78+
_create_taxonomy_field_inner()
79+
self.context.after_execute(_after_text_field_created, True)
6080
else:
61-
def _web_loaded():
62-
field_params["web_id"] = self.context.web.properties["Id"]
63-
self._create_taxonomy_field_query(**field_params)
64-
self.context.web.ensure_property("Id", _web_loaded)
81+
_create_taxonomy_field_inner()
82+
6583
return target_field
6684

67-
def _create_taxonomy_field_query(self, name, ssp_id, term_set_id, anchor_id,
68-
field_id=None, text_field_id=None, web_id=None, list_id=None,
69-
target_field=None):
85+
def _build_taxonomy_field_query(self, name, ssp_id, term_set_id, anchor_id,
86+
field_id=None, text_field_id=None, web_id=None, list_id=None,
87+
target_field=None):
7088
"""
7189
7290
:param str text_field_id: Text Field Id
@@ -199,6 +217,7 @@ def _create_field_as_xml_query(self, schema_xml, field):
199217
self.add_child(field)
200218
qry = ServiceOperationQuery(self, "CreateFieldAsXml", None, schema_xml, "parameters", field)
201219
self.context.add_query(qry)
220+
return field
202221

203222
def get_by_id(self, _id):
204223
"""Gets the fields with the specified ID."""

office365/sharepoint/fields/field_creation_information.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ def __init__(self, title, field_type_kind, description=None):
1111
Represents metadata about fields creation.
1212
1313
:type title: str
14+
:type field_type_kind: int
15+
:type description: str or None
1416
"""
1517
super(FieldCreationInformation, self).__init__()
1618
self.Title = title

tests/sharepoint/test_field.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ def test_1_get_site_fields(self):
1717
self.assertGreater(len(site_fields), 0)
1818

1919
def test_2_get_field(self):
20-
title_field = self.client.site.rootWeb.fields.get_by_internal_name_or_title(self.target_field_name)
21-
self.client.load(title_field)
22-
self.client.execute_query()
20+
title_field = self.client.site.rootWeb.fields.\
21+
get_by_internal_name_or_title(self.target_field_name).get().execute_query()
2322
self.assertIsNotNone(title_field.internal_name)
2423
self.assertEqual(title_field.internal_name, self.target_field_name)
2524
self.assertIsInstance(title_field, FieldText)

tests/sharepoint/test_taxonomy.py

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
from office365.sharepoint.taxonomy.taxonomyField import TaxonomyField
2+
13
from tests.sharepoint.sharepoint_case import SPTestCase
24

35
from office365.sharepoint.fields.field import Field
46

57

68
class TestSPTaxonomy(SPTestCase):
7-
8-
target_field = None # type: Field
9+
target_field = None # type: Field
910

1011
@classmethod
1112
def setUpClass(cls):
@@ -15,19 +16,37 @@ def setUpClass(cls):
1516
def tearDownClass(cls):
1617
pass
1718

18-
def test1_create_taxonomy_field(self):
19+
def test1_create_list_tax_field(self):
1920
ssp_id = "f02be691-d551-462f-aaae-e1c89168cd0b"
2021
term_set_id = "b49f64b3-4722-4336-9a5c-56c326b344d4"
2122
text_field_id = "cd790052-00e3-4317-a090-365cd85795b6"
2223
# list_id = "b9b8e2ef-6f9a-400b-a218-6a4899ea0121"
2324
# web_id = "cd5c86f3-261c-4d3a-8a91-34d6392cdfb9"
24-
tax_field = self.client.web.default_document_library().fields\
25+
tax_field = self.client.web.default_document_library().fields \
2526
.create_taxonomy_field(name="Category",
2627
ssp_id=ssp_id,
2728
term_set_id=term_set_id,
2829
text_field_id=text_field_id).execute_query()
2930
self.assertIsNotNone(tax_field.resource_path)
3031
self.__class__.target_field = tax_field
3132

32-
def test2_delete_taxonomy_field(self):
33+
def test2_get_tax_field(self):
34+
existing_field = self.__class__.target_field.get().execute_query()
35+
self.assertTrue(existing_field.properties.get('TypeAsString'), 'TaxonomyFieldType')
36+
self.assertIsInstance(existing_field, TaxonomyField)
37+
self.assertIsNotNone(existing_field.properties.get('TextField'))
38+
self.assertIsNotNone(existing_field.properties.get('LookupList'))
39+
self.assertIsNotNone(existing_field.properties.get('LookupWebId'))
40+
41+
text_field_id = existing_field.properties.get('TextField')
42+
text_field = self.client.web.default_document_library().fields.get_by_id(text_field_id)
43+
self.client.load(text_field)
44+
self.client.execute_batch()
45+
self.assertIsNotNone(text_field.internal_name)
46+
47+
def test3_delete_tax_field(self):
3348
self.__class__.target_field.delete_object().execute_query()
49+
50+
# text_field_id = self.__class__.target_field.properties.get('TextField')
51+
# text_field = self.client.web.default_document_library().fields.get_by_id(text_field_id)
52+
# self.assertIsNotNone(text_field.resource_path)

0 commit comments

Comments
 (0)