Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable configuring dynamic behavior through client options #36887

Merged
merged 25 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
using System.Collections;
using System.Threading.Tasks;
using Azure.Core;
using Azure.Core.Dynamic;
using Azure.Core.Serialization;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand All @@ -23,30 +23,30 @@ public async Task AnalyzeConversation()
{
var data = new
{
analysisInput = new
AnalysisInput = new
{
conversationItem = new
ConversationItem = new
{
text = "Send an email to Carol about the tomorrow's demo",
id = "1",
participantId = "1",
Text = "Send an email to Carol about the tomorrow's demo",
Id = "1",
ParticipantId = "1",
}
},
parameters = new
Parameters = new
{
projectName = TestEnvironment.ProjectName,
deploymentName = TestEnvironment.DeploymentName,
ProjectName = TestEnvironment.ProjectName,
DeploymentName = TestEnvironment.DeploymentName,
},
kind = "Conversation",
Kind = "Conversation",
};

Response response = await Client.AnalyzeConversationAsync(RequestContent.Create(data));
Response response = await Client.AnalyzeConversationAsync(RequestContent.Create(data, PropertyNamingConvention.CamelCase));

// assert - main object
Assert.IsNotNull(response);

// deserialize
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson();
Assert.IsNotNull(conversationalTaskResult);

// assert - prediction type
Expand Down Expand Up @@ -92,7 +92,7 @@ public async Task AnalyzeConversation_Orchestration_Conversation()
Assert.IsNotNull(response);

// deserialize
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson();
Assert.IsNotNull(conversationalTaskResult);

// assert - prediction type
Expand Down Expand Up @@ -149,7 +149,7 @@ public async Task AnalyzeConversation_Orchestration_Luis()
Assert.IsNotNull(response);

// deserialize
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson();
Assert.IsNotNull(conversationalTaskResult);

// assert - prediction type
Expand Down Expand Up @@ -201,7 +201,7 @@ public async Task AnalyzeConversation_Orchestration_QuestionAnswering()
Assert.IsNotNull(response);

// deserialize
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson();
Assert.IsNotNull(conversationalTaskResult);

// assert - prediction type
Expand Down Expand Up @@ -256,7 +256,7 @@ public async Task SupportsAadAuthentication()

Response response = await client.AnalyzeConversationAsync(RequestContent.Create(data));

dynamic conversationalTaskResult = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic conversationalTaskResult = response.Content.ToDynamicFromJson();
Assert.That((string)conversationalTaskResult.Result.Prediction.TopIntent, Is.EqualTo("Send"));
}

Expand Down Expand Up @@ -322,7 +322,7 @@ public async Task AnalyzeConversation_ConversationSummarization()

Operation<BinaryData> analyzeConversationOperation = await Client.AnalyzeConversationsAsync(WaitUntil.Completed, RequestContent.Create(data));

dynamic jobResults = analyzeConversationOperation.Value.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic jobResults = analyzeConversationOperation.Value.ToDynamicFromJson();
Assert.NotNull(jobResults);

foreach (dynamic analyzeConversationSummarization in jobResults.Tasks.Items)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Threading.Tasks;
using Azure.AI.Language.Conversations.Authoring;
using Azure.Core.Dynamic;
using Azure.Core.TestFramework;
using NUnit.Framework;

Expand Down Expand Up @@ -60,7 +59,7 @@ public async Task SupportsAadAuthentication()

Response response = await client.GetProjectAsync(TestEnvironment.ProjectName);

dynamic project = response.Content.ToDynamicFromJson(DynamicCaseMapping.PascalToCamel);
dynamic project = response.Content.ToDynamicFromJson();
Assert.That((string)project.ProjectKind, Is.EqualTo("Conversation"));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// Licensed under the MIT License.

using System.Threading.Tasks;
using Azure.Core.Serialization;
using Azure.Core.TestFramework;

namespace Azure.AI.Language.Conversations.Tests
Expand Down Expand Up @@ -43,11 +44,13 @@ public override async Task StartTestRecordingAsync()
{
await base.StartTestRecordingAsync();

ConversationsClientOptions options = new ConversationsClientOptions(ServiceVersion);
options.RawContent.PropertyNamingConvention = PropertyNamingConvention.CamelCase;

Client = CreateClient<TClient>(
TestEnvironment.Endpoint,
new AzureKeyCredential(TestEnvironment.ApiKey),
InstrumentClientOptions(
new ConversationsClientOptions(ServiceVersion)));
InstrumentClientOptions(options));
}
}
}
29 changes: 15 additions & 14 deletions sdk/core/Azure.Core/api/Azure.Core.net461.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ protected AsyncPageable(System.Threading.CancellationToken cancellationToken) {
public static partial class AzureCoreExtensions
{
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Dynamic.DynamicCaseMapping caseMapping, Azure.Core.Dynamic.DynamicDateTimeHandling dateTimeHandling = Azure.Core.Dynamic.DynamicDateTimeHandling.Rfc3339) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Dynamic.DynamicDataOptions options) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Serialization.PropertyNamingConvention propertyNamingConvention) { throw null; }
public static System.Threading.Tasks.ValueTask<T?> ToObjectAsync<T>(this System.BinaryData data, Azure.Core.Serialization.ObjectSerializer serializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static object? ToObjectFromJson(this System.BinaryData data) { throw null; }
public static T? ToObject<T>(this System.BinaryData data, Azure.Core.Serialization.ObjectSerializer serializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
Expand Down Expand Up @@ -381,6 +380,7 @@ protected ClientOptions() { }
protected ClientOptions(Azure.Core.DiagnosticsOptions? diagnostics) { }
public static Azure.Core.ClientOptions Default { get { throw null; } }
public Azure.Core.DiagnosticsOptions Diagnostics { get { throw null; } }
public Azure.Core.Serialization.ProtocolOptions Protocol { get { throw null; } }
public Azure.Core.RetryOptions Retry { get { throw null; } }
public Azure.Core.Pipeline.HttpPipelinePolicy? RetryPolicy { get { throw null; } set { } }
public Azure.Core.Pipeline.HttpPipelineTransport Transport { get { throw null; } set { } }
Expand Down Expand Up @@ -544,7 +544,9 @@ protected RequestContent() { }
public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; }
public static Azure.Core.RequestContent Create(byte[] bytes, int index, int length) { throw null; }
public static Azure.Core.RequestContent Create(System.IO.Stream stream) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.ObjectSerializer? serializer = null) { throw null; }
public static Azure.Core.RequestContent Create(object serializable) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.ObjectSerializer? serializer) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.PropertyNamingConvention propertyNamingConvention) { throw null; }
public static Azure.Core.RequestContent Create(System.ReadOnlyMemory<byte> bytes) { throw null; }
public static Azure.Core.RequestContent Create(string content) { throw null; }
public abstract void Dispose();
Expand Down Expand Up @@ -780,11 +782,6 @@ protected sealed override void OnEventWritten(System.Diagnostics.Tracing.EventWr
}
namespace Azure.Core.Dynamic
{
public enum DynamicCaseMapping
{
None = 0,
PascalToCamel = 1,
}
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable
{
Expand Down Expand Up @@ -815,12 +812,6 @@ public void Dispose() { }
System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(System.Linq.Expressions.Expression parameter) { throw null; }
public override string ToString() { throw null; }
}
public partial class DynamicDataOptions
{
public DynamicDataOptions() { }
public Azure.Core.Dynamic.DynamicCaseMapping CaseMapping { get { throw null; } set { } }
public Azure.Core.Dynamic.DynamicDateTimeHandling DateTimeHandling { get { throw null; } set { } }
}
public enum DynamicDateTimeHandling
{
Rfc3339 = 0,
Expand Down Expand Up @@ -1145,6 +1136,16 @@ protected ObjectSerializer() { }
public abstract System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken);
public virtual System.Threading.Tasks.ValueTask<System.BinaryData> SerializeAsync(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public enum PropertyNamingConvention
{
None = 0,
CamelCase = 1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I worry these names aren't clear enough. I thought this was how we're managing dynamic binding resolution (i.e., allowing pascal case), but it looks like we're also using this on RequestContent.Create to control how we serialize?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For what it's worth, I still really like [Flags] public enum DynamicBindingFlags { None = 0, AllowPascalCase = 1, IgnoreCase = 2, IgnoreSeparators = 4, ... } as a separate concept to really hammer home the dynamic renaming half of the equation.

Copy link
Member Author

@annelo-msft annelo-msft Jun 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We explored the flags enum approach, and it had a number of negatives. This is the approach I'd like to take because I think it sets us up best to evolve the type in response to customer feedback. It follows precedents set in a variety of other .NET APIs, for databases and serialization, so I have higher confidence that it will be both consistent and evolvable over other approaches we've considered.

}
public partial class ProtocolOptions
{
internal ProtocolOptions() { }
public Azure.Core.Serialization.PropertyNamingConvention PropertyNamingConvention { get { throw null; } set { } }
}
}
namespace Azure.Messaging
{
Expand Down
29 changes: 15 additions & 14 deletions sdk/core/Azure.Core/api/Azure.Core.net5.0.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,7 @@ protected AsyncPageable(System.Threading.CancellationToken cancellationToken) {
public static partial class AzureCoreExtensions
{
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Dynamic.DynamicCaseMapping caseMapping, Azure.Core.Dynamic.DynamicDateTimeHandling dateTimeHandling = Azure.Core.Dynamic.DynamicDateTimeHandling.Rfc3339) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Dynamic.DynamicDataOptions options) { throw null; }
public static dynamic ToDynamicFromJson(this System.BinaryData utf8Json, Azure.Core.Serialization.PropertyNamingConvention propertyNamingConvention) { throw null; }
public static System.Threading.Tasks.ValueTask<T?> ToObjectAsync<T>(this System.BinaryData data, Azure.Core.Serialization.ObjectSerializer serializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
public static object? ToObjectFromJson(this System.BinaryData data) { throw null; }
public static T? ToObject<T>(this System.BinaryData data, Azure.Core.Serialization.ObjectSerializer serializer, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
Expand Down Expand Up @@ -381,6 +380,7 @@ protected ClientOptions() { }
protected ClientOptions(Azure.Core.DiagnosticsOptions? diagnostics) { }
public static Azure.Core.ClientOptions Default { get { throw null; } }
public Azure.Core.DiagnosticsOptions Diagnostics { get { throw null; } }
public Azure.Core.Serialization.ProtocolOptions Protocol { get { throw null; } }
public Azure.Core.RetryOptions Retry { get { throw null; } }
public Azure.Core.Pipeline.HttpPipelinePolicy? RetryPolicy { get { throw null; } set { } }
public Azure.Core.Pipeline.HttpPipelineTransport Transport { get { throw null; } set { } }
Expand Down Expand Up @@ -544,7 +544,9 @@ protected RequestContent() { }
public static Azure.Core.RequestContent Create(byte[] bytes) { throw null; }
public static Azure.Core.RequestContent Create(byte[] bytes, int index, int length) { throw null; }
public static Azure.Core.RequestContent Create(System.IO.Stream stream) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.ObjectSerializer? serializer = null) { throw null; }
public static Azure.Core.RequestContent Create(object serializable) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.ObjectSerializer? serializer) { throw null; }
public static Azure.Core.RequestContent Create(object serializable, Azure.Core.Serialization.PropertyNamingConvention propertyNamingConvention) { throw null; }
public static Azure.Core.RequestContent Create(System.ReadOnlyMemory<byte> bytes) { throw null; }
public static Azure.Core.RequestContent Create(string content) { throw null; }
public abstract void Dispose();
Expand Down Expand Up @@ -780,11 +782,6 @@ protected sealed override void OnEventWritten(System.Diagnostics.Tracing.EventWr
}
namespace Azure.Core.Dynamic
{
public enum DynamicCaseMapping
{
None = 0,
PascalToCamel = 1,
}
[System.Diagnostics.DebuggerDisplayAttribute("{DebuggerDisplay,nq}")]
public sealed partial class DynamicData : System.Dynamic.IDynamicMetaObjectProvider, System.IDisposable
{
Expand Down Expand Up @@ -815,12 +812,6 @@ public void Dispose() { }
System.Dynamic.DynamicMetaObject System.Dynamic.IDynamicMetaObjectProvider.GetMetaObject(System.Linq.Expressions.Expression parameter) { throw null; }
public override string ToString() { throw null; }
}
public partial class DynamicDataOptions
{
public DynamicDataOptions() { }
public Azure.Core.Dynamic.DynamicCaseMapping CaseMapping { get { throw null; } set { } }
public Azure.Core.Dynamic.DynamicDateTimeHandling DateTimeHandling { get { throw null; } set { } }
}
public enum DynamicDateTimeHandling
{
Rfc3339 = 0,
Expand Down Expand Up @@ -1145,6 +1136,16 @@ protected ObjectSerializer() { }
public abstract System.Threading.Tasks.ValueTask SerializeAsync(System.IO.Stream stream, object? value, System.Type inputType, System.Threading.CancellationToken cancellationToken);
public virtual System.Threading.Tasks.ValueTask<System.BinaryData> SerializeAsync(object? value, System.Type? inputType = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; }
}
public enum PropertyNamingConvention
{
None = 0,
CamelCase = 1,
}
public partial class ProtocolOptions
{
internal ProtocolOptions() { }
public Azure.Core.Serialization.PropertyNamingConvention PropertyNamingConvention { get { throw null; } set { } }
}
}
namespace Azure.Messaging
{
Expand Down
Loading