Skip to content

Commit

Permalink
Merge branch 'main' into gregli/regex-min
Browse files Browse the repository at this point in the history
  • Loading branch information
gregli-msft authored Jan 14, 2025
2 parents 147ddc5 + 0fa1968 commit fa2e0d1
Show file tree
Hide file tree
Showing 149 changed files with 14,457 additions and 819 deletions.
8 changes: 7 additions & 1 deletion releasenotes/releasenotes-1.3.0-rc.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
`IsType(UntypedObject, Type)`\
`AsType(UntypedObject, Type)`

## Updated function behaviors:
- TimeValue function (https://github.com/microsoft/Power-Fx/pull/2731)
- Support for am/pm designators: `TimeValue("6:00pm")` now works (used to return an error)
- Better validation: `TimeValue("1")` would return a time value (equivalent to `Time(0,0,0)`), now returns an error
- Better support for wrapping times around the 24-hour mark: `TimeValue("27:00:00")` now returns the same as `Time(3,0,0)`, consistent with Excel's behavior.

## Other:
- Untyped object
- Read a field from an untyped object by index (https://github.com/microsoft/Power-Fx/pull/2555):
Expand All @@ -39,4 +45,4 @@
- Setting an untyped object via deep mutation is now supported (https://github.com/microsoft/Power-Fx/pull/2548):
`Set(untypedObject.Field, 99)`
`Set(Index(untypedObject, 1).Field, 99) // Reference field by name`
`Set(Index(Index(untypedObject, 1), 1), 99) // Reference field by index`
`Set(Index(Index(untypedObject, 1), 1), 99) // Reference field by index`
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ namespace Microsoft.PowerFx.Connectors
{
public static class Constants
{
public const string XMsAiSensitivity = "x-ms-ai-sensitivity";
public const string XMsBodyName = "x-bodyName";
public const string XMsCapabilities = "x-ms-capabilities";
public const string XMsDynamicList = "x-ms-dynamic-list";
Expand All @@ -17,8 +18,8 @@ public static class Constants
public const string XMsKeyOrder = "x-ms-keyOrder";
public const string XMsKeyType = "x-ms-keyType";
public const string XMsMediaKind = "x-ms-media-kind";
public const string XMsNotificationUrl = "x-ms-notification-url";
public const string XMsNotificationContent = "x-ms-notification-content";
public const string XMsNotificationUrl = "x-ms-notification-url";
public const string XMsPageable = "x-ms-pageable";
public const string XMsPermission = "x-ms-permission";
public const string XMsRelationships = "x-ms-relationships";
Expand Down
70 changes: 38 additions & 32 deletions src/libraries/Microsoft.PowerFx.Connectors/ConnectorFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
using Microsoft.PowerFx.Intellisense;
using Microsoft.PowerFx.Types;
using static Microsoft.PowerFx.Connectors.ConnectorHelperFunctions;

#pragma warning disable SA1117

namespace Microsoft.PowerFx.Connectors
{
Expand Down Expand Up @@ -154,7 +156,7 @@ public IReadOnlyCollection<ErrorResourceKey> Warnings
/// <summary>
/// Return type of the function.
/// </summary>
public FormulaType ReturnType => Operation.GetReturnType(ConnectorSettings.Compatibility);
public FormulaType ReturnType => Operation.GetReturnType(ConnectorSettings);

/// <summary>
/// Minimum number of arguments.
Expand Down Expand Up @@ -292,15 +294,16 @@ public ConnectorType ReturnParameterType
// Those properties are only used by HttpFunctionInvoker
internal ConnectorParameterInternals _internals = null;

private readonly ConnectorLogger _configurationLogger = null;
private readonly ConnectorLogger _configurationLogger = null;

internal ConnectorFunction(OpenApiOperation openApiOperation, bool isSupported, string notSupportedReason, string name, string operationPath, HttpMethod httpMethod, ConnectorSettings connectorSettings, List<ConnectorFunction> functionList, ConnectorLogger configurationLogger, IReadOnlyDictionary<string, FormulaValue> globalValues)
internal ConnectorFunction(OpenApiOperation openApiOperation, bool isSupported, string notSupportedReason, string name, string operationPath, HttpMethod httpMethod, ConnectorSettings connectorSettings, List<ConnectorFunction> functionList,
ConnectorLogger configurationLogger, IReadOnlyDictionary<string, FormulaValue> globalValues)
{
Operation = openApiOperation;
Name = name;
OperationPath = operationPath;
HttpMethod = httpMethod;
ConnectorSettings = connectorSettings;
ConnectorSettings = connectorSettings;
GlobalContext = new ConnectorGlobalContext(functionList ?? throw new ArgumentNullException(nameof(functionList)), globalValues);

_configurationLogger = configurationLogger;
Expand Down Expand Up @@ -985,7 +988,7 @@ private async Task<ConnectorType> GetConnectorSuggestionsFromDynamicSchemaAsync(
return null;
}

ConnectorType connectorType = GetConnectorType(cds.ValuePath, sv, ConnectorSettings.Compatibility);
ConnectorType connectorType = GetConnectorType(cds.ValuePath, sv, ConnectorSettings);

if (connectorType.HasErrors)
{
Expand All @@ -999,29 +1002,32 @@ private async Task<ConnectorType> GetConnectorSuggestionsFromDynamicSchemaAsync(
return connectorType;
}

internal static ConnectorType GetConnectorType(string valuePath, StringValue sv, ConnectorCompatibility compatibility)
internal static ConnectorType GetConnectorType(string valuePath, StringValue sv, ConnectorSettings settings)
{
JsonElement je = ExtractFromJson(sv, valuePath);
return GetConnectorTypeInternal(compatibility, je);
return GetConnectorTypeInternal(settings, je);
}

// Only called by ConnectorTable.GetSchema
// Returns a FormulaType with AssociatedDataSources set (done in AddTabularDataSource)
internal static ConnectorType GetCdpTableType(ICdpTableResolver tableResolver, string connectorName, string valuePath, StringValue stringValue, List<SqlRelationship> sqlRelationships, ConnectorCompatibility compatibility, string datasetName, out string name, out string displayName, out TableDelegationInfo delegationInfo)
internal static ConnectorType GetCdpTableType(ICdpTableResolver tableResolver, string connectorName, string tableName, string valuePath, StringValue stringValue, ConnectorSettings settings, string datasetName,
out string name, out string displayName, out TableDelegationInfo delegationInfo, out IEnumerable<OptionSet> optionSets)
{
// There are some errors when parsing this Json payload but that's not a problem here as we only need x-ms-capabilities parsing to work
OpenApiReaderSettings oars = new OpenApiReaderSettings() { RuleSet = DefaultValidationRuleSet };
ISwaggerSchema tableSchema = SwaggerSchema.New(new OpenApiStringReader(oars).ReadFragment<OpenApiSchema>(stringValue.Value, OpenApi.OpenApiSpecVersion.OpenApi2_0, out OpenApiDiagnostic _));

ServiceCapabilities serviceCapabilities = tableSchema.GetTableCapabilities();
ConnectorPermission tablePermission = tableSchema.GetPermission();
ConnectorPermission tablePermission = tableSchema.GetPermission();

JsonElement jsonElement = ExtractFromJson(stringValue, valuePath, out name, out displayName);
bool isTableReadOnly = tablePermission == ConnectorPermission.PermissionReadOnly;
IList<ReferencedEntity> referencedEntities = GetReferenceEntities(connectorName, stringValue);

ConnectorType connectorType = new ConnectorType(jsonElement, compatibility, sqlRelationships, referencedEntities, datasetName, name, connectorName, tableResolver, serviceCapabilities, isTableReadOnly);

SymbolTable symbolTable = new SymbolTable();
ConnectorType connectorType = new ConnectorType(jsonElement, tableName, symbolTable, settings, referencedEntities, datasetName, name, connectorName, tableResolver, serviceCapabilities, isTableReadOnly);
delegationInfo = ((DataSourceInfo)connectorType.FormulaType._type.AssociatedDataSources.First()).DelegationInfo;
optionSets = symbolTable.OptionSets.Select(kvp => kvp.Value);

return connectorType;
}
Expand Down Expand Up @@ -1075,18 +1081,13 @@ internal class SalesForceReferencedEntity
public bool RestrictedDelete { get; set; }
}

private static ConnectorType GetConnectorTypeInternal(ConnectorCompatibility compatibility, JsonElement je)
private static ConnectorType GetConnectorTypeInternal(ConnectorSettings settings, JsonElement je)
{
OpenApiReaderSettings oars = new OpenApiReaderSettings() { RuleSet = DefaultValidationRuleSet };
OpenApiSchema schema = new OpenApiStringReader(oars).ReadFragment<OpenApiSchema>(je.ToString(), OpenApi.OpenApiSpecVersion.OpenApi2_0, out OpenApiDiagnostic diag);

return new ConnectorType(SwaggerSchema.New(schema), compatibility);
}

private static ConnectorType GetJsonConnectorTypeInternal(ConnectorCompatibility compatibility, JsonElement je, IList<SqlRelationship> sqlRelationships)
{
return new ConnectorType(je, compatibility, sqlRelationships);
}
return new ConnectorType(SwaggerSchema.New(schema), settings);
}

private async Task<ConnectorType> GetConnectorSuggestionsFromDynamicPropertyAsync(NamedValue[] knownParameters, BaseRuntimeConnectorContext runtimeContext, ConnectorDynamicProperty cdp, CancellationToken cancellationToken)
{
Expand All @@ -1106,7 +1107,7 @@ private async Task<ConnectorType> GetConnectorSuggestionsFromDynamicPropertyAsyn
return null;
}

ConnectorType connectorType = GetConnectorType(cdp.ItemValuePath, sv, ConnectorSettings.Compatibility);
ConnectorType connectorType = GetConnectorType(cdp.ItemValuePath, sv, ConnectorSettings);

if (connectorType.HasErrors)
{
Expand Down Expand Up @@ -1400,7 +1401,7 @@ private ConnectorParameterInternals Initialize()
{
// Ex: Api-Version
hiddenRequired = true;
}
}
}
else if (ConnectorSettings.Compatibility.ExcludeInternals())
{
Expand All @@ -1413,8 +1414,8 @@ private ConnectorParameterInternals Initialize()
return null;
}

ConnectorParameter connectorParameter = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(parameter, ConnectorSettings.Compatibility));

ConnectorParameter connectorParameter = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(parameter, ConnectorSettings));

if (connectorParameter.HiddenRecordType != null)
{
errorsAndWarnings.AddError("[Internal error] Unexpected HiddenRecordType non-null value");
Expand Down Expand Up @@ -1459,7 +1460,12 @@ private ConnectorParameterInternals Initialize()
OpenApiSchema bodyPropertySchema = bodyProperty.Value;
string bodyPropertyName = bodyProperty.Key;
bool bodyPropertyRequired = bodySchema.Required.Contains(bodyPropertyName);
bool bodyPropertyHiddenRequired = false;
bool bodyPropertyHiddenRequired = false;

if (ConnectorSettings.UseDefaultBodyNameForSinglePropertyObject && bodySchema.Properties.Count == 1)
{
bodyPropertyName = bodyName;
}

if (bodyPropertySchema.IsInternal())
{
Expand All @@ -1482,12 +1488,12 @@ private ConnectorParameterInternals Initialize()
}

OpenApiParameter bodyParameter = new OpenApiParameter() { Name = bodyPropertyName, Schema = bodyPropertySchema, Description = requestBody.Description, Required = bodyPropertyRequired, Extensions = bodyPropertySchema.Extensions };
ConnectorParameter bodyConnectorParameter2 = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter, requestBody, ConnectorSettings.Compatibility));
ConnectorParameter bodyConnectorParameter2 = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter, requestBody, ConnectorSettings));
openApiBodyParameters.Add(bodyConnectorParameter2, OpenApiExtensions.TryGetOpenApiValue(bodyConnectorParameter2.Schema.Default, null, out FormulaValue defaultValue, errorsAndWarnings) ? defaultValue : null);

if (bodyConnectorParameter2.HiddenRecordType != null)
{
hiddenRequiredParameters.Add(errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter, true, ConnectorSettings.Compatibility)));
{
hiddenRequiredParameters.Add(errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter, true, ConnectorSettings)));
}

List<ConnectorParameter> parameterList = !bodyPropertyRequired ? optionalParameters : bodyPropertyHiddenRequired ? hiddenRequiredParameters : requiredParameters;
Expand All @@ -1506,7 +1512,7 @@ private ConnectorParameterInternals Initialize()
}

OpenApiParameter bodyParameter2 = new OpenApiParameter() { Name = bodyName, Schema = bodySchema, Description = requestBody.Description, Required = requestBody.Required, Extensions = bodySchema.Extensions };
ConnectorParameter bodyConnectorParameter3 = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter2, requestBody, ConnectorSettings.Compatibility));
ConnectorParameter bodyConnectorParameter3 = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter2, requestBody, ConnectorSettings));
openApiBodyParameters.Add(bodyConnectorParameter3, OpenApiExtensions.TryGetOpenApiValue(bodyConnectorParameter3.Schema.Default, null, out FormulaValue defaultValue, errorsAndWarnings) ? defaultValue : null);

if (bodyConnectorParameter3.HiddenRecordType != null)
Expand All @@ -1526,7 +1532,7 @@ private ConnectorParameterInternals Initialize()
OpenApiSchema bodyParameterSchema = new OpenApiSchema() { Type = "string" };

OpenApiParameter bodyParameter3 = new OpenApiParameter() { Name = bodyName, Schema = bodyParameterSchema, Description = "Body", Required = requestBody.Required };
ConnectorParameter bodyParameter = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter3, requestBody, ConnectorSettings.Compatibility));
ConnectorParameter bodyParameter = errorsAndWarnings.AggregateErrorsAndWarnings(new ConnectorParameter(bodyParameter3, requestBody, ConnectorSettings));
openApiBodyParameters.Add(bodyParameter, OpenApiExtensions.TryGetOpenApiValue(bodyParameter.Schema.Default, null, out FormulaValue defaultValue, errorsAndWarnings) ? defaultValue : null);

List<ConnectorParameter> parameterList = requestBody.Required ? requiredParameters : optionalParameters;
Expand Down Expand Up @@ -1569,8 +1575,8 @@ private ConnectorParameterInternals Initialize()
_arityMax = _arityMin + (_optionalParameters.Length == 0 ? 0 : 1);
_warnings = new List<ErrorResourceKey>();

_returnType = errorsAndWarnings.AggregateErrorsAndWarnings(Operation.GetConnectorReturnType(ConnectorSettings.Compatibility));

_returnType = errorsAndWarnings.AggregateErrorsAndWarnings(Operation.GetConnectorReturnType(ConnectorSettings));

if (IsDeprecated)
{
_warnings.Add(ConnectorStringResources.WarnDeprecatedFunction);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,10 @@ private async Task WritePropertyAsync(string propertyName, ISwaggerSchema proper
{
await WriteBlobValueAsync(bv).ConfigureAwait(false);
}
else if (fv is OptionSetValue optionSetValue)
{
WriteStringValue(optionSetValue.Option);
}
else
{
throw new PowerFxConnectorException($"Expected StringValue and got {fv?.GetType()?.Name ?? "<null>"} value, for property {propertyName}");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public void Write(IOpenApiWriter writer, OpenApiSpecVersion specVersion)

IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
return this.GetEnumerator();
}
}
}
Loading

0 comments on commit fa2e0d1

Please sign in to comment.