Merged PR 4493: CppToJson Schema Deserialization Code
Most of this code is boilerplate code that creates an environment that can be used to generate code that deserializes the output of CppToJson.py. The important files are: - CppyToJson.SimpleSchema - GeneratedCode/CppToJson_PythonJsonSerialization.py - SchemaBuildEnvironment/Build.py - SchemaBuildEnvironment/Readme.rst
This commit is contained in:
Родитель
31ca95c271
Коммит
909f1dfa75
|
@ -2,7 +2,7 @@ __pycache__
|
|||
*.pyc
|
||||
*.pyo
|
||||
|
||||
Generated/*
|
||||
**/Generated/*
|
||||
|
||||
Activate.cmd
|
||||
Activate.*.cmd
|
||||
|
@ -14,4 +14,6 @@ Activate.*.sh
|
|||
.coverage
|
||||
coverage.xml
|
||||
|
||||
.vscode/*
|
||||
**/.vscode/*
|
||||
|
||||
Libraries/Python/DataPipelines/v1\.0/DataPipelines/GeneratedCode/Compiler\.ConditionalInvocationQueryMixin\.data
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<Functions *>:
|
||||
<func_name string>
|
||||
|
||||
<raw_return_type string>
|
||||
<simple_return_type string>
|
||||
|
||||
<var_names string *>
|
||||
<raw_var_types string *>
|
||||
<simple_var_types string *>
|
|
@ -0,0 +1,560 @@
|
|||
# --------------------------------------------------------------------------------
|
||||
# |
|
||||
# | WARNING:
|
||||
# | This file was generated; any local changes will be overwritten during
|
||||
# | future invocations of the generator!
|
||||
# |
|
||||
# | Generated by: <SimpleSchemaGenerator>/Plugins/Impl/PythonSerializationImpl.py
|
||||
# | Generated on: 2019-06-05 09:55:01.478584
|
||||
# |
|
||||
# --------------------------------------------------------------------------------
|
||||
import copy
|
||||
import sys
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import six
|
||||
|
||||
import CommonEnvironment
|
||||
from CommonEnvironment.TypeInfo import Arity
|
||||
from CommonEnvironment.TypeInfo.AnyOfTypeInfo import AnyOfTypeInfo
|
||||
from CommonEnvironment.TypeInfo.ClassTypeInfo import ClassTypeInfo
|
||||
from CommonEnvironment.TypeInfo.DictTypeInfo import DictTypeInfo
|
||||
from CommonEnvironment.TypeInfo.GenericTypeInfo import GenericTypeInfo
|
||||
from CommonEnvironment.TypeInfo.ListTypeInfo import ListTypeInfo
|
||||
|
||||
from CommonEnvironment.TypeInfo.FundamentalTypes.Serialization.PythonCodeVisitor import PythonCodeVisitor
|
||||
|
||||
# <Unused import> pylint: disable = W0611
|
||||
# <Unused import> pylint: disable = W0614
|
||||
from CommonEnvironment.TypeInfo.FundamentalTypes.All import * # <Wildcard import> pylint: disable = W0401
|
||||
|
||||
# <Standard import should be placed before...> pylint: disable = C0411
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
import json
|
||||
|
||||
from CommonEnvironment import FileSystem
|
||||
from CommonEnvironment.TypeInfo.FundamentalTypes.Serialization.JsonSerialization import JsonSerialization
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class JsonEncoder(json.JSONEncoder):
|
||||
def default(self, o):
|
||||
if isinstance(o, Object):
|
||||
d = copy.deepcopy(o.__dict__)
|
||||
|
||||
for k in list(six.iterkeys(d)):
|
||||
if k.startswith("_"):
|
||||
del d[k]
|
||||
|
||||
return d
|
||||
|
||||
return getattr(o, "__dict__", o)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# <Method name "..." doesn't conform to PascalCase naming style> pylint: disable = C0103
|
||||
# <Line too long> pylint: disable = C0301
|
||||
# <Too many lines in module> pylint: disable = C0302
|
||||
# <Wrong hanging indentation> pylint: disable = C0330
|
||||
|
||||
# <Too few public methods> pylint: disable = R0903
|
||||
# <Too many public methods> pylint: disable = R0904
|
||||
# <Too many branches> pylint: disable = R0912
|
||||
# <Too many statements> pylint: disable = R0915
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class SerializationException(Exception):
|
||||
def __init__(self, ex_or_string):
|
||||
if isinstance(ex_or_string, six.string_types):
|
||||
super(SerializationException, self).__init__(ex_or_string)
|
||||
else:
|
||||
super(SerializationException, self).__init__(str(ex_or_string))
|
||||
|
||||
self.__dict__ = copy.deepcopy(ex_or_string.__dict__)
|
||||
|
||||
|
||||
class UniqueKeySerializationException(SerializationException): pass
|
||||
class SerializeException(SerializationException): pass
|
||||
class DeserializeException(SerializationException): pass
|
||||
|
||||
|
||||
class DoesNotExist(object): pass
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Utility Methods
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
def Deserialize(
|
||||
root,
|
||||
process_additional_data=False,
|
||||
always_include_optional=False,
|
||||
):
|
||||
return Deserialize_Functions(
|
||||
root,
|
||||
is_root=False,
|
||||
process_additional_data=process_additional_data,
|
||||
always_include_optional=always_include_optional,
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def Deserialize_Functions(
|
||||
items,
|
||||
process_additional_data=False,
|
||||
always_include_optional=False,
|
||||
is_root=False,
|
||||
):
|
||||
"""Deserializes 'Functions' from a JSON object to a python object"""
|
||||
|
||||
if isinstance(items, six.string_types):
|
||||
if FileSystem.IsFilename(items):
|
||||
with open(items) as f:
|
||||
items = json.load(f)
|
||||
else:
|
||||
items = json.loads(items)
|
||||
|
||||
if not isinstance(items, list):
|
||||
if isinstance(items, dict) and "Functions" in items:
|
||||
items = items["Functions"]
|
||||
elif not isinstance(items, dict) and hasattr(items, "Functions"):
|
||||
items = getattr(items, "Functions")
|
||||
elif is_root:
|
||||
items = DoesNotExist
|
||||
|
||||
try:
|
||||
try:
|
||||
items = Deserializer().Functions(
|
||||
items,
|
||||
process_additional_data=process_additional_data,
|
||||
always_include_optional=always_include_optional,
|
||||
)
|
||||
|
||||
if items is DoesNotExist:
|
||||
items = []
|
||||
except:
|
||||
_DecorateActiveException("Functions")
|
||||
except SerializationException:
|
||||
raise
|
||||
except Exception as ex:
|
||||
raise DeserializeException(ex)
|
||||
|
||||
return items
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Type Infos
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
Functions_TypeInfo = ClassTypeInfo(OrderedDict([ ( "func_name", StringTypeInfo(min_length=1) ), ( "raw_return_type", StringTypeInfo(min_length=1) ), ( "simple_return_type", StringTypeInfo(min_length=1) ), ( "var_names", StringTypeInfo(min_length=1, arity=Arity.FromString('*')) ), ( "raw_var_types", StringTypeInfo(min_length=1, arity=Arity.FromString('*')) ), ( "simple_var_types", StringTypeInfo(min_length=1, arity=Arity.FromString('*')) ) ]), require_exact_match=True, arity=Arity.FromString('*'))
|
||||
|
||||
_Functions_TypeInfo_Contents = OrderedDict([("func_name", GenericTypeInfo()), ("raw_return_type", GenericTypeInfo()), ("simple_return_type", GenericTypeInfo()), ("var_names", GenericTypeInfo(arity=Arity.FromString('*'))), ("raw_var_types", GenericTypeInfo(arity=Arity.FromString('*'))), ("simple_var_types", GenericTypeInfo(arity=Arity.FromString('*')))])
|
||||
|
||||
_Functions_TypeInfo = AnyOfTypeInfo([ClassTypeInfo(_Functions_TypeInfo_Contents, require_exact_match=False), DictTypeInfo(_Functions_TypeInfo_Contents, require_exact_match=False)], arity=Arity.FromString('*'))
|
||||
_Functions_func_name_TypeInfo = StringTypeInfo(min_length=1)
|
||||
_Functions_raw_return_type_TypeInfo = StringTypeInfo(min_length=1)
|
||||
_Functions_simple_return_type_TypeInfo = StringTypeInfo(min_length=1)
|
||||
_Functions_var_names_TypeInfo = StringTypeInfo(min_length=1, arity=Arity.FromString('*'))
|
||||
_Functions_raw_var_types_TypeInfo = StringTypeInfo(min_length=1, arity=Arity.FromString('*'))
|
||||
_Functions_simple_var_types_TypeInfo = StringTypeInfo(min_length=1, arity=Arity.FromString('*'))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Deserializer
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
class Deserializer(object):
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions(cls, items, always_include_optional, process_additional_data):
|
||||
if items in [DoesNotExist, None, []]:
|
||||
_Functions_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
results = []
|
||||
|
||||
for this_index, this_item in enumerate(items or []):
|
||||
try:
|
||||
results.append(cls._Functions_Item(this_item, always_include_optional, process_additional_data))
|
||||
except:
|
||||
_DecorateActiveException("Index {}".format(this_index))
|
||||
|
||||
_Functions_TypeInfo.ValidateArity(results)
|
||||
|
||||
return results
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_func_name(cls, item):
|
||||
if item in [DoesNotExist, None]:
|
||||
_Functions_func_name_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
result = cls._Functions_func_name_Item(item)
|
||||
|
||||
_Functions_func_name_TypeInfo.ValidateArity(result)
|
||||
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_raw_return_type(cls, item):
|
||||
if item in [DoesNotExist, None]:
|
||||
_Functions_raw_return_type_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
result = cls._Functions_raw_return_type_Item(item)
|
||||
|
||||
_Functions_raw_return_type_TypeInfo.ValidateArity(result)
|
||||
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_simple_return_type(cls, item):
|
||||
if item in [DoesNotExist, None]:
|
||||
_Functions_simple_return_type_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
result = cls._Functions_simple_return_type_Item(item)
|
||||
|
||||
_Functions_simple_return_type_TypeInfo.ValidateArity(result)
|
||||
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_var_names(cls, items):
|
||||
if items in [DoesNotExist, None, []]:
|
||||
_Functions_var_names_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
results = []
|
||||
|
||||
for this_index, this_item in enumerate(items or []):
|
||||
try:
|
||||
results.append(cls._Functions_var_names_Item(this_item))
|
||||
except:
|
||||
_DecorateActiveException("Index {}".format(this_index))
|
||||
|
||||
_Functions_var_names_TypeInfo.ValidateArity(results)
|
||||
|
||||
return results
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_raw_var_types(cls, items):
|
||||
if items in [DoesNotExist, None, []]:
|
||||
_Functions_raw_var_types_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
results = []
|
||||
|
||||
for this_index, this_item in enumerate(items or []):
|
||||
try:
|
||||
results.append(cls._Functions_raw_var_types_Item(this_item))
|
||||
except:
|
||||
_DecorateActiveException("Index {}".format(this_index))
|
||||
|
||||
_Functions_raw_var_types_TypeInfo.ValidateArity(results)
|
||||
|
||||
return results
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def Functions_simple_var_types(cls, items):
|
||||
if items in [DoesNotExist, None, []]:
|
||||
_Functions_simple_var_types_TypeInfo.ValidateArity(None)
|
||||
return DoesNotExist
|
||||
|
||||
results = []
|
||||
|
||||
for this_index, this_item in enumerate(items or []):
|
||||
try:
|
||||
results.append(cls._Functions_simple_var_types_Item(this_item))
|
||||
except:
|
||||
_DecorateActiveException("Index {}".format(this_index))
|
||||
|
||||
_Functions_simple_var_types_TypeInfo.ValidateArity(results)
|
||||
|
||||
return results
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_Item(cls, item, always_include_optional, process_additional_data):
|
||||
result = _CreatePythonObject(
|
||||
attributes=None,
|
||||
)
|
||||
|
||||
# func_name
|
||||
try:
|
||||
setattr(result, "func_name", cls.Functions_func_name(
|
||||
cls._GetPythonAttribute(
|
||||
item,
|
||||
"func_name",
|
||||
is_optional=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
except:
|
||||
_DecorateActiveException("func_name")
|
||||
|
||||
# raw_return_type
|
||||
try:
|
||||
setattr(result, "raw_return_type", cls.Functions_raw_return_type(
|
||||
cls._GetPythonAttribute(
|
||||
item,
|
||||
"raw_return_type",
|
||||
is_optional=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
except:
|
||||
_DecorateActiveException("raw_return_type")
|
||||
|
||||
# simple_return_type
|
||||
try:
|
||||
setattr(result, "simple_return_type", cls.Functions_simple_return_type(
|
||||
cls._GetPythonAttribute(
|
||||
item,
|
||||
"simple_return_type",
|
||||
is_optional=False,
|
||||
),
|
||||
)
|
||||
)
|
||||
except:
|
||||
_DecorateActiveException("simple_return_type")
|
||||
|
||||
# var_names
|
||||
try:
|
||||
cls._ApplyOptionalChildren(item, "var_names", result, cls.Functions_var_names, always_include_optional)
|
||||
except:
|
||||
_DecorateActiveException("var_names")
|
||||
|
||||
# raw_var_types
|
||||
try:
|
||||
cls._ApplyOptionalChildren(item, "raw_var_types", result, cls.Functions_raw_var_types, always_include_optional)
|
||||
except:
|
||||
_DecorateActiveException("raw_var_types")
|
||||
|
||||
# simple_var_types
|
||||
try:
|
||||
cls._ApplyOptionalChildren(item, "simple_var_types", result, cls.Functions_simple_var_types, always_include_optional)
|
||||
except:
|
||||
_DecorateActiveException("simple_var_types")
|
||||
|
||||
# Additional data
|
||||
if process_additional_data:
|
||||
cls._ApplyAdditionalData(
|
||||
item,
|
||||
result,
|
||||
exclude_names={"func_name", "raw_return_type", "simple_return_type", "var_names", "raw_var_types", "simple_var_types"},
|
||||
)
|
||||
|
||||
_Functions_TypeInfo.ValidateItem(
|
||||
result,
|
||||
recurse=False,
|
||||
require_exact_match=not process_additional_data,
|
||||
)
|
||||
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_func_name_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_func_name_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_raw_return_type_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_raw_return_type_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_simple_return_type_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_simple_return_type_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_var_names_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_var_names_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_raw_var_types_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_raw_var_types_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _Functions_simple_var_types_Item(cls, item):
|
||||
return JsonSerialization.DeserializeItem(_Functions_simple_var_types_TypeInfo, item, **{})
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _ApplyOptionalChildren(cls, items, attribute_name, dest, apply_func, always_include_optional):
|
||||
value = cls._GetPythonAttribute(
|
||||
items,
|
||||
attribute_name,
|
||||
is_optional=True,
|
||||
)
|
||||
|
||||
if value is not DoesNotExist:
|
||||
value = apply_func(value)
|
||||
if value is not DoesNotExist:
|
||||
setattr(dest, attribute_name, value)
|
||||
return
|
||||
|
||||
if always_include_optional:
|
||||
setattr(dest, attribute_name, [])
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _ApplyAdditionalData(
|
||||
cls,
|
||||
source,
|
||||
dest,
|
||||
exclude_names,
|
||||
):
|
||||
for name, child in [(k, v) for k, v in six.iteritems(source if isinstance(source, dict) else source.__dict__) if not k.startswith("_") and k not in exclude_names]:
|
||||
try:
|
||||
if isinstance(child, list):
|
||||
children = []
|
||||
|
||||
for index, item in enumerate(child):
|
||||
item_name = "Index {}".format(index)
|
||||
|
||||
try:
|
||||
children.append(cls._CreateAdditionalDataItem(item_name, item))
|
||||
except:
|
||||
_DecorateActiveException(item_name)
|
||||
|
||||
setattr(dest, name, children)
|
||||
else:
|
||||
setattr(dest, name, cls._CreateAdditionalDataItem(name, child))
|
||||
except:
|
||||
_DecorateActiveException(name)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@classmethod
|
||||
def _CreateAdditionalDataItem(cls, name, source):
|
||||
# The following types should be returned directly without additional conversion
|
||||
if isinstance(source, (int, float, str, bool)):
|
||||
return source
|
||||
|
||||
assert not isinstance(source, list), source
|
||||
|
||||
if not isinstance(source, dict):
|
||||
source = source.__dict__
|
||||
|
||||
source_attribute_names = source.get("_attribute_names", set())
|
||||
|
||||
attributes = OrderedDict()
|
||||
items = OrderedDict()
|
||||
|
||||
for k, v in six.iteritems(source):
|
||||
if k.startswith("_"):
|
||||
continue
|
||||
|
||||
if k in source_attribute_names:
|
||||
attributes[k] = v
|
||||
else:
|
||||
items[k] = v
|
||||
|
||||
if len(items) == 1 and next(six.iterkeys(items)) == source.get("_text_attribute_name", None):
|
||||
return _CreatePythonObject(
|
||||
attributes=attributes,
|
||||
**{"simple_value": source[source["_text_attribute_name"]], "_text_attribute_name": "simple_value"},
|
||||
)
|
||||
|
||||
result = _CreatePythonObject(
|
||||
attributes=attributes,
|
||||
)
|
||||
|
||||
for k, v in six.iteritems(items):
|
||||
try:
|
||||
if isinstance(v, list):
|
||||
new_items = []
|
||||
|
||||
for index, child in enumerate(v):
|
||||
try:
|
||||
new_items.append(cls._CreateAdditionalDataItem("item", child))
|
||||
except:
|
||||
_DecorateActiveException("Index {}".format(index))
|
||||
|
||||
setattr(result, k, new_items)
|
||||
else:
|
||||
new_item = cls._CreateAdditionalDataItem(k, v)
|
||||
|
||||
setattr(result, k, new_item)
|
||||
except:
|
||||
_DecorateActiveException(k)
|
||||
|
||||
return result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@staticmethod
|
||||
def _GetPythonAttribute(
|
||||
item,
|
||||
attribute_name,
|
||||
is_optional=False,
|
||||
):
|
||||
if not isinstance(item, dict):
|
||||
item = item.__dict__
|
||||
|
||||
value = item.get(attribute_name, DoesNotExist)
|
||||
if value is DoesNotExist and not is_optional:
|
||||
raise SerializeException("No items were found")
|
||||
|
||||
return value
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class Object(object):
|
||||
def __init__(self):
|
||||
self._attribute_names = set()
|
||||
|
||||
def __repr__(self):
|
||||
return CommonEnvironment.ObjectReprImpl(self)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def _CreatePythonObject(
|
||||
attributes=None,
|
||||
**kwargs
|
||||
):
|
||||
attributes = attributes or {}
|
||||
|
||||
result = Object()
|
||||
|
||||
for d in [attributes, kwargs]:
|
||||
for k, v in six.iteritems(d):
|
||||
setattr(result, k, v)
|
||||
|
||||
for k in six.iterkeys(attributes):
|
||||
result._attribute_names.add(k)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
def _DecorateActiveException(frame_desc):
|
||||
exception = sys.exc_info()[1]
|
||||
|
||||
if not hasattr(exception, "stack"):
|
||||
setattr(exception, "stack", [])
|
||||
|
||||
exception.stack.insert(0, frame_desc)
|
||||
|
||||
# <The raise statement is not inside an except clause> pylint: disable = E0704
|
||||
raise
|
|
@ -0,0 +1 @@
|
|||
The python code in this directory was generated by ../SchemaBuildEnvironment/Build.py.
|
|
@ -0,0 +1,334 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License
|
||||
# ----------------------------------------------------------------------
|
||||
"""Unit tests for CppToJson_PythonJsonSerialization.py"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
import CommonEnvironment
|
||||
from DataPipelines.GeneratedCode.CppToJson_PythonJsonSerialization import *
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
class TestSuite(unittest.TestCase):
|
||||
# ----------------------------------------------------------------------
|
||||
def test_Empty(self):
|
||||
self.assertEqual(Deserialize([]), [])
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_NoArgs(self):
|
||||
result = Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0].func_name, "Name")
|
||||
self.assertEqual(result[0].raw_return_type, "int1")
|
||||
self.assertEqual(result[0].simple_return_type, "int2")
|
||||
self.assertTrue(not hasattr(result[0], "var_names"))
|
||||
self.assertTrue(not hasattr(result[0], "raw_var_types"))
|
||||
self.assertTrue(not hasattr(result[0], "simple_var_types"))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_WithArgs(self):
|
||||
result = Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["a", "b",],
|
||||
"raw_var_types": ["c", "d",],
|
||||
"simple_var_types": ["e", "f",],
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0].func_name, "Name")
|
||||
self.assertEqual(result[0].raw_return_type, "int1")
|
||||
self.assertEqual(result[0].simple_return_type, "int2")
|
||||
self.assertEqual(result[0].var_names, ["a", "b",])
|
||||
self.assertEqual(result[0].raw_var_types, ["c", "d",])
|
||||
self.assertEqual(result[0].simple_var_types, ["e", "f",])
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_Multiple(self):
|
||||
result = Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name1",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
{
|
||||
"func_name": "Name2",
|
||||
"raw_return_type": "int3",
|
||||
"simple_return_type": "int4",
|
||||
},
|
||||
],
|
||||
)
|
||||
|
||||
self.assertEqual(len(result), 2)
|
||||
|
||||
self.assertEqual(result[0].func_name, "Name1")
|
||||
self.assertEqual(result[0].raw_return_type, "int1")
|
||||
self.assertEqual(result[0].simple_return_type, "int2")
|
||||
self.assertTrue(not hasattr(result[0], "var_names"))
|
||||
self.assertTrue(not hasattr(result[0], "raw_var_types"))
|
||||
self.assertTrue(not hasattr(result[0], "simple_var_types"))
|
||||
|
||||
self.assertEqual(result[1].func_name, "Name2")
|
||||
self.assertEqual(result[1].raw_return_type, "int3")
|
||||
self.assertEqual(result[1].simple_return_type, "int4")
|
||||
self.assertTrue(not hasattr(result[1], "var_names"))
|
||||
self.assertTrue(not hasattr(result[1], "raw_var_types"))
|
||||
self.assertTrue(not hasattr(result[1], "simple_var_types"))
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidName(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"An item was expected",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": None,
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidRawReturnType(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"An item was expected",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": None,
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "",
|
||||
"simple_return_type": "int2",
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidSimpleReturnType(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"An item was expected",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": None,
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "",
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidVarName(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"expected string or bytes-like object", # TODO
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": [None, "b",],
|
||||
"raw_var_types": ["c", "d",],
|
||||
"simple_var_types": ["e", "f",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["", "b",],
|
||||
"raw_var_types": ["c", "d",],
|
||||
"simple_var_types": ["e", "f",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidRawVarType(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"expected string or bytes-like object", # TODO
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["a", "b",],
|
||||
"raw_var_types": ["c", None,],
|
||||
"simple_var_types": ["e", "f",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["a", "b",],
|
||||
"raw_var_types": ["c", "",],
|
||||
"simple_var_types": ["e", "f",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_InvalidSimpleVarType(self):
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"expected string or bytes-like object", # TODO
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["a", "b",],
|
||||
"raw_var_types": ["c", "d",],
|
||||
"simple_var_types": ["e", None, "g",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
self.assertRaisesRegex(
|
||||
Exception,
|
||||
"'' is not a valid 'String' string - Value must have more than 1 character",
|
||||
lambda: Deserialize(
|
||||
[
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"var_names": ["", "b",],
|
||||
"raw_var_types": ["c", "d",],
|
||||
"simple_var_types": ["e", "", "g",],
|
||||
},
|
||||
],
|
||||
),
|
||||
)
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def test_ProcessAdditionalData(self):
|
||||
input = [
|
||||
{
|
||||
"func_name": "Name",
|
||||
"raw_return_type": "int1",
|
||||
"simple_return_type": "int2",
|
||||
"another_value": {"hello": "world",},
|
||||
"another_value2": "a string",
|
||||
"optional_list": [1, 2, 3],
|
||||
},
|
||||
]
|
||||
|
||||
result = Deserialize(input)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertTrue(not hasattr(result[0], "another_value"))
|
||||
|
||||
result = Deserialize(
|
||||
input,
|
||||
process_additional_data=True,
|
||||
)
|
||||
|
||||
self.assertEqual(len(result), 1)
|
||||
self.assertEqual(result[0].another_value.hello, "world")
|
||||
self.assertEqual(result[0].another_value2, "a string")
|
||||
self.assertEqual(result[0].optional_list, [1, 2, 3,])
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(unittest.main(verbosity=2))
|
||||
except KeyboardInterrupt:
|
||||
pass
|
|
@ -0,0 +1,98 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Activate_custom.py
|
||||
# |
|
||||
# | David Brownell <db@DavidBrownell.com>
|
||||
# | 2018-05-07 08:59:57
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Copyright David Brownell 2018-19.
|
||||
# | Distributed under the Boost Software License, Version 1.0.
|
||||
# | (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
"""Performs repository-specific activation activities."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.getenv("DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL"))
|
||||
from RepositoryBootstrap.SetupAndActivate import CommonEnvironment, CurrentShell
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# <Class '<name>' has no '<attr>' member> pylint: disable = E1101
|
||||
# <Unrearchable code> pylint: disable = W0101
|
||||
# <Unused argument> pylint: disable = W0613
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def GetCustomActions(
|
||||
output_stream,
|
||||
configuration,
|
||||
version_specs,
|
||||
generated_dir,
|
||||
debug,
|
||||
verbose,
|
||||
fast,
|
||||
repositories,
|
||||
is_mixin_repo,
|
||||
):
|
||||
"""
|
||||
Returns an action or list of actions that should be invoked as part of the activation process.
|
||||
|
||||
Actions are generic command line statements defined in
|
||||
<Common_Environment>/Libraries/Python/CommonEnvironment/v1.0/CommonEnvironment/Shell/Commands/__init__.py
|
||||
that are converted into statements appropriate for the current scripting language (in most
|
||||
cases, this is Bash on Linux systems and Batch or PowerShell on Windows systems.
|
||||
"""
|
||||
|
||||
return []
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def GetCustomScriptExtractors():
|
||||
"""
|
||||
Returns information that can be used to enumerate, extract, and generate documentation
|
||||
for scripts stored in the Scripts directory in this repository and all repositories
|
||||
that depend upon it.
|
||||
|
||||
****************************************************
|
||||
Note that it is very rare to have the need to implement
|
||||
this method. In most cases, it is safe to delete it.
|
||||
****************************************************
|
||||
|
||||
There concepts are used with custom script extractors:
|
||||
|
||||
- DirGenerator: Method to enumerate sub-directories when searching for scripts in a
|
||||
repository's Scripts directory.
|
||||
|
||||
def Func(directory, version_sepcs) -> [ (subdir, should_recurse), ... ]
|
||||
[ subdir, ... ]
|
||||
(subdir, should_recurse)
|
||||
subdir
|
||||
|
||||
- CreateCommands: Method that creates the shell commands to invoke a script.
|
||||
|
||||
def Func(script_filename) -> [ command, ...]
|
||||
command
|
||||
None # Indicates not supported
|
||||
|
||||
- CreateDocumentation: Method that extracts documentation from a script.
|
||||
|
||||
def Func(script_filename) -> documentation string
|
||||
|
||||
- ScriptNameDecorator: Returns a new name for the script.
|
||||
|
||||
def Func(script_filename) -> name string
|
||||
|
||||
See <Common_Environment>/Activate_custom.py for an example of how script extractors
|
||||
are used to process Python and PowerShell scripts.
|
||||
"""
|
||||
|
||||
return
|
|
@ -0,0 +1,86 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
"""Builds generated code"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
import CommonEnvironment
|
||||
from CommonEnvironment import BuildImpl
|
||||
from CommonEnvironment import CommandLine
|
||||
from CommonEnvironment import FileSystem
|
||||
from CommonEnvironment import Process
|
||||
from CommonEnvironment.Shell.All import CurrentShell
|
||||
from CommonEnvironment.StreamDecorator import StreamDecorator
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@CommandLine.EntryPoint
|
||||
@CommandLine.Constraints(
|
||||
output_stream=None,
|
||||
)
|
||||
def Build(
|
||||
force=False,
|
||||
output_stream=sys.stdout,
|
||||
verbose=False,
|
||||
):
|
||||
return Process.Execute(
|
||||
'"{script}" Generate PythonJson CppToJson "{output_dir}" "/input={input}" /plugin_arg=no_serialization:true{force}{verbose}'.format(
|
||||
script=CurrentShell.CreateScriptName("SimpleSchemaGenerator"),
|
||||
output_dir=os.path.join(_script_dir, "..", "GeneratedCode"),
|
||||
input=os.path.join(_script_dir, "..", "CppToJson.SimpleSchema"),
|
||||
force=" /force" if force else "",
|
||||
verbose=" /verbose" if verbose else "",
|
||||
),
|
||||
output_stream,
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@CommandLine.EntryPoint
|
||||
@CommandLine.Constraints(
|
||||
output_stream=None,
|
||||
)
|
||||
def Clean(
|
||||
output_stream=sys.stdout,
|
||||
):
|
||||
output_dir = os.path.join(_script_dir, "..", "GeneratedCode")
|
||||
if not os.path.isdir(output_dir):
|
||||
output_stream.write("'{}' does not exist.\n".format(output_dir))
|
||||
else:
|
||||
filenames = [
|
||||
"Compiler.ConditionalInvocationQueryMixin.data",
|
||||
"CppToJson_PythonJsonSerialization.py",
|
||||
]
|
||||
|
||||
output_stream.write("Removing content in '{}'...".format(output_dir))
|
||||
with StreamDecorator(output_stream).DoneManager():
|
||||
for filename in filenames:
|
||||
filename = os.path.join(output_dir, filename)
|
||||
FileSystem.RemoveFile(filename)
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(
|
||||
BuildImpl.Main(
|
||||
BuildImpl.Configuration(
|
||||
"SchemaCodeGenerator",
|
||||
requires_output_dir=False,
|
||||
),
|
||||
),
|
||||
)
|
||||
except KeyboardInterrupt:
|
||||
pass
|
|
@ -0,0 +1,5 @@
|
|||
This is a environment suitable for building code in `../GeneratedCode`.
|
||||
|
||||
To get started, run:
|
||||
|
||||
`bootstrap.<cmd|sh> <Common Code Dir>`
|
|
@ -0,0 +1,38 @@
|
|||
@REM ----------------------------------------------------------------------
|
||||
@REM |
|
||||
@REM | Setup.cmd
|
||||
@REM |
|
||||
@REM | David Brownell <db@DavidBrownell.com>
|
||||
@REM | 2018-04-20 11:21:37
|
||||
@REM |
|
||||
@REM ----------------------------------------------------------------------
|
||||
@REM |
|
||||
@REM | Copyright David Brownell 2018-19.
|
||||
@REM | Distributed under the Boost Software License, Version 1.0.
|
||||
@REM | (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
@REM |
|
||||
@REM ----------------------------------------------------------------------
|
||||
@echo off
|
||||
|
||||
@REM ----------------------------------------------------------------------
|
||||
@REM |
|
||||
@REM | Run as:
|
||||
@REM | Setup.cmd [/debug] [/verbose] [/configuration_EQ_<config_name>]*
|
||||
@REM |
|
||||
@REM ----------------------------------------------------------------------
|
||||
|
||||
if "%DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL%"=="" (
|
||||
echo.
|
||||
echo ERROR: Please run Activate.cmd within a repository before running this script. It may be necessary to Setup and Activate the Common_Environment repository before setting up this one.
|
||||
echo.
|
||||
goto end
|
||||
)
|
||||
|
||||
pushd "%~dp0"
|
||||
call %DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL%\RepositoryBootstrap\Impl\Setup.cmd %*
|
||||
set _SETUP_ERROR=%ERRORLEVEL%
|
||||
popd
|
||||
|
||||
if %_SETUP_ERROR% NEQ 0 (exit /B %_SETUP_ERROR%)
|
||||
|
||||
:end
|
|
@ -0,0 +1,38 @@
|
|||
#!/bin/bash
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Setup.sh
|
||||
# |
|
||||
# | David Brownell <db@DavidBrownell.com>
|
||||
# | 2018-05-09 10:37:21
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Copyright David Brownell 2018-19.
|
||||
# | Distributed under the Boost Software License, Version 1.0.
|
||||
# | (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
set -e # Exit on error
|
||||
set +v # Disable output
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Run as:
|
||||
# | ./Setup.sh [/debug] [/verbose] [/configuration=<config_name>]*
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# Note that sudo is necessary because the process will create symbolic links
|
||||
|
||||
if [[ "${DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL}" = "" ]]
|
||||
then
|
||||
echo
|
||||
echo "ERROR: Please run Activate.sh within a repository before running this script. It may be necessary to Setup and Activate the Common_Environment repository before setting up this one."
|
||||
echo
|
||||
|
||||
exit -1
|
||||
fi
|
||||
|
||||
pushd "$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" > /dev/null
|
||||
source $DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL/RepositoryBootstrap/Impl/Setup.sh "$@"
|
||||
popd > /dev/null
|
|
@ -0,0 +1,121 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Setup_custom.py
|
||||
# |
|
||||
# | David Brownell <db@DavidBrownell.com>
|
||||
# | 2018-05-03 22:12:13
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Copyright David Brownell 2018-19.
|
||||
# | Distributed under the Boost Software License, Version 1.0.
|
||||
# | (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
"""Performs repository-specific setup activities."""
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | To setup an environment, run:
|
||||
# |
|
||||
# | Setup(.cmd|.ps1|.sh) [/debug] [/verbose] [/configuration=<config_name>]*
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import CommonEnvironment
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# <Missing function docstring> pylint: disable = C0111
|
||||
# <Line too long> pylint: disable = C0301
|
||||
# <Wrong hanging indentation> pylint: disable = C0330
|
||||
# <Class '<name>' has no '<attr>' member> pylint: disable = E1103
|
||||
# <Unreachable code> pylint: disable = W0101
|
||||
# <Wildcard import> pylint: disable = W0401
|
||||
# <Unused argument> pylint: disable = W0613
|
||||
|
||||
fundamental_repo = os.getenv("DEVELOPMENT_ENVIRONMENT_FUNDAMENTAL")
|
||||
assert os.path.isdir(fundamental_repo), fundamental_repo
|
||||
|
||||
sys.path.insert(0, fundamental_repo)
|
||||
from RepositoryBootstrap import * # <Unused import> pylint: disable = W0614
|
||||
from RepositoryBootstrap.SetupAndActivate import CurrentShell # <Unused import> pylint: disable = W0614
|
||||
from RepositoryBootstrap.SetupAndActivate.Configuration import * # <Unused import> pylint: disable = W0614
|
||||
|
||||
del sys.path[0]
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# There are two types of repositories: Standard and Mixin. Only one standard
|
||||
# repository may be activated within an environment at a time while any number
|
||||
# of mixin repositories can be activated within a standard repository environment.
|
||||
# Standard repositories may be dependent on other repositories (thereby inheriting
|
||||
# their functionality), support multiple configurations, and specify version
|
||||
# information for tools and libraries in themselves or its dependencies.
|
||||
#
|
||||
# Mixin repositories are designed to augment other repositories. They cannot
|
||||
# have configurations or dependencies and may not be activated on their own.
|
||||
#
|
||||
# These difference are summarized in this table:
|
||||
#
|
||||
# Standard Mixin
|
||||
# -------- -----
|
||||
# Can be activated in isolation X
|
||||
# Supports configurations X
|
||||
# Supports VersionSpecs X
|
||||
# Can be dependent upon other repositories X
|
||||
# Can be activated within any other Standard X
|
||||
# repository
|
||||
#
|
||||
# Consider a script that wraps common Git commands. This functionality is useful
|
||||
# across a number of different repositories, yet doesn't have functionality that
|
||||
# is useful on its own; it provides functionality that augments other repositories.
|
||||
# This functionality should be included within a repository that is classified
|
||||
# as a mixin repository.
|
||||
#
|
||||
# To classify a repository as a Mixin repository, decorate the GetDependencies method
|
||||
# with the MixinRepository decorator.
|
||||
#
|
||||
|
||||
|
||||
# @MixinRepository # <-- Uncomment this line to classify this repository as a mixin repository
|
||||
def GetDependencies():
|
||||
"""
|
||||
Returns information about the dependencies required by this repository.
|
||||
|
||||
The return value should be an OrderedDict if the repository supports multiple configurations
|
||||
(aka is configurable) or a single Configuration if not.
|
||||
"""
|
||||
|
||||
return Configuration(
|
||||
"Standard Configuration",
|
||||
[
|
||||
Dependency(
|
||||
"5C7E1B3369B74BC098141FAD290288DA",
|
||||
"Common_SimpleSchemaGenerator",
|
||||
None,
|
||||
"https://github.com/davidbrownell/Common_SimpleSchemaGenerator.git",
|
||||
),
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
def GetCustomActions(debug, verbose, explicit_configurations):
|
||||
"""
|
||||
Returns an action or list of actions that should be invoked as part of the setup process.
|
||||
|
||||
Actions are generic command line statements defined in
|
||||
<Common_Environment>/Libraries/Python/CommonEnvironment/v1.0/CommonEnvironment/Shell/Commands/__init__.py
|
||||
that are converted into statements appropriate for the current scripting language (in most
|
||||
cases, this is Bash on Linux systems and Batch or PowerShell on Windows systems.
|
||||
"""
|
||||
|
||||
return []
|
|
@ -0,0 +1,8 @@
|
|||
This file is used to uniquely identify this repository for the purposes of dependency management.
|
||||
Other repositories that depend on this one will search for this file upon initial setup and
|
||||
generate information that can be used when activating development environments.
|
||||
|
||||
**** PLEASE DO NOT MODIFY, REMOVE, OR RENAME THIS FILE, AS DOING SO WILL LIKELY BREAK OTHER REPOSITORIES! ****
|
||||
|
||||
Friendly Name: SchemaBuildEnvironment
|
||||
Id: DE0092F9E4AF4A44B1FA219707C3AF42
|
|
@ -0,0 +1,111 @@
|
|||
@REM ----------------------------------------------------------------------
|
||||
@REM |
|
||||
@REM | bootstrap.cmd
|
||||
@REM |
|
||||
@REM | David Brownell <db@DavidBrownell.com>
|
||||
@REM | 2019-05-21 08:07:40
|
||||
@REM |
|
||||
@REM ----------------------------------------------------------------------
|
||||
@REM |
|
||||
@REM | Copyright David Brownell 2019
|
||||
@REM | Distributed under the Boost Software License, Version 1.0. See
|
||||
@REM | accompanying file LICENSE_1_0.txt or copy at
|
||||
@REM | http://www.boost.org/LICENSE_1_0.txt.
|
||||
@REM |
|
||||
@REM ----------------------------------------------------------------------
|
||||
@echo off
|
||||
|
||||
IF "%~1"=="" (
|
||||
echo.
|
||||
echo This script bootstraps common library enlistment and setup.
|
||||
echo.
|
||||
echo Usage:
|
||||
echo %0 ^<common code dir^>
|
||||
echo.
|
||||
|
||||
exit /B -1
|
||||
)
|
||||
|
||||
set _COMMON_CODE_DIR=%~1
|
||||
shift /1
|
||||
|
||||
if "%DEVELOPMENT_ENVIRONMENT_REPOSITORY_ACTIVATED_FLAG%" NEQ "" (
|
||||
echo.
|
||||
echo ERROR: Please run this from a standard ^(non-activated^) command prompt.
|
||||
echo.
|
||||
|
||||
exit /B -1
|
||||
)
|
||||
|
||||
REM Bootstrap enlistment and setup of Common_Environment, and then invoke
|
||||
REM bootstrap_impl.py once python is available.
|
||||
|
||||
IF NOT EXIST "%_COMMON_CODE_DIR%\Common\Environment" (
|
||||
git clone https://github.com/davidbrownell/Common_Environment_v3.git "%_COMMON_CODE_DIR%\Common\Environment"
|
||||
if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL%
|
||||
)
|
||||
|
||||
REM Note that the following loop has been crafted to work around batch's crazy
|
||||
REM expansion rules. Modify at your own risk!
|
||||
set _BOOTSTRAP_NAME=
|
||||
set _BOOTSTRAP_CLA=
|
||||
|
||||
:GetRemainingArgs_Begin
|
||||
|
||||
if "%~1"=="" goto :GetRemainingArgs_End
|
||||
|
||||
set _ARG=%~1
|
||||
|
||||
if "%_ARG:~,9%"=="/name_EQ_" goto :GetRemainingArgs_Name
|
||||
if "%_ARG:~,9%"=="-name_EQ_" goto :GetRemainingArgs_Name
|
||||
|
||||
REM If here, we are looking at an arg that should be passed to the script
|
||||
set _BOOTSTRAP_CLA=%_BOOTSTRAP_CLA% "%_ARG%"
|
||||
goto :GetRemainingArgs_Continue
|
||||
|
||||
:GetRemainingArgs_Name
|
||||
REM If here, we are looking at a name argument
|
||||
set _BOOTSTRAP_NAME=%_ARG:~9%
|
||||
goto :GetRemainingArgs_Continue
|
||||
|
||||
:GetRemainingArgs_Continue
|
||||
shift /1
|
||||
goto :GetRemainingArgs_Begin
|
||||
|
||||
:GetRemainingArgs_End
|
||||
|
||||
set _BOOTSTRAP_NAME_ARG=
|
||||
if "%_BOOTSTRAP_NAME%" NEQ "" (
|
||||
set _BOOTSTRAP_NAME_ARG=/name_EQ_%_BOOTSTRAP_NAME%
|
||||
)
|
||||
|
||||
call "%_COMMON_CODE_DIR%\Common\Environment\Setup.cmd" %_BOOTSTRAP_NAME_ARG% %_BOOTSTRAP_CLA%
|
||||
if %ERRORLEVEL% NEQ 0 exit /B %ERRORLEVEL%
|
||||
|
||||
REM Write the environment activation and python execution statements to a temporary
|
||||
REM file so this environment remains unactivated (by doing this, the current script
|
||||
REM can be invoked multiple times from the same environment).
|
||||
set _ACTIVATE_CMD=Activate.cmd
|
||||
|
||||
if "%_BOOTSTRAP_NAME%" NEQ "" (
|
||||
set _ACTIVATE_CMD=Activate.%_BOOTSTRAP_NAME%.cmd
|
||||
)
|
||||
|
||||
(
|
||||
echo @echo off
|
||||
echo call "%_COMMON_CODE_DIR%\Common\Environment\%_ACTIVATE_CMD%" python36
|
||||
echo python "%~dp0bootstrap_impl.py" "%_COMMON_CODE_DIR%" %_BOOTSTRAP_CLA%
|
||||
) >bootstrap_tmp.cmd
|
||||
|
||||
cmd /C bootstrap_tmp.cmd
|
||||
set _ERRORLEVEL=%ERRORLEVEL%
|
||||
del bootstrap_tmp.cmd
|
||||
|
||||
set _ACTIVATE_CMD=
|
||||
set _ARG=
|
||||
set _BOOTSTRAP_CLA=
|
||||
set _BOOTSTRAP_NAME=
|
||||
set _BOOTSTRAP_NAME_ARG=
|
||||
set _COMMON_CODE_DIR=
|
||||
|
||||
if %_ERRORLEVEL% NEQ 0 exit /B %_ERRORLEVEL%
|
|
@ -0,0 +1,103 @@
|
|||
#!/bin/bash
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | bootstrap.sh
|
||||
# |
|
||||
# | David Brownell <db@DavidBrownell.com>
|
||||
# | 2019-05-21 11:27:06
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Copyright David Brownell 2019
|
||||
# | Distributed under the Boost Software License, Version 1.0. See
|
||||
# | accompanying file LICENSE_1_0.txt or copy at
|
||||
# | http://www.boost.org/LICENSE_1_0.txt.
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
set -e # Exit on error
|
||||
set +v # Disable output
|
||||
|
||||
should_continue=1
|
||||
|
||||
if [[ ${should_continue} == 1 && "$1" == "" ]]
|
||||
then
|
||||
echo ""
|
||||
echo "This script bootstraps common library enlistment and setup."
|
||||
echo ""
|
||||
echo " Usage:"
|
||||
echo " $0 <common code dir>"
|
||||
echo ""
|
||||
|
||||
should_continue=0
|
||||
fi
|
||||
|
||||
if [[ ${should_continue} == 1 && ${DEVELOPMENT_ENVIRONMENT_REPOSITORY_ACTIVATED_FLAG} ]]
|
||||
then
|
||||
echo ""
|
||||
echo "ERROR: Please run this from a standard (non-activated) command prompt."
|
||||
echo ""
|
||||
|
||||
should_continue=0
|
||||
fi
|
||||
|
||||
if [[ ${should_continue} == 1 ]]
|
||||
then
|
||||
# Bootstrap enlistment and setup of Common_Environment, and then invoke
|
||||
# bootstrap_impl.py once python is available.
|
||||
|
||||
if [[ ! -e "$1/Common/Environment" ]]
|
||||
then
|
||||
git clone https://github.com/davidbrownell/Common_Environment_v3.git "$1/Common/Environment"
|
||||
fi
|
||||
|
||||
name=""
|
||||
ARGS=()
|
||||
|
||||
for var in "${@:2}"
|
||||
do
|
||||
if [[ $var == /name=* ]] || [[ $var == -name=* ]]
|
||||
then
|
||||
name=`echo $var | cut -d'=' -f 2`
|
||||
else
|
||||
ARGS+=("$var")
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ ! -z "${name}" ]]
|
||||
then
|
||||
name_arg="/name=${name}"
|
||||
else
|
||||
name_arg=""
|
||||
fi
|
||||
|
||||
"$1/Common/Environment/Setup.sh" ${name_arg} ${ARGS[@]}
|
||||
|
||||
# Write the environment activation and python execution statements to a temporary
|
||||
# file so this environment remains unactivated (by doing this, the current script
|
||||
# can be invoked multiple times from the same environment).
|
||||
if [[ ! -z "${name}" ]]
|
||||
then
|
||||
activate_cmd="Activate.${name}.sh"
|
||||
else
|
||||
activate_cmd="Activate.sh"
|
||||
fi
|
||||
|
||||
this_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||
|
||||
cat >bootstrap_tmp.sh <<EOL
|
||||
#!/bin/bash
|
||||
. "$1/Common/Environment/${activate_cmd}" python36
|
||||
python "${this_dir}/bootstrap_impl.py" "$1" ${ARGS[@]}
|
||||
EOL
|
||||
|
||||
chmod +x bootstrap_tmp.sh
|
||||
./bootstrap_tmp.sh
|
||||
error_code=${error_code}
|
||||
|
||||
rm bootstrap_tmp.sh
|
||||
|
||||
if [[ ${error_code} -ne 0 ]]
|
||||
then
|
||||
should_continue=0
|
||||
fi
|
||||
fi
|
|
@ -0,0 +1,217 @@
|
|||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | bootstrap_impl.py
|
||||
# |
|
||||
# | David Brownell <db@DavidBrownell.com>
|
||||
# | 2019-05-21 08:23:15
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
# |
|
||||
# | Copyright David Brownell 2019
|
||||
# | Distributed under the Boost Software License, Version 1.0. See
|
||||
# | accompanying file LICENSE_1_0.txt or copy at
|
||||
# | http://www.boost.org/LICENSE_1_0.txt.
|
||||
# |
|
||||
# ----------------------------------------------------------------------
|
||||
"""Performs repository bootstrap activities (Enlistment and setup)"""
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import sys
|
||||
import textwrap
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import inflect as inflect_mod
|
||||
import six
|
||||
|
||||
import CommonEnvironment
|
||||
from CommonEnvironment.CallOnExit import CallOnExit
|
||||
from CommonEnvironment import CommandLine
|
||||
from CommonEnvironment import FileSystem
|
||||
from CommonEnvironment import Process
|
||||
from CommonEnvironment.Shell.All import CurrentShell
|
||||
from CommonEnvironment.StreamDecorator import StreamDecorator
|
||||
from CommonEnvironment import StringHelpers
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
_script_fullpath = CommonEnvironment.ThisFullpath()
|
||||
_script_dir, _script_name = os.path.split(_script_fullpath)
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
# Tuples in the form:
|
||||
# ("<repo name>", "<clone command line>", "<setup command suffix>" or None)
|
||||
_REPO_DATA = [
|
||||
("Common_EnvironmentEx", 'git clone https://github.com/davidbrownell/Common_EnvironmentEx "{output_dir}"', None),
|
||||
("Common_SimpleSchemaGenerator", 'git clone https://github.com/davidbrownell/Common_SimpleSchemaGenerator "{output_dir}"', None),
|
||||
]
|
||||
|
||||
_ACTIVATION_REPO_CONFIGURATION = None
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
inflect = inflect_mod.engine()
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
@CommandLine.EntryPoint
|
||||
@CommandLine.Constraints(
|
||||
output_dir=CommandLine.DirectoryTypeInfo(),
|
||||
output_stream=None,
|
||||
)
|
||||
def EntryPoint(
|
||||
output_dir,
|
||||
verbose=False,
|
||||
output_stream=sys.stdout,
|
||||
):
|
||||
with StreamDecorator(output_stream).DoneManager(
|
||||
line_prefix="",
|
||||
prefix="\nResults: ",
|
||||
suffix="\n",
|
||||
) as dm:
|
||||
repo_data = OrderedDict()
|
||||
enlistment_repositories = []
|
||||
|
||||
dm.stream.write("Calculating enlistment repositories...")
|
||||
with dm.stream.DoneManager(
|
||||
done_suffix=lambda: "{} found for enlistment".format(inflect.no("repository", len(enlistment_repositories))),
|
||||
suffix="\n",
|
||||
) as this_dm:
|
||||
for data in _REPO_DATA:
|
||||
repo_name = data[0]
|
||||
|
||||
repo_output_dir = os.path.join(output_dir, repo_name.replace("_", os.path.sep))
|
||||
if not os.path.isdir(repo_output_dir):
|
||||
enlistment_repositories.append((repo_output_dir, data))
|
||||
|
||||
repo_data[repo_output_dir] = data
|
||||
|
||||
repo_data[_script_dir] = (_script_dir, None, None)
|
||||
|
||||
if enlistment_repositories:
|
||||
dm.stream.write("Enlisting in {}...".format(inflect.no("repository", len(enlistment_repositories))))
|
||||
with dm.stream.DoneManager(
|
||||
suffix="\n",
|
||||
) as enlist_dm:
|
||||
for index, (output_dir, data) in enumerate(enlistment_repositories):
|
||||
enlist_dm.stream.write("'{}' ({} of {})...".format(data[0], index + 1, len(enlistment_repositories)))
|
||||
with enlist_dm.stream.DoneManager() as this_dm:
|
||||
FileSystem.MakeDirs(os.path.dirname(output_dir))
|
||||
|
||||
temp_directory = output_dir + "_tmp"
|
||||
|
||||
sink = six.moves.StringIO()
|
||||
|
||||
this_dm.result = Process.Execute(
|
||||
data[1].format(
|
||||
output_dir=temp_directory,
|
||||
),
|
||||
StreamDecorator(
|
||||
[
|
||||
sink,
|
||||
StreamDecorator(
|
||||
this_dm.stream if verbose else None,
|
||||
line_prefix="INFO: ",
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
if this_dm.result != 0:
|
||||
if not verbose:
|
||||
this_dm.stream.write(sink.getvalue())
|
||||
|
||||
return this_dm.result
|
||||
|
||||
shutil.move(temp_directory, output_dir)
|
||||
|
||||
dm.stream.write("Setting up {}...".format(inflect.no("repository", len(repo_data))))
|
||||
with dm.stream.DoneManager(
|
||||
suffix="\n",
|
||||
) as setup_dm:
|
||||
command_line_template = "Setup{} {{suffix}}".format(CurrentShell.ScriptExtension)
|
||||
|
||||
for index, (output_dir, data) in enumerate(six.iteritems(repo_data)):
|
||||
setup_dm.stream.write("'{}' ({} of {})...".format(data[0], index + 1, len(repo_data)))
|
||||
with setup_dm.stream.DoneManager() as this_dm:
|
||||
prev_dir = os.getcwd()
|
||||
os.chdir(output_dir)
|
||||
|
||||
with CallOnExit(lambda: os.chdir(prev_dir)):
|
||||
command_line = command_line_template.format(
|
||||
suffix=data[2] or "",
|
||||
)
|
||||
|
||||
if CurrentShell.CategoryName == "Windows":
|
||||
command_line = command_line.replace("=", "_EQ_")
|
||||
elif CurrentShell.CategoryName == "Linux":
|
||||
command_line = "./{}".format(command_line)
|
||||
|
||||
sink = six.moves.StringIO()
|
||||
|
||||
this_dm.result = Process.Execute(
|
||||
command_line,
|
||||
StreamDecorator(
|
||||
[
|
||||
sink,
|
||||
StreamDecorator(
|
||||
this_dm.stream if verbose else None,
|
||||
line_prefix="INFO: ",
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
if this_dm.result != 0:
|
||||
if not verbose:
|
||||
this_dm.stream.write(sink.getvalue())
|
||||
|
||||
return this_dm.result
|
||||
|
||||
dm.stream.write(
|
||||
StringHelpers.LeftJustify(
|
||||
textwrap.dedent(
|
||||
"""\
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
The enlistment and setup of all repositories was successful. To begin
|
||||
development activities, please run the following command. Note that
|
||||
this command must be run every time you open a new terminal window.
|
||||
|
||||
{}{} {}
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
""",
|
||||
).format(
|
||||
". " if CurrentShell.CategoryName == "Linux" else "",
|
||||
os.path.join(
|
||||
_script_dir,
|
||||
"Activate{}{}".format(
|
||||
".{}".format(os.getenv("DEVELOPMENT_ENVIRONMENT_ENVIRONMENT_NAME")) if os.getenv("DEVELOPMENT_ENVIRONMENT_ENVIRONMENT_NAME") != "DefaultEnv" else "",
|
||||
CurrentShell.ScriptExtension,
|
||||
),
|
||||
),
|
||||
_ACTIVATION_REPO_CONFIGURATION or "",
|
||||
),
|
||||
16,
|
||||
skip_first_line=False,
|
||||
),
|
||||
)
|
||||
|
||||
return dm.result
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
# ----------------------------------------------------------------------
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(CommandLine.Main())
|
||||
except KeyboardInterrupt:
|
||||
pass
|
Загрузка…
Ссылка в новой задаче