Added scripting capabilities and cleaned up

This commit is contained in:
2024-04-26 22:52:10 +02:00
parent 68b9b0e8c8
commit b23ba99ba4
18 changed files with 216 additions and 119 deletions

View File

@@ -9,14 +9,17 @@ public partial class MycroForge
{
public class Run : Command, ISubCommandOf<Api>
{
public Run() : base("run", "Run your app")
private readonly ProjectContext _context;
public Run(ProjectContext context) : base("run", "Run your app")
{
_context = context;
this.SetHandler(ExecuteAsync);
}
private async Task ExecuteAsync()
{
await Bash.ExecuteAsync([
await _context.Bash([
"source .venv/bin/activate",
"uvicorn main:app --reload"
]);

View File

@@ -50,13 +50,12 @@ public partial class MycroForge
// Create the config file and initialize the config
await _context.CreateFile("m4g.json", "{}");
await _context.LoadConfig(force: true);
// Create the entrypoint file
await _context.CreateFile("main.py");
// Create the venv
await Bash.ExecuteAsync($"python3 -m venv {Path.Combine(projectRoot, ".venv")}");
await _context.Bash($"python3 -m venv {Path.Combine(projectRoot, ".venv")}");
// Initialize default features
foreach (var feature in _features.Where(f => DefaultFeatures.Contains(f.Name)))
@@ -77,7 +76,7 @@ public partial class MycroForge
Directory.CreateDirectory(directory);
await Bash.ExecuteAsync($"chmod -R 777 {directory}");
await _context.Bash($"chmod -R 777 {directory}");
return directory;
}

View File

@@ -10,8 +10,12 @@ public partial class MycroForge
private static readonly Argument<IEnumerable<string>> PackagesArgument =
new(name: "packages", description: "The names of the packages to install");
public Install() : base("install", "Install packages and update the requirements.txt")
private readonly ProjectContext _context;
public Install(ProjectContext context) :
base("install", "Install packages and update the requirements.txt")
{
_context = context;
AddAlias("i");
AddArgument(PackagesArgument);
this.SetHandler(ExecuteAsync, PackagesArgument);
@@ -19,7 +23,7 @@ public partial class MycroForge
private async Task ExecuteAsync(IEnumerable<string> packages)
{
await Bash.ExecuteAsync(
await _context.Bash(
"source .venv/bin/activate",
$"pip install {string.Join(' ', packages)}",
"pip freeze > requirements.txt"

View File

@@ -14,8 +14,11 @@ public partial class MycroForge
private static readonly Argument<string> NameArgument =
new(name: "name", description: "The name of the migration");
public Migration() : base("migration", "Generate a migration")
private readonly ProjectContext _context;
public Migration(ProjectContext context) : base("migration", "Generate a migration")
{
_context = context;
AddAlias("m");
AddArgument(NameArgument);
this.SetHandler(ExecuteAsync, NameArgument);
@@ -23,7 +26,7 @@ public partial class MycroForge
private async Task ExecuteAsync(string name)
{
await Bash.ExecuteAsync(
await _context.Bash(
"source .venv/bin/activate",
$"alembic revision --autogenerate -m \"{name}\" --rev-id $(date -u +\"%Y%m%d%H%M%S\")"
);

View File

@@ -9,14 +9,17 @@ public partial class MycroForge
{
public class Migrate : Command, ISubCommandOf<Orm>
{
public Migrate() : base("migrate", "Apply migrations to the database")
private readonly ProjectContext _context;
public Migrate(ProjectContext context) : base("migrate", "Apply migrations to the database")
{
_context = context;
this.SetHandler(ExecuteAsync);
}
private async Task ExecuteAsync()
{
await Bash.ExecuteAsync([
await _context.Bash([
"source .venv/bin/activate",
"alembic upgrade head"
]);

View File

@@ -9,14 +9,17 @@ public partial class MycroForge
{
public class Rollback : Command, ISubCommandOf<Orm>
{
public Rollback() : base("rollback", "Rollback the last migration")
private readonly ProjectContext _context;
public Rollback(ProjectContext context) : base("rollback", "Rollback the last migration")
{
_context = context;
this.SetHandler(ExecuteAsync);
}
private async Task ExecuteAsync()
{
await Bash.ExecuteAsync([
await _context.Bash([
"source .venv/bin/activate",
"alembic downgrade -1"
]);

View File

@@ -0,0 +1,82 @@
using System.CommandLine;
using System.Dynamic;
using System.Text;
using IronPython.Hosting;
using MycroForge.CLI.Commands.Interfaces;
namespace MycroForge.CLI.Commands;
public partial class MycroForge
{
public partial class Script
{
public class Run : Command, ISubCommandOf<Script>
{
private readonly ProjectContext _context;
private static readonly Argument<string> NameArgument =
new(name: "name", description: "The name of the script");
private static readonly Argument<IEnumerable<string>> ArgsArgument =
new(name: "args", description: "The args to the script");
public Run(ProjectContext context) : base("run", "Run a script")
{
_context = context;
AddArgument(NameArgument);
AddArgument(ArgsArgument);
this.SetHandler(ExecuteAsync, NameArgument, ArgsArgument);
}
private void ExecuteAsync(string name, IEnumerable<string> args)
{
var engine = Python.CreateEngine();
using var output = new MemoryStream();
using var error = new MemoryStream();
engine.Runtime.IO.SetOutput(output, Encoding.Default);
engine.Runtime.IO.SetErrorOutput(error, Encoding.Default);
var scope = engine.CreateScope();
scope.SetVariable("args", args.ToArray());
scope.SetVariable("context", CreateScriptContext());
try
{
var scriptPath = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".m4g", name
);
engine.ExecuteFile(scriptPath, scope);
if (output.Length > 0)
Console.WriteLine(Encoding.Default.GetString(output.ToArray()));
if (error.Length > 0)
Console.WriteLine(Encoding.Default.GetString(error.ToArray()));
}
catch (Exception e)
{
Console.WriteLine(e);
}
finally
{
engine.Runtime.Shutdown();
}
}
private dynamic CreateScriptContext()
{
var createFile = _context.CreateFile;
var readFile = _context.ReadFile;
var writeFile = _context.WriteFile;
var bash = _context.Bash;
dynamic context = new ExpandoObject();
context.create_file = createFile;
context.read_file = readFile;
context.write_file = writeFile;
context.bash = bash;
return context;
}
}
}
}

View File

@@ -0,0 +1,18 @@
using System.CommandLine;
using MycroForge.CLI.Commands.Interfaces;
namespace MycroForge.CLI.Commands;
public partial class MycroForge
{
public partial class Script : Command, ISubCommandOf<MycroForge>
{
public Script(IEnumerable<ISubCommandOf<Script>> subCommands) :
base("script", "Script related commands")
{
AddAlias("s");
foreach (var subCommandOf in subCommands.Cast<Command>())
AddCommand(subCommandOf);
}
}
}

View File

@@ -10,8 +10,11 @@ public partial class MycroForge
private static readonly Argument<IEnumerable<string>> PackagesArgument =
new(name: "packages", description: "The names of the packages to uninstall");
public Uninstall() : base("uninstall", "Uninstall packages and update the requirements.txt")
private readonly ProjectContext _context;
public Uninstall(ProjectContext context) : base("uninstall", "Uninstall packages and update the requirements.txt")
{
_context = context;
AddAlias("u");
AddArgument(PackagesArgument);
this.SetHandler(ExecuteAsync, PackagesArgument);
@@ -19,7 +22,7 @@ public partial class MycroForge
private async Task ExecuteAsync(IEnumerable<string> packages)
{
await Bash.ExecuteAsync(
await _context.Bash(
"source .venv/bin/activate",
$"pip uninstall {string.Join(' ', packages)}",
"pip freeze > requirements.txt"