Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 3 additions & 0 deletions .markdownlint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"MD024": false
}
9 changes: 0 additions & 9 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,10 @@

## [5.0.0-alpha.21.1](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.21.0...v5.0.0-alpha.21.1) (2025-12-18)


### Features

* Add Json static class with Fable-aware serialization ([#175](https://github.com/fable-compiler/Fable.Python/issues/175)) ([1eb5005](https://github.com/fable-compiler/Fable.Python/commit/1eb500523c6d6f43247bc3510a6045ec8d9d9d4e))


### Bug Fixes

* correct manifest to last released version ([bb9cb88](https://github.com/fable-compiler/Fable.Python/commit/bb9cb881c00b7ea6809ad3a87a35a7ebc0ff9008))
Expand All @@ -23,7 +21,6 @@

## [5.0.0-alpha.21.0](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.21...v5.0.0-alpha.21.0) (2025-12-16)


### Features

* Add exception types ([#173](https://github.com/fable-compiler/Fable.Python/issues/173)) ([72f09b2](https://github.com/fable-compiler/Fable.Python/commit/72f09b2ff6e208e3ab057430a355814611abd46c))
Expand All @@ -33,7 +30,6 @@
* Fable v5 ([#147](https://github.com/fable-compiler/Fable.Python/issues/147)) ([abf8e6a](https://github.com/fable-compiler/Fable.Python/commit/abf8e6a1f7bbc2eae152431d04d6b8b5675f7795))
* FastAPI async handlers ([#174](https://github.com/fable-compiler/Fable.Python/issues/174)) ([26cec1f](https://github.com/fable-compiler/Fable.Python/commit/26cec1f239f9244a7c1da1d00bbf1a479596bb3c))


### Bug Fixes

* add missing models.py for pydantic example and update README ([#168](https://github.com/fable-compiler/Fable.Python/issues/168)) ([b76ce98](https://github.com/fable-compiler/Fable.Python/commit/b76ce989e0598d0007a8a1be9addfea97936eae7))
Expand All @@ -43,35 +39,30 @@
* use plain int/string types for open ([b202a25](https://github.com/fable-compiler/Fable.Python/commit/b202a25bd7f48538fadc50125294a9252714d364))
* use string types for open ([f211f8b](https://github.com/fable-compiler/Fable.Python/commit/f211f8bb9445dd6930926fe48aab6a69720dd30f))


### Miscellaneous Chores

* sync with Fable 5.0.0-alpha.21 ([fd2685c](https://github.com/fable-compiler/Fable.Python/commit/fd2685c2f992c2d8058ac1bc1261d647271359df))

## [5.0.0-alpha.20.2](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.20.1...v5.0.0-alpha.20.2) (2025-12-09)


### Features

* add Python stdlib bindings for logging, random, and expand string module ([#166](https://github.com/fable-compiler/Fable.Python/issues/166)) ([709d6c2](https://github.com/fable-compiler/Fable.Python/commit/709d6c2b29199965926ff639727fdcc1bb2e1fb8))

## [5.0.0-alpha.20.1](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.20...v5.0.0-alpha.20.1) (2025-12-08)


### Bug Fixes

* relax FSharp.Core dependency to >= 5.0.0 ([#163](https://github.com/fable-compiler/Fable.Python/issues/163)) ([10eb65b](https://github.com/fable-compiler/Fable.Python/commit/10eb65b22a157078e1b66bd8fb202b0cd2acbedc))

## [5.0.0-alpha.20](https://github.com/fable-compiler/Fable.Python/compare/v5.0.0-alpha.20...v5.0.0-alpha.20) (2025-12-08)


### Features

* add write ([334e800](https://github.com/fable-compiler/Fable.Python/commit/334e80089c081bda25633f83dae037fc6c8fe6f5))
* Added bindings for Pydantic and FastAPI + examples ([#151](https://github.com/fable-compiler/Fable.Python/issues/151)) ([826629e](https://github.com/fable-compiler/Fable.Python/commit/826629e465fca15d444a4ca37b851b8aab488f9a))
* Fable v5 ([#147](https://github.com/fable-compiler/Fable.Python/issues/147)) ([abf8e6a](https://github.com/fable-compiler/Fable.Python/commit/abf8e6a1f7bbc2eae152431d04d6b8b5675f7795))


### Bug Fixes

* handle return type correctly ([a634168](https://github.com/fable-compiler/Fable.Python/commit/a6341684ac8bb3f1b244f448c22e1fe6f208fbc0))
Expand Down
2 changes: 1 addition & 1 deletion release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"packages": {
".": {
"release-type": "simple",
"release-as": "5.0.0-alpha.21.2",
"release-as": "5.0.0-alpha.21.3",
"include-component-in-tag": false,
"include-v-in-tag": true,
"changelog-path": "CHANGELOG.md"
Expand Down
2 changes: 2 additions & 0 deletions src/Fable.Python.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@

<Compile Include="pydantic/Pydantic.fs" />
<Compile Include="fastapi/FastAPI.fs" />

<Compile Include="fable/Types.fs" />
</ItemGroup>
<ItemGroup>
<Content Include="pyproject.toml; *.fsproj; **\*.fs; **\*.fsi" PackagePath="fable\" />
Expand Down
55 changes: 55 additions & 0 deletions src/fable/Types.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/// Utilities for detecting and working with Fable types at runtime in Python.
/// These helpers are useful when you need to distinguish between native Python types
/// and Fable-compiled F# types (e.g., Int32, Float64, FSharpArray).
module Fable.Python.Fable.Types

open Fable.Core

/// Get the Python type name of an object
[<Emit("type($0).__name__")>]
let typeName (o: obj) : string = nativeOnly

/// Check if an object is a Fable integral type (Int8, Int16, Int32, Int64, UInt8, UInt16, UInt32, UInt64)
let isIntegralType (o: obj) : bool =
match typeName o with
| "Int8"
| "Int16"
| "Int32"
| "Int64"
| "UInt8"
| "UInt16"
| "UInt32"
| "UInt64" -> true
| _ -> false

/// Check if an object is a Fable numeric type (integral types + Float32, Float64)
let isNumericType (o: obj) : bool =
match typeName o with
| "Int8"
| "Int16"
| "Int32"
| "Int64"
| "UInt8"
| "UInt16"
| "UInt32"
| "UInt64"
| "Float32"
| "Float64" -> true
| _ -> false

/// Check if an object is a Fable array type (FSharpArray, GenericArray, or typed arrays)
let isArrayType (o: obj) : bool =
match typeName o with
| "FSharpArray"
| "GenericArray"
| "Int8Array"
| "Int16Array"
| "Int32Array"
| "Int64Array"
| "UInt8Array"
| "UInt16Array"
| "UInt32Array"
| "UInt64Array"
| "Float32Array"
| "Float64Array" -> true
| _ -> false
61 changes: 31 additions & 30 deletions src/fastapi/FastAPI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -136,33 +136,27 @@ type RouterWebSocketAttribute(path: string) =

/// JSON response class
[<Import("JSONResponse", "fastapi.responses")>]
type JSONResponse(content: obj, ?status_code: int) =
class end
type JSONResponse(content: obj, ?status_code: int) = class end

/// HTML response class
[<Import("HTMLResponse", "fastapi.responses")>]
type HTMLResponse(content: string, ?status_code: int) =
class end
type HTMLResponse(content: string, ?status_code: int) = class end

/// Plain text response class
[<Import("PlainTextResponse", "fastapi.responses")>]
type PlainTextResponse(content: string, ?status_code: int) =
class end
type PlainTextResponse(content: string, ?status_code: int) = class end

/// Redirect response class
[<Import("RedirectResponse", "fastapi.responses")>]
type RedirectResponse(url: string, ?status_code: int) =
class end
type RedirectResponse(url: string, ?status_code: int) = class end

/// Streaming response class
[<Import("StreamingResponse", "fastapi.responses")>]
type StreamingResponse(content: obj, ?media_type: string) =
class end
type StreamingResponse(content: obj, ?media_type: string) = class end

/// File response class
[<Import("FileResponse", "fastapi.responses")>]
type FileResponse(path: string, ?filename: string, ?media_type: string) =
class end
type FileResponse(path: string, ?filename: string, ?media_type: string) = class end

// ============================================================================
// Request and WebSocket
Expand Down Expand Up @@ -256,8 +250,7 @@ type WebSocket() =

/// HTTP exception for returning error responses
[<Import("HTTPException", "fastapi")>]
type HTTPException(status_code: int, ?detail: string) =
class end
type HTTPException(status_code: int, ?detail: string) = class end

// ============================================================================
// Dependency Injection
Expand Down Expand Up @@ -422,7 +415,7 @@ type UploadFile() =
/// File parameter marker
[<Import("File", "fastapi")>]
[<Emit("$0()")>]
let File() : UploadFile = nativeOnly
let File () : UploadFile = nativeOnly

/// Form parameter marker
[<Import("Form", "fastapi")>]
Expand Down Expand Up @@ -452,7 +445,10 @@ type APIRouter(?prefix: string, ?tags: ResizeArray<string>) =

/// Include another router with prefix and tags
[<Emit("$0.include_router($1, prefix=$2, tags=$3)")>]
member _.include_router_with_prefix_and_tags(_router: APIRouter, _prefix: string, _tags: ResizeArray<string>) : unit = nativeOnly
member _.include_router_with_prefix_and_tags
(_router: APIRouter, _prefix: string, _tags: ResizeArray<string>)
: unit =
nativeOnly

// ============================================================================
// FastAPI Application
Expand All @@ -471,7 +467,10 @@ type FastAPI(?title: string, ?description: string, ?version: string) =

/// Include a router with prefix and tags
[<Emit("$0.include_router($1, prefix=$2, tags=$3)")>]
member _.include_router_with_prefix_and_tags(_router: APIRouter, _prefix: string, _tags: ResizeArray<string>) : unit = nativeOnly
member _.include_router_with_prefix_and_tags
(_router: APIRouter, _prefix: string, _tags: ResizeArray<string>)
: unit =
nativeOnly

/// Add middleware
[<Emit("$0.add_middleware($1)")>]
Expand Down Expand Up @@ -571,8 +570,7 @@ type OAuth2PasswordRequestForm() =

/// HTTP Basic authentication
[<Import("HTTPBasic", "fastapi.security")>]
type HTTPBasic() =
class end
type HTTPBasic() = class end

/// HTTP Basic credentials
[<Import("HTTPBasicCredentials", "fastapi.security")>]
Expand All @@ -587,8 +585,7 @@ type HTTPBasicCredentials() =

/// HTTP Bearer authentication
[<Import("HTTPBearer", "fastapi.security")>]
type HTTPBearer() =
class end
type HTTPBearer() = class end

/// HTTP Bearer credentials (token in Authorization header)
[<Import("HTTPAuthorizationCredentials", "fastapi.security")>]
Expand All @@ -603,27 +600,23 @@ type HTTPAuthorizationCredentials() =

/// API Key in header
[<Import("APIKeyHeader", "fastapi.security")>]
type APIKeyHeader(name: string) =
class end
type APIKeyHeader(name: string) = class end

/// API Key in query parameter
[<Import("APIKeyQuery", "fastapi.security")>]
type APIKeyQuery(name: string) =
class end
type APIKeyQuery(name: string) = class end

/// API Key in cookie
[<Import("APIKeyCookie", "fastapi.security")>]
type APIKeyCookie(name: string) =
class end
type APIKeyCookie(name: string) = class end

// ============================================================================
// CORS Middleware
// ============================================================================

/// CORS middleware for handling Cross-Origin Resource Sharing
[<Import("CORSMiddleware", "fastapi.middleware.cors")>]
type CORSMiddleware =
class end
type CORSMiddleware = class end

/// CORS middleware configuration helper
module CORSMiddleware =
Expand All @@ -634,7 +627,15 @@ module CORSMiddleware =

/// Add CORS middleware to app with all origins allowed
[<Emit("$0.add_middleware($1, allow_origins=$2, allow_credentials=$3, allow_methods=$4, allow_headers=$5)")>]
let addToApp (_app: FastAPI) (_middleware: obj) (_origins: string array) (_credentials: bool) (_methods: string array) (_headers: string array) : unit = nativeOnly
let addToApp
(_app: FastAPI)
(_middleware: obj)
(_origins: string array)
(_credentials: bool)
(_methods: string array)
(_headers: string array)
: unit =
nativeOnly

// ============================================================================
// Encoders
Expand Down
3 changes: 1 addition & 2 deletions src/flask/Flask.fs
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,7 @@ let make_response_with_status (_body: obj) (_status: int) : Response = nativeOnl

/// Flask Blueprint for modular applications
[<Import("Blueprint", "flask")>]
type Blueprint(name: string, import_name: string, ?url_prefix: string) =
class end
type Blueprint(name: string, import_name: string, ?url_prefix: string) = class end

// ============================================================================
// Flask Application
Expand Down
1 change: 0 additions & 1 deletion src/pydantic/Pydantic.fs
Original file line number Diff line number Diff line change
Expand Up @@ -458,4 +458,3 @@ type Base64Str = string
/// JSON type - validates JSON string and parses it
[<Import("Json", "pydantic")>]
type JsonValue = obj

Loading