chore: adiciona .gitignore e commit.command

This commit is contained in:
João Henrique
2026-08-18 08:25:29 -04:00
parent 68958fde00
commit 8fca456ceb
215 changed files with 65752 additions and 0 deletions
+163
View File
@@ -0,0 +1,163 @@
import Foundation
/// Bridges the SwiftUI app to the Python engine via the `admin/models_api.py`
/// JSON bridge. The app launches the script as a subprocess and reads
/// newline-delimited JSON on stdout (JSON-lines), so long-running commands can
/// stream progress.
enum PythonBridge {
/// Resolve the Python interpreter + script path.
/// Prefers `uv run` so extras are available; falls back to `python3`.
static var scriptURL: URL {
// Search order: cwd + ancestors, the app's own bundle root, home, and
// some common mount points (the repo often lives under /Volumes/...).
let cwd = URL(fileURLWithPath: FileManager.default.currentDirectoryPath)
var searchRoots: [URL] = []
var dir = cwd
for _ in 0..<8 { searchRoots.append(dir); dir.deleteLastPathComponent() }
if let bundle = Bundle.main.resourceURL {
searchRoots.append(bundle)
}
searchRoots.append(URL(fileURLWithPath: NSHomeDirectory()))
searchRoots.append(URL(fileURLWithPath: "/Volumes/Merongo/SISTEMAS/GENIAL SISTEMAS/G-ART"))
for root in searchRoots {
let candidate = root.appendingPathComponent("admin/models_api.py")
if FileManager.default.fileExists(atPath: candidate.path) {
return candidate
}
}
// Fall back to cwd.
return cwd.appendingPathComponent("admin/models_api.py")
}
/// Project root containing `admin/`.
static var projectRoot: URL {
scriptURL.deletingLastPathComponent().deletingLastPathComponent()
}
static var pythonCommand: [String] {
// Prefer `uv run python` (has extras); fall back to `python3`.
if let uv = findUV() {
return [uv, "run", "python", scriptURL.path]
}
return ["python3", scriptURL.path]
}
static var workingDirectory: URL {
projectRoot
}
/// Locate `uv` on PATH or in common install locations.
private static func findUV() -> String? {
if let onPath = which("uv") { return onPath }
let candidates = [
"/usr/local/bin/uv",
"/opt/homebrew/bin/uv",
"/opt/local/bin/uv",
"\(NSHomeDirectory())/.local/bin/uv",
"\(NSHomeDirectory())/.cargo/bin/uv",
"/Library/Frameworks/Python.framework/Versions/3.14/bin/uv",
]
for c in candidates where FileManager.default.isExecutableFile(atPath: c) {
return c
}
return nil
}
private static func which(_ name: String) -> String? {
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
process.arguments = ["which", name]
let pipe = Pipe()
process.standardOutput = pipe
process.standardError = Pipe()
do { try process.run() } catch { return nil }
process.waitUntilExit()
let data = pipe.fileHandleForReading.readDataToEndOfFile()
let path = String(data: data, encoding: .utf8)?.trimmingCharacters(in: .whitespacesAndNewlines)
return (path?.isEmpty ?? true) ? nil : path
}
// MARK: - Streaming JSON-lines
/// Runs a command and collects every parsed JSON document on stdout.
/// `onProgress` is called for each document (used for download progress).
static func run(command: String, arguments: [String: Any] = [:],
onLine: @escaping ([String: Any]) -> Void,
completion: @escaping (Int, String?) -> Void) {
var cmd = pythonCommand
cmd.append(command)
if !arguments.isEmpty, let data = try? JSONSerialization.data(withJSONObject: arguments),
let str = String(data: data, encoding: .utf8) {
cmd.append(str)
}
let process = Process()
process.executableURL = URL(fileURLWithPath: "/usr/bin/env")
process.arguments = cmd
process.currentDirectoryURL = workingDirectory
let pipe = Pipe()
process.standardOutput = pipe
let errPipe = Pipe()
process.standardError = errPipe
var stderrBuffer = ""
var stdoutBuffer = ""
let outputLock = NSLock()
errPipe.fileHandleForReading.readabilityHandler = { handle in
let data = handle.availableData
if let s = String(data: data, encoding: .utf8) { stderrBuffer += s }
}
pipe.fileHandleForReading.readabilityHandler = { handle in
let data = handle.availableData
guard !data.isEmpty, let s = String(data: data, encoding: .utf8) else { return }
outputLock.lock()
stdoutBuffer += s
let parts = stdoutBuffer.split(separator: "\n", omittingEmptySubsequences: false)
stdoutBuffer = String(parts.last ?? "")
let lines = parts.dropLast()
outputLock.unlock()
for line in lines {
if let obj = try? JSONSerialization.jsonObject(with: Data(line.utf8)) as? [String: Any] {
onLine(obj)
}
}
}
process.terminationHandler = { p in
pipe.fileHandleForReading.readabilityHandler = nil
errPipe.fileHandleForReading.readabilityHandler = nil
outputLock.lock()
let finalLine = stdoutBuffer.trimmingCharacters(in: .whitespacesAndNewlines)
stdoutBuffer = ""
outputLock.unlock()
if !finalLine.isEmpty,
let obj = try? JSONSerialization.jsonObject(with: Data(finalLine.utf8)) as? [String: Any] {
onLine(obj)
}
let error = p.terminationStatus == 0 ? nil : (stderrBuffer.isEmpty ? "O comando \(command) falhou (código \(p.terminationStatus))." : stderrBuffer)
completion(Int(p.terminationStatus), error)
}
do {
try process.run()
} catch {
completion(1, error.localizedDescription)
}
}
// MARK: - Convenience: single JSON result
/// Runs a command and delivers the first parsed JSON document as the result.
static func call(command: String, arguments: [String: Any] = [:],
completion: @escaping ([String: Any]?, String?) -> Void) {
var result: [String: Any]?
run(command: command, arguments: arguments, onLine: { obj in
if result == nil { result = obj }
}, completion: { code, err in
completion(result, err)
})
}
}