-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* not working * python script sample not working flask * fixed script working * added runner script * readme * remove folder * revert readme * added gitignore for py files * remove app.py * change script * change readme
- Loading branch information
Showing
4 changed files
with
345 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
_packagemanagement | ||
*.py | ||
requirements.txt | ||
fable_modules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Compile and Run a Python Script | ||
|
||
``` | ||
dotnet tool restore | ||
``` | ||
|
||
then run | ||
|
||
``` | ||
dotnet fsi run_flask_app.fsx flask_sample.fsx | ||
``` | ||
|
||
this will run using `pip-run` for now requirements.txt manual file is supported but inference via `pipreqs` is not working as expected. | ||
|
||
## python dependencies | ||
|
||
* python3 | ||
* pip | ||
* `pipx` > required, used to install global python packages. DEPENDENCY, [install instructions here](https://pipx.pypa.io/stable/) or for mac via brew. | ||
* `pipreqs` for package requiremnts inference : `pipx install pipreqs` will be executed. (not working yet) | ||
* `pip-run` for running with defualt one shot option, which runs your script one time in a temp env (can be installed with pipx), `pipx install pip-run` will be executed | ||
|
||
## pip-run | ||
|
||
* [pip-run](https://github.com/jaraco/pip-run/blob/main/README.rst) is used to run all script in "isolation" taking care of creatinv venv and installing libs in temp dirs and removing them after execution |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
#r "nuget: Fable.Core" | ||
#r "nuget: Fable.Python" | ||
#r "nuget: Feliz.ViewEngine" | ||
#r "nuget: Zanaptak.TypedCssClasses" | ||
// #r "nuget: Fli" | ||
open Fable.Python.Builtins | ||
open Feliz.ViewEngine | ||
open Zanaptak.TypedCssClasses | ||
|
||
// PIP: flask | ||
open Fable.Python.Flask | ||
|
||
type Bulma = CssClasses<"https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.3/css/bulma.min.css", Naming.PascalCase> | ||
|
||
module View = | ||
let title (str: string) = Html.p [ prop.classes [ Bulma.Title ]; prop.text str ] | ||
let subTitle (str: string) = Html.p [ prop.classes [ Bulma.Subtitle ]; prop.text str ] | ||
|
||
let model = {| | ||
Title="Fable Python |> F# ♥️ Python" | ||
Description="Demo Website, Fable Python running on Flask!" | ||
Banner="https://unsplash.it/1200/900?random" | ||
PermaLink="https://fable.io" | ||
Author="[email protected]" | ||
Brand="public/favicon.png" | ||
|} | ||
|
||
let head = | ||
Html.head [ | ||
Html.title [ prop.text model.Title ] | ||
|
||
Html.meta [ prop.charset.utf8 ] | ||
Html.meta [ prop.name "author"; prop.content model.Author ] | ||
Html.meta [ prop.name "description"; prop.content model.Description ] | ||
|
||
Html.meta [ prop.httpEquiv.contentType; prop.content "text/html"; prop.charset.utf8 ] | ||
Html.meta [ prop.name "viewport"; prop.content "width=device-width, initial-scale=1" ] | ||
|
||
Html.meta [ | ||
prop.custom ("http-equiv", "Cache-Control") | ||
prop.content "no-cache, no-store, must-revalidate" | ||
] | ||
Html.meta [ prop.custom ("http-equiv", "Pragma"); prop.content "no-cache" ] | ||
Html.meta [ prop.custom ("http-equiv", "Expires"); prop.content "0" ] | ||
|
||
Html.link [ prop.rel "icon"; prop.href "public/favicon.ico" ] | ||
Html.link [ prop.rel "stylesheet"; prop.href "https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.3/css/bulma.min.css"; prop.crossOrigin.anonymous ] | ||
] | ||
|
||
let body = Html.div [ | ||
title model.Title | ||
subTitle model.Description | ||
] | ||
|
||
let section = | ||
Html.section [ | ||
prop.classes [ Bulma.Hero; Bulma.IsFullheightWithNavbar ] | ||
prop.style [ | ||
style.backgroundImageUrl (model.Banner) | ||
style.backgroundPosition "center" | ||
style.backgroundSize.cover | ||
] | ||
prop.children [ | ||
Html.div [ | ||
prop.classes [ Bulma.HeroBody; Bulma.IsDark ] | ||
prop.children [ Html.div [ prop.classes [ Bulma.Container ]; prop.children body ] ] | ||
] | ||
] | ||
] | ||
|
||
let html = | ||
Html.html [ | ||
head | ||
Html.body [ | ||
section | ||
] | ||
] | ||
|
||
let renderView () = | ||
View.html |> Render.htmlDocument | ||
|
||
// NB: this must not be inside a module for Flask to resolve the app correctly! | ||
// https://stackoverflow.com/questions/57718786/error-launching-flask-app-with-error-failed-to-find-flask-application | ||
let app = Flask.Create(__name__, "/public") | ||
|
||
// Setup the routes. See if we can use attributes instead | ||
app.route("/")(renderView) |> ignore | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,228 @@ | ||
// dotnet fsi run_flask_app flask_sample.fsx [--global](to uses pip-run and venv by default) | ||
#r "nuget: Fli" | ||
#r "nuget: EluciusFTW.SpectreCoff" | ||
//we can use this package to run python commands together with the script | ||
open Fli | ||
open SpectreCoff | ||
|
||
"Python + F#" |> figlet |> toConsole | ||
|
||
// using vscode F# highlight ext can also execute inline python | ||
let python (p : string)= p | ||
|
||
let create_py_venv () = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m venv .venv") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
let install_pip_run_package() = | ||
"install pip-run" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("pipx install pip-run") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
|
||
let isGlobal = | ||
match fsi.CommandLineArgs |> Seq.toList with | ||
|_::_::"--global"::[] -> true | ||
|_::"--global"::_ -> true | ||
|_ -> false | ||
|
||
let install_pipreqs_package() = | ||
"install pipreqs" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("pipx install pipreqs") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
// FAILS... | ||
let gen_pip_requirements_file() = | ||
"execute pipreqs to generate requirements.txt" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m pipreqs .") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let create_requirements() = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("touch requirements.txt") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
let gen_pip_requirements_file_local() = | ||
"execute local pipreqs to generate requirements.txt" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("pipreqs .") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let install_pip_requirements() = | ||
"pip install requirements.txt" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m pip install -r requirements.txt ") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let activate_py_venv () = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("source .venv/bin/activate") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let which_python () = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("which python") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
|
||
/// pip install flask | ||
let pip_install_flask() = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m pip install flask") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
/// pip install extra dependencies if needed, specify them as extra arg ',' separated | ||
let pip_install_extras() = | ||
let dependencies = | ||
match fsi.CommandLineArgs |> Seq.toList with | ||
|_::_::trd::[] -> trd.Split(",") | ||
|_ -> [||] | ||
|
||
for dep in dependencies do | ||
cli { | ||
Shell Shells.BASH | ||
Command ($"python3 -m pip install {dep}") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
let fable_compile_flask_app() = | ||
"FABLE" |> figlet |> toConsole | ||
|
||
let flaskScriptName = | ||
printfn $"args: {fsi.CommandLineArgs}" | ||
match fsi.CommandLineArgs |> Seq.toList with | ||
|_::snd::[] -> snd | ||
|_ -> "app.fsx" | ||
|
||
cli { | ||
Shell Shells.BASH | ||
Command ($"dotnet tool restore && dotnet fable {flaskScriptName} --lang Python --noCache") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let remove_old_app() = | ||
"rm app.py" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command "rm app.py" | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let rename_and_cleanup() = | ||
"rename latest script to app.py" |> C |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command "mv *.py app.py" | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> Output.printText | ||
|
||
let deactivate_py_venv() = | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m deactivate") | ||
} | ||
|> Command.execute | ||
|> Output.printText | ||
|
||
let run_flask_app() = | ||
try | ||
"starting app to listen on http://127.0.0.1:5000" |> P |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("python3 -m flask run") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> ignore | ||
with ex -> | ||
printfn $"script exited with code {ex.Message}" | ||
() | ||
|
||
let one_shot_run_flask_app() = | ||
try | ||
"starting ONE-SHOT app to listen on http://127.0.0.1:5000" |> P |> toConsole | ||
cli { | ||
Shell Shells.BASH | ||
Command ("pip-run flask -r requirements.txt -- -m flask run") | ||
} | ||
|> Command.execute | ||
|> Output.throwIfErrored | ||
|> ignore | ||
with ex -> | ||
$"script exited with code {ex.Message}" |> P |> toConsole | ||
() | ||
|
||
|
||
let isVenv = | ||
match fsi.CommandLineArgs |> Seq.toList with | ||
|_::_::"--venv"::[] -> true | ||
|_::"--venv"::_ -> true | ||
|_ -> false | ||
|
||
// execution | ||
|
||
if isVenv then | ||
create_py_venv() | ||
|> activate_py_venv | ||
|> which_python | ||
printfn "remember to run deactivate at the end of the script, or which python" | ||
|
||
//install_pipreqs_package() | ||
//|> if isGlobal then gen_pip_requirements_file else gen_pip_requirements_file_local | ||
() | ||
|> create_requirements | ||
|> if isGlobal then id else install_pip_run_package | ||
|> fable_compile_flask_app | ||
|> remove_old_app | ||
|> rename_and_cleanup | ||
|> if isGlobal then run_flask_app else one_shot_run_flask_app | ||
|
||
// need a strategy to not break on CTRL-C for this... | ||
// maybe use `fg` ? | ||
// |> deactivate_py_venv | ||
// |> which_python |