コード例 #1
0
 private void CheckNotDisposed()
 {
     if (IsDisposed)
     {
         throw _ectx.Except("SimpleFileHandle has already been disposed");
     }
 }
コード例 #2
0
        public void AddInputVariable(VariableBinding binding, Type type)
        {
            _ectx.AssertValue(binding);
            _ectx.AssertValue(type);

            if (binding is ArrayIndexVariableBinding)
            {
                type = Utils.MarshalInvoke(MakeArray <int>, type);
            }
            else if (binding is DictionaryKeyVariableBinding)
            {
                type = Utils.MarshalInvoke(MakeDictionary <int>, type);
            }

            EntryPointVariable v;

            if (!_vars.TryGetValue(binding.VariableName, out v))
            {
                v = new EntryPointVariable(_ectx, binding.VariableName, type);
                _vars[binding.VariableName] = v;
            }
            else if (v.Type != type)
            {
                throw _ectx.Except($"Variable '{v.Name}' is used as {v.Type} and as {type}");
            }
            v.MarkUsage(true);
        }
コード例 #3
0
        private bool ScanForComponents(IExceptionContext ectx, Type nestedType)
        {
            var attr = nestedType.GetTypeInfo().GetCustomAttributes(typeof(TlcModule.ComponentAttribute), true).FirstOrDefault()
                       as TlcModule.ComponentAttribute;

            if (attr == null)
            {
                return(false);
            }

            bool found = false;

            foreach (var faceType in nestedType.GetInterfaces())
            {
                var faceAttr = faceType.GetTypeInfo().GetCustomAttributes(typeof(TlcModule.ComponentKindAttribute), false).FirstOrDefault()
                               as TlcModule.ComponentKindAttribute;
                if (faceAttr == null)
                {
                    continue;
                }

                if (!typeof(IComponentFactory).IsAssignableFrom(faceType))
                {
                    throw ectx.Except("Component signature '{0}' doesn't inherit from '{1}'", faceType, typeof(IComponentFactory));
                }

                try
                {
                    // In order to populate from JSON, we need to invoke the parameterless ctor. Testing that this is possible.
                    Activator.CreateInstance(nestedType);
                }
                catch (MissingMemberException ex)
                {
                    throw ectx.Except(ex, "Component type '{0}' doesn't have a default constructor", faceType);
                }

                var info  = new ComponentInfo(ectx, faceType, faceAttr.Kind, nestedType, attr);
                var names = (info.Aliases ?? new string[0]).Concat(new[] { info.Name }).Distinct();
                _components.Add(info);

                foreach (var alias in names)
                {
                    var tag = $"{info.Kind}:{alias}";
                    if (_componentMap.ContainsKey(tag))
                    {
                        // Duplicate component name. We need to show a warning here.
                        // REVIEW: we will be able to do this once catalog becomes a part of env.
                        continue;
                    }
                    _componentMap[tag] = info;
                }
            }

            return(found);
        }
コード例 #4
0
        /// <summary>
        /// Performs checks on an EntryPoint input class equivalent to the checks that are done
        /// when parsing a JSON EntryPoint graph.
        ///
        /// Call this method from EntryPoint methods to ensure that range and required checks are performed
        /// in a consistent manner when EntryPoints are created directly from code.
        /// </summary>
        public static void CheckInputArgs(IExceptionContext ectx, object args)
        {
            foreach (var fieldInfo in args.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                var attr = fieldInfo.GetCustomAttributes(typeof(ArgumentAttribute), false).FirstOrDefault()
                           as ArgumentAttribute;
                if (attr == null || attr.Visibility == ArgumentAttribute.VisibilityType.CmdLineOnly)
                {
                    continue;
                }

                var fieldVal  = fieldInfo.GetValue(args);
                var fieldType = fieldInfo.FieldType;

                // Optionals are either left in their Implicit constructed state or
                // a new Explicit optional is constructed. They should never be set
                // to null.
                if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Optional <>) && fieldVal == null)
                {
                    throw ectx.Except("Field '{0}' is Optional<> and set to null instead of an explicit value.", fieldInfo.Name);
                }

                if (attr.IsRequired)
                {
                    bool equalToDefault;
                    if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(Optional <>))
                    {
                        equalToDefault = !((Optional)fieldVal).IsExplicit;
                    }
                    else
                    {
                        equalToDefault = fieldType.IsValueType ? Activator.CreateInstance(fieldType).Equals(fieldVal) : fieldVal == null;
                    }

                    if (equalToDefault)
                    {
                        throw ectx.Except("Field '{0}' is required but is not set.", fieldInfo.Name);
                    }
                }

                var rangeAttr = fieldInfo.GetCustomAttributes(typeof(TlcModule.RangeAttribute), false).FirstOrDefault()
                                as TlcModule.RangeAttribute;
                if (rangeAttr != null && fieldVal != null && !rangeAttr.IsValueWithinRange(fieldVal))
                {
                    throw ectx.Except("Field '{0}' is set to a value that falls outside the range bounds.", fieldInfo.Name);
                }
            }
        }
コード例 #5
0
        internal static Session LoadTFSessionByModelFilePath(IExceptionContext ectx, string modelFile, bool metaGraph = false)
        {
            if (string.IsNullOrEmpty(modelFile))
            {
                throw ectx.Except($"TensorFlow exception triggered while loading model from '{modelFile}'");
            }

            Graph graph;

            try
            {
                if (metaGraph)
                {
                    graph = LoadMetaGraph(modelFile);
                }
                else
                {
                    graph = new Graph();
                    graph.Import(modelFile, "");
                }
            }
            catch (Exception ex)
            {
#pragma warning disable MSML_NoMessagesForLoadContext
                throw ectx.ExceptDecode(ex, "Tensorflow exception triggered while loading model.");
#pragma warning restore MSML_NoMessagesForLoadContext
            }
            return(new Session(graph));
        }
コード例 #6
0
        public static VariableBinding Create(IExceptionContext ectx, string jsonString)
        {
            Contracts.AssertValue(ectx);
            ectx.AssertNonWhiteSpace(jsonString);
            var match = _variableRegex.Match(jsonString);

            if (!match.Success)
            {
                throw ectx.Except($"Unable to parse variable string '{jsonString}'");
            }

            if (match.Groups["NumericAccessor"].Success)
            {
                return(new ArrayIndexVariableBinding(
                           match.Groups["Name"].Value,
                           int.Parse(match.Groups["NumericAccessor"].Value)));
            }

            if (match.Groups["StringAccessor"].Success)
            {
                return(new DictionaryKeyVariableBinding(
                           match.Groups["Name"].Value,
                           match.Groups["StringAccessor"].Value));
            }

            return(new SimpleVariableBinding(match.Groups["Name"].Value));
        }
コード例 #7
0
 /// <summary>
 /// If an exception was ever set through <see cref="Set"/>, raise it as an appropriate
 /// inner exception. This should only be called just prior to dispose, when the workers
 /// have already finished. If there is no stored exception, this will do nothing. Note
 /// that this does not "expire" the exception, that is, if you were to call this again,
 /// it would throw the same exception.
 /// </summary>
 public void ThrowIfSet(IExceptionContext ectx)
 {
     if (_ex != null)
     {
         throw ectx.Except(_ex, "Exception thrown in {0}", _component);
     }
 }
コード例 #8
0
            public ColumnInfo(IExceptionContext ectx, string[] inputColumnNames, DataViewType[] inputTypes, string expression, string outputColumnName, int vectorInputColumn, LambdaNode node, int[] perm)
            {
                ectx.AssertNonEmpty(inputTypes);
                ectx.Assert(Utils.Size(inputTypes) == Utils.Size(inputColumnNames));
                ectx.AssertNonWhiteSpace(expression);
                ectx.AssertNonWhiteSpace(outputColumnName);
                ectx.AssertValue(node);

                InputColumnNames     = inputColumnNames;
                OutputColumnName     = outputColumnName;
                OutputColumnItemType = node.ResultType as PrimitiveDataViewType;
                ectx.AssertValue(OutputColumnItemType);
                VectorInputColumn = vectorInputColumn;
                Perm       = perm;
                Expression = expression;

                InputKinds = new InternalDataKind[inputTypes.Length];
                for (int i = 0; i < inputTypes.Length; i++)
                {
                    InputKinds[i] = inputTypes[i].GetRawKind();
                }

                Del = LambdaCompiler.Compile(out var errors, node);
                if (Utils.Size(errors) > 0)
                {
                    throw ectx.Except($"generating code failed: {errors[0].GetMessage()}");
                }
            }
コード例 #9
0
            internal ComponentInfo(IExceptionContext ectx, Type interfaceType, string kind, Type argumentType, TlcModule.ComponentAttribute attribute)
            {
                Contracts.AssertValueOrNull(ectx);
                ectx.AssertValue(interfaceType);
                ectx.AssertNonEmpty(kind);
                ectx.AssertValue(argumentType);
                ectx.AssertValue(attribute);

                Name        = attribute.Name;
                Description = attribute.Desc;
                if (string.IsNullOrWhiteSpace(attribute.FriendlyName))
                {
                    FriendlyName = Name;
                }
                else
                {
                    FriendlyName = attribute.FriendlyName;
                }

                Kind = kind;
                if (!IsValidName(Kind))
                {
                    throw ectx.Except("Invalid component kind: '{0}'", Kind);
                }

                Aliases = attribute.Aliases;
                if (!IsValidName(Name))
                {
                    throw ectx.Except("Component name '{0}' is not valid.", Name);
                }

                if (Aliases != null && Aliases.Any(x => !IsValidName(x)))
                {
                    throw ectx.Except("Component '{0}' has an invalid alias '{1}'", Name, Aliases.First(x => !IsValidName(x)));
                }

                if (!typeof(IComponentFactory).IsAssignableFrom(argumentType))
                {
                    throw ectx.Except("Component '{0}' must inherit from IComponentFactory", argumentType);
                }

                ArgumentType  = argumentType;
                InterfaceType = interfaceType;
            }
コード例 #10
0
        /// <summary>
        /// Fetches the value of the column by name, in the given row.
        /// Used by the evaluators to retrieve the metrics from the results IDataView.
        /// </summary>
        public static T Fetch <T>(IExceptionContext ectx, DataViewRow row, string name)
        {
            if (!row.Schema.TryGetColumnIndex(name, out int col))
            {
                throw ectx.Except($"Could not find column '{name}'");
            }
            T val = default;

            row.GetGetter <T>(col)(ref val);
            return(val);
        }
コード例 #11
0
            public void Log(ProgressChannel source, ProgressEvent.EventKind kind, ProgressEntry entry)
            {
                _ectx.AssertValue(source);
                _ectx.AssertValueOrNull(entry);

                if (kind == ProgressEvent.EventKind.Start)
                {
                    _ectx.Assert(entry == null);
                    lock (_lock)
                    {
                        // Figure out an appropriate name.
                        int    i             = 1;
                        var    name          = source.Name;
                        string nameCandidate = name;
                        while (!_namesUsed.Add(nameCandidate))
                        {
                            i++;
                            nameCandidate = string.Format("{0} #{1}", name, i);
                        }
                        var newInfo = new CalculationInfo(++_index, nameCandidate, source);
                        _infos.Add(newInfo);
                        _pendingEvents.Enqueue(new ProgressEvent(newInfo.Index, newInfo.Name, newInfo.StartTime, ProgressEvent.EventKind.Start));
                        return;
                    }
                }

                // Not a start event, so we won't modify the _infos.
                CalculationInfo info;

                lock (_lock)
                {
                    info = _infos.FirstOrDefault(x => x.Channel == source);
                    if (info == null)
                    {
                        throw _ectx.Except("Event sent after the calculation lifetime expired.");
                    }
                }
                switch (kind)
                {
                case ProgressEvent.EventKind.Stop:
                    _ectx.Assert(entry == null);
                    info.IsFinished = true;
                    _pendingEvents.Enqueue(new ProgressEvent(info.Index, info.Name, info.StartTime, ProgressEvent.EventKind.Stop));
                    break;

                default:
                    _ectx.Assert(entry != null);
                    _ectx.Assert(kind == ProgressEvent.EventKind.Progress);
                    _ectx.Assert(!info.IsFinished);
                    _pendingEvents.Enqueue(new ProgressEvent(info.Index, info.Name, info.StartTime, entry));
                    break;
                }
            }
コード例 #12
0
        private static IComponentFactory GetComponentJson(IExceptionContext ectx, Type signatureType, string name, JObject settings, ComponentCatalog catalog)
        {
            Contracts.AssertValue(ectx);
            ectx.AssertValue(signatureType);
            ectx.AssertNonEmpty(name);
            ectx.AssertValueOrNull(settings);
            ectx.AssertValue(catalog);

            if (!catalog.TryGetComponentKind(signatureType, out string kind))
            {
                throw ectx.Except($"Component type '{signatureType}' is not a valid signature type.");
            }

            if (!catalog.TryFindComponent(kind, name, out ComponentCatalog.ComponentInfo component))
            {
                var available = catalog.GetAllComponents(kind).Select(x => $"'{x.Name}'");
                throw ectx.Except($"Component '{name}' of kind '{kind}' is not found. Available components are: {string.Join(", ", available)}");
            }

            var inputBuilder = new InputBuilder(ectx, component.ArgumentType, catalog);

            if (settings != null)
            {
                foreach (var pair in settings)
                {
                    if (!inputBuilder.TrySetValueJson(pair.Key, pair.Value))
                    {
                        throw ectx.Except($"Unexpected value for component '{name}', field '{pair.Key}': '{pair.Value}'");
                    }
                }
            }

            var missing = inputBuilder.GetMissingValues().ToArray();

            if (missing.Length > 0)
            {
                throw ectx.Except($"The following required inputs were not provided for component '{name}': {string.Join(", ", missing)}");
            }
            return(inputBuilder.GetInstance() as IComponentFactory);
        }
コード例 #13
0
 /// <summary>
 /// Ensures that the given value can be assigned to an entry point field with
 /// type <paramref name="type"/>. This method will wrap the value in the option
 /// type if needed and throw an exception if the value isn't assignable.
 /// </summary>
 /// <param name="ectx">The exception context.</param>
 /// <param name="type">Type type of the field this value is to be assigned to.</param>
 /// <param name="value">The value, typically originates from either ParseJsonValue, or is an external, user-provided object.</param>
 private static object GetFieldAssignableValue(IExceptionContext ectx, Type type, object value)
 {
     Contracts.AssertValue(ectx);
     ectx.AssertValue(type);
     ectx.AssertValueOrNull(value);
     // If 'type' is optional, make 'value' into an optional (this is the case of optional input).
     value = MakeOptionalIfNeeded(ectx, value, type);
     if (value != null && !type.IsInstanceOfType(value))
     {
         throw ectx.Except($"Unexpected value type: {value.GetType()}");
     }
     return(value);
 }
コード例 #14
0
        private static T Fetch <T>(IExceptionContext ectx, DataViewRow row, string name)
        {
            var column = row.Schema.GetColumnOrNull(name);

            if (!column.HasValue)
            {
                throw ectx.Except($"Could not find column '{name}'");
            }
            T val = default;

            row.GetGetter <T>(column.Value)(ref val);
            return(val);
        }
コード例 #15
0
            internal EntryPointInfo(IExceptionContext ectx, MethodInfo method,
                                    TlcModule.EntryPointAttribute attribute, ObsoleteAttribute obsoleteAttribute)
            {
                Contracts.AssertValueOrNull(ectx);
                ectx.AssertValue(method);
                ectx.AssertValue(attribute);

                Name              = attribute.Name ?? string.Join(".", method.DeclaringType.Name, method.Name);
                Description       = attribute.Desc;
                Method            = method;
                ShortName         = attribute.ShortName;
                FriendlyName      = attribute.UserName;
                XmlInclude        = attribute.XmlInclude;
                ObsoleteAttribute = obsoleteAttribute;

                // There are supposed to be 2 parameters, env and input for non-macro nodes.
                // Macro nodes have a 3rd parameter, the entry point node.
                var parameters = method.GetParameters();

                if (parameters.Length != 2 && parameters.Length != 3)
                {
                    throw ectx.Except("Method '{0}' has {1} parameters, but must have 2 or 3", method.Name, parameters.Length);
                }
                if (parameters[0].ParameterType != typeof(IHostEnvironment))
                {
                    throw ectx.Except("Method '{0}', 1st parameter is {1}, but must be IHostEnvironment", method.Name, parameters[0].ParameterType);
                }
                InputType = parameters[1].ParameterType;
                var outputType = method.ReturnType;

                if (!outputType.IsClass)
                {
                    throw ectx.Except("Method '{0}' returns {1}, but must return a class", method.Name, outputType);
                }
                OutputType = outputType;

                InputKinds  = FindEntryPointKinds(InputType);
                OutputKinds = FindEntryPointKinds(OutputType);
            }
コード例 #16
0
 private static void CheckRange(long src, uint dst, IExceptionContext ectx = null)
 {
     if (src < 0 || src >= uint.MaxValue)
     {
         if (ectx != null)
         {
             ectx.Except("Value long {0} cannot be converted into uint.", src);
         }
         else
         {
             Contracts.Except("Value long {0} cannot be converted into uint.", src);
         }
     }
 }
コード例 #17
0
        int GetColumnIndex(IExceptionContext ch, string name)
        {
            if (string.IsNullOrEmpty(name))
            {
                return(-1);
            }
            int index;

            if (!_input.Schema.TryGetColumnIndex(name, out index))
            {
                throw ch.Except("Unable to find column '{0}'.", name);
            }
            return(index);
        }
コード例 #18
0
 private static void CheckRange(float src, ulong dst, IExceptionContext ectx = null)
 {
     if (src < 0)
     {
         if (ectx != null)
         {
             ectx.Except("Value long {0} cannot be converted into ulong.", src);
         }
         else
         {
             Contracts.Except("Value long {0} cannot be converted into ulong.", src);
         }
     }
 }
コード例 #19
0
        /// <summary>
        /// Searches for the given column name in the schema. This method applies a
        /// common policy that throws an exception if the column is not found
        /// and the column name was explicitly specified. If the column is not found
        /// and the column name was not explicitly specified, it returns null.
        /// </summary>
        public static string FindColumnOrNull(IExceptionContext ectx, DataViewSchema schema, Optional <string> value)
        {
            Contracts.CheckValueOrNull(ectx);
            ectx.CheckValue(schema, nameof(schema));
            ectx.CheckValue(value, nameof(value));

            if (value == "")
            {
                return(null);
            }
            if (schema.GetColumnOrNull(value) == null)
            {
                if (value.IsExplicit)
                {
                    throw ectx.Except("Column '{0}' not found", value);
                }
                return(null);
            }
            return(value);
        }
コード例 #20
0
        public static string FindColumn(IExceptionContext ectx, Schema schema, Optional <string> value)
        {
            Contracts.CheckValueOrNull(ectx);
            ectx.CheckValue(schema, nameof(schema));
            ectx.CheckValue(value, nameof(value));

            if (string.IsNullOrEmpty(value?.Value))
            {
                return(null);
            }
            if (!schema.TryGetColumnIndex(value, out int col))
            {
                if (value.IsExplicit)
                {
                    throw ectx.Except("Column '{0}' not found", value);
                }
                return(null);
            }
            return(value);
        }
コード例 #21
0
        internal static TFSession LoadTFSession(IExceptionContext ectx, byte[] modelBytes, string modelFile = null)
        {
            var graph = new TFGraph();

            try
            {
                graph.Import(modelBytes, "");
            }
            catch (Exception ex)
            {
                if (!string.IsNullOrEmpty(modelFile))
                {
                    throw ectx.Except($"TensorFlow exception triggered while loading model from '{modelFile}'");
                }
#pragma warning disable MSML_NoMessagesForLoadContext
                throw ectx.ExceptDecode(ex, "Tensorflow exception triggered while loading model.");
#pragma warning restore MSML_NoMessagesForLoadContext
            }
            return(new TFSession(graph));
        }
コード例 #22
0
        public static ComponentCatalog.LoadableClassInfo CheckTrainer <TSig>(IExceptionContext ectx, SubComponent <ITrainer, TSig> trainer, string dataFile)
        {
            Contracts.CheckValueOrNull(ectx);
            ectx.CheckUserArg(trainer.IsGood(), nameof(TrainCommand.Arguments.Trainer), "A trainer is required.");

            var info = ComponentCatalog.GetLoadableClassInfo <TSig>(trainer.Kind);

            if (info == null)
            {
                throw ectx.ExceptUserArg(nameof(TrainCommand.Arguments.Trainer), "Unknown trainer: '{0}'", trainer.Kind);
            }
            if (!typeof(ITrainer).IsAssignableFrom(info.Type))
            {
                throw ectx.Except("Loadable class '{0}' does not implement 'ITrainer'", info.LoadNames[0]);
            }
            if (string.IsNullOrWhiteSpace(dataFile))
            {
                throw ectx.ExceptUserArg(nameof(TrainCommand.Arguments.DataFile), "Data file must be defined.");
            }
            return(info);
        }
コード例 #23
0
 /// <summary>
 /// Returns a standard exception for responding to an invalid call to GetAnnotation.
 /// </summary>
 public static Exception ExceptGetAnnotation(this IExceptionContext ctx) => ctx.Except("Invalid call to GetAnnotation");
コード例 #24
0
 internal static Exception ExceptGetMetadata(this IExceptionContext ctx) => ctx.Except("Invalid call to GetMetadata");
コード例 #25
0
        private static JArray BuildInputManifest(IExceptionContext ectx, Type inputType, ModuleCatalog catalog)
        {
            Contracts.AssertValueOrNull(ectx);
            ectx.AssertValue(inputType);
            ectx.AssertValue(catalog);

            // Instantiate a value of the input, to pull defaults out of.
            var defaults = Activator.CreateInstance(inputType);

            var inputs = new List <KeyValuePair <Double, JObject> >();

            foreach (var fieldInfo in inputType.GetFields())
            {
                var inputAttr = fieldInfo.GetCustomAttributes(typeof(ArgumentAttribute), false).FirstOrDefault() as ArgumentAttribute;
                if (inputAttr == null || inputAttr.Visibility == ArgumentAttribute.VisibilityType.CmdLineOnly)
                {
                    continue;
                }
                var jo = new JObject();
                jo[FieldNames.Name] = inputAttr.Name ?? fieldInfo.Name;
                jo[FieldNames.Type] = BuildTypeToken(ectx, fieldInfo, fieldInfo.FieldType, catalog);
                jo[FieldNames.Desc] = inputAttr.HelpText;
                if (inputAttr.Aliases != null)
                {
                    jo[FieldNames.Aliases] = new JArray(inputAttr.Aliases);
                }

                jo[FieldNames.Required]   = inputAttr.IsRequired;
                jo[FieldNames.SortOrder]  = inputAttr.SortOrder;
                jo[FieldNames.IsNullable] = fieldInfo.FieldType.IsGenericType && (fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(Nullable <>));

                var defaultValue = fieldInfo.GetValue(defaults);
                var dataType     = TlcModule.GetDataType(fieldInfo.FieldType);
                if (!inputAttr.IsRequired || (dataType != TlcModule.DataKind.Unknown && defaultValue != null))
                {
                    jo[FieldNames.Default] = BuildValueToken(ectx, defaultValue, fieldInfo.FieldType, catalog);
                }

                if (fieldInfo.FieldType.IsGenericType &&
                    fieldInfo.FieldType.GetGenericTypeDefinition() == typeof(Optional <>))
                {
                    var val = fieldInfo.GetValue(defaults) as Optional;
                    if (val == null && !inputAttr.IsRequired)
                    {
                        throw ectx.Except("Field '{0}' is an Optional<> type but is null by default, instead of set to a constructed implicit default.", fieldInfo.Name);
                    }
                    if (val != null && val.IsExplicit)
                    {
                        throw ectx.Except("Field '{0}' is an Optional<> type with a non-implicit default value.", fieldInfo.Name);
                    }
                }

                var rangeAttr = fieldInfo.GetCustomAttributes(typeof(TlcModule.RangeAttribute), false).FirstOrDefault() as TlcModule.RangeAttribute;
                if (rangeAttr != null)
                {
                    if (!TlcModule.IsNumericKind(TlcModule.GetDataType(fieldInfo.FieldType)))
                    {
                        throw ectx.Except("Field '{0}' has a range but is of a non-numeric type.", fieldInfo.Name);
                    }

                    if (!rangeAttr.Type.Equals(fieldInfo.FieldType))
                    {
                        throw ectx.Except("Field '{0}' has a range attribute that uses a type which is not equal to the field's FieldType.", fieldInfo.Name);
                    }

                    var jRange = new JObject();
                    if (rangeAttr.Sup != null)
                    {
                        jRange[FieldNames.Range.Sup] = JToken.FromObject(rangeAttr.Sup);
                    }
                    if (rangeAttr.Inf != null)
                    {
                        jRange[FieldNames.Range.Inf] = JToken.FromObject(rangeAttr.Inf);
                    }
                    if (rangeAttr.Max != null)
                    {
                        jRange[FieldNames.Range.Max] = JToken.FromObject(rangeAttr.Max);
                    }
                    if (rangeAttr.Min != null)
                    {
                        jRange[FieldNames.Range.Min] = JToken.FromObject(rangeAttr.Min);
                    }
                    jo[FieldNames.Range.Type] = jRange;
                }

                // Handle deprecated/obsolete attributes, passing along the message to the manifest.
                if (fieldInfo.GetCustomAttributes(typeof(ObsoleteAttribute), false).FirstOrDefault() is ObsoleteAttribute obsAttr)
                {
                    var jParam = new JObject
                    {
                        [FieldNames.Deprecated.Message] = JToken.FromObject(obsAttr.Message),
                    };
                    jo[FieldNames.Deprecated.ToString()] = jParam;
                }

                if (fieldInfo.GetCustomAttributes(typeof(TlcModule.SweepableLongParamAttribute), false).FirstOrDefault() is TlcModule.SweepableLongParamAttribute slpAttr)
                {
                    var jParam = new JObject
                    {
                        [FieldNames.SweepableLongParam.RangeType] = JToken.FromObject("Long"),
                        [FieldNames.SweepableLongParam.Min]       = JToken.FromObject(slpAttr.Min),
                        [FieldNames.SweepableLongParam.Max]       = JToken.FromObject(slpAttr.Max)
                    };
                    if (slpAttr.StepSize != null)
                    {
                        jParam[FieldNames.SweepableLongParam.StepSize] = JToken.FromObject(slpAttr.StepSize);
                    }
                    if (slpAttr.NumSteps != null)
                    {
                        jParam[FieldNames.SweepableLongParam.NumSteps] = JToken.FromObject(slpAttr.NumSteps);
                    }
                    if (slpAttr.IsLogScale)
                    {
                        jParam[FieldNames.SweepableLongParam.IsLogScale] = JToken.FromObject(true);
                    }
                    jo[FieldNames.SweepableLongParam.ToString()] = jParam;
                }

                if (fieldInfo.GetCustomAttributes(typeof(TlcModule.SweepableFloatParamAttribute), false).FirstOrDefault() is TlcModule.SweepableFloatParamAttribute sfpAttr)
                {
                    var jParam = new JObject
                    {
                        [FieldNames.SweepableFloatParam.RangeType] = JToken.FromObject("Float"),
                        [FieldNames.SweepableFloatParam.Min]       = JToken.FromObject(sfpAttr.Min),
                        [FieldNames.SweepableFloatParam.Max]       = JToken.FromObject(sfpAttr.Max)
                    };
                    if (sfpAttr.StepSize != null)
                    {
                        jParam[FieldNames.SweepableFloatParam.StepSize] = JToken.FromObject(sfpAttr.StepSize);
                    }
                    if (sfpAttr.NumSteps != null)
                    {
                        jParam[FieldNames.SweepableFloatParam.NumSteps] = JToken.FromObject(sfpAttr.NumSteps);
                    }
                    if (sfpAttr.IsLogScale)
                    {
                        jParam[FieldNames.SweepableFloatParam.IsLogScale] = JToken.FromObject(true);
                    }
                    jo[FieldNames.SweepableFloatParam.ToString()] = jParam;
                }

                if (fieldInfo.GetCustomAttributes(typeof(TlcModule.SweepableDiscreteParamAttribute), false).FirstOrDefault() is TlcModule.SweepableDiscreteParamAttribute sdpAttr)
                {
                    var jParam = new JObject
                    {
                        [FieldNames.SweepableDiscreteParam.RangeType] = JToken.FromObject("Discrete"),
                        [FieldNames.SweepableDiscreteParam.Options]   = JToken.FromObject(sdpAttr.Options)
                    };
                    jo[FieldNames.SweepableDiscreteParam.ToString()] = jParam;
                }

                inputs.Add(new KeyValuePair <Double, JObject>(inputAttr.SortOrder, jo));
            }
            return(new JArray(inputs.OrderBy(x => x.Key).Select(x => x.Value).ToArray()));
        }
コード例 #26
0
        private static JToken BuildTypeToken(IExceptionContext ectx, FieldInfo fieldInfo, Type type, ModuleCatalog catalog)
        {
            Contracts.AssertValueOrNull(ectx);
            ectx.AssertValue(type);
            ectx.AssertValue(catalog);

            // REVIEW: Allows newly introduced types to not break the manifest bulding process.
            // Where possible, these types should be replaced by component kinds.
            if (type == typeof(CommonInputs.IEvaluatorInput) ||
                type == typeof(CommonOutputs.IEvaluatorOutput))
            {
                var jo         = new JObject();
                var typeString = $"{type}".Replace("Microsoft.ML.Runtime.EntryPoints.", "");
                jo[FieldNames.Kind]     = "EntryPoint";
                jo[FieldNames.ItemType] = typeString;
                return(jo);
            }
            type = CSharpGeneratorUtils.ExtractOptionalOrNullableType(type);

            // Dive inside Var.
            if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Var <>))
            {
                type = type.GetGenericArguments()[0];
            }

            var typeEnum = TlcModule.GetDataType(type);

            switch (typeEnum)
            {
            case TlcModule.DataKind.Unknown:
                var jo = new JObject();
                if (type == typeof(JArray))
                {
                    jo[FieldNames.Kind]     = TlcModule.DataKind.Array.ToString();
                    jo[FieldNames.ItemType] = "Node";
                    return(jo);
                }
                if (type == typeof(JObject))
                {
                    return("Bindings");
                }
                var fields = BuildInputManifest(ectx, type, catalog);
                if (fields.Count == 0)
                {
                    throw ectx.Except("Unexpected parameter type: {0}", type);
                }
                jo[FieldNames.Kind]   = "Struct";
                jo[FieldNames.Fields] = fields;
                return(jo);

            case TlcModule.DataKind.Float:
            case TlcModule.DataKind.Int:
            case TlcModule.DataKind.UInt:
            case TlcModule.DataKind.Char:
            case TlcModule.DataKind.String:
            case TlcModule.DataKind.Bool:
            case TlcModule.DataKind.DataView:
            case TlcModule.DataKind.TransformModel:
            case TlcModule.DataKind.PredictorModel:
            case TlcModule.DataKind.FileHandle:
                return(typeEnum.ToString());

            case TlcModule.DataKind.Enum:
                jo = new JObject();
                jo[FieldNames.Kind] = typeEnum.ToString();
                var values = Enum.GetNames(type);
                jo[FieldNames.Values] = new JArray(values);
                return(jo);

            case TlcModule.DataKind.Array:
                jo = new JObject();
                jo[FieldNames.Kind]     = typeEnum.ToString();
                jo[FieldNames.ItemType] = BuildTypeToken(ectx, fieldInfo, type.GetElementType(), catalog);
                return(jo);

            case TlcModule.DataKind.Dictionary:
                jo = new JObject();
                jo[FieldNames.Kind]     = typeEnum.ToString();
                jo[FieldNames.ItemType] = BuildTypeToken(ectx, fieldInfo, type.GetGenericArguments()[1], catalog);
                return(jo);

            case TlcModule.DataKind.Component:
                string kind;
                if (!catalog.TryGetComponentKind(type, out kind))
                {
                    throw ectx.Except("Field '{0}' is a component of unknown kind", fieldInfo.Name);
                }

                jo = new JObject();
                jo[FieldNames.Kind]          = typeEnum.ToString();
                jo[FieldNames.ComponentKind] = kind;
                return(jo);

            case TlcModule.DataKind.State:
                jo = new JObject();
                var typeString = $"{type}".Replace("Microsoft.ML.Runtime.Interfaces.", "");
                jo[FieldNames.Kind]     = "C# Object";
                jo[FieldNames.ItemType] = typeString;
                return(jo);

            default:
                ectx.Assert(false);
                throw ectx.ExceptNotSupp();
            }
        }
コード例 #27
0
        /// <summary>
        /// Build a token for component default value. This will look up the component in the catalog, and if it finds an entry, it will
        /// build a JSON structure that would be parsed into the default value.
        ///
        /// This is an inherently fragile setup in case when the factory is not trivial, but it will work well for 'property bag' factories
        /// that we are currently using.
        /// </summary>
        private static JToken BuildComponentToken(IExceptionContext ectx, IComponentFactory value, ModuleCatalog catalog)
        {
            Contracts.AssertValueOrNull(ectx);
            ectx.AssertValue(value);
            ectx.AssertValue(catalog);

            var type = value.GetType();

            ModuleCatalog.ComponentInfo componentInfo;
            if (!catalog.TryFindComponent(type, out componentInfo))
            {
                // The default component is not in the catalog. This is, technically, allowed, but it means that there's no JSON representation
                // for the default value. We will emit the one the won't parse back.
                return(new JValue("(custom component)"));
            }

            ectx.Assert(componentInfo.ArgumentType == type);

            // Try to invoke default ctor for the factory to obtain defaults.
            object defaults;

            try
            {
                defaults = Activator.CreateInstance(type);
            }
            catch (MissingMemberException ex)
            {
                // There was no default constructor found.
                // This should never happen, since ModuleCatalog would error out if there is no default ctor.
                ectx.Assert(false);
                throw ectx.Except(ex, "Couldn't find default constructor");
            }

            var jResult   = new JObject();
            var jSettings = new JObject();

            jResult[FieldNames.Name] = componentInfo.Name;

            // Iterate over all fields of the factory object, and compare the values with the defaults.
            // If the value differs, insert it into the settings object.
            bool anyValue = false;

            foreach (var fieldInfo in type.GetFields())
            {
                var attr = fieldInfo.GetCustomAttributes(typeof(ArgumentAttribute), false).FirstOrDefault()
                           as ArgumentAttribute;
                if (attr == null || attr.Visibility == ArgumentAttribute.VisibilityType.CmdLineOnly)
                {
                    continue;
                }
                ectx.Assert(!fieldInfo.IsStatic && !fieldInfo.IsInitOnly && !fieldInfo.IsLiteral);

                bool   needValue   = false;
                object actualValue = fieldInfo.GetValue(value);
                if (attr.IsRequired)
                {
                    needValue = true;
                }
                else
                {
                    object defaultValue = fieldInfo.GetValue(defaults);
                    needValue = !Equals(actualValue, defaultValue);
                }
                if (!needValue)
                {
                    continue;
                }
                jSettings[attr.Name ?? fieldInfo.Name] = BuildValueToken(ectx, actualValue, fieldInfo.FieldType, catalog);
                anyValue = true;
            }

            if (anyValue)
            {
                jResult[FieldNames.Settings] = jSettings;
            }
            return(jResult);
        }
コード例 #28
0
 /// <summary>
 /// Returns a standard exception for responding to an invalid call to GetMetadata.
 /// </summary>
 public static Exception ExceptGetMetadata(this IExceptionContext ctx)
 {
     return(ctx.Except("Invalid call to GetMetadata"));
 }
コード例 #29
0
        private static object ParseJsonValue(IExceptionContext ectx, Type type, Attributes attributes, JToken value, ComponentCatalog catalog)
        {
            Contracts.AssertValue(ectx);
            ectx.AssertValue(type);
            ectx.AssertValueOrNull(value);
            ectx.AssertValue(catalog);

            if (value == null)
            {
                return(null);
            }

            if (value is JValue val && val.Value == null)
            {
                return(null);
            }

            if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Optional <>) || type.GetGenericTypeDefinition() == typeof(Nullable <>)))
            {
                if (type.GetGenericTypeDefinition() == typeof(Optional <>) && value.HasValues)
                {
                    value = value.Values().FirstOrDefault();
                }
                type = type.GetGenericArguments()[0];
            }

            if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Var <>)))
            {
                string varName = value.Value <string>();
                ectx.Check(VariableBinding.IsBindingToken(value), "Variable name expected.");
                var variable   = Activator.CreateInstance(type) as IVarSerializationHelper;
                var varBinding = VariableBinding.Create(ectx, varName);
                variable.VarName = varBinding.VariableName;
                return(variable);
            }

            if (type == typeof(JArray) && value is JArray)
            {
                return(value);
            }

            TlcModule.DataKind dt = TlcModule.GetDataType(type);

            try
            {
                switch (dt)
                {
                case TlcModule.DataKind.Bool:
                    return(value.Value <bool>());

                case TlcModule.DataKind.String:
                    return(value.Value <string>());

                case TlcModule.DataKind.Char:
                    return(value.Value <char>());

                case TlcModule.DataKind.Enum:
                    if (!Enum.IsDefined(type, value.Value <string>()))
                    {
                        throw ectx.Except($"Requested value '{value.Value<string>()}' is not a member of the Enum type '{type.Name}'");
                    }
                    return(Enum.Parse(type, value.Value <string>()));

                case TlcModule.DataKind.Float:
                    if (type == typeof(double))
                    {
                        return(value.Value <double>());
                    }
                    else if (type == typeof(float))
                    {
                        return(value.Value <float>());
                    }
                    else
                    {
                        ectx.Assert(false);
                        throw ectx.ExceptNotSupp();
                    }

                case TlcModule.DataKind.Array:
                    var ja = value as JArray;
                    ectx.Check(ja != null, "Expected array value");
                    Func <IExceptionContext, JArray, Attributes, ComponentCatalog, object> makeArray = MakeArray <int>;
                    return(Utils.MarshalInvoke(makeArray, type.GetElementType(), ectx, ja, attributes, catalog));

                case TlcModule.DataKind.Int:
                    if (type == typeof(long))
                    {
                        return(value.Value <long>());
                    }
                    if (type == typeof(int))
                    {
                        return(value.Value <int>());
                    }
                    ectx.Assert(false);
                    throw ectx.ExceptNotSupp();

                case TlcModule.DataKind.UInt:
                    if (type == typeof(ulong))
                    {
                        return(value.Value <ulong>());
                    }
                    if (type == typeof(uint))
                    {
                        return(value.Value <uint>());
                    }
                    ectx.Assert(false);
                    throw ectx.ExceptNotSupp();

                case TlcModule.DataKind.Dictionary:
                    ectx.Check(value is JObject, "Expected object value");
                    Func <IExceptionContext, JObject, Attributes, ComponentCatalog, object> makeDict = MakeDictionary <int>;
                    return(Utils.MarshalInvoke(makeDict, type.GetGenericArguments()[1], ectx, (JObject)value, attributes, catalog));

                case TlcModule.DataKind.Component:
                    var jo = value as JObject;
                    ectx.Check(jo != null, "Expected object value");
                    // REVIEW: consider accepting strings alone.
                    var jName = jo[FieldNames.Name];
                    ectx.Check(jName != null, "Field '" + FieldNames.Name + "' is required for component.");
                    ectx.Check(jName is JValue, "Expected '" + FieldNames.Name + "' field to be a string.");
                    var name = jName.Value <string>();
                    ectx.Check(jo[FieldNames.Settings] == null || jo[FieldNames.Settings] is JObject,
                               "Expected '" + FieldNames.Settings + "' field to be an object");
                    return(GetComponentJson(ectx, type, name, jo[FieldNames.Settings] as JObject, catalog));

                default:
                    var settings = value as JObject;
                    ectx.Check(settings != null, "Expected object value");
                    var inputBuilder = new InputBuilder(ectx, type, catalog);

                    if (inputBuilder._fields.Length == 0)
                    {
                        throw ectx.Except($"Unsupported input type: {dt}");
                    }

                    if (settings != null)
                    {
                        foreach (var pair in settings)
                        {
                            if (!inputBuilder.TrySetValueJson(pair.Key, pair.Value))
                            {
                                throw ectx.Except($"Unexpected value for component '{type}', field '{pair.Key}': '{pair.Value}'");
                            }
                        }
                    }

                    var missing = inputBuilder.GetMissingValues().ToArray();
                    if (missing.Length > 0)
                    {
                        throw ectx.Except($"The following required inputs were not provided for component '{type}': {string.Join(", ", missing)}");
                    }
                    return(inputBuilder.GetInstance());
                }
            }
            catch (FormatException ex)
            {
                if (ex.IsMarked())
                {
                    throw;
                }
                throw ectx.Except(ex, $"Failed to parse JSON value '{value}' as {type}");
            }
        }