Adding entity linking
This commit is contained in:
parent
3a46e20d38
commit
abd116b032
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
public class ArgsContext
|
public class ArgsContext
|
||||||
{
|
{
|
||||||
public string[] Args { get; init; }
|
public string[] Args { get; init; } = Array.Empty<string>();
|
||||||
}
|
}
|
@ -21,12 +21,17 @@ public static class Bash
|
|||||||
if (process is null)
|
if (process is null)
|
||||||
throw new NullReferenceException("Could not initialize bash process.");
|
throw new NullReferenceException("Could not initialize bash process.");
|
||||||
|
|
||||||
process.OutputDataReceived += (sender, args) => { Console.WriteLine(args.Data); };
|
process.OutputDataReceived += (sender, args) =>
|
||||||
|
{
|
||||||
|
// Only print data when it's not empty to prevent noise in the shell
|
||||||
|
if (!string.IsNullOrEmpty(args.Data))
|
||||||
|
Console.WriteLine(args.Data);
|
||||||
|
};
|
||||||
process.BeginOutputReadLine();
|
process.BeginOutputReadLine();
|
||||||
|
|
||||||
process.ErrorDataReceived += (sender, args) =>
|
process.ErrorDataReceived += (sender, args) =>
|
||||||
{
|
{
|
||||||
// Only print error data when it's not empty to prevent noise in the shell
|
// Only print data when it's not empty to prevent noise in the shell
|
||||||
if (!string.IsNullOrEmpty(args.Data))
|
if (!string.IsNullOrEmpty(args.Data))
|
||||||
Console.WriteLine(args.Data);
|
Console.WriteLine(args.Data);
|
||||||
};
|
};
|
||||||
@ -42,6 +47,6 @@ public static class Bash
|
|||||||
await process.WaitForExitAsync();
|
await process.WaitForExitAsync();
|
||||||
|
|
||||||
if (process.ExitCode != 0)
|
if (process.ExitCode != 0)
|
||||||
Console.WriteLine($"Process exited with status code {process.ExitCode}.");
|
Console.WriteLine($"Process finished with exit code {process.ExitCode}.");
|
||||||
}
|
}
|
||||||
}
|
}
|
16
MycroForge.CLI/CodeGen/EntityLinker.cs
Normal file
16
MycroForge.CLI/CodeGen/EntityLinker.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
using MycroForge.Parsing;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.CodeGen;
|
||||||
|
|
||||||
|
public class EntityLinker : PythonSourceModifier
|
||||||
|
{
|
||||||
|
public EntityLinker(string source) : base(source)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object? VisitAssignment(PythonParser.AssignmentContext context)
|
||||||
|
{
|
||||||
|
Console.WriteLine(GetOriginalText(context));
|
||||||
|
return base.VisitAssignment(context);
|
||||||
|
}
|
||||||
|
}
|
@ -14,20 +14,4 @@ public partial class MycroForge
|
|||||||
AddCommand((subCommandOf as Command)!);
|
AddCommand((subCommandOf as Command)!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Run : Command, ISubCommandOf<MycroForge>
|
|
||||||
{
|
|
||||||
public Run() : base("run", "Run your app")
|
|
||||||
{
|
|
||||||
this.SetHandler(ExecuteAsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
await Bash.ExecuteAsync([
|
|
||||||
"source .venv/bin/activate",
|
|
||||||
"uvicorn main:app --reload"
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
37
MycroForge.CLI/Commands/MycroForge.Entity.Link.Many.cs
Normal file
37
MycroForge.CLI/Commands/MycroForge.Entity.Link.Many.cs
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
using System.CommandLine;
|
||||||
|
using MycroForge.CLI.Commands.Interfaces;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.Commands;
|
||||||
|
|
||||||
|
public partial class MycroForge
|
||||||
|
{
|
||||||
|
public partial class Entity
|
||||||
|
{
|
||||||
|
public partial class Link
|
||||||
|
{
|
||||||
|
public class Many : Command, ISubCommandOf<Link>
|
||||||
|
{
|
||||||
|
private static readonly Argument<string> NameArgument =
|
||||||
|
new(name: "primary", description: "The left side of the relation");
|
||||||
|
|
||||||
|
private static readonly Option<string> ToOneOption =
|
||||||
|
new(name: "--to-one", description: "The right side of the relation");
|
||||||
|
|
||||||
|
private static readonly Option<string> ToManyOption =
|
||||||
|
new(name: "--to-many", description: "The right side of the relation");
|
||||||
|
|
||||||
|
public Many() : base("many", "Define a n:m relation")
|
||||||
|
{
|
||||||
|
AddArgument(NameArgument);
|
||||||
|
AddOption(ToOneOption);
|
||||||
|
AddOption(ToManyOption);
|
||||||
|
this.SetHandler(ExecuteAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
38
MycroForge.CLI/Commands/MycroForge.Entity.Link.One.cs
Normal file
38
MycroForge.CLI/Commands/MycroForge.Entity.Link.One.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System.CommandLine;
|
||||||
|
using MycroForge.CLI.Commands.Interfaces;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.Commands;
|
||||||
|
|
||||||
|
public partial class MycroForge
|
||||||
|
{
|
||||||
|
public partial class Entity
|
||||||
|
{
|
||||||
|
public partial class Link
|
||||||
|
{
|
||||||
|
public class One : Command, ISubCommandOf<Link>
|
||||||
|
{
|
||||||
|
private static readonly Argument<string> NameArgument =
|
||||||
|
new(name: "primary", description: "The left side of the relation");
|
||||||
|
|
||||||
|
private static readonly Option<string> ToOneOption =
|
||||||
|
new(name: "--to-one", description: "The right side of the relation");
|
||||||
|
|
||||||
|
private static readonly Option<string> ToManyOption =
|
||||||
|
new(name: "--to-many", description: "The right side of the relation");
|
||||||
|
|
||||||
|
|
||||||
|
public One() : base("one", "Define a 1:n relation")
|
||||||
|
{
|
||||||
|
AddArgument(NameArgument);
|
||||||
|
AddOption(ToOneOption);
|
||||||
|
AddOption(ToManyOption);
|
||||||
|
this.SetHandler(ExecuteAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
MycroForge.CLI/Commands/MycroForge.Entity.Link.cs
Normal file
20
MycroForge.CLI/Commands/MycroForge.Entity.Link.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.CommandLine;
|
||||||
|
using MycroForge.CLI.Commands.Interfaces;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.Commands;
|
||||||
|
|
||||||
|
public partial class MycroForge
|
||||||
|
{
|
||||||
|
public partial class Entity
|
||||||
|
{
|
||||||
|
public partial class Link : Command, ISubCommandOf<Entity>
|
||||||
|
{
|
||||||
|
public Link(IEnumerable<ISubCommandOf<Link>> commands) :
|
||||||
|
base("link", "Define relationships between entities")
|
||||||
|
{
|
||||||
|
foreach (var command in commands)
|
||||||
|
AddCommand((command as Command)!);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
17
MycroForge.CLI/Commands/MycroForge.Entity.cs
Normal file
17
MycroForge.CLI/Commands/MycroForge.Entity.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using System.CommandLine;
|
||||||
|
using MycroForge.CLI.Commands.Interfaces;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.Commands;
|
||||||
|
|
||||||
|
public partial class MycroForge
|
||||||
|
{
|
||||||
|
public partial class Entity : Command, ISubCommandOf<MycroForge>
|
||||||
|
{
|
||||||
|
public Entity(IEnumerable<ISubCommandOf<Entity>> commands) :
|
||||||
|
base("entity", "Manage the entities in your project")
|
||||||
|
{
|
||||||
|
foreach (var command in commands.Cast<Command>())
|
||||||
|
AddCommand(command);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,19 +9,22 @@ public partial class MycroForge
|
|||||||
{
|
{
|
||||||
public partial class Generate
|
public partial class Generate
|
||||||
{
|
{
|
||||||
|
// ReSharper disable once MemberHidesStaticFromOuterClass
|
||||||
public class Entity : Command, ISubCommandOf<Generate>
|
public class Entity : Command, ISubCommandOf<Generate>
|
||||||
{
|
{
|
||||||
private static readonly string[] Template =
|
private static readonly string[] Template =
|
||||||
[
|
[
|
||||||
"from sqlalchemy import INTEGER, Column, String",
|
"from sqlalchemy import String",
|
||||||
|
"from sqlalchemy.orm import Mapped, mapped_column",
|
||||||
"from orm.entities.entity_base import EntityBase",
|
"from orm.entities.entity_base import EntityBase",
|
||||||
"",
|
"",
|
||||||
"class %class_name%(EntityBase):",
|
"class %class_name%(EntityBase):",
|
||||||
"\t__tablename__ = \"%table_name%\"",
|
"\t__tablename__ = \"%table_name%\"",
|
||||||
"\tid = Column(INTEGER, primary_key=True)",
|
"\tid: Mapped[int] = mapped_column(primary_key=True)",
|
||||||
|
"\tvalue: Mapped[str] = mapped_column(String(255))",
|
||||||
"",
|
"",
|
||||||
"\tdef __repr__(self) -> str:",
|
"\tdef __repr__(self) -> str:",
|
||||||
"\t\treturn f\"%class_name%(id={self.id!r})\""
|
"\t\treturn f\"%class_name%(id={self.id!r}, value={self.value!r})\""
|
||||||
];
|
];
|
||||||
|
|
||||||
private static readonly Argument<string> NameArgument =
|
private static readonly Argument<string> NameArgument =
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
using System.CommandLine;
|
|
||||||
using MycroForge.CLI.Commands.Interfaces;
|
|
||||||
|
|
||||||
namespace MycroForge.CLI.Commands;
|
|
||||||
|
|
||||||
public partial class MycroForge
|
|
||||||
{
|
|
||||||
public class Rewrite : Command, ISubCommandOf<MycroForge>
|
|
||||||
{
|
|
||||||
public Rewrite() : base("rewrite", "Test a python source rewriter.")
|
|
||||||
{
|
|
||||||
this.SetHandler(ExecuteAsync);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task ExecuteAsync()
|
|
||||||
{
|
|
||||||
// var path = Path.Combine(Directory.GetCurrentDirectory(), "main.py");
|
|
||||||
// var source = await File.ReadAllTextAsync(path);
|
|
||||||
// var rewriter = new TestRewriter(source);
|
|
||||||
// var rewrite = rewriter.Rewrite();
|
|
||||||
// await File.WriteAllTextAsync(path, rewrite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
23
MycroForge.CLI/Commands/MycroForge.Run.cs
Normal file
23
MycroForge.CLI/Commands/MycroForge.Run.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.CommandLine;
|
||||||
|
using MycroForge.CLI.Commands.Interfaces;
|
||||||
|
|
||||||
|
namespace MycroForge.CLI.Commands;
|
||||||
|
|
||||||
|
public partial class MycroForge
|
||||||
|
{
|
||||||
|
public class Run : Command, ISubCommandOf<MycroForge>
|
||||||
|
{
|
||||||
|
public Run() : base("run", "Run your app")
|
||||||
|
{
|
||||||
|
this.SetHandler(ExecuteAsync);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ExecuteAsync()
|
||||||
|
{
|
||||||
|
await Bash.ExecuteAsync([
|
||||||
|
"source .venv/bin/activate",
|
||||||
|
"uvicorn main:app --reload"
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -41,6 +41,12 @@ public static class ServiceCollectionExtensions
|
|||||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Generate>, Commands.MycroForge.Generate.Router>();
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Generate>, Commands.MycroForge.Generate.Router>();
|
||||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Generate>, Commands.MycroForge.Generate.Migration>();
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Generate>, Commands.MycroForge.Generate.Migration>();
|
||||||
|
|
||||||
|
// Register "m4g entity"
|
||||||
|
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Entity>();
|
||||||
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Entity>, Commands.MycroForge.Entity.Link>();
|
||||||
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Entity.Link>, Commands.MycroForge.Entity.Link.One>();
|
||||||
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Entity.Link>, Commands.MycroForge.Entity.Link.Many>();
|
||||||
|
|
||||||
// Register "m4g migrations"
|
// Register "m4g migrations"
|
||||||
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Migrations>();
|
services.AddScoped<ISubCommandOf<Commands.MycroForge>, Commands.MycroForge.Migrations>();
|
||||||
services.AddScoped<ISubCommandOf<Commands.MycroForge.Migrations>, Commands.MycroForge.Migrations.Apply>();
|
services.AddScoped<ISubCommandOf<Commands.MycroForge.Migrations>, Commands.MycroForge.Migrations.Apply>();
|
||||||
|
@ -36,16 +36,18 @@ public sealed class Orm : IFeature
|
|||||||
|
|
||||||
private static readonly string[] User =
|
private static readonly string[] User =
|
||||||
[
|
[
|
||||||
"from sqlalchemy import INTEGER, Column, String",
|
"from sqlalchemy import String",
|
||||||
|
"from sqlalchemy.orm import Mapped, mapped_column",
|
||||||
"from orm.entities.entity_base import EntityBase",
|
"from orm.entities.entity_base import EntityBase",
|
||||||
"",
|
"",
|
||||||
"class User(EntityBase):",
|
"class User(EntityBase):",
|
||||||
"\t__tablename__ = \"users\"",
|
"\t__tablename__ = \"users\"",
|
||||||
"\tid = Column(INTEGER, primary_key=True)",
|
"\tid: Mapped[int] = mapped_column(primary_key=True)",
|
||||||
"\tfirstname = Column(String(255))",
|
"\tfirstname: Mapped[str] = mapped_column(String(255))",
|
||||||
"\tlastname = Column(String(255))\n",
|
"\tlastname: Mapped[str] = mapped_column(String(255))",
|
||||||
"def __repr__(self) -> str:",
|
"",
|
||||||
"\treturn f\"User(id={self.id!r}, firstname={self.firstname!r}, lastname={self.lastname!r})\""
|
"\tdef __repr__(self) -> str:",
|
||||||
|
"\t\treturn f\"User(id={self.id!r}, firstname={self.firstname!r}, lastname={self.lastname!r})\""
|
||||||
];
|
];
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
@ -27,6 +27,9 @@
|
|||||||
<None Update="scripts\env.py">
|
<None Update="scripts\env.py">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="scripts\user.py">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -1,32 +1,32 @@
|
|||||||
using System.CommandLine;
|
// using System.CommandLine;
|
||||||
using MycroForge.CLI;
|
// using MycroForge.CLI;
|
||||||
|
// using MycroForge.CLI.Exceptions;
|
||||||
|
// using MycroForge.CLI.Extensions;
|
||||||
|
// using Microsoft.Extensions.DependencyInjection;
|
||||||
|
// using Microsoft.Extensions.Hosting;
|
||||||
|
//
|
||||||
|
// using var host = Host
|
||||||
|
// .CreateDefaultBuilder()
|
||||||
|
// .ConfigureServices((_, services) =>
|
||||||
|
// {
|
||||||
|
// services
|
||||||
|
// .AddServices(args)
|
||||||
|
// .AddCommands();
|
||||||
|
// })
|
||||||
|
// .Build();
|
||||||
|
//
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// var ctx = host.Services.GetRequiredService<ProjectContext>();
|
||||||
|
// await ctx.LoadConfig();
|
||||||
|
// await host.Services.GetRequiredService<MycroForge.CLI.Commands.MycroForge>().InvokeAsync(args);
|
||||||
|
// await ctx.SaveConfig();
|
||||||
|
// }
|
||||||
|
// catch(Exception e)
|
||||||
|
// {
|
||||||
|
// Console.WriteLine(e.Message);
|
||||||
|
// }
|
||||||
|
|
||||||
using MycroForge.CLI.CodeGen;
|
using MycroForge.CLI.CodeGen;
|
||||||
using MycroForge.CLI.Exceptions;
|
var src = new EntityLinker(await File.ReadAllTextAsync("scripts/user.py")).Rewrite();
|
||||||
using MycroForge.CLI.Extensions;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
|
|
||||||
using var host = Host
|
|
||||||
.CreateDefaultBuilder()
|
|
||||||
.ConfigureServices((_, services) =>
|
|
||||||
{
|
|
||||||
services
|
|
||||||
.AddServices(args)
|
|
||||||
.AddCommands();
|
|
||||||
})
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var ctx = host.Services.GetRequiredService<ProjectContext>();
|
|
||||||
await ctx.LoadConfig();
|
|
||||||
await host.Services.GetRequiredService<MycroForge.CLI.Commands.MycroForge>().InvokeAsync(args);
|
|
||||||
await ctx.SaveConfig();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Console.WriteLine(e.Message);
|
|
||||||
}
|
|
||||||
|
|
||||||
// var src = new OrmEnvInitializer(await File.ReadAllTextAsync("scripts/env.py")).Rewrite();
|
|
||||||
// Console.WriteLine(src);
|
// Console.WriteLine(src);
|
@ -20,9 +20,9 @@ public class ProjectContext
|
|||||||
{
|
{
|
||||||
if (_argsContext.Args
|
if (_argsContext.Args
|
||||||
is ["init", ..]
|
is ["init", ..]
|
||||||
or ["-?", ..]
|
or ["-?", ..] or [.., "-?"]
|
||||||
or ["-h", ..]
|
or ["-h", ..] or [.., "-h"]
|
||||||
or ["--help"]
|
or ["--help"] or [.., "--help"]
|
||||||
or ["--version"] && !force)
|
or ["--version"] && !force)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -53,14 +53,6 @@ public class ProjectContext
|
|||||||
await Bash.ExecuteAsync($"chmod 777 {fullPath}");
|
await Bash.ExecuteAsync($"chmod 777 {fullPath}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task WriteFile(string path, params string[] content)
|
|
||||||
{
|
|
||||||
var fullPath = Path.Combine(RootDirectory, path);
|
|
||||||
var fileInfo = new FileInfo(fullPath);
|
|
||||||
Directory.CreateDirectory(fileInfo.Directory!.FullName);
|
|
||||||
await File.WriteAllTextAsync(fullPath, string.Join("\n", content));
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<string> ReadFile(string path)
|
public async Task<string> ReadFile(string path)
|
||||||
{
|
{
|
||||||
var fullPath = Path.Combine(RootDirectory, path);
|
var fullPath = Path.Combine(RootDirectory, path);
|
||||||
@ -72,6 +64,14 @@ public class ProjectContext
|
|||||||
return await File.ReadAllTextAsync(fullPath);
|
return await File.ReadAllTextAsync(fullPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task WriteFile(string path, params string[] content)
|
||||||
|
{
|
||||||
|
var fullPath = Path.Combine(RootDirectory, path);
|
||||||
|
var fileInfo = new FileInfo(fullPath);
|
||||||
|
Directory.CreateDirectory(fileInfo.Directory!.FullName);
|
||||||
|
await File.WriteAllTextAsync(fullPath, string.Join("\n", content));
|
||||||
|
}
|
||||||
|
|
||||||
public async Task SaveConfig()
|
public async Task SaveConfig()
|
||||||
{
|
{
|
||||||
if (Config is not null)
|
if (Config is not null)
|
||||||
|
12
MycroForge.CLI/scripts/user.py
Normal file
12
MycroForge.CLI/scripts/user.py
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
from sqlalchemy import String
|
||||||
|
from sqlalchemy.orm import Mapped, mapped_column
|
||||||
|
from orm.entities.entity_base import EntityBase
|
||||||
|
|
||||||
|
class User(EntityBase):
|
||||||
|
__tablename__ = "users"
|
||||||
|
id: Mapped[int] = mapped_column(primary_key=True)
|
||||||
|
firstname: Mapped[str] = mapped_column(String(255))
|
||||||
|
lastname: Mapped[str] = mapped_column(String(255))
|
||||||
|
|
||||||
|
def __repr__(self) -> str:
|
||||||
|
return f"User(id={self.id!r}, firstname={self.firstname!r}, lastname={self.lastname!r})"
|
Loading…
Reference in New Issue
Block a user