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

refactor: Rewrite pyRevit configurations #2482

Draft
wants to merge 50 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
decf1d1
add new configuration project
dosymep Dec 18, 2024
492e6e3
add ini project
dosymep Dec 18, 2024
98c40b3
fix build
dosymep Dec 18, 2024
d9c2251
remove unnecessary usings
dosymep Dec 18, 2024
63393d7
update create config
dosymep Dec 18, 2024
2afea49
rewrite config class to new configs
dosymep Dec 18, 2024
68efd97
change return default value for lists
dosymep Dec 18, 2024
e7c28d7
add override name to create config
dosymep Dec 18, 2024
f4d0b36
added configuration path and save
dosymep Dec 18, 2024
b079c2f
update service interface
dosymep Dec 18, 2024
1b52854
Добавил сервис конфигурации
dosymep Dec 18, 2024
8618fad
fix spelling
dosymep Dec 20, 2024
8e4eddf
add sections classes
dosymep Dec 20, 2024
4bfae44
Merge branch 'develop' into features/configuration
jmcouffin Dec 20, 2024
a22a053
update
dosymep Dec 23, 2024
caea3f3
add configuration name
dosymep Dec 23, 2024
da4575d
add support requred and init features for net48
dosymep Dec 23, 2024
1661d2e
add parse config by reflection
dosymep Dec 23, 2024
08919b5
Merge remote-tracking branch 'origin/features/configuration' into fea…
dosymep Dec 23, 2024
29bc6ef
add attribute settings
dosymep Dec 23, 2024
6baf57d
add save config sections
dosymep Dec 27, 2024
cf74632
update public interface
dosymep Dec 27, 2024
6122fd9
update console config command
dosymep Dec 27, 2024
1b92380
update read and write propeties
dosymep Dec 27, 2024
7faee38
update pyRevit environment config
dosymep Dec 27, 2024
6e10ac0
Merge branch 'develop' into features/configuration
dosymep Dec 27, 2024
3825ecb
fix typo
dosymep Dec 28, 2024
3b09e3e
fix override config name
dosymep Dec 28, 2024
6f81e4a
update getting config file service
dosymep Dec 28, 2024
9e1f6bd
add readonly properti to service (python)
dosymep Dec 28, 2024
0b4fd1c
add user extensions
dosymep Dec 28, 2024
24927a5
update python code
dosymep Dec 28, 2024
0954681
update tests
dosymep Dec 28, 2024
23b218f
add realization
dosymep Dec 28, 2024
c1fef09
add reference
dosymep Dec 28, 2024
5c7dec2
add revit version to config
dosymep Dec 28, 2024
df9de22
fix override config name
dosymep Dec 28, 2024
6375993
fix override config prioritization
dosymep Dec 28, 2024
838f163
update references
dosymep Dec 28, 2024
eae821a
remove references
dosymep Dec 28, 2024
20a7b61
add remove section method
dosymep Jan 10, 2025
1b138bb
add get section names and option names
dosymep Jan 28, 2025
a390d1a
add configs properties
dosymep Jan 28, 2025
2420814
add dynamic section parser
dosymep Jan 28, 2025
ac9b38e
update config class name
dosymep Jan 28, 2025
e078a4b
add save config
dosymep Jan 28, 2025
141e3b3
Merge branch 'develop' into features/configuration
dosymep Jan 28, 2025
b49999b
add remove option when seve section
dosymep Jan 28, 2025
fa49ba2
add skip save value if has in other config
dosymep Jan 28, 2025
0a2c4b1
update configs
dosymep Jan 30, 2025
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
2 changes: 1 addition & 1 deletion dev/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<NetFolder Condition="'$(TargetFramework)' == 'net48'">netfx</NetFolder>
<NetFolder Condition="'$(TargetFramework)' == 'net8.0-windows'">netcore</NetFolder>
<NetFolder Condition="'$(TargetFramework.StartsWith(net8.0))'">netcore</NetFolder>
</PropertyGroup>

<PropertyGroup>
Expand Down
4 changes: 0 additions & 4 deletions dev/pyRevitLabs/pyRevitLabs.Common/pyRevitLabs.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.VisualBasic" Version="4.10.0"/>

<PackageReference Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" Include="MadMilkman.Ini" Version="1.0.6"/>
<PackageReference Condition="'$(TargetFrameworkIdentifier)' == '.NetCoreApp'" Include="MadMilkman.Ini.Unofficial" Version="1.0.1"/>

<Reference Condition="'$(TargetFrameworkIdentifier)' == '.NETFramework'" Include="System.Management"/>
<PackageReference Condition="'$(TargetFrameworkIdentifier)' == '.NetCoreApp'" Include="System.Management" Version="8.0.0"/>
</ItemGroup>
Expand All @@ -36,7 +33,6 @@
<Copy SourceFiles="$(OutDir)\DotNetVersionFinder.dll" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="$(OutDir)\LibGit2Sharp.dll" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="@(LibGit2SharpNative)" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="$(OutDir)\MadMilkman.Ini.dll" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="$(OutDir)\OpenMcdf.dll" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="$(OutDir)\YamlDotNet.dll" DestinationFolder="$(PyRevitBinDir)"/>
<Copy SourceFiles="$(OutDir)\Microsoft.CodeAnalysis.dll" DestinationFolder="$(PyRevitBinDir)"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace pyRevitLabs.Configurations.Ini.Extensions;

public static class IniConfigurationExtensions
{
public static ConfigurationBuilder AddIniConfiguration(this ConfigurationBuilder builder, string configurationPath, bool readOnly = default)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));

if (string.IsNullOrWhiteSpace(configurationPath))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(configurationPath));

return builder.AddConfigurationSource(IniConfiguration.Create(configurationPath, readOnly));
}
}
93 changes: 93 additions & 0 deletions dev/pyRevitLabs/pyRevitLabs.Configurations.Ini/IniConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
using System.Text;
using IniParser;
using IniParser.Model;
using pyRevitLabs.Configurations.Abstractions;
using pyRevitLabs.Configurations.Exceptions;
using pyRevitLabs.Json;

namespace pyRevitLabs.Configurations.Ini;

public sealed class IniConfiguration : ConfigurationBase
{
public static readonly Encoding DefaultIniFileEncoding = new UTF8Encoding(false);

private readonly IniData _iniFile;
private readonly FileIniDataParser _parser;

/// <summary>
/// Create ini configuration instance.
/// </summary>
/// <param name="configurationPath">Configuration path.</param>
/// <param name="readOnly">Admin configurations </param>
private IniConfiguration(string configurationPath, bool readOnly)
: base(configurationPath, readOnly)
{
_parser = new FileIniDataParser();
_iniFile = !File.Exists(configurationPath)
? new IniData()
: _parser.ReadFile(_configurationPath, DefaultIniFileEncoding);
}

/// <summary>
/// Creates IniConfiguration.
/// </summary>
/// <param name="configurationPath">Configuration file path.</param>
/// <param name="readOnly">Mark file is readonly.</param>
/// <returns>Return new IniConfiguration.</returns>
/// <exception cref="ArgumentNullException">When configurationPath is null.</exception>
public static IConfiguration Create(string configurationPath, bool readOnly = default)
{
if (configurationPath is null)
throw new ArgumentNullException(nameof(configurationPath));

return new IniConfiguration(configurationPath, readOnly);
}

/// <inheritdoc />
protected override void SaveConfigurationImpl()
{
_parser.WriteFile(_configurationPath, _iniFile, DefaultIniFileEncoding);
}

/// <inheritdoc />
protected override bool HasSectionImpl(string sectionName)
{
return _iniFile.Sections.ContainsSection(sectionName);
}

/// <inheritdoc />
protected override bool HasSectionKeyImpl(string sectionName, string keyName)
{
return HasSection(sectionName)
&& _iniFile.Sections[sectionName].ContainsKey(keyName);
}

/// <inheritdoc />
protected override bool RemoveValueImpl(string sectionName, string keyName)
{
return _iniFile[sectionName].RemoveKey(keyName);
}

/// <inheritdoc />
protected override T GetValueImpl<T>(string sectionName, string keyName)
{
return JsonConvert.DeserializeObject<T>(_iniFile[sectionName][keyName])
?? throw new ConfigurationException("Cannot deserialize value using the specified key.");
}

/// <inheritdoc />
protected override void SetValueImpl<T>(string sectionName, string keyName, T value)
{
if (!HasSection(sectionName))
{
_iniFile.Sections.AddSection(sectionName);
}

if (!HasSectionKey(sectionName, keyName))
{
_iniFile[sectionName].AddKey(keyName);
}

_iniFile[sectionName][keyName] = JsonConvert.SerializeObject(value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ini-parser-netstandard" Version="2.5.2" />
<Reference Include="pyRevitLabs.Json" HintPath="$(PyRevitDevLibsDir)\pyRevitLabs.Json.dll" Private="false"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\pyRevitLabs.Configurations\pyRevitLabs.Configurations.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace pyRevitLabs.Configurations.Json.Extensions;

public static class JsonConfigurationExtensions
{
public static ConfigurationBuilder AddJsonConfiguration(this ConfigurationBuilder builder, string configurationPath, bool readOnly = default)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));

if (string.IsNullOrWhiteSpace(configurationPath))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(configurationPath));

return builder.AddConfigurationSource(JsonConfiguration.Create(configurationPath, readOnly));
}
}
103 changes: 103 additions & 0 deletions dev/pyRevitLabs/pyRevitLabs.Configurations.Json/JsonConfiguration.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
using System.Text;
using System.Xml;
using pyRevitLabs.Configurations.Abstractions;
using pyRevitLabs.Configurations.Exceptions;
using pyRevitLabs.Json;
using pyRevitLabs.Json.Linq;
using Formatting = pyRevitLabs.Json.Formatting;

namespace pyRevitLabs.Configurations.Json;

public sealed class JsonConfiguration : ConfigurationBase
{
public static readonly Encoding DefaultJsonFileEncoding = Encoding.UTF8;

private readonly JObject _jsonObject;

/// <summary>
/// Create json configuration instance.
/// </summary>
/// <param name="configurationPath">Configuration path.</param>
/// <param name="readOnly">Readonly configurations </param>
private JsonConfiguration(string configurationPath, bool readOnly)
: base(configurationPath, readOnly)
{
_jsonObject = !File.Exists(configurationPath)
? new JObject()
: JObject.Parse(File.ReadAllText(_configurationPath, DefaultJsonFileEncoding));
}

/// <summary>
/// Creates JsonConfiguration.
/// </summary>
/// <param name="configurationPath">Configuration file path.</param>
/// <param name="readOnly">Mark file is readonly.</param>
/// <returns>Return new JsonConfiguration.</returns>
/// <exception cref="ArgumentNullException">When configurationPath is null.</exception>
public static IConfiguration Create(string configurationPath, bool readOnly = default)
{
if (configurationPath is null)
throw new ArgumentNullException(nameof(configurationPath));

return new JsonConfiguration(configurationPath, readOnly);
}

protected override void SaveConfigurationImpl()
{
string jsonString = JsonConvert.SerializeObject(_jsonObject,
new JsonSerializerSettings() {Formatting = Formatting.Indented});
File.WriteAllText(_configurationPath, jsonString, DefaultJsonFileEncoding);
}

protected override bool HasSectionImpl(string sectionName)
{
return _jsonObject.ContainsKey(sectionName);
}

protected override bool HasSectionKeyImpl(string sectionName, string keyName)
{
JObject? sectionObject = _jsonObject[sectionName] as JObject;
return sectionObject?.ContainsKey(keyName) == true;
}

protected override bool RemoveValueImpl(string sectionName, string keyName)
{
_jsonObject[sectionName]![keyName] = null;
return true;
}

protected override T GetValueImpl<T>(string sectionName, string keyName)
{
JToken? token = _jsonObject[sectionName]?[keyName];
return token is null
? throw new ConfigurationException($"Section {sectionName} or keyName {keyName} not found.")
: token.ToObject<T>()
?? throw new ConfigurationException($"Cannot deserialize value with {sectionName} and {keyName}.");
}

protected override void SetValueImpl<T>(string sectionName, string keyName, T value)
{
if (!HasSection(sectionName))
{
JObject fromObject = new();
fromObject.Add(keyName, JToken.FromObject(value!));

_jsonObject.Add(sectionName, fromObject);

return;
}

if (!HasSectionKey(sectionName, keyName))
{
JObject fromObject = new();
fromObject.Add(keyName, JToken.FromObject(value!));

JObject? sectionObject = (JObject?)_jsonObject[sectionName];
sectionObject?.Add(keyName, fromObject);

return;
}

_jsonObject[sectionName]![keyName] = JToken.FromObject(value!);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net48;net8.0</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<LangVersion>12</LangVersion>
</PropertyGroup>

<ItemGroup>
<Reference Include="pyRevitLabs.Json" HintPath="$(PyRevitDevLibsDir)\pyRevitLabs.Json.dll" Private="false"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\pyRevitLabs.Configurations\pyRevitLabs.Configurations.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace pyRevitLabs.Configurations.Yaml.Extensions;

public static class YamlConfigurationExtensions
{
public static ConfigurationBuilder AddYamlConfiguration(this ConfigurationBuilder builder, string configurationPath, bool readOnly = default)
{
if (builder == null)
throw new ArgumentNullException(nameof(builder));

if (string.IsNullOrWhiteSpace(configurationPath))
throw new ArgumentException("Value cannot be null or whitespace.", nameof(configurationPath));

return builder.AddConfigurationSource(YamlConfiguration.Create(configurationPath, readOnly));
}
}
Loading