Skip to content

Commit 48e43cf

Browse files
Generator improvements
1 parent a1e0e72 commit 48e43cf

24 files changed

+254
-148
lines changed

Diff for: generator/__init__.py

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import os
2+
from configparser import ConfigParser
3+
4+
5+
def load_settings():
6+
cp = ConfigParser()
7+
root_dir = os.path.dirname(os.path.abspath(__file__))
8+
config_file = os.path.join(root_dir, 'settings.cfg')
9+
cp.read(config_file)
10+
return cp

Diff for: generator/builders/method_builder.py

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import ast
2+
3+
4+
class MethodBuilder(ast.NodeTransformer):
5+
pass

Diff for: generator/builders/template_context.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
class TemplateContext:
22
def __init__(self, template_path):
3+
"""
4+
:type template_path: str
5+
"""
36
self._template_path = template_path
47

58
def build(self, schema):

Diff for: generator/builders/type_builder.py

+62-23
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,86 @@
11
import ast
22
import os
3-
3+
from os.path import abspath
4+
from pydoc import locate
45

56
import astunparse
67

78

89
class TypeBuilder(ast.NodeTransformer):
910

10-
def __init__(self, options):
11-
self._schema = None
11+
def __init__(self, type_schema, options):
12+
"""
13+
:type type_schema: office365.runtime.odata.odata_type.ODataType
14+
:type options: dict
15+
"""
16+
self._schema = type_schema
1217
self._options = options
18+
self._type_info = None
19+
self._source_tree = None
20+
self._status = None
1321

1422
def generic_visit(self, node):
1523
if isinstance(node, ast.ClassDef):
16-
node.name = self._schema["name"].title()
24+
node.name = self._schema.name.title()
1725
ast.NodeVisitor.generic_visit(self, node)
1826

19-
def build(self, schema):
20-
result = dict(status=None, output_file=None, source_tree=None)
21-
if schema['state'] == 'attached':
22-
result["output_file"] = schema['file']
23-
with open(schema['file']) as f:
24-
result["source_tree"] = ast.parse(f.read())
25-
result["status"] = "updated"
27+
def build(self):
28+
if self.state == 'attached':
29+
with open(self.file) as f:
30+
self._source_tree = ast.parse(f.read())
31+
self._status = "updated"
2632
else:
27-
template_file = self._resolve_template_file(schema['baseType'])
28-
result["output_file"] = os.path.join(self._options['outputPath'], schema["name"] + ".py")
33+
template_file = self._resolve_template_file(self._schema.baseType)
2934
with open(template_file) as f:
30-
result["source_tree"] = ast.parse(f.read())
31-
result["status"] = "created"
32-
self._schema = schema
33-
self.visit(result["source_tree"])
34-
return result
35-
36-
def save(self, result):
37-
code = astunparse.unparse(result["source_tree"])
38-
with open(result["output_file"], 'w') as f:
35+
self._source_tree = ast.parse(f.read())
36+
self._status = "created"
37+
self.visit(self._source_tree)
38+
return self
39+
40+
def save(self):
41+
code = astunparse.unparse(self._source_tree)
42+
with open(self.file, 'w') as f:
3943
f.write(code)
4044

4145
def _resolve_template_file(self, type_name):
4246
file_mapping = {
4347
"ComplexType": "complex_type.py",
4448
"EntityType": "entity_type.py"
4549
}
46-
path = os.path.join(self._options['templatePath'], file_mapping[type_name])
50+
path = abspath(os.path.join(self._options['templatePath'], file_mapping[type_name]))
4751
return path
52+
53+
def _resolve_type(self, type_name):
54+
"""
55+
:type type_name: str
56+
"""
57+
type_info = {}
58+
namespaces = ['directory', 'onedrive', 'mail', 'teams']
59+
types = [locate("office365.{0}.{1}".format(ns, type_name)) for ns in namespaces]
60+
found_modules = [t for t in types if t is not None]
61+
if any(found_modules):
62+
type_info['state'] = 'attached'
63+
type_info['file'] = found_modules[0].__file__
64+
else:
65+
type_info['state'] = 'detached'
66+
type_info['file'] = abspath(os.path.join(self._options['outputPath'], type_name + ".py"))
67+
return type_info
68+
69+
def _ensure_type_info(self):
70+
if self._type_info is None:
71+
self._type_info = self._resolve_type(self._schema.name)
72+
return self._type_info
73+
74+
@property
75+
def state(self):
76+
self._ensure_type_info()
77+
return self._type_info['state']
78+
79+
@property
80+
def file(self):
81+
self._ensure_type_info()
82+
return self._type_info['file']
83+
84+
@property
85+
def status(self):
86+
return self._status

Diff for: generator/generate.py

+20-25
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,36 @@
1+
from generator import load_settings
12
from generator.builders.type_builder import TypeBuilder
23

34
from office365.runtime.odata.odata_v3_reader import ODataV3Reader
45
from office365.runtime.odata.odata_v4_reader import ODataV4Reader
56

67

78
def generate_files(model, options):
9+
"""
10+
:type model: office365.runtime.odata.odata_model.ODataModel
11+
:type options: ConfigParser
12+
"""
813
for name in model.types:
914
type_schema = model.types[name]
10-
builder = TypeBuilder(options)
11-
result = builder.build(type_schema)
12-
if result["status"] == "created":
13-
builder.save(result)
14-
15-
16-
def generate_sharepoint_model():
17-
generator_options = {
18-
'namespace': 'office365.sharepoint',
19-
'metadataPath': './metadata/SharePoint.xml',
20-
'outputPath': '/office365/sharepoint',
21-
'templatePath': '/generator/templates',
22-
}
23-
reader = ODataV3Reader(generator_options)
15+
builder = TypeBuilder(type_schema, options)
16+
builder.build()
17+
if builder.status == "created":
18+
builder.save()
19+
20+
21+
def generate_sharepoint_model(settings):
22+
reader = ODataV3Reader(settings.get('sharepoint', 'metadataPath'))
2423
model = reader.generate_model()
25-
generate_files(model, generator_options)
24+
generate_files(model, settings)
2625

2726

28-
def generate_graph_model():
29-
options = {
30-
'namespace': 'office365',
31-
'metadataPath': './metadata/MicrosoftGraph.xml',
32-
'outputPath': '../office365',
33-
'templatePath': '../generator/templates',
34-
}
35-
reader = ODataV4Reader(options)
27+
def generate_graph_model(settings):
28+
reader = ODataV4Reader(settings.get('microsoftgraph', 'metadataPath'))
3629
model = reader.generate_model()
37-
generate_files(model, options)
30+
generate_files(model, settings)
3831

3932

4033
if __name__ == '__main__':
41-
generate_graph_model()
34+
generator_settings = load_settings()
35+
# generate_graph_model(settings)
36+
generate_sharepoint_model(generator_settings)

Diff for: generator/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
astunparse==1.6.3

Diff for: generator/settings.cfg

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[microsoftgraph]
2+
namespace = office365
3+
metadataPath = ./metadata/MicrosoftGraph.xml
4+
outputPath = ../office365
5+
templatePath: ../generator/templates
6+
7+
8+
[sharepoint]
9+
namespace = 'office365.sharepoint
10+
metadataPath = ./metadata/SharePoint.xml
11+
outputPath = ../office365/sharepoint
12+
templatePath = ./templates

Diff for: office365/actions/search_query.py

+18-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
1+
from office365.runtime.client_result import ClientResult
2+
from office365.runtime.http.http_method import HttpMethod
13
from office365.runtime.queries.service_operation_query import ServiceOperationQuery
24

35

4-
class SearchQuery(ServiceOperationQuery):
5-
def __init__(self, entity_type, query_text, return_type):
6-
super(SearchQuery, self).__init__(entity_type, "search", {"q": query_text}, None, None, return_type)
6+
def create_search_query(drive_item, query_text):
7+
"""
8+
9+
:param office365.onedrive.driveItem.DriveItem drive_item:
10+
:param str query_text:
11+
"""
12+
result = ClientResult(drive_item.context)
13+
qry = ServiceOperationQuery(drive_item, "search", {"q": query_text}, None, None, result)
14+
15+
def _construct_query(request):
16+
"""
17+
:type request: office365.runtime.http.request_options.RequestOptions
18+
"""
19+
request.method = HttpMethod.Get
20+
drive_item.context.before_execute(_construct_query)
21+
return qry

Diff for: office365/directory/user.py

+3
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,9 @@ def get_calendar_view(self, start_dt, end_dt):
106106
self.context.add_query(qry)
107107

108108
def _construct_request(request):
109+
"""
110+
:type request: office365.runtime.http.request_options.RequestOptions
111+
"""
109112
request.method = HttpMethod.Get
110113
request.url += "?startDateTime={0}&endDateTime={1}".format(start_dt.isoformat(), end_dt.isoformat())
111114

Diff for: office365/entity.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def delete_object(self):
2323
@property
2424
def context(self):
2525
"""
26-
:rtype: office365.graph.graph_client.GraphClient
26+
:rtype: office365.graph_client.GraphClient
2727
"""
2828
return self._context
2929

Diff for: office365/entity_collection.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ def __getitem__(self, key):
1717
return super(EntityCollection, self).__getitem__(key)
1818
return self._item_type(self.context, ResourcePath(key, self.resource_path))
1919

20-
def add_from_json(self, params):
20+
def add_from_json(self, json):
2121
"""Creates a Entity resource from JSON
2222
23-
:type params: dict
23+
:type json: dict
2424
:rtype: office365.entity.Entity
2525
"""
26-
entity_object = self._item_type(self.context)
27-
self.add_child(entity_object)
28-
qry = CreateEntityQuery(self, params, entity_object)
26+
entity = self._item_type(self.context)
27+
self.add_child(entity)
28+
qry = CreateEntityQuery(self, json, entity)
2929
self.context.add_query(qry)
30-
return entity_object
30+
return entity
3131

3232
@property
3333
def context(self):

Diff for: office365/graph_client.py

-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
from office365.actions.download_content_query import DownloadContentQuery
2-
from office365.actions.search_query import SearchQuery
32
from office365.actions.upload_content_query import UploadContentQuery
43
from office365.directory.applicationCollection import ApplicationCollection
54
from office365.directory.directory import Directory
@@ -81,8 +80,6 @@ def _build_specific_query(self, request):
8180
request.method = HttpMethod.Get
8281
elif isinstance(query, UploadContentQuery):
8382
request.method = HttpMethod.Put
84-
elif isinstance(query, SearchQuery):
85-
request.method = HttpMethod.Get
8683

8784
def authenticate_request(self, request):
8885
"""

Diff for: office365/onedrive/driveItem.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from office365.actions.search_query import SearchQuery
1+
from office365.actions.search_query import create_search_query
22
from office365.base_item import BaseItem
33
from office365.directory.permission import Permission
44
from office365.directory.permission_collection import PermissionCollection
@@ -248,11 +248,12 @@ def search(self, query_text):
248248
"""Search the hierarchy of items for items matching a query. You can search within a folder hierarchy,
249249
a whole drive, or files shared with the current user.
250250
251-
:type query_text: str"""
252-
result = ClientResult(self.context)
253-
qry = SearchQuery(self, query_text, result)
251+
:type query_text: str
252+
:rtype: ClientResult
253+
"""
254+
qry = create_search_query(self, query_text)
254255
self.context.add_query(qry)
255-
return result
256+
return qry.return_type
256257

257258
def invite(self, recipients, message, require_sign_in=True, send_invitation=True, roles=None):
258259
"""Sends a sharing invitation for a driveItem. A sharing invitation provides permissions to the recipients

Diff for: office365/runtime/odata/odata_base_reader.py

-31
This file was deleted.

Diff for: office365/runtime/odata/odata_method.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class ODataMethod(object):
2+
pass

Diff for: office365/runtime/odata/odata_model.py

+7-25
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,15 @@
1-
from pydoc import locate
2-
3-
41
class ODataModel(object):
52
"""OData model"""
63
_types = {}
7-
_namespaces = ['directory', 'onedrive', 'mail', 'teams']
84

95
@property
106
def types(self):
117
return self._types
128

13-
def resolve_type(self, schema):
14-
type_alias = schema['name']
15-
types = [locate("office365.{0}.{1}".format(ns, type_alias)) for ns in self._namespaces]
16-
found_modules = [t for t in types if t is not None]
17-
if any(found_modules):
18-
schema['state'] = 'attached'
19-
schema['file'] = found_modules[0].__file__
20-
else:
21-
schema['state'] = 'detached'
22-
schema['file'] = ''
23-
schema['properties'] = {}
24-
self._types[type_alias] = schema
25-
26-
def resolve_property(self, type_schema, prop_schema):
27-
alias = prop_schema['name']
28-
if type_schema['state'] == 'detached':
29-
prop_schema['state'] = 'detached'
30-
else:
31-
prop_schema['state'] = 'attached'
32-
type_alias = type_schema['name']
33-
self._types[type_alias]['properties'][alias] = prop_schema
9+
def add_type(self, type_schema):
10+
"""
11+
:type type_schema: office365.runtime.odata.odata_type.ODataType
12+
:return:
13+
"""
14+
type_alias = type_schema.name
15+
self._types[type_alias] = type_schema

Diff for: office365/runtime/odata/odata_parameter.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class ODataParameter(object):
2+
pass

0 commit comments

Comments
 (0)