Skip to content

Commit 48e43cf

Browse files
Generator improvements
1 parent a1e0e72 commit 48e43cf

24 files changed

+254
-148
lines changed

generator/__init__.py

Lines changed: 10 additions & 0 deletions
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

generator/builders/method_builder.py

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

generator/builders/template_context.py

Lines changed: 3 additions & 0 deletions
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):

generator/builders/type_builder.py

Lines changed: 62 additions & 23 deletions
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

generator/generate.py

Lines changed: 20 additions & 25 deletions
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)

generator/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
astunparse==1.6.3

generator/settings.cfg

Lines changed: 12 additions & 0 deletions
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

office365/actions/search_query.py

Lines changed: 18 additions & 3 deletions
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

office365/directory/user.py

Lines changed: 3 additions & 0 deletions
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

office365/entity.py

Lines changed: 1 addition & 1 deletion
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

0 commit comments

Comments
 (0)